libbacktrace: use real .opd for debuginfo on ppc64 v1 ABI

PR libbacktrace/114201
	* elf.c (elf_add): Add caller_opd parameter.  Change all callers.
	Release opd data after all recursive calls.
This commit is contained in:
Ian Lance Taylor 2024-03-01 18:50:03 -08:00
parent 306a4c3223
commit 282455d313

View File

@ -6501,8 +6501,9 @@ backtrace_uncompress_lzma (struct backtrace_state *state,
static int static int
elf_add (struct backtrace_state *state, const char *filename, int descriptor, elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const unsigned char *memory, size_t memory_size, const unsigned char *memory, size_t memory_size,
uintptr_t base_address, backtrace_error_callback error_callback, uintptr_t base_address, struct elf_ppc64_opd_data *caller_opd,
void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf, 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, struct dwarf_data **fileline_entry, int exe, int debuginfo,
const char *with_buildid_data, uint32_t with_buildid_size) const char *with_buildid_data, uint32_t with_buildid_size)
{ {
@ -6557,6 +6558,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
struct elf_view split_debug_view[DEBUG_MAX]; struct elf_view split_debug_view[DEBUG_MAX];
unsigned char split_debug_view_valid[DEBUG_MAX]; unsigned char split_debug_view_valid[DEBUG_MAX];
struct elf_ppc64_opd_data opd_data, *opd; struct elf_ppc64_opd_data opd_data, *opd;
int opd_view_valid;
struct dwarf_sections dwarf_sections; struct dwarf_sections dwarf_sections;
if (!debuginfo) if (!debuginfo)
@ -6584,6 +6586,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debug_view_valid = 0; debug_view_valid = 0;
memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid); memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);
opd = NULL; opd = NULL;
opd_view_valid = 0;
if (!elf_get_view (state, descriptor, memory, memory_size, 0, sizeof ehdr, if (!elf_get_view (state, descriptor, memory, memory_size, 0, sizeof ehdr,
error_callback, data, &ehdr_view)) error_callback, data, &ehdr_view))
@ -6867,9 +6870,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
opd->addr = shdr->sh_addr; opd->addr = shdr->sh_addr;
opd->data = (const char *) opd_data.view.view.data; opd->data = (const char *) opd_data.view.view.data;
opd->size = shdr->sh_size; opd->size = shdr->sh_size;
opd_view_valid = 1;
} }
} }
// A debuginfo file may not have a useful .opd section, but we can use the
// one from the original executable.
if (opd == NULL)
opd = caller_opd;
if (symtab_shndx == 0) if (symtab_shndx == 0)
symtab_shndx = dynsym_shndx; symtab_shndx = dynsym_shndx;
if (symtab_shndx != 0) if (symtab_shndx != 0)
@ -6948,9 +6957,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
elf_release_view (state, &debuglink_view, error_callback, data); elf_release_view (state, &debuglink_view, error_callback, data);
if (debugaltlink_view_valid) if (debugaltlink_view_valid)
elf_release_view (state, &debugaltlink_view, error_callback, data); elf_release_view (state, &debugaltlink_view, error_callback, data);
ret = elf_add (state, "", d, NULL, 0, base_address, error_callback, ret = elf_add (state, "", d, NULL, 0, base_address, opd,
data, fileline_fn, found_sym, found_dwarf, NULL, 0, error_callback, data, fileline_fn, found_sym,
1, NULL, 0); found_dwarf, NULL, 0, 1, NULL, 0);
if (ret < 0) if (ret < 0)
backtrace_close (d, error_callback, data); backtrace_close (d, error_callback, data);
else if (descriptor >= 0) else if (descriptor >= 0)
@ -6965,12 +6974,6 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
buildid_view_valid = 0; buildid_view_valid = 0;
} }
if (opd)
{
elf_release_view (state, &opd->view, error_callback, data);
opd = NULL;
}
if (debuglink_name != NULL) if (debuglink_name != NULL)
{ {
int d; int d;
@ -6985,9 +6988,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
elf_release_view (state, &debuglink_view, error_callback, data); elf_release_view (state, &debuglink_view, error_callback, data);
if (debugaltlink_view_valid) if (debugaltlink_view_valid)
elf_release_view (state, &debugaltlink_view, error_callback, data); elf_release_view (state, &debugaltlink_view, error_callback, data);
ret = elf_add (state, "", d, NULL, 0, base_address, error_callback, ret = elf_add (state, "", d, NULL, 0, base_address, opd,
data, fileline_fn, found_sym, found_dwarf, NULL, 0, error_callback, data, fileline_fn, found_sym,
1, NULL, 0); found_dwarf, NULL, 0, 1, NULL, 0);
if (ret < 0) if (ret < 0)
backtrace_close (d, error_callback, data); backtrace_close (d, error_callback, data);
else if (descriptor >= 0) else if (descriptor >= 0)
@ -7013,7 +7016,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
{ {
int ret; int ret;
ret = elf_add (state, filename, d, NULL, 0, base_address, ret = elf_add (state, filename, d, NULL, 0, base_address, opd,
error_callback, data, fileline_fn, found_sym, error_callback, data, fileline_fn, found_sym,
found_dwarf, &fileline_altlink, 0, 1, found_dwarf, &fileline_altlink, 0, 1,
debugaltlink_buildid_data, debugaltlink_buildid_size); debugaltlink_buildid_data, debugaltlink_buildid_size);
@ -7050,7 +7053,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (ret) if (ret)
{ {
ret = elf_add (state, filename, -1, gnu_debugdata_uncompressed, ret = elf_add (state, filename, -1, gnu_debugdata_uncompressed,
gnu_debugdata_uncompressed_size, base_address, gnu_debugdata_uncompressed_size, base_address, opd,
error_callback, data, fileline_fn, found_sym, error_callback, data, fileline_fn, found_sym,
found_dwarf, NULL, 0, 0, NULL, 0); found_dwarf, NULL, 0, 0, NULL, 0);
if (ret >= 0 && descriptor >= 0) if (ret >= 0 && descriptor >= 0)
@ -7059,6 +7062,13 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
} }
} }
if (opd_view_valid)
{
elf_release_view (state, &opd->view, error_callback, data);
opd_view_valid = 0;
opd = NULL;
}
/* Read all the debug sections in a single view, since they are /* Read all the debug sections in a single view, since they are
probably adjacent in the file. If any of sections are probably adjacent in the file. If any of sections are
uncompressed, we never release this view. */ uncompressed, we never release this view. */
@ -7305,7 +7315,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (split_debug_view_valid[i]) if (split_debug_view_valid[i])
elf_release_view (state, &split_debug_view[i], error_callback, data); elf_release_view (state, &split_debug_view[i], error_callback, data);
} }
if (opd) if (opd_view_valid)
elf_release_view (state, &opd->view, error_callback, data); elf_release_view (state, &opd->view, error_callback, data);
if (descriptor >= 0) if (descriptor >= 0)
backtrace_close (descriptor, error_callback, data); backtrace_close (descriptor, error_callback, data);
@ -7369,7 +7379,7 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
return 0; return 0;
} }
if (elf_add (pd->state, filename, descriptor, NULL, 0, info->dlpi_addr, if (elf_add (pd->state, filename, descriptor, NULL, 0, info->dlpi_addr, NULL,
pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym, pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
&found_dwarf, NULL, 0, 0, NULL, 0)) &found_dwarf, NULL, 0, 0, NULL, 0))
{ {
@ -7398,9 +7408,9 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
fileline elf_fileline_fn = elf_nodebug; fileline elf_fileline_fn = elf_nodebug;
struct phdr_data pd; struct phdr_data pd;
ret = elf_add (state, filename, descriptor, NULL, 0, 0, error_callback, data, ret = elf_add (state, filename, descriptor, NULL, 0, 0, NULL, error_callback,
&elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, NULL, data, &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0,
0); NULL, 0);
if (!ret) if (!ret)
return 0; return 0;