/* * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include #include #include #include #include #include #ifdef _MSC_VER #include #include #include #else #include #endif #include "constants.h" #include "defines.h" #include "bytes.h" #include "utils.h" #include "unpack.h" void* must_malloc(size_t size) { size_t msize = size; #ifdef USE_MTRACE if (msize >= 0 && msize < sizeof(int)) msize = sizeof(int); // see 0xbaadf00d below #endif void* ptr = (msize > PSIZE_MAX || msize <= 0) ? null : malloc(msize); if (ptr != null) { memset(ptr, 0, size); } else { unpack_abort(ERROR_ENOMEM); } mtrace('m', ptr, size); return ptr; } void mkdirs(int oklen, char* path) { if (strlen(path) <= (size_t)oklen) return; char dir[PATH_MAX]; strcpy(dir, path); char* slash = strrchr(dir, '/'); if (slash == 0) return; *slash = 0; mkdirs(oklen, dir); MKDIR(dir); } #ifndef PRODUCT #ifndef STATIC_BUILD // use the definition in libjvm when building statically void breakpoint() { } // hook for debugger int assert_failed(const char* p) { char message[1<<12]; sprintf(message, "@assert failed: %s\n", p); fprintf(stdout, "%s", 1+message); breakpoint(); unpack_abort(message); return 0; } #endif #endif void unpack_abort(const char* msg, unpacker* u) { if (msg == null) msg = "corrupt pack file or internal error"; if (u == null) u = unpacker::current(); if (u == null) { fprintf(stderr, "Error: unpacker: %s\n", msg); ::abort(); return; } u->abort(msg); } bool unpack_aborting(unpacker* u) { if (u == null) u = unpacker::current(); if (u == null) { fprintf(stderr, "Error: unpacker: no current instance\n"); ::abort(); return true; } return u->aborting(); } #ifdef USE_MTRACE // Use this occasionally for detecting storage leaks in unpack. void mtrace(char c, void* ptr, size_t size) { if (c == 'f') *(int*)ptr = 0xbaadf00d; static FILE* mtfp; if (mtfp == (FILE*)-1) return; if (mtfp == null) { if (getenv("USE_MTRACE") == null) { mtfp = (FILE*)-1; return; } char fname[1024]; sprintf(fname, "mtr%d.txt", getpid()); mtfp = fopen(fname, "w"); if (mtfp == null) mtfp = stdout; } fprintf(mtfp, "%c %p %p\n", c, ptr, (void*)size); } /* # Script for processing memory traces. # It should report only a limited number (2) of "suspended" blocks, # even if a large number of archive segments are processed. # It should report no "leaked" blocks at all. nawk < mtr*.txt ' function checkleaks(what) { nd = 0 for (ptr in allocated) { if (allocated[ptr] == 1) { print NR ": " what " " ptr #allocated[ptr] = 0 # stop the dangle nd++ } } if (nd > 0) print NR ": count " what " " nd } /^[mfr]/ { ptr = $2 a1 = ($1 == "m")? 1: 0 a0 = 0+allocated[ptr] allocated[ptr] = a1 if (a0 + a1 != 1) { if (a0 == 0 && a1 == 0) print NR ": double free " ptr else if (a0 == 1 && a1 == 1) print NR ": double malloc " ptr else print NR ": oddity " $0 } next } /^s/ { checkleaks("suspended") next } { print NR ": unrecognized " $0 } END { checkleaks("leaked") } ' */ #endif // USE_MTRACE