hotspot/src/os/aix/vm/porting_aix.cpp
changeset 33743 e21d93a9e062
parent 31352 a6ab7217b5cc
child 35594 cc13089c6327
child 35515 179755aaa4e0
equal deleted inserted replaced
33742:cff2b8a9e2c5 33743:e21d93a9e062
    21  * questions.
    21  * questions.
    22  *
    22  *
    23  */
    23  */
    24 
    24 
    25 #include "asm/assembler.hpp"
    25 #include "asm/assembler.hpp"
       
    26 #include "loadlib_aix.hpp"
    26 #include "memory/allocation.hpp"
    27 #include "memory/allocation.hpp"
    27 #include "memory/allocation.inline.hpp"
    28 #include "memory/allocation.inline.hpp"
       
    29 // For CritSect
       
    30 #include "misc_aix.hpp"
       
    31 #include "porting_aix.hpp"
    28 #include "runtime/os.hpp"
    32 #include "runtime/os.hpp"
    29 #include "loadlib_aix.hpp"
       
    30 #include "porting_aix.hpp"
       
    31 #include "utilities/debug.hpp"
    33 #include "utilities/debug.hpp"
    32 
    34 
    33 #include <demangle.h>
    35 #include <demangle.h>
    34 #include <sys/debug.h>
    36 #include <sys/debug.h>
    35 
    37 
    42 #define MAX_FUNC_SEARCH_LEN 0x10000
    44 #define MAX_FUNC_SEARCH_LEN 0x10000
    43 // Any PC below this value is considered toast.
    45 // Any PC below this value is considered toast.
    44 #define MINIMUM_VALUE_FOR_PC ((unsigned int*)0x1024)
    46 #define MINIMUM_VALUE_FOR_PC ((unsigned int*)0x1024)
    45 
    47 
    46 #define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2))
    48 #define PTRDIFF_BYTES(p1,p2) (((ptrdiff_t)p1) - ((ptrdiff_t)p2))
    47 
       
    48 // Align a pointer without having to cast.
       
    49 inline char* align_ptr_up(char* ptr, intptr_t alignment) {
       
    50   return (char*) align_size_up((intptr_t)ptr, alignment);
       
    51 }
       
    52 
       
    53 // Trace if verbose to tty.
       
    54 // I use these now instead of the Xtrace system because the latter is
       
    55 // not available at init time, hence worthless. Until we fix this, all
       
    56 // tracing here is done with -XX:+Verbose.
       
    57 #define trcVerbose(fmt, ...) { \
       
    58   if (Verbose) { \
       
    59     fprintf(stderr, fmt, ##__VA_ARGS__); \
       
    60     fputc('\n', stderr); fflush(stderr); \
       
    61   } \
       
    62 }
       
    63 #define ERRBYE(s) { trcVerbose(s); return -1; }
       
    64 
    49 
    65 // Unfortunately, the interface of dladdr makes the implementator
    50 // Unfortunately, the interface of dladdr makes the implementator
    66 // responsible for maintaining memory for function name/library
    51 // responsible for maintaining memory for function name/library
    67 // name. I guess this is because most OS's keep those values as part
    52 // name. I guess this is because most OS's keep those values as part
    68 // of the mapped executable image ready to use. On AIX, this doesn't
    53 // of the mapped executable image ready to use. On AIX, this doesn't
   137   // weed out obvious bogus states
   122   // weed out obvious bogus states
   138   if (pc < MINIMUM_VALUE_FOR_PC) {
   123   if (pc < MINIMUM_VALUE_FOR_PC) {
   139     ERRBYE("invalid program counter");
   124     ERRBYE("invalid program counter");
   140   }
   125   }
   141 
   126 
       
   127   // We see random but frequent crashes in this function since some months mainly on shutdown
       
   128   // (-XX:+DumpInfoAtExit). It appears the page we are reading is randomly disappearing while
       
   129   // we read it (?).
       
   130   // As the pc cannot be trusted to be anything sensible lets make all reads via SafeFetch. Also
       
   131   // bail if this is not a text address right now.
       
   132   if (!LoadedLibraries::find_for_text_address(pc, NULL)) {
       
   133     ERRBYE("not a text address");
       
   134   }
       
   135 
       
   136   // .. (Note that is_readable_pointer returns true if safefetch stubs are not there yet;
       
   137   // in that case I try reading the traceback table unsafe - I rather risk secondary crashes in
       
   138   // error files than not having a callstack.)
       
   139 #define CHECK_POINTER_READABLE(p) \
       
   140   if (!MiscUtils::is_readable_pointer(p)) { \
       
   141     ERRBYE("pc not readable"); \
       
   142   }
       
   143 
   142   codeptr_t pc2 = pc;
   144   codeptr_t pc2 = pc;
   143 
   145 
   144   // make sure the pointer is word aligned.
   146   // Make sure the pointer is word aligned.
   145   pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4);
   147   pc2 = (codeptr_t) align_ptr_up((char*)pc2, 4);
       
   148   CHECK_POINTER_READABLE(pc2)
   146 
   149 
   147   // Find start of traceback table.
   150   // Find start of traceback table.
   148   // (starts after code, is marked by word-aligned (32bit) zeros)
   151   // (starts after code, is marked by word-aligned (32bit) zeros)
   149   while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) {
   152   while ((*pc2 != NULL) && (searchcount++ < MAX_FUNC_SEARCH_LEN)) {
       
   153     CHECK_POINTER_READABLE(pc2)
   150     pc2++;
   154     pc2++;
   151   }
   155   }
   152   if (*pc2 != 0) {
   156   if (*pc2 != 0) {
   153     ERRBYE("could not find traceback table within 5000 bytes of program counter");
   157     ERRBYE("no traceback table found");
   154   }
   158   }
   155   //
   159   //
   156   // Set up addressability to the traceback table
   160   // Set up addressability to the traceback table
   157   //
   161   //
   158   tb = (struct tbtable*) (pc2 + 1);
   162   tb = (struct tbtable*) (pc2 + 1);
   160   // Is this really a traceback table? No way to be sure but
   164   // Is this really a traceback table? No way to be sure but
   161   // some indicators we can check.
   165   // some indicators we can check.
   162   if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) {
   166   if (tb->tb.lang >= 0xf && tb->tb.lang <= 0xfb) {
   163     // Language specifiers, go from 0 (C) to 14 (Objective C).
   167     // Language specifiers, go from 0 (C) to 14 (Objective C).
   164     // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm.
   168     // According to spec, 0xf-0xfa reserved, 0xfb-0xff reserved for ibm.
   165     ERRBYE("not a traceback table");
   169     ERRBYE("no traceback table found");
   166   }
   170   }
   167 
   171 
   168   // Existence of fields in the tbtable extension are contingent upon
   172   // Existence of fields in the tbtable extension are contingent upon
   169   // specific fields in the base table.  Check for their existence so
   173   // specific fields in the base table.  Check for their existence so
   170   // that we can address the function name if it exists.
   174   // that we can address the function name if it exists.
   171   pc2 = (codeptr_t) tb +
   175   pc2 = (codeptr_t) tb +
   172     sizeof(struct tbtable_short)/sizeof(int);
   176     sizeof(struct tbtable_short)/sizeof(int);
   173   if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0)
   177   if (tb->tb.fixedparms != 0 || tb->tb.floatparms != 0)
   174     pc2++;
   178     pc2++;
   175 
   179 
       
   180   CHECK_POINTER_READABLE(pc2)
       
   181 
   176   if (tb->tb.has_tboff == TRUE) {
   182   if (tb->tb.has_tboff == TRUE) {
   177 
   183 
   178     // I want to know the displacement
   184     // I want to know the displacement
   179     const unsigned int tb_offset = *pc2;
   185     const unsigned int tb_offset = *pc2;
   180     codeptr_t start_of_procedure =
   186     codeptr_t start_of_procedure =
   181     (codeptr_t)(((char*)tb) - 4 - tb_offset);  // (-4 to omit leading 0000)
   187     (codeptr_t)(((char*)tb) - 4 - tb_offset);  // (-4 to omit leading 0000)
   182 
   188 
   183     // Weed out the cases where we did find the wrong traceback table.
   189     // Weed out the cases where we did find the wrong traceback table.
   184     if (pc < start_of_procedure) {
   190     if (pc < start_of_procedure) {
   185       ERRBYE("could not find (the real) traceback table within 5000 bytes of program counter");
   191       ERRBYE("no traceback table found");
   186     }
   192     }
   187 
   193 
   188     // return the displacement
   194     // return the displacement
   189     if (p_displacement) {
   195     if (p_displacement) {
   190       (*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure);
   196       (*p_displacement) = (int) PTRDIFF_BYTES(pc, start_of_procedure);
   202     pc2++;
   208     pc2++;
   203 
   209 
   204   if (tb->tb.has_ctl == TRUE)
   210   if (tb->tb.has_ctl == TRUE)
   205     pc2 += (*pc2) + 1; // don't care
   211     pc2 += (*pc2) + 1; // don't care
   206 
   212 
       
   213   CHECK_POINTER_READABLE(pc2)
       
   214 
   207   //
   215   //
   208   // return function name if it exists.
   216   // return function name if it exists.
   209   //
   217   //
   210   if (p_name && namelen > 0) {
   218   if (p_name && namelen > 0) {
   211     if (tb->tb.name_present) {
   219     if (tb->tb.name_present) {
       
   220       // Copy name from text because it may not be zero terminated.
       
   221       // 256 is good enough for most cases; do not use large buffers here.
   212       char buf[256];
   222       char buf[256];
   213       const short l = MIN2<short>(*((short*)pc2), sizeof(buf) - 1);
   223       const short l = MIN2<short>(*((short*)pc2), sizeof(buf) - 1);
   214       memcpy(buf, (char*)pc2 + sizeof(short), l);
   224       // Be very careful.
   215       buf[l] = '\0';
   225       int i = 0; char* const p = (char*)pc2 + sizeof(short);
       
   226       while (i < l && MiscUtils::is_readable_pointer(p + i)) {
       
   227         buf[i] = p[i];
       
   228         i++;
       
   229       }
       
   230       buf[i] = '\0';
   216 
   231 
   217       p_name[0] = '\0';
   232       p_name[0] = '\0';
   218 
   233 
   219       // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
   234       // If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
   220       if (demangle) {
   235       if (demangle) {
   273   info->dli_fname = ZEROSTRING;
   288   info->dli_fname = ZEROSTRING;
   274   info->dli_sname = ZEROSTRING;
   289   info->dli_sname = ZEROSTRING;
   275   info->dli_saddr = NULL;
   290   info->dli_saddr = NULL;
   276 
   291 
   277   address p = (address) addr;
   292   address p = (address) addr;
   278   const LoadedLibraryModule* lib = NULL;
   293   loaded_module_t lm;
       
   294   bool found = false;
   279 
   295 
   280   enum { noclue, code, data } type = noclue;
   296   enum { noclue, code, data } type = noclue;
   281 
   297 
   282   trcVerbose("dladdr(%p)...", p);
   298   trcVerbose("dladdr(%p)...", p);
   283 
   299 
   284   // Note: input address may be a function. I accept both a pointer to
   300   // Note: input address may be a function. I accept both a pointer to
   285   // the entry of a function and a pointer to the function decriptor.
   301   // the entry of a function and a pointer to the function decriptor.
   286   // (see ppc64 ABI)
   302   // (see ppc64 ABI)
   287   lib = LoadedLibraries::find_for_text_address(p);
   303   found = LoadedLibraries::find_for_text_address(p, &lm);
   288   if (lib) {
   304   if (found) {
   289     type = code;
   305     type = code;
   290   }
   306   }
   291 
   307 
   292   if (!lib) {
   308   if (!found) {
   293     // Not a pointer into any text segment. Is it a function descriptor?
   309     // Not a pointer into any text segment. Is it a function descriptor?
   294     const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p;
   310     const FunctionDescriptor* const pfd = (const FunctionDescriptor*) p;
   295     p = pfd->entry();
   311     p = pfd->entry();
   296     if (p) {
   312     if (p) {
   297       lib = LoadedLibraries::find_for_text_address(p);
   313       found = LoadedLibraries::find_for_text_address(p, &lm);
   298       if (lib) {
   314       if (found) {
   299         type = code;
   315         type = code;
   300       }
   316       }
   301     }
   317     }
   302   }
   318   }
   303 
   319 
   304   if (!lib) {
   320   if (!found) {
   305     // Neither direct code pointer nor function descriptor. A data ptr?
   321     // Neither direct code pointer nor function descriptor. A data ptr?
   306     p = (address)addr;
   322     p = (address)addr;
   307     lib = LoadedLibraries::find_for_data_address(p);
   323     found = LoadedLibraries::find_for_data_address(p, &lm);
   308     if (lib) {
   324     if (found) {
   309       type = data;
   325       type = data;
   310     }
   326     }
   311   }
   327   }
   312 
   328 
   313   // If we did find the shared library this address belongs to (either
   329   // If we did find the shared library this address belongs to (either
   314   // code or data segment) resolve library path and, if possible, the
   330   // code or data segment) resolve library path and, if possible, the
   315   // symbol name.
   331   // symbol name.
   316   if (lib) {
   332   if (found) {
   317     const char* const interned_libpath =
   333 
   318       dladdr_fixed_strings.intern(lib->get_fullpath());
   334     // No need to intern the libpath, that one is already interned one layer below.
   319     if (interned_libpath) {
   335     info->dli_fname = lm.path;
   320       info->dli_fname = interned_libpath;
       
   321     }
       
   322 
   336 
   323     if (type == code) {
   337     if (type == code) {
   324 
   338 
   325       // For code symbols resolve function name and displacement. Use
   339       // For code symbols resolve function name and displacement. Use
   326       // displacement to calc start of function.
   340       // displacement to calc start of function.
   327       char funcname[256] = "";
   341       char funcname[256] = "";
   328       int displacement = 0;
   342       int displacement = 0;
   329 
   343 
   330       if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
   344       if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
   331                       NULL, NULL, 0, true /* demangle */) == 0) {
   345                       NULL, NULL, 0, false) == 0) {
   332         if (funcname[0] != '\0') {
   346         if (funcname[0] != '\0') {
   333           const char* const interned = dladdr_fixed_strings.intern(funcname);
   347           const char* const interned = dladdr_fixed_strings.intern(funcname);
   334           info->dli_sname = interned;
   348           info->dli_sname = interned;
   335           trcVerbose("... function name: %s ...", interned);
   349           trcVerbose("... function name: %s ...", interned);
   336         }
   350         }