aboutsummaryrefslogtreecommitdiff
path: root/bfd/elflink.h
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2001-12-13 11:09:34 +0000
committerJakub Jelinek <jakub@redhat.com>2001-12-13 11:09:34 +0000
commit6576570080f306b7799bd1deb2abffdbcc6dc0a5 (patch)
tree7195727fd9a8486b8f920c7dd3b39148ba67d838 /bfd/elflink.h
parent49d5aff7e554f7aa7ce868f70d85f98ceed622bf (diff)
downloadgdb-6576570080f306b7799bd1deb2abffdbcc6dc0a5.zip
gdb-6576570080f306b7799bd1deb2abffdbcc6dc0a5.tar.gz
gdb-6576570080f306b7799bd1deb2abffdbcc6dc0a5.tar.bz2
* elf-bfd.h (enum elf_link_info_type): New.
(struct bfd_elf_section_data): Remove stab_info and merge_info fields, add sec_info and sec_info_type. (struct elf_obj_tdata): Add eh_frame_hdr field. (_bfd_elf_discard_section_eh_frame): New prototype. (_bfd_elf_discard_section_eh_frame_hdr): Likewise. (_bfd_elf_eh_frame_section_offset): Likewise. (_bfd_elf_write_section_eh_frame): Likewise. (_bfd_elf_write_section_eh_frame_hdr): Likewise. * Makefile.am (BFD32_BACKENDS): Add elf-eh-frame.lo. (BFD32_BACKENDS_CFILES): Add elf-eh-frame.c. (elf-eh-frame.lo): New. * Makefile.in: Rebuilt. * configure.in (elf): Add elf-eh-frame.lo. * configure: Rebuilt. * elf.c (_bfd_elf_print_private_bfd_data): Support PT_GNU_EH_FRAME. (map_sections_to_segments): Create PT_GNU_EH_FRAME if requested. (get_program_header_size): Take into account PT_GNU_EH_FRAME segment. (_bfd_elf_rela_local_sym): Use sec_info_type and sec_info. (_bfd_elf_rel_local_sym): Likewise. (_bfd_elf_section_offset): Likewise. Call _bfd_elf_eh_frame_section_offset too. * elfxx-ia64.c (elfNN_ia64_relocate_section): Use sec_info_type and sec_info. * elf64-alpha.c (elf64_alpha_relocate_section): Likewise. * elf-eh-frame.c: New file. * elflink.h (elf_link_add_object_symbols): Don't optimize SHF_MERGE .stab sections. Set sec_info_type, use sec_info instead of merge_info and stab_info. (elf_link_create_dynamic_sections): Create .eh_frame_hdr section if --eh-frame-hdr. (elf_bfd_final_link): Write .eh_frame_hdr section. (elf_link_sec_merge_syms): Use sec_info_type and sec_info. (elf_link_input_bfd): Likewise. Call _bfd_elf_write_section_eh_frame to write .eh_frame sections. (elf_bfd_discard_info): Add output_bfd argument. Call _bfd_elf_discard_section_eh_frame and _bfd_elf_discard_section_eh_frame_hdr. (elf_section_ignore_discarded_relocs): Use sec_info_type, not section names. * bfd-in.h (bfd_elf32_discard_info, bfd_elf64_discard_info): Adjust prototypes. * bfd-in2.h (bfd_elf32_discard_info, bfd_elf64_discard_info): Likewise. * elf/common.h (PT_GNU_EH_FRAME): Define. * bfdlink.h (struct bfd_link_info): Add eh_frame_hdr field. * emultempl/elf32.em (finish): Supply output_bfd to bfd_elf*_discard_info. (OPTION_EH_FRAME_HDR): Define. (longopts): Add --eh-frame-hdr. (parse_args): Handle it. (list_options): Add --eh-frame-hdr to help. * emultempl/hppaelf.em (finish): Supply output_bfd to bfd_elf*_discard_info. * scripttempl/elf.sc (.eh_frame_hdr): Add. * readelf.c (get_segment_type): Support PT_GNU_EH_FRAME.
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r--bfd/elflink.h203
1 files changed, 151 insertions, 52 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h
index d78832d..37ea63d 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -2214,7 +2214,7 @@ elf_link_add_object_symbols (abfd, info)
asection *stab, *stabstr;
stab = bfd_get_section_by_name (abfd, ".stab");
- if (stab != NULL)
+ if (stab != NULL && !(stab->flags & SEC_MERGE))
{
stabstr = bfd_get_section_by_name (abfd, ".stabstr");
@@ -2226,8 +2226,10 @@ elf_link_add_object_symbols (abfd, info)
if (! _bfd_link_section_stabs (abfd,
& hash_table->stab_info,
stab, stabstr,
- &secdata->stab_info))
+ &secdata->sec_info))
goto error_return;
+ if (secdata->sec_info)
+ secdata->sec_info_type = ELF_INFO_TYPE_STABS;
}
}
}
@@ -2238,10 +2240,18 @@ elf_link_add_object_symbols (abfd, info)
asection *s;
for (s = abfd->sections; s != NULL; s = s->next)
- if ((s->flags & SEC_MERGE)
- && ! _bfd_merge_section (abfd, & hash_table->merge_info, s,
- & elf_section_data (s)->merge_info))
- goto error_return;
+ if (s->flags & SEC_MERGE)
+ {
+ struct bfd_elf_section_data *secdata;
+
+ secdata = elf_section_data (s);
+ if (! _bfd_merge_section (abfd,
+ & hash_table->merge_info,
+ s, &secdata->sec_info))
+ goto error_return;
+ else if (secdata->sec_info)
+ secdata->sec_info_type = ELF_INFO_TYPE_MERGE;
+ }
}
return true;
@@ -2300,6 +2310,16 @@ elf_link_create_dynamic_sections (abfd, info)
return false;
}
+ if (! info->traditional_format
+ && info->hash->creator->flavour == bfd_target_elf_flavour)
+ {
+ s = bfd_make_section (abfd, ".eh_frame_hdr");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ }
+
/* Create sections to hold version informations. These are removed
if they are not needed. */
s = bfd_make_section (abfd, ".gnu.version_d");
@@ -5522,6 +5542,19 @@ elf_bfd_final_link (abfd, info)
goto error_return;
}
+ if (info->eh_frame_hdr)
+ {
+ o = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+ ".eh_frame_hdr");
+ if (o
+ && (elf_section_data (o)->sec_info_type
+ == ELF_INFO_TYPE_EH_FRAME_HDR))
+ {
+ if (! _bfd_elf_write_section_eh_frame_hdr (abfd, o))
+ goto error_return;
+ }
+ }
+
if (finfo.symstrtab != NULL)
_bfd_stringtab_free (finfo.symstrtab);
if (finfo.contents != NULL)
@@ -5671,14 +5704,14 @@ elf_link_sec_merge_syms (h, data)
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& ((sec = h->root.u.def.section)->flags & SEC_MERGE)
- && elf_section_data (sec)->merge_info)
+ && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE)
{
bfd *output_bfd = (bfd *) data;
h->root.u.def.value =
_bfd_merged_section_offset (output_bfd,
&h->root.u.def.section,
- elf_section_data (sec)->merge_info,
+ elf_section_data (sec)->sec_info,
h->root.u.def.value, (bfd_vma) 0);
}
@@ -6170,11 +6203,12 @@ elf_link_input_bfd (finfo, input_bfd)
else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
{
isec = section_from_elf_index (input_bfd, isym->st_shndx);
- if (isec && elf_section_data (isec)->merge_info
+ if (isec
+ && elf_section_data (isec)->sec_info_type == ELF_INFO_TYPE_MERGE
&& ELF_ST_TYPE (isym->st_info) != STT_SECTION)
isym->st_value =
_bfd_merged_section_offset (output_bfd, &isec,
- elf_section_data (isec)->merge_info,
+ elf_section_data (isec)->sec_info,
isym->st_value, (bfd_vma) 0);
}
else if (isym->st_shndx == SHN_ABS)
@@ -6358,8 +6392,8 @@ elf_link_input_bfd (finfo, input_bfd)
&& ! bfd_is_abs_section (h->root.u.def.section)
&& bfd_is_abs_section (h->root.u.def.section
->output_section)
- && elf_section_data (h->root.u.def.section)->merge_info
- == NULL)
+ && (elf_section_data (h->root.u.def.section)
+ ->sec_info_type != ELF_INFO_TYPE_MERGE))
{
#if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0)
@@ -6391,7 +6425,8 @@ elf_link_input_bfd (finfo, input_bfd)
if (sec != NULL
&& ! bfd_is_abs_section (sec)
&& bfd_is_abs_section (sec->output_section)
- && elf_section_data (sec)->merge_info == NULL)
+ && (elf_section_data (sec)->sec_info_type
+ != ELF_INFO_TYPE_MERGE))
{
#if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0
@@ -6640,30 +6675,45 @@ elf_link_input_bfd (finfo, input_bfd)
{
/* Section written out. */
}
- else if (elf_section_data (o)->stab_info)
+ else switch (elf_section_data (o)->sec_info_type)
{
+ case ELF_INFO_TYPE_STABS:
if (! (_bfd_write_section_stabs
- (output_bfd, &elf_hash_table (finfo->info)->stab_info,
- o, &elf_section_data (o)->stab_info, contents)))
+ (output_bfd,
+ &elf_hash_table (finfo->info)->stab_info,
+ o, &elf_section_data (o)->sec_info, contents)))
return false;
- }
- else if (elf_section_data (o)->merge_info)
- {
+ break;
+ case ELF_INFO_TYPE_MERGE:
if (! (_bfd_write_merged_section
- (output_bfd, o, elf_section_data (o)->merge_info)))
- return false;
- }
- else
- {
- bfd_size_type sec_size;
-
- sec_size = (o->_cooked_size != 0 ? o->_cooked_size : o->_raw_size);
- if (! (o->flags & SEC_EXCLUDE)
- && ! bfd_set_section_contents (output_bfd, o->output_section,
- contents,
- (file_ptr) o->output_offset,
- sec_size))
+ (output_bfd, o, elf_section_data (o)->sec_info)))
return false;
+ break;
+ case ELF_INFO_TYPE_EH_FRAME:
+ {
+ asection *ehdrsec;
+
+ ehdrsec
+ = bfd_get_section_by_name (elf_hash_table (finfo->info)->dynobj,
+ ".eh_frame_hdr");
+ if (! (_bfd_elf_write_section_eh_frame (output_bfd, o, ehdrsec,
+ contents)))
+ return false;
+ }
+ break;
+ default:
+ {
+ bfd_size_type sec_size;
+
+ sec_size = (o->_cooked_size != 0 ? o->_cooked_size : o->_raw_size);
+ if (! (o->flags & SEC_EXCLUDE)
+ && ! bfd_set_section_contents (output_bfd, o->output_section,
+ contents,
+ (file_ptr) o->output_offset,
+ sec_size))
+ return false;
+ }
+ break;
}
}
@@ -7881,24 +7931,28 @@ elf_reloc_symbol_deleted_p (offset, cookie)
which is true for all known assemblers. */
boolean
-elf_bfd_discard_info (info)
+elf_bfd_discard_info (output_bfd, info)
+ bfd *output_bfd;
struct bfd_link_info *info;
{
struct elf_reloc_cookie cookie;
- asection *o;
+ asection *stab, *eh, *ehdr;
Elf_Internal_Shdr *symtab_hdr;
Elf_External_Sym *freesyms;
struct elf_backend_data *bed;
bfd *abfd;
boolean ret = false;
+ boolean strip = info->strip == strip_all || info->strip == strip_debugger;
if (info->relocateable
|| info->traditional_format
|| info->hash->creator->flavour != bfd_target_elf_flavour
- || ! is_elf_hash_table (info)
- || info->strip == strip_all
- || info->strip == strip_debugger)
+ || ! is_elf_hash_table (info))
return false;
+
+ ehdr = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+ ".eh_frame_hdr");
+
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
{
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
@@ -7909,8 +7963,18 @@ elf_bfd_discard_info (info)
if ((abfd->flags & DYNAMIC) != 0)
continue;
- o = bfd_get_section_by_name (abfd, ".stab");
- if (! o && ! bed->elf_backend_discard_info)
+ eh = NULL;
+ if (ehdr)
+ {
+ eh = bfd_get_section_by_name (abfd, ".eh_frame");
+ if (eh && eh->_raw_size == 0)
+ eh = NULL;
+ }
+
+ stab = strip ? NULL : bfd_get_section_by_name (abfd, ".stab");
+ if ((! stab || elf_section_data(stab)->sec_info_type != ELF_INFO_TYPE_STABS)
+ && ! eh
+ && (strip || ! bed->elf_backend_discard_info))
continue;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -7955,19 +8019,19 @@ elf_bfd_discard_info (info)
}
}
- if (o)
+ if (stab)
{
cookie.rels = (NAME(_bfd_elf,link_read_relocs)
- (abfd, o, (PTR) NULL,
+ (abfd, stab, (PTR) NULL,
(Elf_Internal_Rela *) NULL,
info->keep_memory));
if (cookie.rels)
{
cookie.rel = cookie.rels;
cookie.relend =
- cookie.rels + o->reloc_count * bed->s->int_rels_per_ext_rel;
- if (_bfd_discard_section_stabs (abfd, o,
- elf_section_data (o)->stab_info,
+ cookie.rels + stab->reloc_count * bed->s->int_rels_per_ext_rel;
+ if (_bfd_discard_section_stabs (abfd, stab,
+ elf_section_data (stab)->sec_info,
elf_reloc_symbol_deleted_p,
&cookie))
ret = true;
@@ -7976,6 +8040,30 @@ elf_bfd_discard_info (info)
}
}
+ if (eh)
+ {
+ cookie.rels = NULL;
+ cookie.rel = NULL;
+ cookie.relend = NULL;
+ if (eh->reloc_count)
+ cookie.rels = (NAME(_bfd_elf,link_read_relocs)
+ (abfd, eh, (PTR) NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory));
+ if (cookie.rels)
+ {
+ cookie.rel = cookie.rels;
+ cookie.relend =
+ cookie.rels + eh->reloc_count * bed->s->int_rels_per_ext_rel;
+ }
+ if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
+ elf_reloc_symbol_deleted_p,
+ &cookie))
+ ret = true;
+ if (! info->keep_memory)
+ free (cookie.rels);
+ }
+
if (bed->elf_backend_discard_info)
{
if (bed->elf_backend_discard_info (abfd, &cookie, info))
@@ -7985,6 +8073,11 @@ elf_bfd_discard_info (info)
if (freesyms)
free (freesyms);
}
+
+ if (ehdr
+ && _bfd_elf_discard_section_eh_frame_hdr (output_bfd,
+ info, ehdr))
+ ret = true;
return ret;
}
@@ -7992,13 +8085,19 @@ static boolean
elf_section_ignore_discarded_relocs (sec)
asection *sec;
{
- if (strcmp (sec->name, ".stab") == 0)
- return true;
- else if ((get_elf_backend_data (sec->owner)
- ->elf_backend_ignore_discarded_relocs != NULL)
- && (*get_elf_backend_data (sec->owner)
- ->elf_backend_ignore_discarded_relocs) (sec))
+ switch (elf_section_data (sec)->sec_info_type)
+ {
+ case ELF_INFO_TYPE_STABS:
+ case ELF_INFO_TYPE_EH_FRAME:
+ return true;
+ default:
+ break;
+ }
+ if ((get_elf_backend_data (sec->owner)->elf_backend_ignore_discarded_relocs
+ != NULL)
+ && (*get_elf_backend_data (sec->owner)
+ ->elf_backend_ignore_discarded_relocs) (sec))
return true;
- else
- return false;
+
+ return false;
}