https://sourceware.org/bugzilla/show_bug.cgi?id=33658
Bug ID: 33658
Summary: eh_frame_hdr is not used if it comes after eh_frame
Product: elfutils
Version: unspecified
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: libdw
Assignee: unassigned at sourceware dot org
Reporter: shimin.guo at skydio dot com
CC: elfutils-devel at sourceware dot org
Target Milestone: ---
In the function getcfi_shdr in libdw/dwarf_getcfi_elf.c, the code calls
getcfi_scn_eh_frame immediately after seeing the .eh_frame section. If by that
time, it hasn't yet seen the .eh_frame_hdr, the search table in .eh_frame_hdr
will not be used, resulting in large performance penalty for large binaries.
We encountered the issue because we have a large binary created with the gold
linker with hundreds of thousands of FDEs, where .eh_frame_hdr comes after
.eh_frame. When using "perf script" on data the contains about 50k samples, the
current version takes more than an hour, whereas with a fix like the following
(not meant to be an actual patch, for illustration purposes only,) it takes
only seconds.
diff --git a/libdw/dwarf_getcfi_elf.c b/libdw/dwarf_getcfi_elf.c
index adcaea0..7625b69 100644
--- a/libdw/dwarf_getcfi_elf.c
+++ b/libdw/dwarf_getcfi_elf.c
@@ -282,6 +282,10 @@ getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
Elf_Scn *hdr_scn = NULL;
GElf_Addr hdr_vaddr = 0;
Elf_Scn *scn = NULL;
+ Elf_Scn *eh_frame_scn = NULL;
+ bool has_eh_frame_hdr = false;
+ bool has_eh_frame = false;
+ GElf_Shdr eh_frame_shdr_mem;
while ((scn = elf_nextscn (elf, scn)) != NULL)
{
GElf_Shdr shdr_mem;
@@ -293,20 +297,39 @@ getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
continue;
if (!strcmp (name, ".eh_frame_hdr"))
{
+ has_eh_frame_hdr = true;
hdr_scn = scn;
hdr_vaddr = shdr->sh_addr;
+ if (has_eh_frame)
+ {
+ return getcfi_scn_eh_frame (elf, ehdr, eh_frame_scn,
&eh_frame_shdr_mem,
+ hdr_scn, hdr_vaddr);
+ }
}
else if (!strcmp (name, ".eh_frame"))
{
+ has_eh_frame = true;
if (shdr->sh_type != SHT_NOBITS)
- return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
+ {
+ if (has_eh_frame_hdr)
+ {
+ return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
hdr_scn, hdr_vaddr);
+ }
+ else
+ {
+ eh_frame_scn = scn;
+ eh_frame_shdr_mem = *shdr;
+ }
+ }
else
return NULL;
}
- }
}
-
+ if (eh_frame_scn != NULL)
+ return getcfi_scn_eh_frame (elf, ehdr, eh_frame_scn, &eh_frame_shdr_mem,
+ hdr_scn, hdr_vaddr);
+ }
return (void *) -1l;
}
--
You are receiving this mail because:
You are on the CC list for the bug.