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 } |