53#if BACKTRACE_XCOFF_SIZE != 32 && BACKTRACE_XCOFF_SIZE != 64
54#error "Unknown BACKTRACE_XCOFF_SIZE"
59#if BACKTRACE_XCOFF_SIZE == 32
71#define XCOFF_MAGIC 0737
85#define XCOFF_MAGIC 0767
89#define F_SHROBJ 0x2000
93#if BACKTRACE_XCOFF_SIZE == 32
108#define _OVERFLOW_MARKER 65535
127#define STYP_DWARF 0x10
128#define STYP_TEXT 0x20
129#define STYP_OVRFLO 0x8000
131#define SSUBTYP_DWINFO 0x10000
132#define SSUBTYP_DWLINE 0x20000
133#define SSUBTYP_DWARNGE 0x50000
134#define SSUBTYP_DWABREV 0x60000
135#define SSUBTYP_DWSTR 0x70000
136#define SSUBTYP_DWRNGES 0x80000
142#if BACKTRACE_XCOFF_SIZE == 32
152#define n_name _u._name
153#define n_zeroes _u._s._zeroes
154#define n_offset_ _u._s._offset
186#define ISFCN(x) ((x) & 0x0020)
194#if BACKTRACE_XCOFF_SIZE == 32
214#if BACKTRACE_XCOFF_SIZE == 32
236#if BACKTRACE_XCOFF_SIZE == 32
262#if BACKTRACE_XCOFF_SIZE == 32
263#define XCOFF_AIX_TEXTBASE 0x10000000u
265#define XCOFF_AIX_TEXTBASE 0x100000000ul
270#define AIAMAGBIG "<bigaf>\n"
276 char fl_gst64off[20];
448 const uintptr_t *key = (
const uintptr_t *) vkey;
455 else if ((entry->
size == 0 && addr > entry->
address)
468 if (!
state->threaded)
516 if (!
state->threaded)
551 callback (
data, addr, NULL, 0, 0);
566 const unsigned char *strtab,
size_t strtab_size)
568#if BACKTRACE_XCOFF_SIZE == 32
569 if (asym->n_zeroes != 0)
575 return strdup (
name);
578 if (asym->n_sclass & 0x80)
580 if (asym->n_offset_ >= strtab_size)
582 return (
const char *) strtab + asym->n_offset_;
590 const b_xcoff_syment *syms,
size_t nsyms,
591 const unsigned char *strtab,
size_t strtab_size,
595 size_t xcoff_symbol_count;
596 size_t xcoff_symbol_size;
602 xcoff_symbol_count = 0;
603 for (i = 0; i < nsyms; ++i)
605 const b_xcoff_syment *asym = &syms[i];
608 &&
ISFCN (asym->n_type) && asym->n_numaux > 0 && asym->n_scnum > 0)
609 ++xcoff_symbol_count;
614 xcoff_symbol_size = xcoff_symbol_count *
sizeof (
struct xcoff_symbol);
618 if (xcoff_symbols == NULL)
622 for (i = 0; i < nsyms; ++i)
624 const b_xcoff_syment *asym = &syms[i];
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);
634 xcoff_symbols[j].
size = aux->x_fcn.x_fsize;
645 sdata->symbols = xcoff_symbols;
646 sdata->count = xcoff_symbol_count;
659 if (fn1->
pc < fn2->
pc)
661 else if (fn1->
pc > fn2->
pc)
672 const uintptr_t *key = (
const uintptr_t *) vkey;
679 else if ((entry->
size == 0 &&
pc > entry->
pc)
707 const uintptr_t *key = (
const uintptr_t *) vkey;
712 if (lnno < entry->
begin)
714 else if (lnno > entry->
end)
730 void *
data,
int *found)
735 const unsigned char *lineptr;
765 while (lineptr + LINESZ <= fdata->linenos + fdata->
linenos_size)
795 lnno += fn->
lnno - 1;
801 lnno += fn->
lnno - 1;
824 if (!
state->threaded)
832 if (ret != 0 || found)
849 if (ret != 0 || found)
858 return callback (
data, pc, NULL, 0, NULL);
867 const b_xcoff_syment *syms,
size_t nsyms,
868 const unsigned char *strtab,
size_t strtab_size,
875 const b_xcoff_syment *fsym;
876 const b_xcoff_auxent *aux;
881 uintptr_t lnno, lnnoptr;
890 memset (fdata, 0,
sizeof *fdata);
901 for (i = 0; i < nsyms; ++i)
903 const b_xcoff_syment *asym = &syms[i];
905 switch (asym->n_sclass)
908 begin = asym->n_value;
940 if (asym->n_numaux > 0 && strcmp (
filename,
".file") == 0)
942 aux = (
const b_xcoff_auxent *) (asym + 1);
943 if (aux->x_file._x.x_zeroes != 0)
951 else if (aux->x_file._x.x_offset < strtab_size)
952 filename = (
const char *) strtab + aux->x_file._x.x_offset;
964 if (!
ISFCN (asym->n_type) || asym->n_numaux == 0
965 || asym->n_scnum <= 0)
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)
975 fsize = aux->x_fcn.x_fsize;
980 if (asym->n_numaux == 0)
985 if (
name == NULL || strcmp (
name,
".bf") != 0)
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;
995 lnno = aux->x_block.x_lnno;
1014 i += asym->n_numaux;
1029 if (!
state->threaded)
1077 void *
data,
fileline *fileline_fn,
int *found_sym,
int exe)
1097 int sects_view_valid;
1098 int linenos_view_valid;
1099 int syms_view_valid;
1101 int dwarf_view_valid;
1108 sects_view_valid = 0;
1109 linenos_view_valid = 0;
1110 syms_view_valid = 0;
1112 dwarf_view_valid = 0;
1121 memcpy (&fhdr, fhdr_view.
data,
sizeof fhdr);
1134 if ((exe && (fhdr.f_flags &
F_SHROBJ))
1135 || (!exe && !(fhdr.f_flags &
F_SHROBJ)))
1143 offset +
sizeof (fhdr) + fhdr.f_opthdr,
1146 sects_view_valid = 1;
1150 for (i = 0; i < fhdr.f_nscns; ++i)
1151 if ((sects[i].s_flags & 0xffff) ==
STYP_TEXT)
1153 if (i == fhdr.f_nscns)
1172#if BACKTRACE_XCOFF_SIZE == 32
1173 if (nlnno == _OVERFLOW_MARKER)
1177 for (i = 0; i < fhdr.f_nscns; ++i)
1180 && sects[i].s_nlnno == sntext)
1191 if (fhdr.f_symptr != 0)
1198 syms_size = fhdr.f_nsyms *
sizeof (b_xcoff_syment);
1204 syms_view_valid = 1;
1207 (
const unsigned char *) syms_view.
data + syms_size,
1210 str_off = fhdr.f_symptr + syms_size;
1228 syms_view.
data, fhdr.f_nsyms,
1229 str_view.
data, str_size,
1246 memset (dwsect, 0,
sizeof dwsect);
1247 for (i = 0; i < fhdr.f_nscns; ++i)
1252 if ((sects[i].s_flags & 0xffff) !=
STYP_DWARF
1253 || sects[i].s_size == 0)
1256 switch (sects[i].s_flags & 0xffff0000)
1276 if (min_offset == 0 || (
off_t) sects[i].s_scnptr < min_offset)
1279 if (end > max_offset)
1284 if (min_offset != 0 && max_offset != 0)
1287 max_offset - min_offset,
1290 dwarf_view_valid = 1;
1294 if (dwsect[i].offset == 0)
1295 dwsect[i].
data = NULL;
1297 dwsect[i].
data = ((
const unsigned char *) dwarf_view.
data
1298 + (dwsect[i].
offset - min_offset));
1324 if (!dwarf_view_valid && fhdr.f_symptr != 0 && lnnoptr != 0)
1333 linenos_view_valid = 1;
1336 syms_view.
data, fhdr.f_nsyms,
1337 str_view.
data, str_size,
1338 linenos_view.
data, linenos_size,
1344 sects_view_valid = 0;
1345 if (syms_view_valid)
1347 syms_view_valid = 0;
1357 if (sects_view_valid)
1361 if (syms_view_valid)
1363 if (linenos_view_valid)
1365 if (dwarf_view_valid)
1367 if (descriptor != -1 && offset == 0)
1372#ifdef HAVE_LOADQUERY
1378xcoff_parse_decimal (
const char *buf,
size_t size,
off_t *off)
1383 if (size >=
sizeof str)
1385 memcpy (str, buf, size);
1387 *off = strtol (str, &end, 10);
1388 if (*end !=
'\0' && *end !=
' ')
1418 memcpy (&fl_hdr, view.data, sizeof (
b_ar_fl_hdr));
1422 if (memcmp (fl_hdr.fl_magic,
AIAMAGBIG, 8) != 0)
1425 memlen = strlen (member);
1428 if (!xcoff_parse_decimal (fl_hdr.fl_fstmoff,
sizeof fl_hdr.fl_fstmoff, &off))
1439 ar_hdr = (
const b_ar_hdr *) view.data;
1448 if (
len == memlen && !memcmp (ar_hdr->
ar_name, member, memlen))
1450 off = (off +
sizeof (
b_ar_hdr) + memlen + 1) & ~1;
1456 data, fileline_fn, found_sym, 0))
1486 const struct ld_info *ldinfo;
1488 unsigned int buflen;
1507 ret = loadquery (L_GETINFO, buf, buflen);
1512 while (ret == -1 && errno == ENOMEM);
1519 ldinfo = (
const struct ld_info *) buf;
1520 while ((
const char *) ldinfo < (
const char *) buf + buflen)
1524 if (*ldinfo->ldinfo_filename !=
'/')
1528 data, &does_not_exist);
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;
1539 xcoff_armem_add (
state, descriptor, base_address, member,
1545 fileline_fn, &lib_found_sym, 0);
1551 if (ldinfo->ldinfo_next == 0)
1553 ldinfo = (
const struct ld_info *) ((
const char *) ldinfo
1554 + ldinfo->ldinfo_next);
1575 memset (&zero_base_address, 0,
sizeof zero_base_address);
1581#ifdef HAVE_LOADQUERY
1586 if (!
state->threaded)
1590 else if (
state->syminfo_fn == NULL)
1602 if (!
state->threaded)
1605 *fileline_fn = xcoff_fileline_fn;
1613 *fileline_fn = xcoff_fileline_fn;
void * backtrace_vector_grow(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data, struct backtrace_vector *vec)
int backtrace_vector_release(struct backtrace_state *state ATTRIBUTE_UNUSED, struct backtrace_vector *vec, backtrace_error_callback error_callback, void *data)
void * backtrace_alloc(struct backtrace_state *state ATTRIBUTE_UNUSED, size_t size, backtrace_error_callback error_callback, void *data)
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)
void(* backtrace_syminfo_callback)(void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize)
void(* backtrace_error_callback)(void *data, const char *msg, int errnum)
int(* backtrace_full_callback)(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
static void error_callback(void *data, const char *msg, int errnum)
#define strncpy(_dst, _src, _len)
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)
void backtrace_qsort(void *base, size_t count, size_t size, int(*compar)(const void *, const void *))
void backtrace_release_view(struct backtrace_state *state, struct backtrace_view *view, backtrace_error_callback error_callback, void *data)
#define backtrace_atomic_load_pointer(p)
int(* fileline)(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
#define libbacktrace_add_base(pc, base)
const unsigned char * data[DEBUG_MAX]
int backtrace_close(int descriptor, backtrace_error_callback error_callback, void *data)
#define backtrace_atomic_store_pointer(p, v)
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)
int backtrace_open(const char *filename, backtrace_error_callback error_callback, void *data, int *does_not_exist)
#define __sync_bool_compare_and_swap(A, B, C)
Functions to help with cleanup.
struct xcoff_fileline_data * next
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)
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)
static void xcoff_add_syminfo_data(struct backtrace_state *state, struct xcoff_syminfo_data *xdata)
static int xcoff_symbol_compare(const void *v1, const void *v2)
static int xcoff_func_search(const void *vkey, const void *ventry)
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)
static int xcoff_fileline(struct backtrace_state *state, uintptr_t pc, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data)
static int xcoff_incl_search(const void *vkey, const void *ventry)
struct xcoff_symbol * symbols
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)
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)
int backtrace_initialize(struct backtrace_state *state, const char *filename ATTRIBUTE_UNUSED, int descriptor, backtrace_error_callback error_callback, void *data, fileline *fileline_fn)
static int xcoff_symbol_search(const void *vkey, const void *ventry)
static int xcoff_incl_compare(const void *v1, const void *v2)
#define XCOFF_AIX_TEXTBASE
struct backtrace_vector vec
const unsigned char * linenos
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)
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)
struct libbacktrace_base_address base_address
static const char * xcoff_symname(const b_xcoff_syment *asym, const unsigned char *strtab, size_t strtab_size)
struct backtrace_vector vec
union b_xcoff_lineno::@14 l_addr
const unsigned char * data
struct xcoff_incl_vector incl_vec
static int xcoff_func_compare(const void *v1, const void *v2)
struct xcoff_func_vector func_vec
struct xcoff_syminfo_data * next