diff options
author | Jakub Jelinek <jakub@redhat.com> | 2001-12-13 11:09:34 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2001-12-13 11:09:34 +0000 |
commit | 6576570080f306b7799bd1deb2abffdbcc6dc0a5 (patch) | |
tree | 7195727fd9a8486b8f920c7dd3b39148ba67d838 /bfd/elflink.h | |
parent | 49d5aff7e554f7aa7ce868f70d85f98ceed622bf (diff) | |
download | gdb-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.h | 203 |
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; } |