Based on patch by Max Filippov.
* internal.h: If FDPIC, #include <link.h> and/or <sys/link.h>.
(libbacktrace_using_fdpic): Define.
(struct libbacktrace_base_address): Define.
(libbacktrace_add_base): Define.
(backtrace_dwarf_add): Change base_address to struct
libbacktrace_base_address.
* dwarf.c (struct dwarf_data): Change base_address to struct
libbacktrace_base_address.
(add_ranges, find_address_ranges, build_ddress_map): Likewise.
(build_dwarf_data, build_dwarf_add): Likewise.
(add_low_high_range): Change base_address to struct
libbacktrace_base_address. Use libbacktrace_add_base.
(add_ranges_from_ranges, add_ranges_from_rnglists): Likewise.
(add_line): Use libbacktrace_add_base.
* elf.c (elf_initialize_syminfo): Change base_address to struct
libbacktrace_base_address. Use libbacktrace_add_base.
(elf_add): Change base_address to struct
libbacktrace_base_address.
(phdr_callback): Likewise. Initialize base_address.m.
(backtrace_initialize): If using FDPIC, don't call elf_add with
main executable; always use dl_iterate_phdr.
* macho.c (macho_add_symtab): Change base_address to struct
libbacktrace_base_address. Use libbacktrace_add_base.
(macho_syminfo): Change base_address to struct
libbacktrace_base_address.
(macho_add_fat, macho_add_dsym, macho_add): Likewise.
(backtrace_initialize): Likewise. Initialize base_address.m.
* pecoff.c (coff_initialize_syminfo): Change base_address to
struct libbacktrace_base_address. Use libbacktrace_add_base.
(coff_add): Change base_address to struct
libbacktrace_base_address. Initialize base_address.m.
struct dwarf_data *next;
/* The data for .gnu_debugaltlink. */
struct dwarf_data *altlink;
- /* The base address for this file. */
- uintptr_t base_address;
+ /* The base address mapping for this file. */
+ struct libbacktrace_base_address base_address;
/* A sorted list of address ranges. */
struct unit_addrs *addrs;
/* Number of address ranges in list. */
static int
add_low_high_range (struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
- struct unit *u, const struct pcrange *pcrange,
+ struct libbacktrace_base_address base_address,
+ int is_bigendian, struct unit *u,
+ const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state,
void *rdata, uintptr_t lowpc,
uintptr_t highpc,
/* Add in the base address of the module when recording PC values,
so that we can look up the PC directly. */
- lowpc += base_address;
- highpc += base_address;
+ lowpc = libbacktrace_add_base (lowpc, base_address);
+ highpc = libbacktrace_add_base (highpc, base_address);
return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);
}
add_ranges_from_ranges (
struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ struct libbacktrace_base_address base_address, int is_bigendian,
struct unit *u, uintptr_t base,
const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata,
base = (uintptr_t) high;
else
{
- if (!add_range (state, rdata,
- (uintptr_t) low + base + base_address,
- (uintptr_t) high + base + base_address,
- error_callback, data, vec))
+ uintptr_t rl, rh;
+
+ rl = libbacktrace_add_base ((uintptr_t) low + base, base_address);
+ rh = libbacktrace_add_base ((uintptr_t) high + base, base_address);
+ if (!add_range (state, rdata, rl, rh, error_callback, data, vec))
return 0;
}
}
add_ranges_from_rnglists (
struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ struct libbacktrace_base_address base_address, int is_bigendian,
struct unit *u, uintptr_t base,
const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata,
u->addrsize, is_bigendian, index,
error_callback, data, &high))
return 0;
- if (!add_range (state, rdata, low + base_address,
- high + base_address, error_callback, data,
- vec))
+ if (!add_range (state, rdata,
+ libbacktrace_add_base (low, base_address),
+ libbacktrace_add_base (high, base_address),
+ error_callback, data, vec))
return 0;
}
break;
error_callback, data, &low))
return 0;
length = read_uleb128 (&rnglists_buf);
- low += base_address;
+ low = libbacktrace_add_base (low, base_address);
if (!add_range (state, rdata, low, low + length,
error_callback, data, vec))
return 0;
low = read_uleb128 (&rnglists_buf);
high = read_uleb128 (&rnglists_buf);
- if (!add_range (state, rdata, low + base + base_address,
- high + base + base_address,
+ if (!add_range (state, rdata,
+ libbacktrace_add_base (low + base, base_address),
+ libbacktrace_add_base (high + base, base_address),
error_callback, data, vec))
return 0;
}
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
high = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
- if (!add_range (state, rdata, low + base_address,
- high + base_address, error_callback, data,
- vec))
+ if (!add_range (state, rdata,
+ libbacktrace_add_base (low, base_address),
+ libbacktrace_add_base (high, base_address),
+ error_callback, data, vec))
return 0;
}
break;
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
length = (uintptr_t) read_uleb128 (&rnglists_buf);
- low += base_address;
+ low = libbacktrace_add_base (low, base_address);
if (!add_range (state, rdata, low, low + length,
error_callback, data, vec))
return 0;
static int
add_ranges (struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ struct libbacktrace_base_address base_address, int is_bigendian,
struct unit *u, uintptr_t base, const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata,
uintptr_t lowpc, uintptr_t highpc,
read, 0 if there is some error. */
static int
-find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
+find_address_ranges (struct backtrace_state *state,
+ struct libbacktrace_base_address base_address,
struct dwarf_buf *unit_buf,
const struct dwarf_sections *dwarf_sections,
int is_bigendian, struct dwarf_data *altlink,
on success, 0 on failure. */
static int
-build_address_map (struct backtrace_state *state, uintptr_t base_address,
+build_address_map (struct backtrace_state *state,
+ struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian, struct dwarf_data *altlink,
backtrace_error_callback error_callback, void *data,
/* Add in the base address here, so that we can look up the PC
directly. */
- ln->pc = pc + ddata->base_address;
+ ln->pc = libbacktrace_add_base (pc, ddata->base_address);
ln->filename = filename;
ln->lineno = lineno;
static struct dwarf_data *
build_dwarf_data (struct backtrace_state *state,
- uintptr_t base_address,
+ struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *altlink,
int
backtrace_dwarf_add (struct backtrace_state *state,
- uintptr_t base_address,
+ struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *fileline_altlink,
static int
elf_initialize_syminfo (struct backtrace_state *state,
- uintptr_t base_address,
+ struct libbacktrace_base_address base_address,
const unsigned char *symtab_data, size_t symtab_size,
const unsigned char *strtab, size_t strtab_size,
backtrace_error_callback error_callback,
= *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr));
else
elf_symbols[j].address = sym->st_value;
- elf_symbols[j].address += base_address;
+ elf_symbols[j].address =
+ libbacktrace_add_base (elf_symbols[j].address, base_address);
elf_symbols[j].size = sym->st_size;
++j;
}
static int
elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const unsigned char *memory, size_t memory_size,
- uintptr_t base_address, struct elf_ppc64_opd_data *caller_opd,
+ struct libbacktrace_base_address base_address,
+ struct elf_ppc64_opd_data *caller_opd,
backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym, int *found_dwarf,
struct dwarf_data **fileline_entry, int exe, int debuginfo,
const char *filename;
int descriptor;
int does_not_exist;
+ struct libbacktrace_base_address base_address;
fileline elf_fileline_fn;
int found_dwarf;
return 0;
}
- if (elf_add (pd->state, filename, descriptor, NULL, 0, info->dlpi_addr, NULL,
+ base_address.m = info->dlpi_addr;
+ if (elf_add (pd->state, filename, descriptor, NULL, 0, base_address, NULL,
pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
&found_dwarf, NULL, 0, 0, NULL, 0))
{
fileline elf_fileline_fn = elf_nodebug;
struct phdr_data pd;
- ret = elf_add (state, filename, descriptor, NULL, 0, 0, NULL, error_callback,
- data, &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0,
- NULL, 0);
- if (!ret)
- return 0;
+ /* When using fdpic we must use dl_iterate_phdr for all modules, including
+ the main executable, so that we can get the right base address
+ mapping. */
+ if (!libbacktrace_using_fdpic ())
+ {
+ struct libbacktrace_base_address zero_base_address;
+
+ memset (&zero_base_address, 0, sizeof zero_base_address);
+ ret = elf_add (state, filename, descriptor, NULL, 0, zero_base_address,
+ NULL, error_callback, data, &elf_fileline_fn, &found_sym,
+ &found_dwarf, NULL, 1, 0, NULL, 0);
+ if (!ret)
+ return 0;
+ }
pd.state = state;
pd.error_callback = error_callback;
struct dwarf_data;
+/* The load address mapping. */
+
+#if defined(__FDPIC__) && defined(HAVE_DL_ITERATE_PHDR) && (defined(HAVE_LINK_H) || defined(HAVE_SYS_LINK_H))
+
+#ifdef HAVE_LINK_H
+ #include <link.h>
+#endif
+#ifdef HAVE_SYS_LINK_H
+ #include <sys/link.h>
+#endif
+
+#define libbacktrace_using_fdpic() (1)
+
+struct libbacktrace_base_address
+{
+ struct elf32_fdpic_loadaddr m;
+};
+
+#define libbacktrace_add_base(pc, base) \
+ ((uintptr_t) (__RELOC_POINTER ((pc), (base).m)))
+
+#else /* not _FDPIC__ */
+
+#define libbacktrace_using_fdpic() (0)
+
+struct libbacktrace_base_address
+{
+ uintptr_t m;
+};
+
+#define libbacktrace_add_base(pc, base) ((pc) + (base).m)
+
+#endif /* not _FDPIC__ */
+
/* Add file/line information for a DWARF module. */
extern int backtrace_dwarf_add (struct backtrace_state *state,
- uintptr_t base_address,
+ struct libbacktrace_base_address base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *fileline_altlink,
/* Forward declaration. */
static int macho_add (struct backtrace_state *, const char *, int, off_t,
- const unsigned char *, uintptr_t, int,
- backtrace_error_callback, void *, fileline *, int *);
+ const unsigned char *, struct libbacktrace_base_address,
+ int, backtrace_error_callback, void *, fileline *,
+ int *);
/* A dummy callback function used when we can't find any debug info. */
static int
macho_add_symtab (struct backtrace_state *state, int descriptor,
- uintptr_t base_address, int is_64,
+ struct libbacktrace_base_address base_address, int is_64,
off_t symoff, unsigned int nsyms, off_t stroff,
unsigned int strsize,
backtrace_error_callback error_callback, void *data)
if (name[0] == '_')
++name;
macho_symbols[j].name = name;
- macho_symbols[j].address = value + base_address;
+ macho_symbols[j].address = libbacktrace_add_base (value, base_address);
++j;
}
static int
macho_add_fat (struct backtrace_state *state, const char *filename,
int descriptor, int swapped, off_t offset,
- const unsigned char *match_uuid, uintptr_t base_address,
+ const unsigned char *match_uuid,
+ struct libbacktrace_base_address base_address,
int skip_symtab, uint32_t nfat_arch, int is_64,
backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym)
static int
macho_add_dsym (struct backtrace_state *state, const char *filename,
- uintptr_t base_address, const unsigned char *uuid,
+ struct libbacktrace_base_address base_address,
+ const unsigned char *uuid,
backtrace_error_callback error_callback, void *data,
fileline* fileline_fn)
{
static int
macho_add (struct backtrace_state *state, const char *filename, int descriptor,
off_t offset, const unsigned char *match_uuid,
- uintptr_t base_address, int skip_symtab,
+ struct libbacktrace_base_address base_address, int skip_symtab,
backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym)
{
c = _dyld_image_count ();
for (i = 0; i < c; ++i)
{
- uintptr_t base_address;
+ struct libbacktrace_base_address base_address;
const char *name;
int d;
fileline mff;
continue;
}
- base_address = _dyld_get_image_vmaddr_slide (i);
+ base_address.m = _dyld_get_image_vmaddr_slide (i);
mff = macho_nodebug;
if (!macho_add (state, name, d, 0, NULL, base_address, 0,
void *data, fileline *fileline_fn)
{
fileline macho_fileline_fn;
+ struct libbacktrace_base_address zero_base_address;
int found_sym;
macho_fileline_fn = macho_nodebug;
- if (!macho_add (state, filename, descriptor, 0, NULL, 0, 0,
+ memset (&zero_base_address, 0, sizeof zero_base_address);
+ if (!macho_add (state, filename, descriptor, 0, NULL, zero_base_address, 0,
error_callback, data, &macho_fileline_fn, &found_sym))
return 0;
static int
coff_initialize_syminfo (struct backtrace_state *state,
- uintptr_t base_address, int is_64,
- const b_coff_section_header *sects, size_t sects_num,
- const b_coff_external_symbol *syms, size_t syms_size,
- const unsigned char *strtab, size_t strtab_size,
+ struct libbacktrace_base_address base_address,
+ int is_64, const b_coff_section_header *sects,
+ size_t sects_num, const b_coff_external_symbol *syms,
+ size_t syms_size, const unsigned char *strtab,
+ size_t strtab_size,
backtrace_error_callback error_callback,
void *data, struct coff_syminfo_data *sdata)
{
secnum = coff_read2 (asym->section_number);
coff_sym->name = name;
- coff_sym->address = (coff_read4 (asym->value)
- + sects[secnum - 1].virtual_address
- + base_address);
+ coff_sym->address =
+ libbacktrace_add_base ((coff_read4 (asym->value)
+ + sects[secnum - 1].virtual_address),
+ base_address);
coff_sym++;
}
struct backtrace_view debug_view;
int debug_view_valid;
int is_64;
- uintptr_t image_base;
- uintptr_t base_address = 0;
+ struct libbacktrace_base_address image_base;
+ struct libbacktrace_base_address base_address;
struct dwarf_sections dwarf_sections;
*found_sym = 0;
(sects_view.data + fhdr.size_of_optional_header);
is_64 = 0;
+ memset (&image_base, 0, sizeof image_base);
if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
{
if (opt_hdr->magic == PE_MAGIC)
- image_base = opt_hdr->u.pe.image_base;
+ image_base.m = opt_hdr->u.pe.image_base;
else if (opt_hdr->magic == PEP_MAGIC)
{
- image_base = opt_hdr->u.pep.image_base;
+ image_base.m = opt_hdr->u.pep.image_base;
is_64 = 1;
}
else
goto fail;
}
}
- else
- image_base = 0;
/* Read the symbol table and the string table. */
+ (sections[i].offset - min_offset));
}
+ memset (&base_address, 0, sizeof base_address);
#ifdef HAVE_WINDOWS_H
- base_address = module_handle - image_base;
+ base_address.m = module_handle - image_base.m;
#endif
if (!backtrace_dwarf_add (state, base_address, &dwarf_sections,