utils.cpp revision 16278:de18c7fc80ea
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