Patch ieee128-lib-patch005b
[official-gcc.git] / libbacktrace / xcoff.c
blob507edded709d9d250a319182afe449c41af09875
1 /* xcoff.c -- Get debug data from an XCOFF file for backtraces.
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
3 Adapted from elf.c.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 (2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
17 (3) The name of the author may not be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE. */
33 #include "config.h"
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
40 #ifdef HAVE_LOADQUERY
41 #include <sys/ldr.h>
42 #endif
44 #include "backtrace.h"
45 #include "internal.h"
47 /* The configure script must tell us whether we are 32-bit or 64-bit
48 XCOFF. We could make this code test and support either possibility,
49 but there is no point. This code only works for the currently
50 running executable, which means that we know the XCOFF mode at
51 configure time. */
53 #if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64
54 #error "Unknown BACKTRACE_XCOFF_SIZE"
55 #endif
57 /* XCOFF file header. */
59 #if BACKTRACE_XCOFF_SIZE == 32
61 typedef struct {
62 uint16_t f_magic;
63 uint16_t f_nscns;
64 uint32_t f_timdat;
65 uint32_t f_symptr;
66 uint32_t f_nsyms;
67 uint16_t f_opthdr;
68 uint16_t f_flags;
69 } b_xcoff_filhdr;
71 #define XCOFF_MAGIC 0737
73 #else /* BACKTRACE_XCOFF_SIZE != 32 */
75 typedef struct {
76 uint16_t f_magic;
77 uint16_t f_nscns;
78 uint32_t f_timdat;
79 uint64_t f_symptr;
80 uint16_t f_opthdr;
81 uint16_t f_flags;
82 uint32_t f_nsyms;
83 } b_xcoff_filhdr;
85 #define XCOFF_MAGIC 0767
87 #endif /* BACKTRACE_XCOFF_SIZE != 32 */
89 #define F_SHROBJ 0x2000 /* File is a shared object. */
91 /* XCOFF section header. */
93 #if BACKTRACE_XCOFF_SIZE == 32
95 typedef struct {
96 char s_name[8];
97 uint32_t s_paddr;
98 uint32_t s_vaddr;
99 uint32_t s_size;
100 uint32_t s_scnptr;
101 uint32_t s_relptr;
102 uint32_t s_lnnoptr;
103 uint16_t s_nreloc;
104 uint16_t s_nlnno;
105 uint32_t s_flags;
106 } b_xcoff_scnhdr;
108 #define _OVERFLOW_MARKER 65535
110 #else /* BACKTRACE_XCOFF_SIZE != 32 */
112 typedef struct {
113 char name[8];
114 uint64_t s_paddr;
115 uint64_t s_vaddr;
116 uint64_t s_size;
117 uint64_t s_scnptr;
118 uint64_t s_relptr;
119 uint64_t s_lnnoptr;
120 uint32_t s_nreloc;
121 uint32_t s_nlnno;
122 uint32_t s_flags;
123 } b_xcoff_scnhdr;
125 #endif /* BACKTRACE_XCOFF_SIZE != 32 */
127 #define STYP_DWARF 0x10 /* DWARF debugging section. */
128 #define STYP_TEXT 0x20 /* Executable text (code) section. */
129 #define STYP_OVRFLO 0x8000 /* Line-number field overflow section. */
131 #define SSUBTYP_DWINFO 0x10000 /* DWARF info section. */
132 #define SSUBTYP_DWLINE 0x20000 /* DWARF line-number section. */
133 #define SSUBTYP_DWARNGE 0x50000 /* DWARF aranges section. */
134 #define SSUBTYP_DWABREV 0x60000 /* DWARF abbreviation section. */
135 #define SSUBTYP_DWSTR 0x70000 /* DWARF strings section. */
137 /* XCOFF symbol. */
139 #define SYMNMLEN 8
141 #if BACKTRACE_XCOFF_SIZE == 32
143 typedef struct {
144 union {
145 char _name[SYMNMLEN];
146 struct {
147 uint32_t _zeroes;
148 uint32_t _offset;
149 } _s;
150 } _u;
151 #define n_name _u._name
152 #define n_zeroes _u._s._zeroes
153 #define n_offset_ _u._s._offset
155 uint32_t n_value;
156 int16_t n_scnum;
157 uint16_t n_type;
158 uint8_t n_sclass;
159 uint8_t n_numaux;
160 } __attribute__ ((packed)) b_xcoff_syment;
162 #else /* BACKTRACE_XCOFF_SIZE != 32 */
164 typedef struct {
165 uint64_t n_value;
166 uint32_t n_offset_;
167 int16_t n_scnum;
168 uint16_t n_type;
169 uint8_t n_sclass;
170 uint8_t n_numaux;
171 } __attribute__ ((packed)) b_xcoff_syment;
173 #endif /* BACKTRACE_XCOFF_SIZE != 32 */
175 #define SYMESZ 18
177 #define C_EXT 2 /* External symbol. */
178 #define C_FCN 101 /* Beginning or end of function. */
179 #define C_FILE 103 /* Source file name. */
180 #define C_HIDEXT 107 /* Unnamed external symbol. */
181 #define C_BINCL 108 /* Beginning of include file. */
182 #define C_EINCL 109 /* End of include file. */
183 #define C_WEAKEXT 111 /* Weak external symbol. */
185 #define ISFCN(x) ((x) & 0x0020)
187 /* XCOFF AUX entry. */
189 #define AUXESZ 18
190 #define FILNMLEN 14
192 typedef union {
193 #if BACKTRACE_XCOFF_SIZE == 32
194 struct {
195 uint16_t pad;
196 uint16_t x_lnnohi;
197 uint16_t x_lnno;
198 } x_block;
199 #else
200 struct {
201 uint32_t x_lnno;
202 } x_block;
203 #endif
204 union {
205 char x_fname[FILNMLEN];
206 struct {
207 uint32_t x_zeroes;
208 uint32_t x_offset;
209 char pad[FILNMLEN-8];
210 uint8_t x_ftype;
211 } _x;
212 } x_file;
213 #if BACKTRACE_XCOFF_SIZE == 32
214 struct {
215 uint32_t x_exptr;
216 uint32_t x_fsize;
217 uint32_t x_lnnoptr;
218 uint32_t x_endndx;
219 } x_fcn;
220 #else
221 struct {
222 uint64_t x_lnnoptr;
223 uint32_t x_fsize;
224 uint32_t x_endndx;
225 } x_fcn;
226 #endif
227 struct {
228 uint8_t pad[AUXESZ-1];
229 uint8_t x_auxtype;
230 } x_auxtype;
231 } __attribute__ ((packed)) b_xcoff_auxent;
233 /* XCOFF line number entry. */
235 #if BACKTRACE_XCOFF_SIZE == 32
237 typedef struct {
238 union {
239 uint32_t l_symndx;
240 uint32_t l_paddr;
241 } l_addr;
242 uint16_t l_lnno;
243 } b_xcoff_lineno;
245 #define LINESZ 6
247 #else /* BACKTRACE_XCOFF_SIZE != 32 */
249 typedef struct {
250 union {
251 uint32_t l_symndx;
252 uint64_t l_paddr;
253 } l_addr;
254 uint32_t l_lnno;
255 } b_xcoff_lineno;
257 #define LINESZ 12
259 #endif /* BACKTRACE_XCOFF_SIZE != 32 */
261 #if BACKTRACE_XCOFF_SIZE == 32
262 #define XCOFF_AIX_TEXTBASE 0x10000000u
263 #else
264 #define XCOFF_AIX_TEXTBASE 0x100000000ul
265 #endif
267 /* AIX big archive fixed-length header. */
269 #define AIAMAGBIG "<bigaf>\n"
271 typedef struct {
272 char fl_magic[8]; /* Archive magic string. */
273 char fl_memoff[20]; /* Offset to member table. */
274 char fl_gstoff[20]; /* Offset to global symbol table. */
275 char fl_gst64off[20]; /* Offset to global symbol table for 64-bit objects. */
276 char fl_fstmoff[20]; /* Offset to first archive member. */
277 char fl_freeoff[20]; /* Offset to first member on free list. */
278 } b_ar_fl_hdr;
280 /* AIX big archive file member header. */
282 typedef struct {
283 char ar_size[20]; /* File member size - decimal. */
284 char ar_nxtmem[20]; /* Next member offset - decimal. */
285 char ar_prvmem[20]; /* Previous member offset - decimal. */
286 char ar_date[12]; /* File member date - decimal. */
287 char ar_uid[12]; /* File member userid - decimal. */
288 char ar_gid[12]; /* File member group id - decimal. */
289 char ar_mode[12]; /* File member mode - octal. */
290 char ar_namlen[4]; /* File member name length - decimal. */
291 char ar_name[2]; /* Start of member name. */
292 } b_ar_hdr;
295 /* Information we keep for an XCOFF symbol. */
297 struct xcoff_symbol
299 /* The name of the symbol. */
300 const char *name;
301 /* The address of the symbol. */
302 uintptr_t address;
303 /* The size of the symbol. */
304 size_t size;
307 /* Information to pass to xcoff_syminfo. */
309 struct xcoff_syminfo_data
311 /* Symbols for the next module. */
312 struct xcoff_syminfo_data *next;
313 /* The XCOFF symbols, sorted by address. */
314 struct xcoff_symbol *symbols;
315 /* The number of symbols. */
316 size_t count;
319 /* Information about an include file. */
321 struct xcoff_incl
323 /* File name. */
324 const char *filename;
325 /* Offset to first line number from the include file. */
326 uintptr_t begin;
327 /* Offset to last line number from the include file. */
328 uintptr_t end;
331 /* A growable vector of include files information. */
333 struct xcoff_incl_vector
335 /* Memory. This is an array of struct xcoff_incl. */
336 struct backtrace_vector vec;
337 /* Number of include files. */
338 size_t count;
341 /* A growable vector of functions information. */
343 struct xcoff_func
345 /* PC. */
346 uintptr_t pc;
347 /* The size of the function. */
348 size_t size;
349 /* Function name. */
350 const char *name;
351 /* File name. */
352 const char *filename;
353 /* Pointer to first lnno entry. */
354 uintptr_t lnnoptr;
355 /* Base address of containing section. */
356 uintptr_t sect_base;
357 /* Starting source line number. */
358 int lnno;
361 /* A growable vector of function information. This is used while
362 reading the function symbols. */
364 struct xcoff_func_vector
366 /* Memory. This is an array of struct xcoff_func. */
367 struct backtrace_vector vec;
368 /* Number of valid mappings. */
369 size_t count;
372 /* The information we need to map a PC to a file and line. */
374 struct xcoff_fileline_data
376 /* The data for the next file we know about. */
377 struct xcoff_fileline_data *next;
378 /* Functions information. */
379 struct xcoff_func_vector func_vec;
380 /* Include files information. */
381 struct xcoff_incl_vector incl_vec;
382 /* Line numbers information. */
383 const unsigned char *linenos;
384 size_t linenos_size;
385 uint64_t lnnoptr0;
386 /* Loader address. */
387 uintptr_t base_address;
390 /* Information we gather for the DWARF sections we care about. */
392 struct dwsect_info
394 /* Section file offset. */
395 off_t offset;
396 /* Section size. */
397 size_t size;
398 /* Section contents, after read from file. */
399 const unsigned char *data;
402 /* A dummy callback function used when we can't find any debug info. */
404 static int
405 xcoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
406 uintptr_t pc ATTRIBUTE_UNUSED,
407 backtrace_full_callback callback ATTRIBUTE_UNUSED,
408 backtrace_error_callback error_callback, void *data)
410 error_callback (data, "no debug info in XCOFF executable", -1);
411 return 0;
414 /* A dummy callback function used when we can't find a symbol
415 table. */
417 static void
418 xcoff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
419 uintptr_t addr ATTRIBUTE_UNUSED,
420 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
421 backtrace_error_callback error_callback, void *data)
423 error_callback (data, "no symbol table in XCOFF executable", -1);
426 /* Compare struct xcoff_symbol for qsort. */
428 static int
429 xcoff_symbol_compare (const void *v1, const void *v2)
431 const struct xcoff_symbol *e1 = (const struct xcoff_symbol *) v1;
432 const struct xcoff_symbol *e2 = (const struct xcoff_symbol *) v2;
434 if (e1->address < e2->address)
435 return -1;
436 else if (e1->address > e2->address)
437 return 1;
438 else
439 return 0;
442 /* Compare an ADDR against an xcoff_symbol for bsearch. */
444 static int
445 xcoff_symbol_search (const void *vkey, const void *ventry)
447 const uintptr_t *key = (const uintptr_t *) vkey;
448 const struct xcoff_symbol *entry = (const struct xcoff_symbol *) ventry;
449 uintptr_t addr;
451 addr = *key;
452 if (addr < entry->address)
453 return -1;
454 else if ((entry->size == 0 && addr > entry->address)
455 || (entry->size > 0 && addr >= entry->address + entry->size))
456 return 1;
457 else
458 return 0;
461 /* Add XDATA to the list in STATE. */
463 static void
464 xcoff_add_syminfo_data (struct backtrace_state *state,
465 struct xcoff_syminfo_data *xdata)
467 if (!state->threaded)
469 struct xcoff_syminfo_data **pp;
471 for (pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
472 *pp != NULL;
473 pp = &(*pp)->next)
475 *pp = xdata;
477 else
479 while (1)
481 struct xcoff_syminfo_data **pp;
483 pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
485 while (1)
487 struct xcoff_syminfo_data *p;
489 p = backtrace_atomic_load_pointer (pp);
491 if (p == NULL)
492 break;
494 pp = &p->next;
497 if (__sync_bool_compare_and_swap (pp, NULL, xdata))
498 break;
503 /* Return the symbol name and value for an ADDR. */
505 static void
506 xcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr,
507 backtrace_syminfo_callback callback,
508 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
509 void *data)
511 struct xcoff_syminfo_data *edata;
512 struct xcoff_symbol *sym = NULL;
513 const char *name;
515 if (!state->threaded)
517 for (edata = (struct xcoff_syminfo_data *) state->syminfo_data;
518 edata != NULL;
519 edata = edata->next)
521 sym = ((struct xcoff_symbol *)
522 bsearch (&addr, edata->symbols, edata->count,
523 sizeof (struct xcoff_symbol), xcoff_symbol_search));
524 if (sym != NULL)
525 break;
528 else
530 struct xcoff_syminfo_data **pp;
532 pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
533 while (1)
535 edata = backtrace_atomic_load_pointer (pp);
536 if (edata == NULL)
537 break;
539 sym = ((struct xcoff_symbol *)
540 bsearch (&addr, edata->symbols, edata->count,
541 sizeof (struct xcoff_symbol), xcoff_symbol_search));
542 if (sym != NULL)
543 break;
545 pp = &edata->next;
549 if (sym == NULL)
550 callback (data, addr, NULL, 0, 0);
551 else
553 name = sym->name;
554 /* AIX prepends a '.' to function entry points, remove it. */
555 if (name && *name == '.')
556 ++name;
557 callback (data, addr, name, sym->address, sym->size);
561 /* Return the name of an XCOFF symbol. */
563 static const char *
564 xcoff_symname (const b_xcoff_syment *asym,
565 const unsigned char *strtab, size_t strtab_size)
567 #if BACKTRACE_XCOFF_SIZE == 32
568 if (asym->n_zeroes != 0)
570 /* Make a copy as we will release the symtab view. */
571 char name[SYMNMLEN+1];
572 strncpy (name, asym->n_name, SYMNMLEN);
573 name[SYMNMLEN] = '\0';
574 return strdup (name);
576 #endif
577 if (asym->n_sclass & 0x80)
578 return NULL; /* .debug */
579 if (asym->n_offset_ >= strtab_size)
580 return NULL;
581 return (const char *) strtab + asym->n_offset_;
584 /* Initialize the symbol table info for xcoff_syminfo. */
586 static int
587 xcoff_initialize_syminfo (struct backtrace_state *state,
588 uintptr_t base_address,
589 const b_xcoff_scnhdr *sects,
590 const b_xcoff_syment *syms, size_t nsyms,
591 const unsigned char *strtab, size_t strtab_size,
592 backtrace_error_callback error_callback, void *data,
593 struct xcoff_syminfo_data *sdata)
595 size_t xcoff_symbol_count;
596 size_t xcoff_symbol_size;
597 struct xcoff_symbol *xcoff_symbols;
598 size_t i;
599 unsigned int j;
601 /* We only care about function symbols. Count them. */
602 xcoff_symbol_count = 0;
603 for (i = 0; i < nsyms; ++i)
605 const b_xcoff_syment *asym = &syms[i];
606 if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
607 || asym->n_sclass == C_WEAKEXT)
608 && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
609 ++xcoff_symbol_count;
611 i += asym->n_numaux;
614 xcoff_symbol_size = xcoff_symbol_count * sizeof (struct xcoff_symbol);
615 xcoff_symbols = ((struct xcoff_symbol *)
616 backtrace_alloc (state, xcoff_symbol_size, error_callback,
617 data));
618 if (xcoff_symbols == NULL)
619 return 0;
621 j = 0;
622 for (i = 0; i < nsyms; ++i)
624 const b_xcoff_syment *asym = &syms[i];
625 if ((asym->n_sclass == C_EXT || asym->n_sclass == C_HIDEXT
626 || asym->n_sclass == C_WEAKEXT)
627 && ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
629 const b_xcoff_auxent *aux = (const b_xcoff_auxent *) (asym + 1);
630 xcoff_symbols[j].name = xcoff_symname (asym, strtab, strtab_size);
631 xcoff_symbols[j].address = base_address + asym->n_value
632 - sects[asym->n_scnum - 1].s_paddr;
633 /* x_fsize will be 0 if there is no debug information. */
634 xcoff_symbols[j].size = aux->x_fcn.x_fsize;
635 ++j;
638 i += asym->n_numaux;
641 backtrace_qsort (xcoff_symbols, xcoff_symbol_count,
642 sizeof (struct xcoff_symbol), xcoff_symbol_compare);
644 sdata->next = NULL;
645 sdata->symbols = xcoff_symbols;
646 sdata->count = xcoff_symbol_count;
648 return 1;
651 /* Compare struct xcoff_func for qsort. */
653 static int
654 xcoff_func_compare (const void *v1, const void *v2)
656 const struct xcoff_func *fn1 = (const struct xcoff_func *) v1;
657 const struct xcoff_func *fn2 = (const struct xcoff_func *) v2;
659 if (fn1->pc < fn2->pc)
660 return -1;
661 else if (fn1->pc > fn2->pc)
662 return 1;
663 else
664 return 0;
667 /* Compare a PC against an xcoff_func for bsearch. */
669 static int
670 xcoff_func_search (const void *vkey, const void *ventry)
672 const uintptr_t *key = (const uintptr_t *) vkey;
673 const struct xcoff_func *entry = (const struct xcoff_func *) ventry;
674 uintptr_t pc;
676 pc = *key;
677 if (pc < entry->pc)
678 return -1;
679 else if ((entry->size == 0 && pc > entry->pc)
680 || (entry->size > 0 && pc >= entry->pc + entry->size))
681 return 1;
682 else
683 return 0;
686 /* Compare struct xcoff_incl for qsort. */
688 static int
689 xcoff_incl_compare (const void *v1, const void *v2)
691 const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1;
692 const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2;
694 if (in1->begin < in2->begin)
695 return -1;
696 else if (in1->begin > in2->begin)
697 return 1;
698 else
699 return 0;
702 /* Find a lnnoptr in an include file. */
704 static int
705 xcoff_incl_search (const void *vkey, const void *ventry)
707 const uintptr_t *key = (const uintptr_t *) vkey;
708 const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry;
709 uintptr_t lnno;
711 lnno = *key;
712 if (lnno < entry->begin)
713 return -1;
714 else if (lnno > entry->end)
715 return 1;
716 else
717 return 0;
720 /* Look for a PC in the function vector for one module. On success,
721 call CALLBACK and return whatever it returns. On error, call
722 ERROR_CALLBACK and return 0. Sets *FOUND to 1 if the PC is found,
723 0 if not. */
725 static int
726 xcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED,
727 struct xcoff_fileline_data *fdata, uintptr_t pc,
728 backtrace_full_callback callback,
729 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
730 void *data, int *found)
732 const struct xcoff_incl *incl, *bincl;
733 const struct xcoff_func *fn;
734 const b_xcoff_lineno *lineno;
735 const unsigned char *lineptr;
736 const char *function;
737 const char *filename;
738 uintptr_t lnnoptr, match;
739 uint32_t lnno = 0;
741 *found = 1;
743 if ((pc & 3) != 0)
744 ++pc;
746 /* Find the function first. */
747 fn = ((struct xcoff_func *)
748 bsearch (&pc, fdata->func_vec.vec.base, fdata->func_vec.count,
749 sizeof (struct xcoff_func), xcoff_func_search));
750 if (fn == NULL)
752 *found = 0;
753 return 0;
756 filename = fn->filename;
758 /* Find the line number next. */
760 /* Skip first entry that points to symtab. */
761 lnnoptr = fn->lnnoptr + LINESZ;
762 match = lnnoptr;
764 lineptr = fdata->linenos + (lnnoptr - fdata->lnnoptr0);
765 while (lineptr + LINESZ <= fdata->linenos + fdata->linenos_size)
767 lineno = (const b_xcoff_lineno *) lineptr;
768 if (lineno->l_lnno == 0)
769 break;
770 if (pc <= fdata->base_address + lineno->l_addr.l_paddr - fn->sect_base)
771 break;
772 match = lnnoptr;
773 lnno = lineno->l_lnno;
775 lnnoptr += LINESZ;
776 lineptr += LINESZ;
779 /* If part of a function other than the beginning comes from an
780 include file, the line numbers are absolute, rather than
781 relative to the beginning of the function. */
782 incl = ((struct xcoff_incl *)
783 bsearch (&match, fdata->incl_vec.vec.base,
784 fdata->incl_vec.count, sizeof (struct xcoff_incl),
785 xcoff_incl_search));
786 if (incl != NULL)
788 bincl = ((struct xcoff_incl *)
789 bsearch (&fn->lnnoptr, fdata->incl_vec.vec.base,
790 fdata->incl_vec.count, sizeof (struct xcoff_incl),
791 xcoff_incl_search));
792 if (bincl != NULL && strcmp (incl->filename, bincl->filename) == 0)
794 lnno += fn->lnno - 1;
796 filename = incl->filename;
798 else
800 lnno += fn->lnno - 1;
803 function = fn->name;
804 /* AIX prepends a '.' to function entry points, remove it. */
805 if (function != NULL && *function == '.')
806 ++function;
807 return callback (data, pc, filename, lnno, function);
810 /* Return the file/line information for a PC using the XCOFF lineno
811 mapping we built earlier. */
813 static int
814 xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
815 backtrace_full_callback callback,
816 backtrace_error_callback error_callback, void *data)
819 struct xcoff_fileline_data *fdata;
820 int found;
821 int ret;
823 if (!state->threaded)
825 for (fdata = (struct xcoff_fileline_data *) state->fileline_data;
826 fdata != NULL;
827 fdata = fdata->next)
829 ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
830 data, &found);
831 if (ret != 0 || found)
832 return ret;
835 else
837 struct xcoff_fileline_data **pp;
839 pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
840 while (1)
842 fdata = backtrace_atomic_load_pointer (pp);
843 if (fdata == NULL)
844 break;
846 ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
847 data, &found);
848 if (ret != 0 || found)
849 return ret;
851 pp = &fdata->next;
855 /* FIXME: See if any libraries have been dlopen'ed. */
857 return callback (data, pc, NULL, 0, NULL);
860 /* Initialize the function vector info for xcoff_fileline. */
862 static int
863 xcoff_initialize_fileline (struct backtrace_state *state,
864 uintptr_t base_address,
865 const b_xcoff_scnhdr *sects,
866 const b_xcoff_syment *syms, size_t nsyms,
867 const unsigned char *strtab, size_t strtab_size,
868 const unsigned char *linenos, size_t linenos_size,
869 uint64_t lnnoptr0,
870 backtrace_error_callback error_callback, void *data)
872 struct xcoff_fileline_data *fdata;
873 struct xcoff_func *fn;
874 const b_xcoff_syment *fsym;
875 const b_xcoff_auxent *aux;
876 const char *filename;
877 const char *name;
878 struct xcoff_incl *incl;
879 uintptr_t begin, end;
880 uintptr_t lnno, lnnoptr;
881 uint32_t fsize;
882 size_t i;
884 fdata = ((struct xcoff_fileline_data *)
885 backtrace_alloc (state, sizeof (struct xcoff_fileline_data),
886 error_callback, data));
887 if (fdata == NULL)
888 return 0;
889 memset (fdata, 0, sizeof *fdata);
890 fdata->base_address = base_address;
891 fdata->linenos = linenos;
892 fdata->linenos_size = linenos_size;
893 fdata->lnnoptr0 = lnnoptr0;
895 begin = 0;
896 filename = NULL;
897 fsym = NULL;
898 lnnoptr = 0;
899 fsize = 0;
900 for (i = 0; i < nsyms; ++i)
902 const b_xcoff_syment *asym = &syms[i];
904 switch (asym->n_sclass)
906 case C_BINCL:
907 begin = asym->n_value;
908 break;
910 case C_EINCL:
911 if (begin == 0)
912 break;
913 end = asym->n_value;
914 incl = ((struct xcoff_incl *)
915 backtrace_vector_grow (state, sizeof (struct xcoff_incl),
916 error_callback, data,
917 &fdata->incl_vec.vec));
918 if (incl != NULL)
920 incl->filename = xcoff_symname (asym, strtab, strtab_size);
921 incl->begin = begin;
922 incl->end = end;
923 ++fdata->incl_vec.count;
925 begin = 0;
926 break;
928 case C_FILE:
929 filename = xcoff_symname (asym, strtab, strtab_size);
930 if (filename == NULL)
931 break;
933 /* If the file auxiliary entry is not used, the symbol name is
934 the name of the source file. If the file auxiliary entry is
935 used, then the symbol name should be .file, and the first
936 file auxiliary entry (by convention) contains the source
937 file name. */
939 if (asym->n_numaux > 0 && strcmp (filename, ".file") == 0)
941 aux = (const b_xcoff_auxent *) (asym + 1);
942 if (aux->x_file._x.x_zeroes != 0)
944 /* Make a copy as we will release the symtab view. */
945 char name[FILNMLEN+1];
946 strncpy (name, aux->x_file.x_fname, FILNMLEN);
947 name[FILNMLEN] = '\0';
948 filename = strdup (name);
950 else if (aux->x_file._x.x_offset < strtab_size)
951 filename = (const char *) strtab + aux->x_file._x.x_offset;
952 else
953 filename = NULL;
955 break;
957 case C_EXT:
958 case C_HIDEXT:
959 case C_WEAKEXT:
960 fsym = NULL;
961 lnnoptr = 0;
962 fsize = 0;
963 if (!ISFCN (asym->n_type) || asym->n_numaux == 0
964 || asym->n_scnum <= 0)
965 break;
966 if (filename == NULL)
967 break;
968 aux = (const b_xcoff_auxent *) (asym + 1);
969 lnnoptr = aux->x_fcn.x_lnnoptr;
970 if (lnnoptr < lnnoptr0
971 || lnnoptr + LINESZ > lnnoptr0 + linenos_size)
972 break;
973 /* x_fsize will be 0 if there is no debug information. */
974 fsize = aux->x_fcn.x_fsize;
975 fsym = asym;
976 break;
978 case C_FCN:
979 if (asym->n_numaux == 0)
980 break;
981 if (fsym == NULL)
982 break;
983 name = xcoff_symname (asym, strtab, strtab_size);
984 if (name == NULL || strcmp (name, ".bf") != 0)
986 fsym = NULL;
987 break;
989 aux = (const b_xcoff_auxent *) (asym + 1);
990 #if BACKTRACE_XCOFF_SIZE == 32
991 lnno = (uint32_t) aux->x_block.x_lnnohi << 16
992 | aux->x_block.x_lnno;
993 #else
994 lnno = aux->x_block.x_lnno;
995 #endif
996 fn = ((struct xcoff_func *)
997 backtrace_vector_grow (state, sizeof (struct xcoff_func),
998 error_callback, data,
999 &fdata->func_vec.vec));
1000 if (fn == NULL)
1001 break;
1002 fn->name = xcoff_symname (fsym, strtab, strtab_size);
1003 fn->filename = filename;
1004 fn->sect_base = sects[fsym->n_scnum - 1].s_paddr;
1005 fn->pc = base_address + fsym->n_value - fn->sect_base;
1006 fn->size = fsize;
1007 fn->lnno = lnno;
1008 fn->lnnoptr = lnnoptr;
1009 ++fdata->func_vec.count;
1010 break;
1013 i += asym->n_numaux;
1016 if (!backtrace_vector_release (state, &fdata->func_vec.vec, error_callback,
1017 data))
1018 goto fail;
1019 backtrace_qsort (fdata->func_vec.vec.base, fdata->func_vec.count,
1020 sizeof (struct xcoff_func), xcoff_func_compare);
1022 if (!backtrace_vector_release (state, &fdata->incl_vec.vec, error_callback,
1023 data))
1024 goto fail;
1025 backtrace_qsort (fdata->incl_vec.vec.base, fdata->incl_vec.count,
1026 sizeof (struct xcoff_incl), xcoff_incl_compare);
1028 if (!state->threaded)
1030 struct xcoff_fileline_data **pp;
1032 for (pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
1033 *pp != NULL;
1034 pp = &(*pp)->next)
1036 *pp = fdata;
1038 else
1040 while (1)
1042 struct xcoff_fileline_data **pp;
1044 pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
1046 while (1)
1048 struct xcoff_fileline_data *p;
1050 p = backtrace_atomic_load_pointer (pp);
1052 if (p == NULL)
1053 break;
1055 pp = &p->next;
1058 if (__sync_bool_compare_and_swap (pp, NULL, fdata))
1059 break;
1063 return 1;
1065 fail:
1066 return 0;
1069 /* Add the backtrace data for one XCOFF file. Returns 1 on success,
1070 0 on failure (in both cases descriptor is closed). */
1072 static int
1073 xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
1074 uintptr_t base_address, backtrace_error_callback error_callback,
1075 void *data, fileline *fileline_fn, int *found_sym, int exe)
1077 struct backtrace_view fhdr_view;
1078 struct backtrace_view sects_view;
1079 struct backtrace_view linenos_view;
1080 struct backtrace_view syms_view;
1081 struct backtrace_view str_view;
1082 struct backtrace_view dwarf_view;
1083 b_xcoff_filhdr fhdr;
1084 const b_xcoff_scnhdr *sects;
1085 const b_xcoff_scnhdr *stext;
1086 uint64_t lnnoptr;
1087 uint32_t nlnno;
1088 off_t str_off;
1089 off_t min_offset;
1090 off_t max_offset;
1091 struct dwsect_info dwsect[DEBUG_MAX];
1092 size_t sects_size;
1093 size_t syms_size;
1094 int32_t str_size;
1095 int sects_view_valid;
1096 int linenos_view_valid;
1097 int syms_view_valid;
1098 int str_view_valid;
1099 int dwarf_view_valid;
1100 int magic_ok;
1101 int i;
1102 struct dwarf_sections dwarf_sections;
1104 *found_sym = 0;
1106 sects_view_valid = 0;
1107 linenos_view_valid = 0;
1108 syms_view_valid = 0;
1109 str_view_valid = 0;
1110 dwarf_view_valid = 0;
1112 str_size = 0;
1114 /* Map the XCOFF file header. */
1115 if (!backtrace_get_view (state, descriptor, offset, sizeof (b_xcoff_filhdr),
1116 error_callback, data, &fhdr_view))
1117 goto fail;
1119 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
1120 magic_ok = (fhdr.f_magic == XCOFF_MAGIC);
1122 backtrace_release_view (state, &fhdr_view, error_callback, data);
1124 if (!magic_ok)
1126 if (exe)
1127 error_callback (data, "executable file is not XCOFF", 0);
1128 goto fail;
1131 /* Verify object is of expected type. */
1132 if ((exe && (fhdr.f_flags & F_SHROBJ))
1133 || (!exe && !(fhdr.f_flags & F_SHROBJ)))
1134 goto fail;
1136 /* Read the section headers. */
1138 sects_size = fhdr.f_nscns * sizeof (b_xcoff_scnhdr);
1140 if (!backtrace_get_view (state, descriptor,
1141 offset + sizeof (fhdr) + fhdr.f_opthdr,
1142 sects_size, error_callback, data, &sects_view))
1143 goto fail;
1144 sects_view_valid = 1;
1145 sects = (const b_xcoff_scnhdr *) sects_view.data;
1147 /* FIXME: assumes only one .text section. */
1148 for (i = 0; i < fhdr.f_nscns; ++i)
1149 if ((sects[i].s_flags & 0xffff) == STYP_TEXT)
1150 break;
1151 if (i == fhdr.f_nscns)
1152 goto fail;
1154 stext = &sects[i];
1156 /* AIX ldinfo_textorg includes the XCOFF headers. */
1157 base_address = (exe ? XCOFF_AIX_TEXTBASE : base_address) + stext->s_scnptr;
1159 lnnoptr = stext->s_lnnoptr;
1160 nlnno = stext->s_nlnno;
1162 #if BACKTRACE_XCOFF_SIZE == 32
1163 if (nlnno == _OVERFLOW_MARKER)
1165 int sntext = i + 1;
1166 /* Find the matching .ovrflo section. */
1167 for (i = 0; i < fhdr.f_nscns; ++i)
1169 if (((sects[i].s_flags & 0xffff) == STYP_OVRFLO)
1170 && sects[i].s_nlnno == sntext)
1172 nlnno = sects[i].s_vaddr;
1173 break;
1177 #endif
1179 /* Read the symbol table and the string table. */
1181 if (fhdr.f_symptr != 0)
1183 struct xcoff_syminfo_data *sdata;
1185 /* Symbol table is followed by the string table. The string table
1186 starts with its length (on 4 bytes).
1187 Map the symbol table and the length of the string table. */
1188 syms_size = fhdr.f_nsyms * sizeof (b_xcoff_syment);
1190 if (!backtrace_get_view (state, descriptor, offset + fhdr.f_symptr,
1191 syms_size + 4, error_callback, data,
1192 &syms_view))
1193 goto fail;
1194 syms_view_valid = 1;
1196 memcpy (&str_size, syms_view.data + syms_size, 4);
1198 str_off = fhdr.f_symptr + syms_size;
1200 if (str_size > 4)
1202 /* Map string table (including the length word). */
1204 if (!backtrace_get_view (state, descriptor, offset + str_off,
1205 str_size, error_callback, data, &str_view))
1206 goto fail;
1207 str_view_valid = 1;
1210 sdata = ((struct xcoff_syminfo_data *)
1211 backtrace_alloc (state, sizeof *sdata, error_callback, data));
1212 if (sdata == NULL)
1213 goto fail;
1215 if (!xcoff_initialize_syminfo (state, base_address, sects,
1216 syms_view.data, fhdr.f_nsyms,
1217 str_view.data, str_size,
1218 error_callback, data, sdata))
1220 backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
1221 goto fail;
1224 *found_sym = 1;
1226 xcoff_add_syminfo_data (state, sdata);
1229 /* Read all the DWARF sections in a single view, since they are
1230 probably adjacent in the file. We never release this view. */
1232 min_offset = 0;
1233 max_offset = 0;
1234 memset (dwsect, 0, sizeof dwsect);
1235 for (i = 0; i < fhdr.f_nscns; ++i)
1237 off_t end;
1238 int idx;
1240 if ((sects[i].s_flags & 0xffff) != STYP_DWARF
1241 || sects[i].s_size == 0)
1242 continue;
1243 /* Map DWARF section to array index. */
1244 switch (sects[i].s_flags & 0xffff0000)
1246 case SSUBTYP_DWINFO:
1247 idx = DEBUG_INFO;
1248 break;
1249 case SSUBTYP_DWLINE:
1250 idx = DEBUG_LINE;
1251 break;
1252 case SSUBTYP_DWABREV:
1253 idx = DEBUG_ABBREV;
1254 break;
1255 case SSUBTYP_DWARNGE:
1256 idx = DEBUG_RANGES;
1257 break;
1258 case SSUBTYP_DWSTR:
1259 idx = DEBUG_STR;
1260 break;
1261 default:
1262 continue;
1264 if (min_offset == 0 || (off_t) sects[i].s_scnptr < min_offset)
1265 min_offset = sects[i].s_scnptr;
1266 end = sects[i].s_scnptr + sects[i].s_size;
1267 if (end > max_offset)
1268 max_offset = end;
1269 dwsect[idx].offset = sects[i].s_scnptr;
1270 dwsect[idx].size = sects[i].s_size;
1272 if (min_offset != 0 && max_offset != 0)
1274 if (!backtrace_get_view (state, descriptor, offset + min_offset,
1275 max_offset - min_offset,
1276 error_callback, data, &dwarf_view))
1277 goto fail;
1278 dwarf_view_valid = 1;
1280 for (i = 0; i < (int) DEBUG_MAX; ++i)
1282 if (dwsect[i].offset == 0)
1283 dwsect[i].data = NULL;
1284 else
1285 dwsect[i].data = ((const unsigned char *) dwarf_view.data
1286 + (dwsect[i].offset - min_offset));
1289 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1291 dwarf_sections.data[DEBUG_INFO] = dwsect[DEBUG_INFO].data;
1292 dwarf_sections.size[DEBUG_INFO] = dwsect[DEBUG_INFO].size;
1293 #if BACKTRACE_XCOFF_SIZE == 32
1294 /* XXX workaround for broken lineoff */
1295 dwarf_sections.data[DEBUG_LINE] = dwsect[DEBUG_LINE].data - 4;
1296 #else
1297 /* XXX workaround for broken lineoff */
1298 dwarf_sections.data[DEBUG_LINE] = dwsect[DEBUG_LINE].data - 12;
1299 #endif
1300 dwarf_sections.size[DEBUG_LINE] = dwsect[DEBUG_LINE].size;
1301 dwarf_sections.data[DEBUG_ABBREV] = dwsect[DEBUG_ABBREV].data;
1302 dwarf_sections.size[DEBUG_ABBREV] = dwsect[DEBUG_ABBREV].size;
1303 dwarf_sections.data[DEBUG_RANGES] = dwsect[DEBUG_RANGES].data;
1304 dwarf_sections.size[DEBUG_RANGES] = dwsect[DEBUG_RANGES].size;
1305 dwarf_sections.data[DEBUG_STR] = dwsect[DEBUG_STR].data;
1306 dwarf_sections.size[DEBUG_STR] = dwsect[DEBUG_STR].size;
1308 if (!backtrace_dwarf_add (state, 0, &dwarf_sections,
1309 1, /* big endian */
1310 NULL, /* altlink */
1311 error_callback, data, fileline_fn,
1312 NULL /* returned fileline_entry */))
1313 goto fail;
1316 /* Read the XCOFF line number entries if DWARF sections not found. */
1318 if (!dwarf_view_valid && fhdr.f_symptr != 0 && lnnoptr != 0)
1320 size_t linenos_size = (size_t) nlnno * LINESZ;
1322 /* We never release this view. */
1323 if (!backtrace_get_view (state, descriptor, offset + lnnoptr,
1324 linenos_size,
1325 error_callback, data, &linenos_view))
1326 goto fail;
1327 linenos_view_valid = 1;
1329 if (xcoff_initialize_fileline (state, base_address, sects,
1330 syms_view.data, fhdr.f_nsyms,
1331 str_view.data, str_size,
1332 linenos_view.data, linenos_size,
1333 lnnoptr, error_callback, data))
1334 *fileline_fn = xcoff_fileline;
1337 backtrace_release_view (state, &sects_view, error_callback, data);
1338 sects_view_valid = 0;
1339 if (syms_view_valid)
1340 backtrace_release_view (state, &syms_view, error_callback, data);
1341 syms_view_valid = 0;
1343 /* We've read all we need from the executable. */
1344 if (!backtrace_close (descriptor, error_callback, data))
1345 goto fail;
1346 descriptor = -1;
1348 return 1;
1350 fail:
1351 if (sects_view_valid)
1352 backtrace_release_view (state, &sects_view, error_callback, data);
1353 if (str_view_valid)
1354 backtrace_release_view (state, &str_view, error_callback, data);
1355 if (syms_view_valid)
1356 backtrace_release_view (state, &syms_view, error_callback, data);
1357 if (linenos_view_valid)
1358 backtrace_release_view (state, &linenos_view, error_callback, data);
1359 if (dwarf_view_valid)
1360 backtrace_release_view (state, &dwarf_view, error_callback, data);
1361 if (descriptor != -1 && offset == 0)
1362 backtrace_close (descriptor, error_callback, data);
1363 return 0;
1366 #ifdef HAVE_LOADQUERY
1368 /* Read an integer value in human-readable format from an AIX
1369 big archive fixed-length or member header. */
1371 static int
1372 xcoff_parse_decimal (const char *buf, size_t size, off_t *off)
1374 char str[32];
1375 char *end;
1377 if (size >= sizeof str)
1378 return 0;
1379 memcpy (str, buf, size);
1380 str[size] = '\0';
1381 *off = strtol (str, &end, 10);
1382 if (*end != '\0' && *end != ' ')
1383 return 0;
1385 return 1;
1388 /* Add the backtrace data for a member of an AIX big archive.
1389 Returns 1 on success, 0 on failure. */
1391 static int
1392 xcoff_armem_add (struct backtrace_state *state, int descriptor,
1393 uintptr_t base_address, const char *member,
1394 backtrace_error_callback error_callback, void *data,
1395 fileline *fileline_fn, int *found_sym)
1397 struct backtrace_view view;
1398 b_ar_fl_hdr fl_hdr;
1399 const b_ar_hdr *ar_hdr;
1400 off_t off;
1401 off_t len;
1402 int memlen;
1404 *found_sym = 0;
1406 /* Map archive fixed-length header. */
1408 if (!backtrace_get_view (state, descriptor, 0, sizeof (b_ar_fl_hdr),
1409 error_callback, data, &view))
1410 goto fail;
1412 memcpy (&fl_hdr, view.data, sizeof (b_ar_fl_hdr));
1414 backtrace_release_view (state, &view, error_callback, data);
1416 if (memcmp (fl_hdr.fl_magic, AIAMAGBIG, 8) != 0)
1417 goto fail;
1419 memlen = strlen (member);
1421 /* Read offset of first archive member. */
1422 if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff, sizeof fl_hdr.fl_fstmoff, &off))
1423 goto fail;
1424 while (off != 0)
1426 /* Map archive member header and member name. */
1428 if (!backtrace_get_view (state, descriptor, off,
1429 sizeof (b_ar_hdr) + memlen,
1430 error_callback, data, &view))
1431 break;
1433 ar_hdr = (const b_ar_hdr *) view.data;
1435 /* Read archive member name length. */
1436 if (!xcoff_parse_decimal (ar_hdr->ar_namlen, sizeof ar_hdr->ar_namlen,
1437 &len))
1439 backtrace_release_view (state, &view, error_callback, data);
1440 break;
1442 if (len == memlen && !memcmp (ar_hdr->ar_name, member, memlen))
1444 off = (off + sizeof (b_ar_hdr) + memlen + 1) & ~1;
1446 /* The archive can contain several members with the same name
1447 (e.g. 32-bit and 64-bit), so continue if not ok. */
1449 if (xcoff_add (state, descriptor, off, base_address, error_callback,
1450 data, fileline_fn, found_sym, 0))
1452 backtrace_release_view (state, &view, error_callback, data);
1453 return 1;
1457 /* Read offset of next archive member. */
1458 if (!xcoff_parse_decimal (ar_hdr->ar_nxtmem, sizeof ar_hdr->ar_nxtmem,
1459 &off))
1461 backtrace_release_view (state, &view, error_callback, data);
1462 break;
1464 backtrace_release_view (state, &view, error_callback, data);
1467 fail:
1468 /* No matching member found. */
1469 backtrace_close (descriptor, error_callback, data);
1470 return 0;
1473 /* Add the backtrace data for dynamically loaded libraries. */
1475 static void
1476 xcoff_add_shared_libs (struct backtrace_state *state,
1477 backtrace_error_callback error_callback,
1478 void *data, fileline *fileline_fn, int *found_sym)
1480 const struct ld_info *ldinfo;
1481 void *buf;
1482 unsigned int buflen;
1483 const char *member;
1484 int descriptor;
1485 int does_not_exist;
1486 int lib_found_sym;
1487 int ret;
1489 /* Retrieve the list of loaded libraries. */
1491 buf = NULL;
1492 buflen = 512;
1495 buf = realloc (buf, buflen);
1496 if (buf == NULL)
1498 ret = -1;
1499 break;
1501 ret = loadquery (L_GETINFO, buf, buflen);
1502 if (ret == 0)
1503 break;
1504 buflen *= 2;
1506 while (ret == -1 && errno == ENOMEM);
1507 if (ret != 0)
1509 free (buf);
1510 return;
1513 ldinfo = (const struct ld_info *) buf;
1514 while ((const char *) ldinfo < (const char *) buf + buflen)
1516 if (*ldinfo->ldinfo_filename != '/')
1517 goto next;
1519 descriptor = backtrace_open (ldinfo->ldinfo_filename, error_callback,
1520 data, &does_not_exist);
1521 if (descriptor < 0)
1522 goto next;
1524 /* Check if it is an archive (member name not empty). */
1526 member = ldinfo->ldinfo_filename + strlen (ldinfo->ldinfo_filename) + 1;
1527 if (*member)
1529 xcoff_armem_add (state, descriptor,
1530 (uintptr_t) ldinfo->ldinfo_textorg, member,
1531 error_callback, data, fileline_fn, &lib_found_sym);
1533 else
1535 xcoff_add (state, descriptor, 0, (uintptr_t) ldinfo->ldinfo_textorg,
1536 error_callback, data, fileline_fn, &lib_found_sym, 0);
1538 if (lib_found_sym)
1539 *found_sym = 1;
1541 next:
1542 if (ldinfo->ldinfo_next == 0)
1543 break;
1544 ldinfo = (const struct ld_info *) ((const char *) ldinfo
1545 + ldinfo->ldinfo_next);
1548 free (buf);
1550 #endif /* HAVE_LOADQUERY */
1552 /* Initialize the backtrace data we need from an XCOFF executable.
1553 Returns 1 on success, 0 on failure. */
1556 backtrace_initialize (struct backtrace_state *state,
1557 const char *filename ATTRIBUTE_UNUSED, int descriptor,
1558 backtrace_error_callback error_callback,
1559 void *data, fileline *fileline_fn)
1561 int ret;
1562 int found_sym;
1563 fileline xcoff_fileline_fn = xcoff_nodebug;
1565 ret = xcoff_add (state, descriptor, 0, 0, error_callback, data,
1566 &xcoff_fileline_fn, &found_sym, 1);
1567 if (!ret)
1568 return 0;
1570 #ifdef HAVE_LOADQUERY
1571 xcoff_add_shared_libs (state, error_callback, data, &xcoff_fileline_fn,
1572 &found_sym);
1573 #endif
1575 if (!state->threaded)
1577 if (found_sym)
1578 state->syminfo_fn = xcoff_syminfo;
1579 else if (state->syminfo_fn == NULL)
1580 state->syminfo_fn = xcoff_nosyms;
1582 else
1584 if (found_sym)
1585 backtrace_atomic_store_pointer (&state->syminfo_fn, xcoff_syminfo);
1586 else
1587 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1588 xcoff_nosyms);
1591 if (!state->threaded)
1593 if (state->fileline_fn == NULL || state->fileline_fn == xcoff_nodebug)
1594 *fileline_fn = xcoff_fileline_fn;
1596 else
1598 fileline current_fn;
1600 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1601 if (current_fn == NULL || current_fn == xcoff_nodebug)
1602 *fileline_fn = xcoff_fileline_fn;
1605 return 1;