Add support for files that contain multiple symbol index tables. Fixes PR 15835
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 4d19e6fb1376c0294ce8370ca9ddd500eff2eea1..bbf5b0222fee10c96501eb4c5ce2a8d55af2a0c5 100644 (file)
 #define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER))
 #endif
 
+typedef struct elf_section_list
+{
+  Elf_Internal_Shdr * hdr;
+  struct elf_section_list * next;
+} elf_section_list;
+
 char * program_name = "readelf";
 static unsigned long archive_file_offset;
 static unsigned long archive_file_size;
@@ -188,7 +194,7 @@ static Elf_Internal_Ehdr elf_header;
 static Elf_Internal_Shdr * section_headers;
 static Elf_Internal_Phdr * program_headers;
 static Elf_Internal_Dyn *  dynamic_section;
-static Elf_Internal_Shdr * symtab_shndx_hdr;
+static elf_section_list * symtab_shndx_list;
 static int show_name;
 static int do_dynamic;
 static int do_syms;
@@ -4984,27 +4990,30 @@ get_32bit_elf_symbols (FILE * file,
   if (esyms == NULL)
     goto exit_point;
 
-  shndx = NULL;
-  if (symtab_shndx_hdr != NULL
-      && (symtab_shndx_hdr->sh_link
-         == (unsigned long) (section - section_headers)))
-    {
-      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
-                                                   symtab_shndx_hdr->sh_offset,
-                                                   1, symtab_shndx_hdr->sh_size,
-                                                   _("symbol table section indicies"));
-      if (shndx == NULL)
-       goto exit_point;
-      /* PR17531: file: heap-buffer-overflow */
-      else if (symtab_shndx_hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-       {
-         error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
-                printable_section_name (symtab_shndx_hdr),
-                (unsigned long) symtab_shndx_hdr->sh_size,
-                (unsigned long) section->sh_size);
-         goto exit_point;
+  {
+    elf_section_list * entry;
+
+    shndx = NULL;
+    for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
+      if (entry->hdr->sh_link == (unsigned long) (section - section_headers))
+       {
+         shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
+                                                      entry->hdr->sh_offset,
+                                                      1, entry->hdr->sh_size,
+                                                      _("symbol table section indicies"));
+         if (shndx == NULL)
+           goto exit_point;
+         /* PR17531: file: heap-buffer-overflow */
+         else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+           {
+             error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+                    printable_section_name (entry->hdr),
+                    (unsigned long) entry->hdr->sh_size,
+                    (unsigned long) section->sh_size);
+             goto exit_point;
+           }
        }
-    }
+  }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
@@ -5094,25 +5103,30 @@ get_64bit_elf_symbols (FILE * file,
   if (!esyms)
     goto exit_point;
 
-  if (symtab_shndx_hdr != NULL
-      && (symtab_shndx_hdr->sh_link
-         == (unsigned long) (section - section_headers)))
-    {
-      shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
-                                                   symtab_shndx_hdr->sh_offset,
-                                                   1, symtab_shndx_hdr->sh_size,
-                                                   _("symbol table section indicies"));
-      if (shndx == NULL)
-       goto exit_point;
-      else if (symtab_shndx_hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
-       {
-         error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
-                printable_section_name (symtab_shndx_hdr),
-                (unsigned long) symtab_shndx_hdr->sh_size,
-                (unsigned long) section->sh_size);
-         goto exit_point;
+  {
+    elf_section_list * entry;
+
+    shndx = NULL;
+    for (entry = symtab_shndx_list; entry != NULL; entry = entry->next)
+      if (entry->hdr->sh_link == (unsigned long) (section - section_headers))
+       {
+         shndx = (Elf_External_Sym_Shndx *) get_data (NULL, file,
+                                                      entry->hdr->sh_offset,
+                                                      1, entry->hdr->sh_size,
+                                                      _("symbol table section indicies"));
+         if (shndx == NULL)
+           goto exit_point;
+         /* PR17531: file: heap-buffer-overflow */
+         else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+           {
+             error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+                    printable_section_name (entry->hdr),
+                    (unsigned long) entry->hdr->sh_size,
+                    (unsigned long) section->sh_size);
+             goto exit_point;
+           }
        }
-    }
+  }
 
   isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
 
@@ -5470,7 +5484,7 @@ process_section_headers (FILE * file)
   dynamic_symbols = NULL;
   dynamic_strings = NULL;
   dynamic_syminfo = NULL;
-  symtab_shndx_hdr = NULL;
+  symtab_shndx_list = NULL;
 
   eh_addr_size = is_32bit_elf ? 4 : 8;
   switch (elf_header.e_machine)
@@ -5575,12 +5589,10 @@ process_section_headers (FILE * file)
        }
       else if (section->sh_type == SHT_SYMTAB_SHNDX)
        {
-         if (symtab_shndx_hdr != NULL)
-           {
-             error (_("File contains multiple symtab shndx tables\n"));
-             continue;
-           }
-         symtab_shndx_hdr = section;
+         elf_section_list * entry = xmalloc (sizeof * entry);
+         entry->hdr = section;
+         entry->next = symtab_shndx_list;
+         symtab_shndx_list = entry;
        }
       else if (section->sh_type == SHT_SYMTAB)
        CHECK_ENTSIZE (section, i, Sym);
This page took 0.027815 seconds and 4 git commands to generate.