The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
xcoff.c
Go to the documentation of this file.
1/* xcoff.c -- Get debug data from an XCOFF file for backtraces.
2 Copyright (C) 2012-2024 Free Software Foundation, Inc.
3 Adapted from elf.c.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
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.
16
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.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33#include "config.h"
34
35#include <errno.h>
36#include <stdlib.h>
37#include <string.h>
38#include <sys/types.h>
39
40#ifdef HAVE_LOADQUERY
41#include <sys/ldr.h>
42#endif
43
44#include "backtrace.h"
45#include "internal.h"
46
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. */
52
53#if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64
54#error "Unknown BACKTRACE_XCOFF_SIZE"
55#endif
56
57/* XCOFF file header. */
58
59#if BACKTRACE_XCOFF_SIZE == 32
60
61typedef 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;
70
71#define XCOFF_MAGIC 0737
72
73#else /* BACKTRACE_XCOFF_SIZE != 32 */
74
84
85#define XCOFF_MAGIC 0767
86
87#endif /* BACKTRACE_XCOFF_SIZE != 32 */
88
89#define F_SHROBJ 0x2000 /* File is a shared object. */
90
91/* XCOFF section header. */
92
93#if BACKTRACE_XCOFF_SIZE == 32
94
95typedef 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;
107
108#define _OVERFLOW_MARKER 65535
109
110#else /* BACKTRACE_XCOFF_SIZE != 32 */
111
112typedef 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;
124
125#endif /* BACKTRACE_XCOFF_SIZE != 32 */
126
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. */
130
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. */
136#define SSUBTYP_DWRNGES 0x80000 /* DWARF ranges section. */
137
138/* XCOFF symbol. */
139
140#define SYMNMLEN 8
141
142#if BACKTRACE_XCOFF_SIZE == 32
143
144typedef struct {
145 union {
146 char _name[SYMNMLEN];
147 struct {
148 uint32_t _zeroes;
149 uint32_t _offset;
150 } _s;
151 } _u;
152#define n_name _u._name
153#define n_zeroes _u._s._zeroes
154#define n_offset_ _u._s._offset
155
156 uint32_t n_value;
157 int16_t n_scnum;
158 uint16_t n_type;
159 uint8_t n_sclass;
160 uint8_t n_numaux;
161} __attribute__ ((packed)) b_xcoff_syment;
162
163#else /* BACKTRACE_XCOFF_SIZE != 32 */
164
165typedef struct {
166 uint64_t n_value;
168 int16_t n_scnum;
172} __attribute__ ((packed)) b_xcoff_syment;
173
174#endif /* BACKTRACE_XCOFF_SIZE != 32 */
175
176#define SYMESZ 18
177
178#define C_EXT 2 /* External symbol. */
179#define C_FCN 101 /* Beginning or end of function. */
180#define C_FILE 103 /* Source file name. */
181#define C_HIDEXT 107 /* Unnamed external symbol. */
182#define C_BINCL 108 /* Beginning of include file. */
183#define C_EINCL 109 /* End of include file. */
184#define C_WEAKEXT 111 /* Weak external symbol. */
185
186#define ISFCN(x) ((x) & 0x0020)
187
188/* XCOFF AUX entry. */
189
190#define AUXESZ 18
191#define FILNMLEN 14
192
193typedef union {
194#if BACKTRACE_XCOFF_SIZE == 32
195 struct {
196 uint16_t pad;
197 uint16_t x_lnnohi;
198 uint16_t x_lnno;
199 } x_block;
200#else
201 struct {
202 uint32_t x_lnno;
203 } x_block;
204#endif
205 union {
206 char x_fname[FILNMLEN];
207 struct {
208 uint32_t x_zeroes;
209 uint32_t x_offset;
210 char pad[FILNMLEN-8];
211 uint8_t x_ftype;
212 } _x;
213 } x_file;
214#if BACKTRACE_XCOFF_SIZE == 32
215 struct {
216 uint32_t x_exptr;
217 uint32_t x_fsize;
218 uint32_t x_lnnoptr;
219 uint32_t x_endndx;
220 } x_fcn;
221#else
222 struct {
223 uint64_t x_lnnoptr;
224 uint32_t x_fsize;
225 uint32_t x_endndx;
226 } x_fcn;
227#endif
228 struct {
229 uint8_t pad[AUXESZ-1];
230 uint8_t x_auxtype;
231 } x_auxtype;
232} __attribute__ ((packed)) b_xcoff_auxent;
233
234/* XCOFF line number entry. */
235
236#if BACKTRACE_XCOFF_SIZE == 32
237
238typedef struct {
239 union {
240 uint32_t l_symndx;
241 uint32_t l_paddr;
242 } l_addr;
243 uint16_t l_lnno;
245
246#define LINESZ 6
247
248#else /* BACKTRACE_XCOFF_SIZE != 32 */
249
250typedef struct {
251 union {
252 uint32_t l_symndx;
253 uint64_t l_paddr;
254 } l_addr;
257
258#define LINESZ 12
259
260#endif /* BACKTRACE_XCOFF_SIZE != 32 */
261
262#if BACKTRACE_XCOFF_SIZE == 32
263#define XCOFF_AIX_TEXTBASE 0x10000000u
264#else
265#define XCOFF_AIX_TEXTBASE 0x100000000ul
266#endif
267
268/* AIX big archive fixed-length header. */
269
270#define AIAMAGBIG "<bigaf>\n"
271
272typedef struct {
273 char fl_magic[8]; /* Archive magic string. */
274 char fl_memoff[20]; /* Offset to member table. */
275 char fl_gstoff[20]; /* Offset to global symbol table. */
276 char fl_gst64off[20]; /* Offset to global symbol table for 64-bit objects. */
277 char fl_fstmoff[20]; /* Offset to first archive member. */
278 char fl_freeoff[20]; /* Offset to first member on free list. */
280
281/* AIX big archive file member header. */
282
283typedef struct {
284 char ar_size[20]; /* File member size - decimal. */
285 char ar_nxtmem[20]; /* Next member offset - decimal. */
286 char ar_prvmem[20]; /* Previous member offset - decimal. */
287 char ar_date[12]; /* File member date - decimal. */
288 char ar_uid[12]; /* File member userid - decimal. */
289 char ar_gid[12]; /* File member group id - decimal. */
290 char ar_mode[12]; /* File member mode - octal. */
291 char ar_namlen[4]; /* File member name length - decimal. */
292 char ar_name[2]; /* Start of member name. */
293} b_ar_hdr;
294
295
296/* Information we keep for an XCOFF symbol. */
297
299{
300 /* The name of the symbol. */
301 const char *name;
302 /* The address of the symbol. */
303 uintptr_t address;
304 /* The size of the symbol. */
305 size_t size;
306};
307
308/* Information to pass to xcoff_syminfo. */
309
311{
312 /* Symbols for the next module. */
314 /* The XCOFF symbols, sorted by address. */
316 /* The number of symbols. */
317 size_t count;
318};
319
320/* Information about an include file. */
321
323{
324 /* File name. */
325 const char *filename;
326 /* Offset to first line number from the include file. */
327 uintptr_t begin;
328 /* Offset to last line number from the include file. */
329 uintptr_t end;
330};
331
332/* A growable vector of include files information. */
333
335{
336 /* Memory. This is an array of struct xcoff_incl. */
338 /* Number of include files. */
339 size_t count;
340};
341
342/* A growable vector of functions information. */
343
345{
346 /* PC. */
347 uintptr_t pc;
348 /* The size of the function. */
349 size_t size;
350 /* Function name. */
351 const char *name;
352 /* File name. */
353 const char *filename;
354 /* Pointer to first lnno entry. */
355 uintptr_t lnnoptr;
356 /* Base address of containing section. */
357 uintptr_t sect_base;
358 /* Starting source line number. */
359 int lnno;
360};
361
362/* A growable vector of function information. This is used while
363 reading the function symbols. */
364
366{
367 /* Memory. This is an array of struct xcoff_func. */
369 /* Number of valid mappings. */
370 size_t count;
371};
372
373/* The information we need to map a PC to a file and line. */
374
376{
377 /* The data for the next file we know about. */
379 /* Functions information. */
381 /* Include files information. */
383 /* Line numbers information. */
384 const unsigned char *linenos;
386 uint64_t lnnoptr0;
387 /* Loader address. */
389};
390
391/* Information we gather for the DWARF sections we care about. */
392
394{
395 /* Section file offset. */
397 /* Section size. */
398 size_t size;
399 /* Section contents, after read from file. */
400 const unsigned char *data;
401};
402
403/* A dummy callback function used when we can't find any debug info. */
404
405static int
407 uintptr_t pc ATTRIBUTE_UNUSED,
410{
411 error_callback (data, "no debug info in XCOFF executable", -1);
412 return 0;
413}
414
415/* A dummy callback function used when we can't find a symbol
416 table. */
417
418static void
420 uintptr_t addr ATTRIBUTE_UNUSED,
423{
424 error_callback (data, "no symbol table in XCOFF executable", -1);
425}
426
427/* Compare struct xcoff_symbol for qsort. */
428
429static int
430xcoff_symbol_compare (const void *v1, const void *v2)
431{
432 const struct xcoff_symbol *e1 = (const struct xcoff_symbol *) v1;
433 const struct xcoff_symbol *e2 = (const struct xcoff_symbol *) v2;
434
435 if (e1->address < e2->address)
436 return -1;
437 else if (e1->address > e2->address)
438 return 1;
439 else
440 return 0;
441}
442
443/* Compare an ADDR against an xcoff_symbol for bsearch. */
444
445static int
446xcoff_symbol_search (const void *vkey, const void *ventry)
447{
448 const uintptr_t *key = (const uintptr_t *) vkey;
449 const struct xcoff_symbol *entry = (const struct xcoff_symbol *) ventry;
450 uintptr_t addr;
451
452 addr = *key;
453 if (addr < entry->address)
454 return -1;
455 else if ((entry->size == 0 && addr > entry->address)
456 || (entry->size > 0 && addr >= entry->address + entry->size))
457 return 1;
458 else
459 return 0;
460}
461
462/* Add XDATA to the list in STATE. */
463
464static void
466 struct xcoff_syminfo_data *xdata)
467{
468 if (!state->threaded)
469 {
470 struct xcoff_syminfo_data **pp;
471
472 for (pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
473 *pp != NULL;
474 pp = &(*pp)->next)
475 ;
476 *pp = xdata;
477 }
478 else
479 {
480 while (1)
481 {
482 struct xcoff_syminfo_data **pp;
483
484 pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
485
486 while (1)
487 {
488 struct xcoff_syminfo_data *p;
489
491
492 if (p == NULL)
493 break;
494
495 pp = &p->next;
496 }
497
498 if (__sync_bool_compare_and_swap (pp, NULL, xdata))
499 break;
500 }
501 }
502}
503
504/* Return the symbol name and value for an ADDR. */
505
506static void
510 void *data)
511{
512 struct xcoff_syminfo_data *edata;
513 struct xcoff_symbol *sym = NULL;
514 const char *name;
515
516 if (!state->threaded)
517 {
518 for (edata = (struct xcoff_syminfo_data *) state->syminfo_data;
519 edata != NULL;
520 edata = edata->next)
521 {
522 sym = ((struct xcoff_symbol *)
523 bsearch (&addr, edata->symbols, edata->count,
524 sizeof (struct xcoff_symbol), xcoff_symbol_search));
525 if (sym != NULL)
526 break;
527 }
528 }
529 else
530 {
531 struct xcoff_syminfo_data **pp;
532
533 pp = (struct xcoff_syminfo_data **) (void *) &state->syminfo_data;
534 while (1)
535 {
537 if (edata == NULL)
538 break;
539
540 sym = ((struct xcoff_symbol *)
541 bsearch (&addr, edata->symbols, edata->count,
542 sizeof (struct xcoff_symbol), xcoff_symbol_search));
543 if (sym != NULL)
544 break;
545
546 pp = &edata->next;
547 }
548 }
549
550 if (sym == NULL)
551 callback (data, addr, NULL, 0, 0);
552 else
553 {
554 name = sym->name;
555 /* AIX prepends a '.' to function entry points, remove it. */
556 if (name && *name == '.')
557 ++name;
558 callback (data, addr, name, sym->address, sym->size);
559 }
560}
561
562/* Return the name of an XCOFF symbol. */
563
564static const char *
565xcoff_symname (const b_xcoff_syment *asym,
566 const unsigned char *strtab, size_t strtab_size)
567{
568#if BACKTRACE_XCOFF_SIZE == 32
569 if (asym->n_zeroes != 0)
570 {
571 /* Make a copy as we will release the symtab view. */
572 char name[SYMNMLEN+1];
573 strncpy (name, asym->n_name, SYMNMLEN);
574 name[SYMNMLEN] = '\0';
575 return strdup (name);
576 }
577#endif
578 if (asym->n_sclass & 0x80)
579 return NULL; /* .debug */
580 if (asym->n_offset_ >= strtab_size)
581 return NULL;
582 return (const char *) strtab + asym->n_offset_;
583}
584
585/* Initialize the symbol table info for xcoff_syminfo. */
586
587static int
589 struct libbacktrace_base_address base_address,
590 const b_xcoff_syment *syms, size_t nsyms,
591 const unsigned char *strtab, size_t strtab_size,
594{
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;
600
601 /* We only care about function symbols. Count them. */
602 xcoff_symbol_count = 0;
603 for (i = 0; i < nsyms; ++i)
604 {
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;
610
611 i += asym->n_numaux;
612 }
613
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;
620
621 j = 0;
622 for (i = 0; i < nsyms; ++i)
623 {
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)
628 {
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 =
632 libbacktrace_add_base (asym->n_value, base_address);
633 /* x_fsize will be 0 if there is no debug information. */
634 xcoff_symbols[j].size = aux->x_fcn.x_fsize;
635 ++j;
636 }
637
638 i += asym->n_numaux;
639 }
640
641 backtrace_qsort (xcoff_symbols, xcoff_symbol_count,
642 sizeof (struct xcoff_symbol), xcoff_symbol_compare);
643
644 sdata->next = NULL;
645 sdata->symbols = xcoff_symbols;
646 sdata->count = xcoff_symbol_count;
647
648 return 1;
649}
650
651/* Compare struct xcoff_func for qsort. */
652
653static int
654xcoff_func_compare (const void *v1, const void *v2)
655{
656 const struct xcoff_func *fn1 = (const struct xcoff_func *) v1;
657 const struct xcoff_func *fn2 = (const struct xcoff_func *) v2;
658
659 if (fn1->pc < fn2->pc)
660 return -1;
661 else if (fn1->pc > fn2->pc)
662 return 1;
663 else
664 return 0;
665}
666
667/* Compare a PC against an xcoff_func for bsearch. */
668
669static int
670xcoff_func_search (const void *vkey, const void *ventry)
671{
672 const uintptr_t *key = (const uintptr_t *) vkey;
673 const struct xcoff_func *entry = (const struct xcoff_func *) ventry;
674 uintptr_t pc;
675
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;
684}
685
686/* Compare struct xcoff_incl for qsort. */
687
688static int
689xcoff_incl_compare (const void *v1, const void *v2)
690{
691 const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1;
692 const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2;
693
694 if (in1->begin < in2->begin)
695 return -1;
696 else if (in1->begin > in2->begin)
697 return 1;
698 else
699 return 0;
700}
701
702/* Find a lnnoptr in an include file. */
703
704static int
705xcoff_incl_search (const void *vkey, const void *ventry)
706{
707 const uintptr_t *key = (const uintptr_t *) vkey;
708 const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry;
709 uintptr_t lnno;
710
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;
718}
719
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. */
724
725static int
727 struct xcoff_fileline_data *fdata, uintptr_t pc,
730 void *data, int *found)
731{
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;
740
741 *found = 1;
742
743 if ((pc & 3) != 0)
744 ++pc;
745
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)
751 {
752 *found = 0;
753 return 0;
754 }
755
756 filename = fn->filename;
757
758 /* Find the line number next. */
759
760 /* Skip first entry that points to symtab. */
761 lnnoptr = fn->lnnoptr + LINESZ;
762 match = lnnoptr;
763
764 lineptr = fdata->linenos + (lnnoptr - fdata->lnnoptr0);
765 while (lineptr + LINESZ <= fdata->linenos + fdata->linenos_size)
766 {
767 lineno = (const b_xcoff_lineno *) lineptr;
768 if (lineno->l_lnno == 0)
769 break;
770 if (pc <= libbacktrace_add_base (lineno->l_addr.l_paddr,
771 fdata->base_address))
772 break;
773 match = lnnoptr;
774 lnno = lineno->l_lnno;
775
776 lnnoptr += LINESZ;
777 lineptr += LINESZ;
778 }
779
780 /* If part of a function other than the beginning comes from an
781 include file, the line numbers are absolute, rather than
782 relative to the beginning of the function. */
783 incl = ((struct xcoff_incl *)
784 bsearch (&match, fdata->incl_vec.vec.base,
785 fdata->incl_vec.count, sizeof (struct xcoff_incl),
787 if (incl != NULL)
788 {
789 bincl = ((struct xcoff_incl *)
790 bsearch (&fn->lnnoptr, fdata->incl_vec.vec.base,
791 fdata->incl_vec.count, sizeof (struct xcoff_incl),
793 if (bincl != NULL && strcmp (incl->filename, bincl->filename) == 0)
794 {
795 lnno += fn->lnno - 1;
796 }
797 filename = incl->filename;
798 }
799 else
800 {
801 lnno += fn->lnno - 1;
802 }
803
804 function = fn->name;
805 /* AIX prepends a '.' to function entry points, remove it. */
806 if (function != NULL && *function == '.')
807 ++function;
808 return callback (data, pc, filename, lnno, function);
809}
810
811/* Return the file/line information for a PC using the XCOFF lineno
812 mapping we built earlier. */
813
814static int
815xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
818
819{
820 struct xcoff_fileline_data *fdata;
821 int found;
822 int ret;
823
824 if (!state->threaded)
825 {
826 for (fdata = (struct xcoff_fileline_data *) state->fileline_data;
827 fdata != NULL;
828 fdata = fdata->next)
829 {
830 ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
831 data, &found);
832 if (ret != 0 || found)
833 return ret;
834 }
835 }
836 else
837 {
838 struct xcoff_fileline_data **pp;
839
840 pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
841 while (1)
842 {
844 if (fdata == NULL)
845 break;
846
847 ret = xcoff_lookup_pc (state, fdata, pc, callback, error_callback,
848 data, &found);
849 if (ret != 0 || found)
850 return ret;
851
852 pp = &fdata->next;
853 }
854 }
855
856 /* FIXME: See if any libraries have been dlopen'ed. */
857
858 return callback (data, pc, NULL, 0, NULL);
859}
860
861/* Initialize the function vector info for xcoff_fileline. */
862
863static int
866 const b_xcoff_scnhdr *sects,
867 const b_xcoff_syment *syms, size_t nsyms,
868 const unsigned char *strtab, size_t strtab_size,
869 const unsigned char *linenos, size_t linenos_size,
870 uint64_t lnnoptr0,
872{
873 struct xcoff_fileline_data *fdata;
874 struct xcoff_func *fn;
875 const b_xcoff_syment *fsym;
876 const b_xcoff_auxent *aux;
877 const char *filename;
878 const char *name;
879 struct xcoff_incl *incl;
880 uintptr_t begin, end;
881 uintptr_t lnno, lnnoptr;
882 uint32_t fsize;
883 size_t i;
884
885 fdata = ((struct xcoff_fileline_data *)
886 backtrace_alloc (state, sizeof (struct xcoff_fileline_data),
888 if (fdata == NULL)
889 return 0;
890 memset (fdata, 0, sizeof *fdata);
891 fdata->base_address = base_address;
892 fdata->linenos = linenos;
893 fdata->linenos_size = linenos_size;
894 fdata->lnnoptr0 = lnnoptr0;
895
896 begin = 0;
897 filename = NULL;
898 fsym = NULL;
899 lnnoptr = 0;
900 fsize = 0;
901 for (i = 0; i < nsyms; ++i)
902 {
903 const b_xcoff_syment *asym = &syms[i];
904
905 switch (asym->n_sclass)
906 {
907 case C_BINCL:
908 begin = asym->n_value;
909 break;
910
911 case C_EINCL:
912 if (begin == 0)
913 break;
914 end = asym->n_value;
915 incl = ((struct xcoff_incl *)
916 backtrace_vector_grow (state, sizeof (struct xcoff_incl),
918 &fdata->incl_vec.vec));
919 if (incl != NULL)
920 {
921 incl->filename = xcoff_symname (asym, strtab, strtab_size);
922 incl->begin = begin;
923 incl->end = end;
924 ++fdata->incl_vec.count;
925 }
926 begin = 0;
927 break;
928
929 case C_FILE:
930 filename = xcoff_symname (asym, strtab, strtab_size);
931 if (filename == NULL)
932 break;
933
934 /* If the file auxiliary entry is not used, the symbol name is
935 the name of the source file. If the file auxiliary entry is
936 used, then the symbol name should be .file, and the first
937 file auxiliary entry (by convention) contains the source
938 file name. */
939
940 if (asym->n_numaux > 0 && strcmp (filename, ".file") == 0)
941 {
942 aux = (const b_xcoff_auxent *) (asym + 1);
943 if (aux->x_file._x.x_zeroes != 0)
944 {
945 /* Make a copy as we will release the symtab view. */
946 char name[FILNMLEN+1];
947 strncpy (name, aux->x_file.x_fname, FILNMLEN);
948 name[FILNMLEN] = '\0';
949 filename = strdup (name);
950 }
951 else if (aux->x_file._x.x_offset < strtab_size)
952 filename = (const char *) strtab + aux->x_file._x.x_offset;
953 else
954 filename = NULL;
955 }
956 break;
957
958 case C_EXT:
959 case C_HIDEXT:
960 case C_WEAKEXT:
961 fsym = NULL;
962 lnnoptr = 0;
963 fsize = 0;
964 if (!ISFCN (asym->n_type) || asym->n_numaux == 0
965 || asym->n_scnum <= 0)
966 break;
967 if (filename == NULL)
968 break;
969 aux = (const b_xcoff_auxent *) (asym + 1);
970 lnnoptr = aux->x_fcn.x_lnnoptr;
971 if (lnnoptr < lnnoptr0
972 || lnnoptr + LINESZ > lnnoptr0 + linenos_size)
973 break;
974 /* x_fsize will be 0 if there is no debug information. */
975 fsize = aux->x_fcn.x_fsize;
976 fsym = asym;
977 break;
978
979 case C_FCN:
980 if (asym->n_numaux == 0)
981 break;
982 if (fsym == NULL)
983 break;
984 name = xcoff_symname (asym, strtab, strtab_size);
985 if (name == NULL || strcmp (name, ".bf") != 0)
986 {
987 fsym = NULL;
988 break;
989 }
990 aux = (const b_xcoff_auxent *) (asym + 1);
991#if BACKTRACE_XCOFF_SIZE == 32
992 lnno = (uint32_t) aux->x_block.x_lnnohi << 16
993 | aux->x_block.x_lnno;
994#else
995 lnno = aux->x_block.x_lnno;
996#endif
997 fn = ((struct xcoff_func *)
998 backtrace_vector_grow (state, sizeof (struct xcoff_func),
1000 &fdata->func_vec.vec));
1001 if (fn == NULL)
1002 break;
1003 fn->name = xcoff_symname (fsym, strtab, strtab_size);
1004 fn->filename = filename;
1005 fn->sect_base = sects[fsym->n_scnum - 1].s_paddr;
1006 fn->pc = libbacktrace_add_base (fsym->n_value, base_address);
1007 fn->size = fsize;
1008 fn->lnno = lnno;
1009 fn->lnnoptr = lnnoptr;
1010 ++fdata->func_vec.count;
1011 break;
1012 }
1013
1014 i += asym->n_numaux;
1015 }
1016
1018 data))
1019 goto fail;
1021 sizeof (struct xcoff_func), xcoff_func_compare);
1022
1024 data))
1025 goto fail;
1027 sizeof (struct xcoff_incl), xcoff_incl_compare);
1028
1029 if (!state->threaded)
1030 {
1031 struct xcoff_fileline_data **pp;
1032
1033 for (pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
1034 *pp != NULL;
1035 pp = &(*pp)->next)
1036 ;
1037 *pp = fdata;
1038 }
1039 else
1040 {
1041 while (1)
1042 {
1043 struct xcoff_fileline_data **pp;
1044
1045 pp = (struct xcoff_fileline_data **) (void *) &state->fileline_data;
1046
1047 while (1)
1048 {
1049 struct xcoff_fileline_data *p;
1050
1052
1053 if (p == NULL)
1054 break;
1055
1056 pp = &p->next;
1057 }
1058
1059 if (__sync_bool_compare_and_swap (pp, NULL, fdata))
1060 break;
1061 }
1062 }
1063
1064 return 1;
1065
1066fail:
1067 return 0;
1068}
1069
1070/* Add the backtrace data for one XCOFF file. Returns 1 on success,
1071 0 on failure (in both cases descriptor is closed). */
1072
1073static int
1074xcoff_add (struct backtrace_state *state, int descriptor, off_t offset,
1077 void *data, fileline *fileline_fn, int *found_sym, int exe)
1078{
1079 struct backtrace_view fhdr_view;
1080 struct backtrace_view sects_view;
1081 struct backtrace_view linenos_view;
1082 struct backtrace_view syms_view;
1083 struct backtrace_view str_view;
1084 struct backtrace_view dwarf_view;
1085 b_xcoff_filhdr fhdr;
1086 const b_xcoff_scnhdr *sects;
1087 const b_xcoff_scnhdr *stext;
1088 uint64_t lnnoptr;
1089 uint32_t nlnno;
1090 off_t str_off;
1091 off_t min_offset;
1092 off_t max_offset;
1093 struct dwsect_info dwsect[DEBUG_MAX];
1094 size_t sects_size;
1095 size_t syms_size;
1096 int32_t str_size;
1097 int sects_view_valid;
1098 int linenos_view_valid;
1099 int syms_view_valid;
1100 int str_view_valid;
1101 int dwarf_view_valid;
1102 int magic_ok;
1103 int i;
1105
1106 *found_sym = 0;
1107
1108 sects_view_valid = 0;
1109 linenos_view_valid = 0;
1110 syms_view_valid = 0;
1111 str_view_valid = 0;
1112 dwarf_view_valid = 0;
1113
1114 str_size = 0;
1115
1116 /* Map the XCOFF file header. */
1117 if (!backtrace_get_view (state, descriptor, offset, sizeof (b_xcoff_filhdr),
1118 error_callback, data, &fhdr_view))
1119 goto fail;
1120
1121 memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
1122 magic_ok = (fhdr.f_magic == XCOFF_MAGIC);
1123
1125
1126 if (!magic_ok)
1127 {
1128 if (exe)
1129 error_callback (data, "executable file is not XCOFF", 0);
1130 goto fail;
1131 }
1132
1133 /* Verify object is of expected type. */
1134 if ((exe && (fhdr.f_flags & F_SHROBJ))
1135 || (!exe && !(fhdr.f_flags & F_SHROBJ)))
1136 goto fail;
1137
1138 /* Read the section headers. */
1139
1140 sects_size = fhdr.f_nscns * sizeof (b_xcoff_scnhdr);
1141
1142 if (!backtrace_get_view (state, descriptor,
1143 offset + sizeof (fhdr) + fhdr.f_opthdr,
1144 sects_size, error_callback, data, &sects_view))
1145 goto fail;
1146 sects_view_valid = 1;
1147 sects = (const b_xcoff_scnhdr *) sects_view.data;
1148
1149 /* FIXME: assumes only one .text section. */
1150 for (i = 0; i < fhdr.f_nscns; ++i)
1151 if ((sects[i].s_flags & 0xffff) == STYP_TEXT)
1152 break;
1153 if (i == fhdr.f_nscns)
1154 goto fail;
1155
1156 stext = &sects[i];
1157
1158 /* base_address represents the difference between the
1159 virtual memory address of the shared object or a loaded
1160 executable and the offset of that object in the file
1161 from which it was loaded.
1162 On AIX, virtual address is either fixed for executable
1163 or given by ldinfo. This address will include the XCOFF
1164 headers. */
1165 base_address.m = ((exe ? XCOFF_AIX_TEXTBASE : base_address.m)
1166 + stext->s_scnptr
1167 - stext->s_paddr);
1168
1169 lnnoptr = stext->s_lnnoptr;
1170 nlnno = stext->s_nlnno;
1171
1172#if BACKTRACE_XCOFF_SIZE == 32
1173 if (nlnno == _OVERFLOW_MARKER)
1174 {
1175 int sntext = i + 1;
1176 /* Find the matching .ovrflo section. */
1177 for (i = 0; i < fhdr.f_nscns; ++i)
1178 {
1179 if (((sects[i].s_flags & 0xffff) == STYP_OVRFLO)
1180 && sects[i].s_nlnno == sntext)
1181 {
1182 nlnno = sects[i].s_vaddr;
1183 break;
1184 }
1185 }
1186 }
1187#endif
1188
1189 /* Read the symbol table and the string table. */
1190
1191 if (fhdr.f_symptr != 0)
1192 {
1193 struct xcoff_syminfo_data *sdata;
1194
1195 /* Symbol table is followed by the string table. The string table
1196 starts with its length (on 4 bytes).
1197 Map the symbol table and the length of the string table. */
1198 syms_size = fhdr.f_nsyms * sizeof (b_xcoff_syment);
1199
1200 if (!backtrace_get_view (state, descriptor, offset + fhdr.f_symptr,
1201 syms_size + 4, error_callback, data,
1202 &syms_view))
1203 goto fail;
1204 syms_view_valid = 1;
1205
1206 memcpy (&str_size,
1207 (const unsigned char *) syms_view.data + syms_size,
1208 4);
1209
1210 str_off = fhdr.f_symptr + syms_size;
1211
1212 if (str_size > 4)
1213 {
1214 /* Map string table (including the length word). */
1215
1216 if (!backtrace_get_view (state, descriptor, offset + str_off,
1217 str_size, error_callback, data, &str_view))
1218 goto fail;
1219 str_view_valid = 1;
1220 }
1221
1222 sdata = ((struct xcoff_syminfo_data *)
1224 if (sdata == NULL)
1225 goto fail;
1226
1227 if (!xcoff_initialize_syminfo (state, base_address,
1228 syms_view.data, fhdr.f_nsyms,
1229 str_view.data, str_size,
1231 {
1233 goto fail;
1234 }
1235
1236 *found_sym = 1;
1237
1239 }
1240
1241 /* Read all the DWARF sections in a single view, since they are
1242 probably adjacent in the file. We never release this view. */
1243
1244 min_offset = 0;
1245 max_offset = 0;
1246 memset (dwsect, 0, sizeof dwsect);
1247 for (i = 0; i < fhdr.f_nscns; ++i)
1248 {
1249 off_t end;
1250 int idx;
1251
1252 if ((sects[i].s_flags & 0xffff) != STYP_DWARF
1253 || sects[i].s_size == 0)
1254 continue;
1255 /* Map DWARF section to array index. */
1256 switch (sects[i].s_flags & 0xffff0000)
1257 {
1258 case SSUBTYP_DWINFO:
1259 idx = DEBUG_INFO;
1260 break;
1261 case SSUBTYP_DWLINE:
1262 idx = DEBUG_LINE;
1263 break;
1264 case SSUBTYP_DWABREV:
1265 idx = DEBUG_ABBREV;
1266 break;
1267 case SSUBTYP_DWRNGES:
1268 idx = DEBUG_RANGES;
1269 break;
1270 case SSUBTYP_DWSTR:
1271 idx = DEBUG_STR;
1272 break;
1273 default:
1274 continue;
1275 }
1276 if (min_offset == 0 || (off_t) sects[i].s_scnptr < min_offset)
1277 min_offset = sects[i].s_scnptr;
1278 end = sects[i].s_scnptr + sects[i].s_size;
1279 if (end > max_offset)
1280 max_offset = end;
1281 dwsect[idx].offset = sects[i].s_scnptr;
1282 dwsect[idx].size = sects[i].s_size;
1283 }
1284 if (min_offset != 0 && max_offset != 0)
1285 {
1286 if (!backtrace_get_view (state, descriptor, offset + min_offset,
1287 max_offset - min_offset,
1288 error_callback, data, &dwarf_view))
1289 goto fail;
1290 dwarf_view_valid = 1;
1291
1292 for (i = 0; i < (int) DEBUG_MAX; ++i)
1293 {
1294 if (dwsect[i].offset == 0)
1295 dwsect[i].data = NULL;
1296 else
1297 dwsect[i].data = ((const unsigned char *) dwarf_view.data
1298 + (dwsect[i].offset - min_offset));
1299 }
1300
1301 memset (&dwarf_sections, 0, sizeof dwarf_sections);
1302
1313
1314 if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,
1315 1, /* big endian */
1316 NULL, /* altlink */
1317 error_callback, data, fileline_fn,
1318 NULL /* returned fileline_entry */))
1319 goto fail;
1320 }
1321
1322 /* Read the XCOFF line number entries if DWARF sections not found. */
1323
1324 if (!dwarf_view_valid && fhdr.f_symptr != 0 && lnnoptr != 0)
1325 {
1326 size_t linenos_size = (size_t) nlnno * LINESZ;
1327
1328 /* We never release this view. */
1329 if (!backtrace_get_view (state, descriptor, offset + lnnoptr,
1330 linenos_size,
1331 error_callback, data, &linenos_view))
1332 goto fail;
1333 linenos_view_valid = 1;
1334
1335 if (xcoff_initialize_fileline (state, base_address, sects,
1336 syms_view.data, fhdr.f_nsyms,
1337 str_view.data, str_size,
1338 linenos_view.data, linenos_size,
1339 lnnoptr, error_callback, data))
1340 *fileline_fn = xcoff_fileline;
1341 }
1342
1344 sects_view_valid = 0;
1345 if (syms_view_valid)
1347 syms_view_valid = 0;
1348
1349 /* We've read all we need from the executable. */
1350 if (!backtrace_close (descriptor, error_callback, data))
1351 goto fail;
1352 descriptor = -1;
1353
1354 return 1;
1355
1356 fail:
1357 if (sects_view_valid)
1359 if (str_view_valid)
1361 if (syms_view_valid)
1363 if (linenos_view_valid)
1365 if (dwarf_view_valid)
1367 if (descriptor != -1 && offset == 0)
1368 backtrace_close (descriptor, error_callback, data);
1369 return 0;
1370}
1371
1372#ifdef HAVE_LOADQUERY
1373
1374/* Read an integer value in human-readable format from an AIX
1375 big archive fixed-length or member header. */
1376
1377static int
1378xcoff_parse_decimal (const char *buf, size_t size, off_t *off)
1379{
1380 char str[32];
1381 char *end;
1382
1383 if (size >= sizeof str)
1384 return 0;
1385 memcpy (str, buf, size);
1386 str[size] = '\0';
1387 *off = strtol (str, &end, 10);
1388 if (*end != '\0' && *end != ' ')
1389 return 0;
1390
1391 return 1;
1392}
1393
1394/* Add the backtrace data for a member of an AIX big archive.
1395 Returns 1 on success, 0 on failure. */
1396
1397static int
1398xcoff_armem_add (struct backtrace_state *state, int descriptor,
1399 struct libbacktrace_base_address base_address,
1400 const char *member, backtrace_error_callback error_callback,
1401 void *data, fileline *fileline_fn, int *found_sym)
1402{
1403 struct backtrace_view view;
1404 b_ar_fl_hdr fl_hdr;
1405 const b_ar_hdr *ar_hdr;
1406 off_t off;
1407 off_t len;
1408 int memlen;
1409
1410 *found_sym = 0;
1411
1412 /* Map archive fixed-length header. */
1413
1414 if (!backtrace_get_view (state, descriptor, 0, sizeof (b_ar_fl_hdr),
1415 error_callback, data, &view))
1416 goto fail;
1417
1418 memcpy (&fl_hdr, view.data, sizeof (b_ar_fl_hdr));
1419
1421
1422 if (memcmp (fl_hdr.fl_magic, AIAMAGBIG, 8) != 0)
1423 goto fail;
1424
1425 memlen = strlen (member);
1426
1427 /* Read offset of first archive member. */
1428 if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff, sizeof fl_hdr.fl_fstmoff, &off))
1429 goto fail;
1430 while (off != 0)
1431 {
1432 /* Map archive member header and member name. */
1433
1434 if (!backtrace_get_view (state, descriptor, off,
1435 sizeof (b_ar_hdr) + memlen,
1436 error_callback, data, &view))
1437 break;
1438
1439 ar_hdr = (const b_ar_hdr *) view.data;
1440
1441 /* Read archive member name length. */
1442 if (!xcoff_parse_decimal (ar_hdr->ar_namlen, sizeof ar_hdr->ar_namlen,
1443 &len))
1444 {
1446 break;
1447 }
1448 if (len == memlen && !memcmp (ar_hdr->ar_name, member, memlen))
1449 {
1450 off = (off + sizeof (b_ar_hdr) + memlen + 1) & ~1;
1451
1452 /* The archive can contain several members with the same name
1453 (e.g. 32-bit and 64-bit), so continue if not ok. */
1454
1455 if (xcoff_add (state, descriptor, off, base_address, error_callback,
1456 data, fileline_fn, found_sym, 0))
1457 {
1459 return 1;
1460 }
1461 }
1462
1463 /* Read offset of next archive member. */
1464 if (!xcoff_parse_decimal (ar_hdr->ar_nxtmem, sizeof ar_hdr->ar_nxtmem,
1465 &off))
1466 {
1468 break;
1469 }
1471 }
1472
1473 fail:
1474 /* No matching member found. */
1475 backtrace_close (descriptor, error_callback, data);
1476 return 0;
1477}
1478
1479/* Add the backtrace data for dynamically loaded libraries. */
1480
1481static void
1482xcoff_add_shared_libs (struct backtrace_state *state,
1484 void *data, fileline *fileline_fn, int *found_sym)
1485{
1486 const struct ld_info *ldinfo;
1487 void *buf;
1488 unsigned int buflen;
1489 const char *member;
1490 int descriptor;
1491 int does_not_exist;
1492 int lib_found_sym;
1493 int ret;
1494
1495 /* Retrieve the list of loaded libraries. */
1496
1497 buf = NULL;
1498 buflen = 512;
1499 do
1500 {
1501 buf = realloc (buf, buflen);
1502 if (buf == NULL)
1503 {
1504 ret = -1;
1505 break;
1506 }
1507 ret = loadquery (L_GETINFO, buf, buflen);
1508 if (ret == 0)
1509 break;
1510 buflen *= 2;
1511 }
1512 while (ret == -1 && errno == ENOMEM);
1513 if (ret != 0)
1514 {
1515 free (buf);
1516 return;
1517 }
1518
1519 ldinfo = (const struct ld_info *) buf;
1520 while ((const char *) ldinfo < (const char *) buf + buflen)
1521 {
1522 struct libbacktrace_base_address base_address;
1523
1524 if (*ldinfo->ldinfo_filename != '/')
1525 goto next;
1526
1527 descriptor = backtrace_open (ldinfo->ldinfo_filename, error_callback,
1528 data, &does_not_exist);
1529 if (descriptor < 0)
1530 goto next;
1531
1532 /* Check if it is an archive (member name not empty). */
1533
1534 member = ldinfo->ldinfo_filename + strlen (ldinfo->ldinfo_filename) + 1;
1535 memset (&base_address, 0, sizeof base_address);
1536 base_address.m = (uintptr_t) ldinfo->ldinfo_textorg;
1537 if (*member)
1538 {
1539 xcoff_armem_add (state, descriptor, base_address, member,
1540 error_callback, data, fileline_fn, &lib_found_sym);
1541 }
1542 else
1543 {
1544 xcoff_add (state, descriptor, 0, base_address, error_callback, data,
1545 fileline_fn, &lib_found_sym, 0);
1546 }
1547 if (lib_found_sym)
1548 *found_sym = 1;
1549
1550 next:
1551 if (ldinfo->ldinfo_next == 0)
1552 break;
1553 ldinfo = (const struct ld_info *) ((const char *) ldinfo
1554 + ldinfo->ldinfo_next);
1555 }
1556
1557 free (buf);
1558}
1559#endif /* HAVE_LOADQUERY */
1560
1561/* Initialize the backtrace data we need from an XCOFF executable.
1562 Returns 1 on success, 0 on failure. */
1563
1564int
1566 const char *filename ATTRIBUTE_UNUSED, int descriptor,
1568 void *data, fileline *fileline_fn)
1569{
1570 struct libbacktrace_base_address zero_base_address;
1571 int ret;
1572 int found_sym;
1573 fileline xcoff_fileline_fn = xcoff_nodebug;
1574
1575 memset (&zero_base_address, 0, sizeof zero_base_address);
1576 ret = xcoff_add (state, descriptor, 0, zero_base_address,
1577 error_callback, data, &xcoff_fileline_fn, &found_sym, 1);
1578 if (!ret)
1579 return 0;
1580
1581#ifdef HAVE_LOADQUERY
1582 xcoff_add_shared_libs (state, error_callback, data, &xcoff_fileline_fn,
1583 &found_sym);
1584#endif
1585
1586 if (!state->threaded)
1587 {
1588 if (found_sym)
1589 state->syminfo_fn = xcoff_syminfo;
1590 else if (state->syminfo_fn == NULL)
1591 state->syminfo_fn = xcoff_nosyms;
1592 }
1593 else
1594 {
1595 if (found_sym)
1597 else
1598 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
1599 xcoff_nosyms);
1600 }
1601
1602 if (!state->threaded)
1603 {
1604 if (state->fileline_fn == NULL || state->fileline_fn == xcoff_nodebug)
1605 *fileline_fn = xcoff_fileline_fn;
1606 }
1607 else
1608 {
1609 fileline current_fn;
1610
1611 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
1612 if (current_fn == NULL || current_fn == xcoff_nodebug)
1613 *fileline_fn = xcoff_fileline_fn;
1614 }
1615
1616 return 1;
1617}
void * backtrace_vector_grow(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data, struct backtrace_vector *vec)
Definition alloc.c:80
int backtrace_vector_release(struct backtrace_state *state ATTRIBUTE_UNUSED, struct backtrace_vector *vec, backtrace_error_callback error_callback, void *data)
Definition alloc.c:143
void * backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data)
Definition alloc.c:51
void backtrace_free(struct backtrace_state *state ATTRIBUTE_UNUSED, void *p, size_t size ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
Definition alloc.c:69
void(* backtrace_syminfo_callback)(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
Definition backtrace.h:165
void(* backtrace_error_callback)(void *data, const char *msg, int errnum)
Definition backtrace.h:66
int(* backtrace_full_callback)(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
Definition backtrace.h:100
static void error_callback(void *data, const char *msg, int errnum)
Definition print.c:53
uint16_t n_type
Definition xcoff.c:169
uint8_t n_sclass
Definition xcoff.c:170
uint64_t n_value
Definition xcoff.c:166
uint32_t n_offset_
Definition xcoff.c:167
uint8_t n_numaux
Definition xcoff.c:171
int16_t n_scnum
Definition xcoff.c:168
#define strncpy(_dst, _src, _len)
Definition build.h:594
int backtrace_dwarf_add(struct backtrace_state *state, struct libbacktrace_base_address base_address, const struct dwarf_sections *dwarf_sections, int is_bigendian, struct dwarf_data *fileline_altlink, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, struct dwarf_data **fileline_entry)
Definition dwarf.c:4536
#define ATTRIBUTE_UNUSED
Definition filenames.h:42
#define __attribute__(x)
Definition filenames.h:38
free(array)
#define realloc
void backtrace_qsort(void *base, size_t count, size_t size, int(*compar)(const void *, const void *))
Definition sort.c:61
void backtrace_release_view(struct backtrace_state *state, struct backtrace_view *view, backtrace_error_callback error_callback, void *data)
Definition read.c:102
#define backtrace_atomic_load_pointer(p)
Definition internal.h:115
const void * data
Definition internal.h:185
int(* fileline)(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
Definition internal.h:127
#define libbacktrace_add_base(pc, base)
Definition internal.h:361
const unsigned char * data[DEBUG_MAX]
Definition internal.h:323
@ DEBUG_RANGES
Definition internal.h:309
@ DEBUG_LINE
Definition internal.h:307
@ DEBUG_INFO
Definition internal.h:306
@ DEBUG_ABBREV
Definition internal.h:308
@ DEBUG_MAX
Definition internal.h:316
@ DEBUG_STR
Definition internal.h:310
int backtrace_close(int descriptor, backtrace_error_callback error_callback, void *data)
Definition posix.c:95
size_t size[DEBUG_MAX]
Definition internal.h:324
#define backtrace_atomic_store_pointer(p, v)
Definition internal.h:117
int backtrace_get_view(struct backtrace_state *state, int descriptor, off_t offset, uint64_t size, backtrace_error_callback error_callback, void *data, struct backtrace_view *view)
Definition read.c:48
int backtrace_open(const char *filename, backtrace_error_callback error_callback, void *data, int *does_not_exist)
Definition posix.c:59
#define __sync_bool_compare_and_swap(A, B, C)
Definition internal.h:77
unsigned short uint16_t
unsigned int uint32_t
unsigned char uint8_t
long long int off_t
unsigned long int size_t
static char const * name
void * state
Definition testlib.c:46
Functions to help with cleanup.
static fr_slen_t data
Definition value.h:1340
uint32_t f_timdat
Definition xcoff.c:78
#define C_FILE
Definition xcoff.c:180
#define C_BINCL
Definition xcoff.c:182
uint64_t f_symptr
Definition xcoff.c:79
#define C_EXT
Definition xcoff.c:178
struct xcoff_fileline_data * next
Definition xcoff.c:378
static void xcoff_syminfo(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr, backtrace_syminfo_callback callback, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data)
Definition xcoff.c:507
uint16_t f_flags
Definition xcoff.c:81
uint32_t f_nsyms
Definition xcoff.c:82
uint64_t s_scnptr
Definition xcoff.c:117
static int xcoff_lookup_pc(struct backtrace_state *state ATTRIBUTE_UNUSED, struct xcoff_fileline_data *fdata, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data, int *found)
Definition xcoff.c:726
#define F_SHROBJ
Definition xcoff.c:89
#define ISFCN(x)
Definition xcoff.c:186
#define LINESZ
Definition xcoff.c:258
static void xcoff_add_syminfo_data(struct backtrace_state *state, struct xcoff_syminfo_data *xdata)
Definition xcoff.c:465
#define AIAMAGBIG
Definition xcoff.c:270
size_t size
Definition xcoff.c:398
const char * name
Definition xcoff.c:301
static int xcoff_symbol_compare(const void *v1, const void *v2)
Definition xcoff.c:430
#define SSUBTYP_DWSTR
Definition xcoff.c:135
static int xcoff_func_search(const void *vkey, const void *ventry)
Definition xcoff.c:670
#define XCOFF_MAGIC
Definition xcoff.c:85
uint32_t l_lnno
Definition xcoff.c:255
#define AUXESZ
Definition xcoff.c:190
uint32_t s_nlnno
Definition xcoff.c:121
#define SSUBTYP_DWABREV
Definition xcoff.c:134
#define SSUBTYP_DWRNGES
Definition xcoff.c:136
#define C_FCN
Definition xcoff.c:179
uintptr_t lnnoptr
Definition xcoff.c:355
#define SYMNMLEN
Definition xcoff.c:140
uint64_t lnnoptr0
Definition xcoff.c:386
uintptr_t address
Definition xcoff.c:303
static void xcoff_nosyms(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr ATTRIBUTE_UNUSED, backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
Definition xcoff.c:419
char ar_namlen[4]
Definition xcoff.c:291
#define C_HIDEXT
Definition xcoff.c:181
uint64_t s_paddr
Definition xcoff.c:114
const char * filename
Definition xcoff.c:353
uint32_t s_nreloc
Definition xcoff.c:120
char ar_nxtmem[20]
Definition xcoff.c:285
uint64_t s_vaddr
Definition xcoff.c:115
static int xcoff_fileline(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
Definition xcoff.c:815
static int xcoff_incl_search(const void *vkey, const void *ventry)
Definition xcoff.c:705
struct xcoff_symbol * symbols
Definition xcoff.c:315
uint64_t s_lnnoptr
Definition xcoff.c:119
uintptr_t end
Definition xcoff.c:329
uint64_t s_size
Definition xcoff.c:116
#define STYP_DWARF
Definition xcoff.c:127
static int xcoff_nodebug(struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED, backtrace_full_callback callback ATTRIBUTE_UNUSED, backtrace_error_callback error_callback, void *data)
Definition xcoff.c:406
static int xcoff_initialize_fileline(struct backtrace_state *state, struct libbacktrace_base_address base_address, const b_xcoff_scnhdr *sects, const b_xcoff_syment *syms, size_t nsyms, const unsigned char *strtab, size_t strtab_size, const unsigned char *linenos, size_t linenos_size, uint64_t lnnoptr0, backtrace_error_callback error_callback, void *data)
Definition xcoff.c:864
int backtrace_initialize(struct backtrace_state *state, const char *filename ATTRIBUTE_UNUSED, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
Definition xcoff.c:1565
static int xcoff_symbol_search(const void *vkey, const void *ventry)
Definition xcoff.c:446
static int xcoff_incl_compare(const void *v1, const void *v2)
Definition xcoff.c:689
#define XCOFF_AIX_TEXTBASE
Definition xcoff.c:265
char ar_name[2]
Definition xcoff.c:292
#define STYP_OVRFLO
Definition xcoff.c:129
struct backtrace_vector vec
Definition xcoff.c:337
const char * name
Definition xcoff.c:351
#define FILNMLEN
Definition xcoff.c:191
const unsigned char * linenos
Definition xcoff.c:384
off_t offset
Definition xcoff.c:396
size_t size
Definition xcoff.c:305
#define SSUBTYP_DWLINE
Definition xcoff.c:132
static int xcoff_initialize_syminfo(struct backtrace_state *state, struct libbacktrace_base_address base_address, const b_xcoff_syment *syms, size_t nsyms, const unsigned char *strtab, size_t strtab_size, backtrace_error_callback error_callback, void *data, struct xcoff_syminfo_data *sdata)
Definition xcoff.c:588
uint16_t f_opthdr
Definition xcoff.c:80
#define C_WEAKEXT
Definition xcoff.c:184
uint64_t s_relptr
Definition xcoff.c:118
int lnno
Definition xcoff.c:359
uintptr_t pc
Definition xcoff.c:347
static int xcoff_add(struct backtrace_state *state, int descriptor, off_t offset, struct libbacktrace_base_address base_address, backtrace_error_callback error_callback, void *data, fileline *fileline_fn, int *found_sym, int exe)
Definition xcoff.c:1074
struct libbacktrace_base_address base_address
Definition xcoff.c:388
static const char * xcoff_symname(const b_xcoff_syment *asym, const unsigned char *strtab, size_t strtab_size)
Definition xcoff.c:565
#define SSUBTYP_DWINFO
Definition xcoff.c:131
uint32_t s_flags
Definition xcoff.c:122
uint16_t f_magic
Definition xcoff.c:76
struct backtrace_vector vec
Definition xcoff.c:368
union b_xcoff_lineno::@14 l_addr
const unsigned char * data
Definition xcoff.c:400
#define STYP_TEXT
Definition xcoff.c:128
size_t size
Definition xcoff.c:349
struct xcoff_incl_vector incl_vec
Definition xcoff.c:382
#define C_EINCL
Definition xcoff.c:183
static int xcoff_func_compare(const void *v1, const void *v2)
Definition xcoff.c:654
struct xcoff_func_vector func_vec
Definition xcoff.c:380
uintptr_t sect_base
Definition xcoff.c:357
uint16_t f_nscns
Definition xcoff.c:77
uintptr_t begin
Definition xcoff.c:327
struct xcoff_syminfo_data * next
Definition xcoff.c:313
const char * filename
Definition xcoff.c:325
size_t linenos_size
Definition xcoff.c:385