summaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2004-05-07 15:33:36 +0000
committerH.J. Lu <hjl.tools@gmail.com>2004-05-07 15:33:36 +0000
commite4b17d5c7a6d8aed00816280dbed1f026b7be380 (patch)
tree4eb7ac0e5a0be68392fdab01f4dad72bcf446b7f /binutils
parent5f9b892013f7eacc96a3915f14005c59b5a1d3c5 (diff)
downloadbinutils-gdb-e4b17d5c7a6d8aed00816280dbed1f026b7be380.tar.gz
2004-05-07 H.J. Lu <hongjiu.lu@intel.com>
* readelf.c (section_groups): New. (group_count): New. (section_headers_groups): New. (process_section_groups): Populate group_count, section_groups and section_headers_groups. (process_unwind): Support section group. (process_object): Always call process_section_groups. Free section_groups and section_headers_groups.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog11
-rw-r--r--binutils/readelf.c138
2 files changed, 133 insertions, 16 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index bfeb69fdc0d..26298dc8861 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,14 @@
+2004-05-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ * readelf.c (section_groups): New.
+ (group_count): New.
+ (section_headers_groups): New.
+ (process_section_groups): Populate group_count, section_groups
+ and section_headers_groups.
+ (process_unwind): Support section group.
+ (process_object): Always call process_section_groups. Free
+ section_groups and section_headers_groups.
+
2004-04-30 H.J. Lu <hongjiu.lu@intel.com>
* readelf.c (process_section_headers): Use %3lu on sh_info.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 94a9bd0c108..5a4ad45276b 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -164,6 +164,23 @@ int do_arch;
int do_notes;
int is_32bit_elf;
+struct group_list
+{
+ struct group_list *next;
+ unsigned int section_index;
+};
+
+struct group
+{
+ struct group_list *root;
+ unsigned int group_index;
+};
+
+struct group *section_groups;
+size_t group_count = 0;
+
+struct group **section_headers_groups;
+
/* A dynamic array of flags indicating which sections require dumping. */
char *dump_sects = NULL;
unsigned int num_dump_sects = 0;
@@ -3732,9 +3749,7 @@ process_section_groups (FILE *file)
{
Elf_Internal_Shdr *section;
unsigned int i;
-
- if (!do_section_groups)
- return 1;
+ struct group *group;
if (elf_header.e_shnum == 0)
{
@@ -3750,10 +3765,33 @@ process_section_groups (FILE *file)
abort ();
}
+ section_headers_groups = calloc (elf_header.e_shnum,
+ sizeof (struct group *));
+
+ if (section_headers_groups == NULL)
+ {
+ error (_("Out of memory\n"));
+ return 0;
+ }
+
/* Scan the sections for the group section. */
for (i = 0, section = section_headers;
i < elf_header.e_shnum;
i++, section++)
+ if (section->sh_type == SHT_GROUP)
+ group_count++;
+
+ section_groups = calloc (group_count, sizeof (struct group));
+
+ if (section_groups == NULL)
+ {
+ error (_("Out of memory\n"));
+ return 0;
+ }
+
+ for (i = 0, section = section_headers, group = section_groups;
+ i < elf_header.e_shnum;
+ i++, section++)
{
if (section->sh_type == SHT_GROUP)
{
@@ -3805,24 +3843,54 @@ process_section_groups (FILE *file)
size = (section->sh_size / section->sh_entsize) - 1;
entry = byte_get (indices, 4);
indices += 4;
- printf ("\n%s group section `%s' [%s] contains %u sections:\n",
- get_group_flags (entry), name, group_name, size);
-
- printf (_(" [Index] Name\n"));
+
+ if (do_section_groups)
+ {
+ printf ("\n%s group section `%s' [%s] contains %u sections:\n",
+ get_group_flags (entry), name, group_name, size);
+
+ printf (_(" [Index] Name\n"));
+ }
+
+ group->group_index = i;
+
for (j = 0; j < size; j++)
{
+ struct group_list *g;
+
entry = byte_get (indices, 4);
indices += 4;
- sec = SECTION_HEADER (entry);
- printf (" [%5u] %s\n",
- entry, SECTION_NAME (sec));
+ if (section_headers_groups [SECTION_HEADER_INDEX (entry)]
+ != NULL)
+ {
+ error (_("section [%5u] already in group section [%5u]\n"),
+ entry, section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
+ continue;
+ }
+
+ section_headers_groups [SECTION_HEADER_INDEX (entry)]
+ = group;
+
+ if (do_section_groups)
+ {
+ sec = SECTION_HEADER (entry);
+ printf (" [%5u] %s\n",
+ entry, SECTION_NAME (sec));
+ }
+
+ g = xmalloc (sizeof (struct group_list));
+ g->section_index = entry;
+ g->next = group->root;
+ group->root = g;
}
if (strtab)
free (strtab);
if (start)
free (start);
+
+ group++;
}
}
@@ -4302,8 +4370,24 @@ process_unwind (FILE *file)
unwstart = i + 1;
len = sizeof (ELF_STRING_ia64_unwind_once) - 1;
- if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once,
- len) == 0)
+ if ((unwsec->sh_flags & SHF_GROUP) != 0)
+ {
+ /* We need to find which section group it is in. */
+ struct group_list *g = section_headers_groups [i]->root;
+
+ for (; g != NULL; g = g->next)
+ {
+ sec = SECTION_HEADER (g->section_index);
+ if (strcmp (SECTION_NAME (sec),
+ ELF_STRING_ia64_unwind_info) == 0)
+ break;
+ }
+
+ if (g == NULL)
+ i = elf_header.e_shnum;
+ }
+ else if (strncmp (SECTION_NAME (unwsec),
+ ELF_STRING_ia64_unwind_once, len) == 0)
{
/* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */
len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
@@ -10432,9 +10516,10 @@ process_object (char *file_name, FILE *file)
if (! process_file_header ())
return 1;
- if (! process_section_headers (file))
+ if (! process_section_headers (file)
+ || ! process_section_groups (file))
{
- /* Without loaded section headers we
+ /* Without loaded section headers and section groups we
cannot process lots of things. */
do_unwind = do_version = do_dump = do_arch = 0;
@@ -10457,8 +10542,6 @@ process_object (char *file_name, FILE *file)
process_section_contents (file);
- process_section_groups (file);
-
process_corefile_contents (file);
process_gnu_liblist (file);
@@ -10503,6 +10586,29 @@ process_object (char *file_name, FILE *file)
dynamic_syminfo = NULL;
}
+ if (section_headers_groups)
+ {
+ free (section_headers_groups);
+ section_headers_groups = NULL;
+ }
+
+ if (section_groups)
+ {
+ struct group_list *g, *next;
+
+ for (i = 0; i < group_count; i++)
+ {
+ for (g = section_groups [i].root; g != NULL; g = next)
+ {
+ next = g->next;
+ free (g);
+ }
+ }
+
+ free (section_groups);
+ section_groups = NULL;
+ }
+
return 0;
}