1/*
2 * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include <stdarg.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <limits.h>
31
32#include <sys/stat.h>
33
34#ifdef _MSC_VER
35#include <direct.h>
36#include <io.h>
37#include <process.h>
38#else
39#include <unistd.h>
40#endif
41
42#include "constants.h"
43#include "defines.h"
44#include "bytes.h"
45#include "utils.h"
46
47#include "unpack.h"
48
49void* must_malloc(size_t size) {
50 size_t msize = size;
51 #ifdef USE_MTRACE
52 if (msize >= 0 && msize < sizeof(int))
53 msize = sizeof(int); // see 0xbaadf00d below
54 #endif
55 void* ptr = (msize > PSIZE_MAX || msize <= 0) ? null : malloc(msize);
56 if (ptr != null) {
57 memset(ptr, 0, size);
58 } else {
59 unpack_abort(ERROR_ENOMEM);
60 }
61 mtrace('m', ptr, size);
62 return ptr;
63}
64
65void mkdirs(int oklen, char* path) {
66
67 if (strlen(path) <= (size_t)oklen) return;
68 char dir[PATH_MAX];
69
70 strcpy(dir, path);
71 char* slash = strrchr(dir, '/');
72 if (slash == 0) return;
73 *slash = 0;
74 mkdirs(oklen, dir);
75 MKDIR(dir);
76}
77
78
79#ifndef PRODUCT
80#ifndef STATIC_BUILD
81// use the definition in libjvm when building statically
82void breakpoint() { } // hook for debugger
83int assert_failed(const char* p) {
84 char message[1<<12];
85 sprintf(message, "@assert failed: %s\n", p);
86 fprintf(stdout, "%s", 1+message);
87 breakpoint();
88 unpack_abort(message);
89 return 0;
90}
91#endif
92#endif
93
94void unpack_abort(const char* msg, unpacker* u) {
95 if (msg == null) msg = "corrupt pack file or internal error";
96 if (u == null)
97 u = unpacker::current();
98 if (u == null) {
99 fprintf(stderr, "Error: unpacker: %s\n", msg);
100 ::abort();
101 return;
102 }
103 u->abort(msg);
104}
105
106bool unpack_aborting(unpacker* u) {
107 if (u == null)
108 u = unpacker::current();
109 if (u == null) {
110 fprintf(stderr, "Error: unpacker: no current instance\n");
111 ::abort();
112 return true;
113 }
114 return u->aborting();
115}
116
117#ifdef USE_MTRACE
118// Use this occasionally for detecting storage leaks in unpack.
119void mtrace(char c, void* ptr, size_t size) {
120 if (c == 'f') *(int*)ptr = 0xbaadf00d;
121 static FILE* mtfp;
122 if (mtfp == (FILE*)-1) return;
123 if (mtfp == null) {
124 if (getenv("USE_MTRACE") == null) {
125 mtfp = (FILE*)-1;
126 return;
127 }
128 char fname[1024];
129 sprintf(fname, "mtr%d.txt", getpid());
130 mtfp = fopen(fname, "w");
131 if (mtfp == null)
132 mtfp = stdout;
133 }
134 fprintf(mtfp, "%c %p %p\n", c, ptr, (void*)size);
135}
136
137/* # Script for processing memory traces.
138 # It should report only a limited number (2) of "suspended" blocks,
139 # even if a large number of archive segments are processed.
140 # It should report no "leaked" blocks at all.
141 nawk < mtr*.txt '
142 function checkleaks(what) {
143 nd = 0
144 for (ptr in allocated) {
145 if (allocated[ptr] == 1) {
146 print NR ": " what " " ptr
147 #allocated[ptr] = 0 # stop the dangle
148 nd++
149 }
150 }
151 if (nd > 0) print NR ": count " what " " nd
152 }
153
154 /^[mfr]/ {
155 ptr = $2
156 a1 = ($1 == "m")? 1: 0
157 a0 = 0+allocated[ptr]
158 allocated[ptr] = a1
159 if (a0 + a1 != 1) {
160 if (a0 == 0 && a1 == 0)
161 print NR ": double free " ptr
162 else if (a0 == 1 && a1 == 1)
163 print NR ": double malloc " ptr
164 else
165 print NR ": oddity " $0
166 }
167 next
168 }
169
170 /^s/ {
171 checkleaks("suspended")
172 next
173 }
174
175 {
176 print NR ": unrecognized " $0
177 }
178 END {
179 checkleaks("leaked")
180 }
181'
182*/
183#endif // USE_MTRACE
184