< prev index next >

src/os/aix/vm/porting_aix.cpp

Print this page
rev 9211 : 8140645: Recent Developments for AIX
Summary: Port recent developments from SAP for AIX to the OpenJDK

*** 28,37 **** --- 28,40 ---- #include "runtime/os.hpp" #include "loadlib_aix.hpp" #include "porting_aix.hpp" #include "utilities/debug.hpp" + // For CritSect + #include "misc_aix.hpp" + #include <demangle.h> #include <sys/debug.h> ////////////////////////////////// // Provide implementation for dladdr based on LoadedLibraries pool and
*** 43,57 **** // Any PC below this value is considered toast. #define MINIMUM_VALUE_FOR_PC ((unsigned int*)0x1024) #define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2)) - // Align a pointer without having to cast. - inline char* align_ptr_up(char* ptr, intptr_t alignment) { - return (char*) align_size_up((intptr_t)ptr, alignment); - } - // Trace if verbose to tty. // I use these now instead of the Xtrace system because the latter is // not available at init time, hence worthless. Until we fix this, all // tracing here is done with -XX:+Verbose. #define trcVerbose(fmt, ...) { \ --- 46,55 ----
*** 137,158 **** // weed out obvious bogus states if (pc < MINIMUM_VALUE_FOR_PC) { ERRBYE("invalid program counter"); } codeptr_t pc2 = pc; // make sure the pointer is word aligned. pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4); // Find start of traceback table. // (starts after code, is marked by word-aligned (32bit) zeros) while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) { pc2++; } if (*pc2 != 0) { ! ERRBYE("could not find traceback table within 5000 bytes of program counter"); } // // Set up addressability to the traceback table // tb = (struct tbtable*) (pc2 + 1); --- 135,175 ---- // weed out obvious bogus states if (pc < MINIMUM_VALUE_FOR_PC) { ERRBYE("invalid program counter"); } + // We see random but frequent crashes in this function since some months mainly on shutdown + // (-XX:+DumpInfoAtExit). It appears the page we are reading is randomly disappearing while + // we read it (?). + // As the pc cannot be trusted to be anything sensible lets make all reads via SafeFetch. Also + // bail if this is not a text address right now. + if (!LoadedLibraries::find_for_text_address(pc, NULL)) { + ERRBYE("not a text address"); + } + + // .. (note that is_readable_pointer returns true if safefetch stubs are not there yet; + // in that case I try reading the traceback table unsafe - I rather risk secondary crashes in + // error files than not having a callstack) + #define CHECK_POINTER_READABLE(p) \ + if (!MiscUtils::is_readable_pointer(p)) { \ + ERRBYE("pc not readable"); \ + } + codeptr_t pc2 = pc; // make sure the pointer is word aligned. pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4); + CHECK_POINTER_READABLE(pc2) // Find start of traceback table. // (starts after code, is marked by word-aligned (32bit) zeros) while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) { + CHECK_POINTER_READABLE(pc2) pc2++; } if (*pc2 != 0) { ! ERRBYE("no traceback table found"); } // // Set up addressability to the traceback table // tb = (struct tbtable*) (pc2 + 1);
*** 160,190 **** // Is this really a traceback table? No way to be sure but // some indicators we can check. if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) { // Language specifiers, go from 0 (C) to 14 (Objective C). // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm. ! ERRBYE("not a traceback table"); } // Existence of fields in the tbtable extension are contingent upon // specific fields in the base table. Check for their existence so // that we can address the function name if it exists. pc2 = (codeptr_t) tb + sizeof(struct tbtable_short)/sizeof(int); if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0) pc2++; if (tb->tb.has_tboff == TRUE) { // I want to know the displacement const unsigned int tb_offset = *pc2; codeptr_t start_of_procedure = (codeptr_t)(((char*)tb) - 4 - tb_offset); // (-4 to omit leading 0000) // Weed out the cases where we did find the wrong traceback table. if (pc < start_of_procedure) { ! ERRBYE("could not find (the real) traceback table within 5000 bytes of program counter"); } // return the displacement if (p_displacement) { (*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure); --- 177,209 ---- // Is this really a traceback table? No way to be sure but // some indicators we can check. if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) { // Language specifiers, go from 0 (C) to 14 (Objective C). // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm. ! ERRBYE("no traceback table found"); } // Existence of fields in the tbtable extension are contingent upon // specific fields in the base table. Check for their existence so // that we can address the function name if it exists. pc2 = (codeptr_t) tb + sizeof(struct tbtable_short)/sizeof(int); if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0) pc2++; + CHECK_POINTER_READABLE(pc2) + if (tb->tb.has_tboff == TRUE) { // I want to know the displacement const unsigned int tb_offset = *pc2; codeptr_t start_of_procedure = (codeptr_t)(((char*)tb) - 4 - tb_offset); // (-4 to omit leading 0000) // Weed out the cases where we did find the wrong traceback table. if (pc < start_of_procedure) { ! ERRBYE("no traceback table found"); } // return the displacement if (p_displacement) { (*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure);
*** 202,220 **** pc2++; if (tb->tb.has_ctl == TRUE) pc2 += (*pc2) + 1; // don't care // // return function name if it exists. // if (p_name && namelen > 0) { if (tb->tb.name_present) { char buf[256]; const short l = MIN2<short>(*((short*)pc2), sizeof(buf) - 1); ! memcpy(buf, (char*)pc2 + sizeof(short), l); ! buf[l] = '\0'; p_name[0] = '\0'; // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h). if (demangle) { --- 221,248 ---- pc2++; if (tb->tb.has_ctl == TRUE) pc2 += (*pc2) + 1; // don't care + CHECK_POINTER_READABLE(pc2) + // // return function name if it exists. // if (p_name && namelen > 0) { if (tb->tb.name_present) { + // copy name from text because it may not be zero terminated. + // 256 is good enough for most cases; do not use large buffers here. char buf[256]; const short l = MIN2<short>(*((short*)pc2), sizeof(buf) - 1); ! // be very careful. ! int i = 0; char* const p = (char*)pc2 + sizeof(short); ! while (i < l && MiscUtils::is_readable_pointer(p + i)) { ! buf[i] = p[i]; ! i++; ! } ! buf[i] = '\0'; p_name[0] = '\0'; // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h). if (demangle) {
*** 273,336 **** info->dli_fname = ZEROSTRING; info->dli_sname = ZEROSTRING; info->dli_saddr = NULL; address p = (address) addr; ! const LoadedLibraryModule* lib = NULL; enum { noclue, code, data } type = noclue; trcVerbose("dladdr(%p)...", p); // Note: input address may be a function. I accept both a pointer to // the entry of a function and a pointer to the function decriptor. // (see ppc64 ABI) ! lib = LoadedLibraries::find_for_text_address(p); ! if (lib) { type = code; } ! if (!lib) { // Not a pointer into any text segment. Is it a function descriptor? const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p; p = pfd->entry(); if (p) { ! lib = LoadedLibraries::find_for_text_address(p); ! if (lib) { type = code; } } } ! if (!lib) { // Neither direct code pointer nor function descriptor. A data ptr? p = (address)addr; ! lib = LoadedLibraries::find_for_data_address(p); ! if (lib) { type = data; } } // If we did find the shared library this address belongs to (either // code or data segment) resolve library path and, if possible, the // symbol name. ! if (lib) { ! const char* const interned_libpath = ! dladdr_fixed_strings.intern(lib->get_fullpath()); ! if (interned_libpath) { ! info->dli_fname = interned_libpath; ! } if (type == code) { // For code symbols resolve function name and displacement. Use // displacement to calc start of function. char funcname[256] = ""; int displacement = 0; if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement, ! NULL, NULL, 0, true /* demangle */) == 0) { if (funcname[0] != '\0') { const char* const interned = dladdr_fixed_strings.intern(funcname); info->dli_sname = interned; trcVerbose("... function name: %s ...", interned); } --- 301,363 ---- info->dli_fname = ZEROSTRING; info->dli_sname = ZEROSTRING; info->dli_saddr = NULL; address p = (address) addr; ! loaded_module_t lm; ! bool found = false; enum { noclue, code, data } type = noclue; trcVerbose("dladdr(%p)...", p); // Note: input address may be a function. I accept both a pointer to // the entry of a function and a pointer to the function decriptor. // (see ppc64 ABI) ! found = LoadedLibraries::find_for_text_address(p, &lm); ! if (found) { type = code; } ! if (!found) { // Not a pointer into any text segment. Is it a function descriptor? const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p; p = pfd->entry(); if (p) { ! found = LoadedLibraries::find_for_text_address(p, &lm); ! if (found) { type = code; } } } ! if (!found) { // Neither direct code pointer nor function descriptor. A data ptr? p = (address)addr; ! found = LoadedLibraries::find_for_data_address(p, &lm); ! if (found) { type = data; } } // If we did find the shared library this address belongs to (either // code or data segment) resolve library path and, if possible, the // symbol name. ! if (found) { ! ! // No need to intern the libpath, that one is already interned one layer below. ! info->dli_fname = lm.path; if (type == code) { // For code symbols resolve function name and displacement. Use // displacement to calc start of function. char funcname[256] = ""; int displacement = 0; if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement, ! NULL, NULL, 0, false) == 0) { if (funcname[0] != '\0') { const char* const interned = dladdr_fixed_strings.intern(funcname); info->dli_sname = interned; trcVerbose("... function name: %s ...", interned); }
*** 369,373 **** --- 396,401 ---- } return rc; // error: return 0 [sic] } +
< prev index next >