summaryrefslogtreecommitdiff
path: root/bfd/section.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2001-12-17 00:40:53 +0000
committerAlan Modra <amodra@bigpond.net.au>2001-12-17 00:40:53 +0000
commit19bfe0412bce6da812ba98b51eb61436b6820c34 (patch)
tree8d2b1c7841a9f6528cdcaa128a60480a2e41e4b7 /bfd/section.c
parent8b0e17d3af0ac1c6e3a9524c7e52207f412db86c (diff)
downloadgdb-19bfe0412bce6da812ba98b51eb61436b6820c34.tar.gz
hash bfd sections for fast lookup and create.
bfd/ChangeLog * bfd.c (struct _bfd): Add section_htab, section_tail. * libbfd-in.h (_bfd_delete_bfd): Declare. (bfd_section_hash_newfunc): Declare. * opncls.c (_bfd_new_bfd): Free memory on failure. Init section_htab and section_tail. (_bfd_delete_bfd): New function. (bfd_openr): Use it. (bfd_fdopenr): Likewise. (bfd_openstreamr): Likewise. (bfd_openw): Likewise. (bfd_close): Likewise. (bfd_close_all_done): Likewise. (bfd_release): Comment. * section.c (struct section_hash_entry): New. (bfd_section_hash_newfunc): New function. (section_hash_lookup): Define. (bfd_section_init): New function, split out from bfd_make_section_anyway. (bfd_get_section_by_name): Lookup via hash table. (bfd_get_unique_section_name): Likewise. (bfd_make_section_old_way): Rewrite to use hash table. (bfd_make_section_anyway): Likewise. (bfd_make_section): Likewise. Return NULL for attempts to make BFD_{ABS,COM,UND,IND}_SECTION_NAME. (_bfd_strip_section_from_output): Adjust section_tail if needed. * configure.in: Bump bfd version. * configure: Regenerate. * libbfd.h: Regenerate. * bfd-in2.h: Regenerate. ld/ChangeLog * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Adjust section_tail when fiddling with section list. (gld${EMULATION_NAME}_list_options): Ensure sentences aren't broken into separate strings to make translation easier. * emultempl/mmo.em (mmo_place_orphan): Adjust section_tail when fiddling with section list. * emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
Diffstat (limited to 'bfd/section.c')
-rw-r--r--bfd/section.c238
1 files changed, 160 insertions, 78 deletions
diff --git a/bfd/section.c b/bfd/section.c
index 903f769c913..73567d9f64e 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -629,6 +629,92 @@ STD_SECTION (bfd_abs_section, 0, bfd_abs_symbol, BFD_ABS_SECTION_NAME, 2);
STD_SECTION (bfd_ind_section, 0, bfd_ind_symbol, BFD_IND_SECTION_NAME, 3);
#undef STD_SECTION
+struct section_hash_entry
+{
+ struct bfd_hash_entry root;
+ asection section;
+};
+
+/* Initialize an entry in the section hash table. */
+
+struct bfd_hash_entry *
+bfd_section_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (entry == NULL)
+ {
+ entry = bfd_hash_allocate (table, sizeof (struct section_hash_entry));
+ if (entry == NULL)
+ return entry;
+ }
+
+ /* Call the allocation method of the superclass. */
+ entry = bfd_hash_newfunc (entry, table, string);
+ if (entry != NULL)
+ {
+ memset ((PTR) &((struct section_hash_entry *) entry)->section,
+ 0, sizeof (asection));
+ }
+
+ return entry;
+}
+
+#define section_hash_lookup(table, string, create, copy) \
+ ((struct section_hash_entry *) \
+ bfd_hash_lookup ((table), (string), (create), (copy)))
+
+/* Initializes a new section. NEWSECT->NAME is already set. */
+
+static asection *bfd_section_init PARAMS ((bfd *, asection *));
+
+static asection *
+bfd_section_init (abfd, newsect)
+ bfd *abfd;
+ asection *newsect;
+{
+ static int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
+
+ newsect->id = section_id;
+ newsect->index = abfd->section_count;
+ newsect->flags = SEC_NO_FLAGS;
+
+ newsect->userdata = NULL;
+ newsect->contents = NULL;
+ newsect->next = (asection *) NULL;
+ newsect->relocation = (arelent *) NULL;
+ newsect->reloc_count = 0;
+ newsect->line_filepos = 0;
+ newsect->owner = abfd;
+ newsect->comdat = NULL;
+
+ /* Create a symbol whose only job is to point to this section. This
+ is useful for things like relocs which are relative to the base
+ of a section. */
+ newsect->symbol = bfd_make_empty_symbol (abfd);
+ if (newsect->symbol == NULL)
+ return NULL;
+
+ newsect->symbol->name = newsect->name;
+ newsect->symbol->value = 0;
+ newsect->symbol->section = newsect;
+ newsect->symbol->flags = BSF_SECTION_SYM;
+
+ newsect->symbol_ptr_ptr = &newsect->symbol;
+
+ if (! BFD_SEND (abfd, _new_section_hook, (abfd, newsect)))
+ return NULL;
+
+ section_id++;
+ abfd->section_count++;
+ *abfd->section_tail = newsect;
+ abfd->section_tail = &newsect->next;
+ return newsect;
+}
+
/*
DOCDD
INODE
@@ -662,11 +748,12 @@ bfd_get_section_by_name (abfd, name)
bfd *abfd;
const char *name;
{
- asection *sect;
+ struct section_hash_entry *sh;
+
+ sh = section_hash_lookup (&abfd->section_htab, name, false, false);
+ if (sh != NULL)
+ return &sh->section;
- for (sect = abfd->sections; sect != NULL; sect = sect->next)
- if (!strcmp (sect->name, name))
- return sect;
return NULL;
}
@@ -713,7 +800,7 @@ bfd_get_unique_section_name (abfd, templat, count)
abort ();
sprintf (sname + len, ".%d", num++);
}
- while (bfd_get_section_by_name (abfd, sname) != NULL);
+ while (section_hash_lookup (&abfd->section_htab, sname, false, false));
if (count != NULL)
*count = num;
@@ -750,12 +837,40 @@ bfd_make_section_old_way (abfd, name)
bfd *abfd;
const char *name;
{
- asection *sec = bfd_get_section_by_name (abfd, name);
- if (sec == (asection *) NULL)
+ struct section_hash_entry *sh;
+ asection *newsect;
+
+ if (abfd->output_has_begun)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ if (strcmp (name, BFD_ABS_SECTION_NAME) == 0)
+ return bfd_abs_section_ptr;
+
+ if (strcmp (name, BFD_COM_SECTION_NAME) == 0)
+ return bfd_com_section_ptr;
+
+ if (strcmp (name, BFD_UND_SECTION_NAME) == 0)
+ return bfd_und_section_ptr;
+
+ if (strcmp (name, BFD_IND_SECTION_NAME) == 0)
+ return bfd_ind_section_ptr;
+
+ sh = section_hash_lookup (&abfd->section_htab, name, true, false);
+ if (sh == NULL)
+ return NULL;
+
+ newsect = &sh->section;
+ if (newsect->name != NULL)
{
- sec = bfd_make_section (abfd, name);
+ /* Section already exists. */
+ return newsect;
}
- return sec;
+
+ newsect->name = name;
+ return bfd_section_init (abfd, newsect);
}
/*
@@ -780,10 +895,8 @@ bfd_make_section_anyway (abfd, name)
bfd *abfd;
const char *name;
{
- static int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
+ struct section_hash_entry *sh;
asection *newsect;
- asection **prev = &abfd->sections;
- asection *sect = abfd->sections;
if (abfd->output_has_begun)
{
@@ -791,56 +904,24 @@ bfd_make_section_anyway (abfd, name)
return NULL;
}
- while (sect)
- {
- prev = &sect->next;
- sect = sect->next;
- }
-
- newsect = (asection *) bfd_zalloc (abfd, (bfd_size_type) sizeof (asection));
- if (newsect == NULL)
+ sh = section_hash_lookup (&abfd->section_htab, name, true, false);
+ if (sh == NULL)
return NULL;
- newsect->name = name;
- newsect->id = section_id;
- newsect->index = abfd->section_count;
- newsect->flags = SEC_NO_FLAGS;
-
- newsect->userdata = NULL;
- newsect->contents = NULL;
- newsect->next = (asection *) NULL;
- newsect->relocation = (arelent *) NULL;
- newsect->reloc_count = 0;
- newsect->line_filepos = 0;
- newsect->owner = abfd;
- newsect->comdat = NULL;
-
- /* Create a symbol whos only job is to point to this section. This is
- useful for things like relocs which are relative to the base of a
- section. */
- newsect->symbol = bfd_make_empty_symbol (abfd);
- if (newsect->symbol == NULL)
+ newsect = &sh->section;
+ if (newsect->name != NULL)
{
- bfd_release (abfd, newsect);
- return NULL;
- }
- newsect->symbol->name = name;
- newsect->symbol->value = 0;
- newsect->symbol->section = newsect;
- newsect->symbol->flags = BSF_SECTION_SYM;
-
- newsect->symbol_ptr_ptr = &newsect->symbol;
-
- if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true)
- {
- bfd_release (abfd, newsect);
- return NULL;
+ /* We are making a section of the same name. It can't go in
+ section_htab without generating a unique section name and
+ that would be pointless; We don't need to traverse the
+ hash table. */
+ newsect = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (newsect == NULL)
+ return NULL;
}
- section_id++;
- abfd->section_count++;
- *prev = newsect;
- return newsect;
+ newsect->name = name;
+ return bfd_section_init (abfd, newsect);
}
/*
@@ -862,35 +943,34 @@ bfd_make_section (abfd, name)
bfd *abfd;
const char *name;
{
- asection *sect = abfd->sections;
+ struct section_hash_entry *sh;
+ asection *newsect;
- if (strcmp (name, BFD_ABS_SECTION_NAME) == 0)
- {
- return bfd_abs_section_ptr;
- }
- if (strcmp (name, BFD_COM_SECTION_NAME) == 0)
- {
- return bfd_com_section_ptr;
- }
- if (strcmp (name, BFD_UND_SECTION_NAME) == 0)
+ if (abfd->output_has_begun)
{
- return bfd_und_section_ptr;
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
}
- if (strcmp (name, BFD_IND_SECTION_NAME) == 0)
- {
- return bfd_ind_section_ptr;
- }
+ if (strcmp (name, BFD_ABS_SECTION_NAME) == 0
+ || strcmp (name, BFD_COM_SECTION_NAME) == 0
+ || strcmp (name, BFD_UND_SECTION_NAME) == 0
+ || strcmp (name, BFD_IND_SECTION_NAME) == 0)
+ return NULL;
- while (sect)
+ sh = section_hash_lookup (&abfd->section_htab, name, true, false);
+ if (sh == NULL)
+ return NULL;
+
+ newsect = &sh->section;
+ if (newsect->name != NULL)
{
- if (!strcmp (sect->name, name))
- return NULL;
- sect = sect->next;
+ /* Section already exists. */
+ return newsect;
}
- /* The name is not already used; go ahead and make a new section. */
- return bfd_make_section_anyway (abfd, name);
+ newsect->name = name;
+ return bfd_section_init (abfd, newsect);
}
/*
@@ -1278,6 +1358,8 @@ _bfd_strip_section_from_output (info, s)
if (*spp == os)
{
*spp = os->next;
+ if (os->next == NULL)
+ os->owner->section_tail = spp;
os->owner->section_count--;
break;
}