]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: Make sure to get .eh_frame_hdr with .eh_frame in getcfi_shdr users/mark/try-getcfi_shdr
authorMark Wielaard <mark@klomp.org>
Fri, 5 Dec 2025 15:13:32 +0000 (16:13 +0100)
committerMark Wielaard <mark@klomp.org>
Fri, 5 Dec 2025 15:24:52 +0000 (16:24 +0100)
If we find a .eh_frame section we want to make sure to also get the
search table section .eh_frame_hdr. Otherwise lookups will be very
slow. Only create a Dwarf_CFI without a search table as a last resort.

* libdw/dwarf_getcfi_elf.c (getcfi_shdr): Keep iterating
        through the shdrs till both .eh_frame and .eh_frame_hdr are
        found. Check both aren't SHT_NOBITS.

Suggested-by: Shimin Guo <shimin.guo@skydio.com>
Signed-off-by: Mark Wielaard <mark@klomp.org>
libdw/dwarf_getcfi_elf.c

index c0e3cadd24894637216422e1ed88515087f9a701..5b510653768889d22c55371f9daca216120524f3 100644 (file)
@@ -281,6 +281,8 @@ getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
 
   if (shstrndx != 0)
     {
+      Elf_Scn *eh_scn = NULL;
+      GElf_Shdr eh_shdr_mem;
       Elf_Scn *hdr_scn = NULL;
       GElf_Addr hdr_vaddr = 0;
       Elf_Scn *scn = NULL;
@@ -295,18 +297,38 @@ getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
            continue;
          if (!strcmp (name, ".eh_frame_hdr"))
            {
-             hdr_scn = scn;
-             hdr_vaddr = shdr->sh_addr;
+             if (shdr->sh_type != SHT_NOBITS)
+               {
+                 hdr_scn = scn;
+                 hdr_vaddr = shdr->sh_addr;
+
+                 if (eh_scn != NULL)
+                   return getcfi_scn_eh_frame (elf, ehdr,
+                                               eh_scn, &eh_shdr_mem,
+                                               hdr_scn, hdr_vaddr);
+               }
            }
          else if (!strcmp (name, ".eh_frame"))
            {
              if (shdr->sh_type != SHT_NOBITS)
-               return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
-                                           hdr_scn, hdr_vaddr);
-             else
-               return NULL;
+               {
+                 eh_scn = scn;
+                 eh_shdr_mem = *shdr;
+
+                 if (hdr_scn != NULL)
+                   return getcfi_scn_eh_frame (elf, ehdr,
+                                               eh_scn, &eh_shdr_mem,
+                                               hdr_scn, hdr_vaddr);
+               }
            }
        }
+
+      /* .eh_frame without .eh_frame_hdr will be slow, might want to
+        generate our own search table?  */
+      if (eh_scn != NULL)
+       return getcfi_scn_eh_frame (elf, ehdr,
+                                   eh_scn, &eh_shdr_mem,
+                                   NULL, 0);
     }
 
   return (void *) -1l;