RFC: Don't use section name to set ELF section data
H. J. Lu
hjl@lucon.org
Sat Jun 14 19:14:00 GMT 2003
Here is my first attempt. It passed "make check" on Linux/i386. I'd
like to know if I am on the right track before I finish my work.
H.J.
-------------- next part --------------
bfd/
2003-06-14 H.J. Lu <hongjiu.lu@intel.com>
* elf-bfd.h (elf_section_type). New.
(elf_section_flags): New.
* elf.c (special_section): New.
(_bfd_elf_new_section_hook): Check special_section to set
elf_section_type and elf_section_flags.
(elf_fake_sections): Don't use section name to set ELF section
data.
* section.c (bfd_abs_section): Remove const.
(bfd_und_section): Likewise.
(bfd_com_section): Likewise.
(bfd_ind_section): Likewise.
gas/
2003-06-14 H.J. Lu <hongjiu.lu@intel.com>
* config/obj-elf.c (elf_get_sec_type_attr): New function.
(special_section): Updated.
(elf_sec_set_private_data): New function.
(obj_elf_change_section): Call elf_get_sec_type_attr. Set
elf_section_type and elf_section_flags.
(obj_elf_section): Initialize type to -1.
(elf_frob_file): Set SHT_GROUP.
* config/obj-elf.h (obj_sec_set_private_data): New.
(elf_sec_set_private_data): Declared.
* subsegs.c (subseg_get): Call obj_sec_set_private_data if it
is defined.
--- binutils/bfd/elf-bfd.h.type 2003-06-13 08:34:09.000000000 -0700
+++ binutils/bfd/elf-bfd.h 2003-06-14 09:55:40.000000000 -0700
@@ -1050,6 +1050,8 @@ struct bfd_elf_section_data
};
#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
+#define elf_section_type(sec) (elf_section_data(sec)->this_hdr.sh_type)
+#define elf_section_flags(sec) (elf_section_data(sec)->this_hdr.sh_flags)
#define elf_group_name(sec) (elf_section_data(sec)->group.name)
#define elf_group_id(sec) (elf_section_data(sec)->group.id)
#define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group)
--- binutils/bfd/elf.c.type 2003-06-13 08:34:09.000000000 -0700
+++ binutils/bfd/elf.c 2003-06-14 11:56:22.000000000 -0700
@@ -2231,6 +2231,35 @@ bfd_section_from_elf_index (abfd, index)
return elf_elfsections (abfd)[index]->bfd_section;
}
+struct special_section
+{
+ const char *name;
+ int type;
+ int attributes;
+ size_t length;
+};
+
+static struct special_section const special_sections[] =
+{
+ { ".dynamic", SHT_DYNAMIC, SHF_ALLOC, 0},
+ { ".dynstr", SHT_STRTAB, SHF_ALLOC, 0},
+ { ".dynsym", SHT_DYNSYM, SHF_ALLOC, 0},
+ { ".got", SHT_PROGBITS, 0, 0},
+ { ".hash", SHT_HASH, SHF_ALLOC, 0},
+ { ".interp", SHT_PROGBITS, 0, 0},
+ { ".plt", SHT_PROGBITS, 0, 0},
+ { ".shstrtab",SHT_STRTAB, 0, 0},
+ { ".strtab", SHT_STRTAB, 0, 0},
+ { ".symtab", SHT_SYMTAB, 0, 0},
+ { ".gnu.version",SHT_GNU_versym,0, 0},
+ { ".gnu.version_d",SHT_GNU_verdef,0, 0},
+ { ".gnu.version_r",SHT_GNU_verneed,0, 0},
+ { ".note", SHT_NOTE, 0, 5},
+ { ".rel", SHT_REL, 0, 4},
+ { ".rela", SHT_RELA, 0, 5},
+ { NULL, 0, 0, 0}
+};
+
bfd_boolean
_bfd_elf_new_section_hook (abfd, sec)
bfd *abfd;
@@ -2241,11 +2270,37 @@ _bfd_elf_new_section_hook (abfd, sec)
sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
if (sdata == NULL)
{
+ int i;
+
bfd_size_type amt = sizeof (*sdata);
sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt);
if (sdata == NULL)
return FALSE;
sec->used_by_bfd = (PTR) sdata;
+
+ /* See if this is one of the special sections. */
+ for (i = 0; special_sections[i].name != NULL; i++)
+ if (sec->name
+ && ((special_sections[i].length
+ && strncmp (sec->name, special_sections[i].name,
+ special_sections[i].length) == 0)
+ || strcmp (sec->name, special_sections[i].name) == 0))
+ {
+ elf_section_type (sec) = special_sections[i].type;
+ elf_section_flags (sec) = special_sections[i].attributes;
+ break;
+ }
+
+ if (special_sections[i].name == NULL)
+ {
+ if (strncmp (sec->name, ".stab", 5) == 0
+ && strcmp (sec->name
+ + strlen (sec->name) - 3, "str") == 0)
+ elf_section_type (sec) = SHT_STRTAB;
+ }
+
+ if (!elf_section_type (sec))
+ elf_section_type (sec) = (unsigned int) -1;
}
/* Indicate whether or not this section should use RELA relocations. */
@@ -2486,55 +2541,52 @@ elf_fake_sections (abfd, asect, failedpt
this_hdr->bfd_section = asect;
this_hdr->contents = NULL;
- /* FIXME: This should not be based on section names. */
- if (strcmp (asect->name, ".dynstr") == 0)
- this_hdr->sh_type = SHT_STRTAB;
- else if (strcmp (asect->name, ".hash") == 0)
+ switch (this_hdr->sh_type)
{
- this_hdr->sh_type = SHT_HASH;
+ default:
+ (*_bfd_error_handler)
+ (_("%s: Section `%s' has unknown type 0x%0x"),
+ bfd_get_filename (asect->owner), asect->name,
+ this_hdr->sh_type);
+ abort ();
+ break;
+
+ case SHT_STRTAB:
+ case SHT_INIT_ARRAY:
+ case SHT_FINI_ARRAY:
+ case SHT_PREINIT_ARRAY:
+ case SHT_NOTE:
+ case SHT_NOBITS:
+ case SHT_PROGBITS:
+ break;
+
+ case SHT_HASH:
this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
- }
- else if (strcmp (asect->name, ".dynsym") == 0)
- {
- this_hdr->sh_type = SHT_DYNSYM;
+ break;
+
+ case SHT_DYNSYM:
this_hdr->sh_entsize = bed->s->sizeof_sym;
- }
- else if (strcmp (asect->name, ".dynamic") == 0)
- {
- this_hdr->sh_type = SHT_DYNAMIC;
+ break;
+
+ case SHT_DYNAMIC:
this_hdr->sh_entsize = bed->s->sizeof_dyn;
- }
- else if (strncmp (asect->name, ".rela", 5) == 0
- && get_elf_backend_data (abfd)->may_use_rela_p)
- {
- this_hdr->sh_type = SHT_RELA;
- this_hdr->sh_entsize = bed->s->sizeof_rela;
- }
- else if (strncmp (asect->name, ".rel", 4) == 0
- && get_elf_backend_data (abfd)->may_use_rel_p)
- {
- this_hdr->sh_type = SHT_REL;
- this_hdr->sh_entsize = bed->s->sizeof_rel;
- }
- else if (strcmp (asect->name, ".init_array") == 0)
- this_hdr->sh_type = SHT_INIT_ARRAY;
- else if (strcmp (asect->name, ".fini_array") == 0)
- this_hdr->sh_type = SHT_FINI_ARRAY;
- else if (strcmp (asect->name, ".preinit_array") == 0)
- this_hdr->sh_type = SHT_PREINIT_ARRAY;
- else if (strncmp (asect->name, ".note", 5) == 0)
- this_hdr->sh_type = SHT_NOTE;
- else if (strncmp (asect->name, ".stab", 5) == 0
- && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
- this_hdr->sh_type = SHT_STRTAB;
- else if (strcmp (asect->name, ".gnu.version") == 0)
- {
- this_hdr->sh_type = SHT_GNU_versym;
+ break;
+
+ case SHT_RELA:
+ if (get_elf_backend_data (abfd)->may_use_rela_p)
+ this_hdr->sh_entsize = bed->s->sizeof_rela;
+ break;
+
+ case SHT_REL:
+ if (get_elf_backend_data (abfd)->may_use_rel_p)
+ this_hdr->sh_entsize = bed->s->sizeof_rel;
+ break;
+
+ case SHT_GNU_versym:
this_hdr->sh_entsize = sizeof (Elf_External_Versym);
- }
- else if (strcmp (asect->name, ".gnu.version_d") == 0)
- {
- this_hdr->sh_type = SHT_GNU_verdef;
+ break;
+
+ case SHT_GNU_verdef:
this_hdr->sh_entsize = 0;
/* objcopy or strip will copy over sh_info, but may not set
cverdefs. The linker will set cverdefs, but sh_info will be
@@ -2544,10 +2596,9 @@ elf_fake_sections (abfd, asect, failedpt
else
BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
- }
- else if (strcmp (asect->name, ".gnu.version_r") == 0)
- {
- this_hdr->sh_type = SHT_GNU_verneed;
+ break;
+
+ case SHT_GNU_verneed:
this_hdr->sh_entsize = 0;
/* objcopy or strip will copy over sh_info, but may not set
cverrefs. The linker will set cverrefs, but sh_info will be
@@ -2557,18 +2608,21 @@ elf_fake_sections (abfd, asect, failedpt
else
BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
- }
- else if ((asect->flags & SEC_GROUP) != 0)
- {
- this_hdr->sh_type = SHT_GROUP;
+ break;
+
+ case SHT_GROUP:
this_hdr->sh_entsize = 4;
- }
- else if ((asect->flags & SEC_ALLOC) != 0
- && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ break;
+
+ case (unsigned int) -1:
+ if ((asect->flags & SEC_ALLOC) != 0
+ && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|| (asect->flags & SEC_NEVER_LOAD) != 0))
- this_hdr->sh_type = SHT_NOBITS;
- else
- this_hdr->sh_type = SHT_PROGBITS;
+ this_hdr->sh_type = SHT_NOBITS;
+ else
+ this_hdr->sh_type = SHT_PROGBITS;
+ break;
+ }
if ((asect->flags & SEC_ALLOC) != 0)
this_hdr->sh_flags |= SHF_ALLOC;
--- binutils/bfd/section.c.type 2003-06-13 09:41:32.000000000 -0700
+++ binutils/bfd/section.c 2003-06-14 09:47:21.000000000 -0700
@@ -532,18 +532,18 @@ CODE_FRAGMENT
.#define BFD_IND_SECTION_NAME "*IND*"
.
.{* The absolute section. *}
-.extern const asection bfd_abs_section;
+.extern asection bfd_abs_section;
.#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
.#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
.{* Pointer to the undefined section. *}
-.extern const asection bfd_und_section;
+.extern asection bfd_und_section;
.#define bfd_und_section_ptr ((asection *) &bfd_und_section)
.#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
.{* Pointer to the common section. *}
-.extern const asection bfd_com_section;
+.extern asection bfd_com_section;
.#define bfd_com_section_ptr ((asection *) &bfd_com_section)
.{* Pointer to the indirect section. *}
-.extern const asection bfd_ind_section;
+.extern asection bfd_ind_section;
.#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
.#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
.
@@ -616,7 +616,7 @@ static const asymbol global_syms[] =
#define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \
const asymbol * const SYM = (asymbol *) &global_syms[IDX]; \
- const asection SEC = \
+ asection SEC = \
/* name, id, index, next, flags, user_set_vma, reloc_done, */ \
{ NAME, IDX, 0, NULL, FLAGS, 0, 0, \
\
--- binutils/gas/config/obj-elf.c.type 2003-06-13 08:34:09.000000000 -0700
+++ binutils/gas/config/obj-elf.c 2003-06-14 11:53:17.000000000 -0700
@@ -86,6 +86,8 @@ static void obj_elf_symver PARAMS ((int)
static void obj_elf_subsection PARAMS ((int));
static void obj_elf_popsection PARAMS ((int));
static void obj_elf_tls_common PARAMS ((int));
+static bfd_boolean elf_get_sec_type_attr (const char *, bfd_boolean,
+ int *, int *);
static const pseudo_typeS elf_pseudo_table[] =
{
@@ -631,9 +633,13 @@ static struct special_section const spec
{ ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
{ ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
{ ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { ".init_array",SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
- { ".fini_array",SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
- { ".preinit_array",SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".init_array",SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".fini_array",SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".preinit_array",SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".debug_line",SHT_PROGBITS, 0 },
+ { ".debug_info",SHT_PROGBITS, 0 },
+ { ".debug_abbrev",SHT_PROGBITS,0 },
+ { ".debug_aranges",SHT_PROGBITS,0 },
#ifdef ELF_TC_SPECIAL_SECTIONS
ELF_TC_SPECIAL_SECTIONS
@@ -658,52 +664,22 @@ static struct special_section const spec
{ NULL, 0, 0 }
};
-void
-obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push)
- const char *name;
- int type;
- int attr;
- int entsize;
- const char *group_name;
- int linkonce;
- int push;
+static bfd_boolean
+elf_get_sec_type_attr (const char *name, bfd_boolean new,
+ int *type, int *attr)
{
- asection *old_sec;
- segT sec;
- flagword flags;
int i;
-
-#ifdef md_flush_pending_output
- md_flush_pending_output ();
-#endif
-
- /* Switch to the section, creating it if necessary. */
- if (push)
- {
- struct section_stack *elt;
- elt = xmalloc (sizeof (struct section_stack));
- elt->next = section_stack;
- elt->seg = now_seg;
- elt->prev_seg = previous_section;
- elt->subseg = now_subseg;
- elt->prev_subseg = previous_subsection;
- section_stack = elt;
- }
- previous_section = now_seg;
- previous_subsection = now_subseg;
-
- old_sec = bfd_get_section_by_name (stdoutput, name);
- sec = subseg_new (name, 0);
+ bfd_boolean found = FALSE;
/* See if this is one of the special sections. */
for (i = 0; special_sections[i].name != NULL; i++)
if (strcmp (name, special_sections[i].name) == 0)
{
- if (type == SHT_NULL)
- type = special_sections[i].type;
- else if (type != special_sections[i].type)
+ if (*type == -1)
+ *type = special_sections[i].type;
+ else if (*type != special_sections[i].type)
{
- if (old_sec == NULL
+ if (new
/* FIXME: gcc, as of 2002-10-22, will emit
.section .init_array,"aw",@progbits
@@ -719,25 +695,89 @@ obj_elf_change_section (name, type, attr
else
{
as_warn (_("ignoring incorrect section type for %s"), name);
- type = special_sections[i].type;
+ *type = special_sections[i].type;
}
}
- if ((attr &~ special_sections[i].attributes) != 0
- && old_sec == NULL)
+ if (new && (*attr &~ special_sections[i].attributes) != 0)
{
/* As a GNU extension, we permit a .note section to be
allocatable. If the linker sees an allocateable .note
section, it will create a PT_NOTE segment in the output
file. */
if (strcmp (name, ".note") != 0
- || attr != SHF_ALLOC)
+ || *attr != SHF_ALLOC)
as_warn (_("setting incorrect section attributes for %s"),
name);
}
- attr |= special_sections[i].attributes;
+ *attr |= special_sections[i].attributes;
+ found = TRUE;
break;
}
+ return found;
+}
+
+void
+elf_sec_set_private_data (bfd *abfd, asection *sec)
+{
+ if (!_bfd_elf_new_section_hook (abfd, sec))
+ as_fatal (_("can't allocate ELF private section data: %s"),
+ bfd_errmsg (bfd_get_error ()));
+
+ if (elf_section_type (sec) == (unsigned int) -1)
+ {
+ unsigned int type = -1, attr = 0;
+
+ if (elf_get_sec_type_attr (sec->name, TRUE, &type, &attr))
+ {
+ elf_section_type (sec) = type;
+ elf_section_flags (sec) = attr;
+ }
+ }
+}
+
+void
+obj_elf_change_section (name, type, attr, entsize, group_name, linkonce, push)
+ const char *name;
+ int type;
+ int attr;
+ int entsize;
+ const char *group_name;
+ int linkonce;
+ int push;
+{
+ asection *old_sec;
+ segT sec;
+ flagword flags;
+
+#ifdef md_flush_pending_output
+ md_flush_pending_output ();
+#endif
+
+ /* Switch to the section, creating it if necessary. */
+ if (push)
+ {
+ struct section_stack *elt;
+ elt = xmalloc (sizeof (struct section_stack));
+ elt->next = section_stack;
+ elt->seg = now_seg;
+ elt->prev_seg = previous_section;
+ elt->subseg = now_subseg;
+ elt->prev_subseg = previous_subsection;
+ section_stack = elt;
+ }
+ previous_section = now_seg;
+ previous_subsection = now_subseg;
+
+ old_sec = bfd_get_section_by_name (stdoutput, name);
+ sec = subseg_new (name, 0);
+
+ if (elf_get_sec_type_attr (name, old_sec == NULL, &type, &attr))
+ {
+ elf_section_type (sec) = type;
+ elf_section_flags (sec) = attr;
+ }
+
/* Convert ELF type and flags to BFD flags. */
flags = (SEC_RELOC
| ((attr & SHF_WRITE) ? 0 : SEC_READONLY)
@@ -986,7 +1026,7 @@ obj_elf_section (push)
name = obj_elf_section_name ();
if (name == NULL)
return;
- type = SHT_NULL;
+ type = -1;
attr = 0;
group_name = NULL;
entsize = 0;
@@ -2078,6 +2118,7 @@ elf_frob_file ()
as_fatal (_("can't create group: %s"),
bfd_errmsg (bfd_get_error ()));
}
+ elf_section_type (s) = SHT_GROUP;
/* Pass a pointer to the first section in this group. */
elf_next_in_group (s) = list.head[i];
--- binutils/gas/config/obj-elf.h.type 2002-09-18 22:11:17.000000000 -0700
+++ binutils/gas/config/obj-elf.h 2003-06-14 11:06:34.000000000 -0700
@@ -134,6 +134,11 @@ int elf_s_get_other PARAMS ((symbolS *))
extern asection *gdb_section;
+#ifndef obj_sec_set_private_data
+#define obj_sec_set_private_data elf_sec_set_private_data
+#endif
+extern void elf_sec_set_private_data (bfd *, asection *);
+
#ifndef obj_frob_file
#define obj_frob_file elf_frob_file
#endif
--- binutils/gas/subsegs.c.type 2002-12-08 13:41:58.000000000 -0800
+++ binutils/gas/subsegs.c 2003-06-14 11:06:45.000000000 -0700
@@ -422,6 +422,10 @@ subseg_get (segname, force_new)
else
secptr = bfd_make_section_anyway (stdoutput, segname);
+#ifdef obj_sec_set_private_data
+ obj_sec_set_private_data (stdoutput, secptr);
+#endif
+
seginfo = seg_info (secptr);
if (! seginfo)
{
More information about the Binutils
mailing list