* 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.
This commit is contained in:
Jakub Jelinek 2001-12-13 11:09:34 +00:00
parent 49d5aff7e5
commit 6576570080
22 changed files with 1366 additions and 77 deletions

View file

@ -1,3 +1,50 @@
2001-12-13 Jakub Jelinek <jakub@redhat.com>
* 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.
2001-12-12 Richard Henderson <rth@redhat.com> 2001-12-12 Richard Henderson <rth@redhat.com>
* syms.c (_bfd_generic_read_minisymbols): Early return for * syms.c (_bfd_generic_read_minisymbols): Early return for

View file

@ -223,6 +223,7 @@ BFD32_BACKENDS = \
elf32.lo \ elf32.lo \
elflink.lo \ elflink.lo \
elf-strtab.lo \ elf-strtab.lo \
elf-eh-frame.lo \
epoc-pe-arm.lo \ epoc-pe-arm.lo \
epoc-pei-arm.lo \ epoc-pei-arm.lo \
hp300bsd.lo \ hp300bsd.lo \
@ -365,6 +366,7 @@ BFD32_BACKENDS_CFILES = \
elf32.c \ elf32.c \
elflink.c \ elflink.c \
elf-strtab.c \ elf-strtab.c \
elf-eh-frame.c \
epoc-pe-arm.c \ epoc-pe-arm.c \
epoc-pei-arm.c \ epoc-pei-arm.c \
hp300bsd.c \ hp300bsd.c \
@ -1149,6 +1151,7 @@ elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/elf/external.h
elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
elf-eh-frame.lo: elf-eh-frame.c
epoc-pe-arm.lo: epoc-pe-arm.c pe-arm.c $(INCDIR)/filenames.h \ epoc-pe-arm.lo: epoc-pe-arm.c pe-arm.c $(INCDIR)/filenames.h \
coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h \ coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h \
$(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \

View file

@ -351,6 +351,7 @@ BFD32_BACKENDS = \
elf32.lo \ elf32.lo \
elflink.lo \ elflink.lo \
elf-strtab.lo \ elf-strtab.lo \
elf-eh-frame.lo \
epoc-pe-arm.lo \ epoc-pe-arm.lo \
epoc-pei-arm.lo \ epoc-pei-arm.lo \
hp300bsd.lo \ hp300bsd.lo \
@ -494,6 +495,7 @@ BFD32_BACKENDS_CFILES = \
elf32.c \ elf32.c \
elflink.c \ elflink.c \
elf-strtab.c \ elf-strtab.c \
elf-eh-frame.c \
epoc-pe-arm.c \ epoc-pe-arm.c \
epoc-pei-arm.c \ epoc-pei-arm.c \
hp300bsd.c \ hp300bsd.c \
@ -1693,6 +1695,7 @@ elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \
elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
$(INCDIR)/elf/external.h $(INCDIR)/elf/external.h
elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h
elf-eh-frame.lo: elf-eh-frame.c
epoc-pe-arm.lo: epoc-pe-arm.c pe-arm.c $(INCDIR)/filenames.h \ epoc-pe-arm.lo: epoc-pe-arm.c pe-arm.c $(INCDIR)/filenames.h \
coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h \ coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h \
$(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \

View file

@ -636,9 +636,9 @@ extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
extern struct bfd_link_needed_list *bfd_elf_get_runpath_list extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
PARAMS ((bfd *, struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf32_discard_info extern boolean bfd_elf32_discard_info
PARAMS ((struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf64_discard_info extern boolean bfd_elf64_discard_info
PARAMS ((struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
/* Return an upper bound on the number of bytes required to store a /* Return an upper bound on the number of bytes required to store a
copy of ABFD's program header table entries. Return -1 if an error copy of ABFD's program header table entries. Return -1 if an error

View file

@ -642,9 +642,9 @@ extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
extern struct bfd_link_needed_list *bfd_elf_get_runpath_list extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
PARAMS ((bfd *, struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf32_discard_info extern boolean bfd_elf32_discard_info
PARAMS ((struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf64_discard_info extern boolean bfd_elf64_discard_info
PARAMS ((struct bfd_link_info *)); PARAMS ((bfd *, struct bfd_link_info *));
/* Return an upper bound on the number of bytes required to store a /* Return an upper bound on the number of bytes required to store a
copy of ABFD's program header table entries. Return -1 if an error copy of ABFD's program header table entries. Return -1 if an error

2
bfd/configure vendored
View file

@ -5921,7 +5921,7 @@ selarchs="$f"
# Target backend .o files. # Target backend .o files.
tb= tb=
elf="elf.lo elflink.lo elf-strtab.lo dwarf1.lo" elf="elf.lo elflink.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo"
for vec in $selvecs for vec in $selvecs
do do

View file

@ -503,7 +503,7 @@ selarchs="$f"
# Target backend .o files. # Target backend .o files.
tb= tb=
elf="elf.lo elflink.lo elf-strtab.lo dwarf1.lo" elf="elf.lo elflink.lo elf-strtab.lo elf-eh-frame.lo dwarf1.lo"
for vec in $selvecs for vec in $selvecs
do do

View file

@ -223,6 +223,16 @@ struct elf_link_local_dynamic_entry
Elf_Internal_Sym isym; Elf_Internal_Sym isym;
}; };
enum elf_link_info_type
{
ELF_INFO_TYPE_NONE,
ELF_INFO_TYPE_STABS,
ELF_INFO_TYPE_MERGE,
ELF_INFO_TYPE_EH_FRAME,
ELF_INFO_TYPE_EH_FRAME_HDR,
ELF_INFO_TYPE_LAST
};
/* ELF linker hash table. */ /* ELF linker hash table. */
struct elf_link_hash_table struct elf_link_hash_table
@ -848,11 +858,11 @@ struct bfd_elf_section_data
no dynamic symbol for this section. */ no dynamic symbol for this section. */
long dynindx; long dynindx;
/* A pointer used for .stab linking optimizations. */ /* A pointer used for various section optimizations. */
PTR stab_info; PTR sec_info;
/* A pointer used for SEC_MERGE optimizations. */ /* Type of that information. */
PTR merge_info; enum elf_link_info_type sec_info_type;
/* Group name, if this section is part of a group. */ /* Group name, if this section is part of a group. */
const char *group_name; const char *group_name;
@ -1043,6 +1053,10 @@ struct elf_obj_tdata
/* Used to determine if the e_flags field has been initialized */ /* Used to determine if the e_flags field has been initialized */
boolean flags_init; boolean flags_init;
/* Used to determine if PT_GNU_EH_FRAME segment header should be
created. */
boolean eh_frame_hdr;
/* Number of symbol version definitions we are about to emit. */ /* Number of symbol version definitions we are about to emit. */
unsigned int cverdefs; unsigned int cverdefs;
@ -1271,6 +1285,18 @@ extern boolean _bfd_elf_strtab_emit
extern void _bfd_elf_strtab_finalize extern void _bfd_elf_strtab_finalize
PARAMS ((struct elf_strtab_hash *)); PARAMS ((struct elf_strtab_hash *));
extern boolean _bfd_elf_discard_section_eh_frame
PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *,
boolean (*) (bfd_vma, PTR), struct elf_reloc_cookie *));
extern boolean _bfd_elf_discard_section_eh_frame_hdr
PARAMS ((bfd *, struct bfd_link_info *, asection *));
extern bfd_vma _bfd_elf_eh_frame_section_offset
PARAMS ((bfd *, asection *, bfd_vma));
extern boolean _bfd_elf_write_section_eh_frame
PARAMS ((bfd *, asection *, asection *, bfd_byte *));
extern boolean _bfd_elf_write_section_eh_frame_hdr
PARAMS ((bfd *, asection *));
extern boolean _bfd_elf_link_record_dynamic_symbol extern boolean _bfd_elf_link_record_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
extern long _bfd_elf_link_lookup_local_dynindx extern long _bfd_elf_link_lookup_local_dynindx

1039
bfd/elf-eh-frame.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -812,6 +812,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
case PT_NOTE: pt = "NOTE"; break; case PT_NOTE: pt = "NOTE"; break;
case PT_SHLIB: pt = "SHLIB"; break; case PT_SHLIB: pt = "SHLIB"; break;
case PT_PHDR: pt = "PHDR"; break; case PT_PHDR: pt = "PHDR"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break; default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
} }
fprintf (f, "%8s off 0x", pt); fprintf (f, "%8s off 0x", pt);
@ -2794,7 +2795,7 @@ map_sections_to_segments (abfd)
asection **hdrpp; asection **hdrpp;
boolean phdr_in_segment = true; boolean phdr_in_segment = true;
boolean writable; boolean writable;
asection *dynsec; asection *dynsec, *eh_frame_hdr;
bfd_size_type amt; bfd_size_type amt;
if (elf_tdata (abfd)->segment_map != NULL) if (elf_tdata (abfd)->segment_map != NULL)
@ -3034,6 +3035,24 @@ map_sections_to_segments (abfd)
} }
} }
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
segment. */
eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
if (eh_frame_hdr != NULL && (eh_frame_hdr->flags & SEC_LOAD))
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
m->p_type = PT_GNU_EH_FRAME;
m->count = 1;
m->sections[0] = eh_frame_hdr;
*pm = m;
pm = &m->next;
}
free (sections); free (sections);
sections = NULL; sections = NULL;
@ -3548,6 +3567,13 @@ get_program_header_size (abfd)
++segs; ++segs;
} }
if (elf_tdata (abfd)->eh_frame_hdr
&& bfd_get_section_by_name (abfd, ".eh_frame_hdr") != NULL)
{
/* We need a PT_GNU_EH_FRAME segment. */
++segs;
}
for (s = abfd->sections; s != NULL; s = s->next) for (s = abfd->sections; s != NULL; s = s->next)
{ {
if ((s->flags & SEC_LOAD) != 0 if ((s->flags & SEC_LOAD) != 0
@ -6392,14 +6418,14 @@ _bfd_elf_rela_local_sym (abfd, sym, sec, rel)
+ sym->st_value); + sym->st_value);
if ((sec->flags & SEC_MERGE) if ((sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION && ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& elf_section_data (sec)->merge_info) && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE)
{ {
asection *msec; asection *msec;
msec = sec; msec = sec;
rel->r_addend = rel->r_addend =
_bfd_merged_section_offset (abfd, &msec, _bfd_merged_section_offset (abfd, &msec,
elf_section_data (sec)->merge_info, elf_section_data (sec)->sec_info,
sym->st_value + rel->r_addend, sym->st_value + rel->r_addend,
(bfd_vma) 0) (bfd_vma) 0)
- relocation; - relocation;
@ -6417,11 +6443,11 @@ _bfd_elf_rel_local_sym (abfd, sym, psec, addend)
{ {
asection *sec = *psec; asection *sec = *psec;
if (elf_section_data (sec)->merge_info == NULL) if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE)
return sym->st_value + addend; return sym->st_value + addend;
return _bfd_merged_section_offset (abfd, psec, return _bfd_merged_section_offset (abfd, psec,
elf_section_data (sec)->merge_info, elf_section_data (sec)->sec_info,
sym->st_value + addend, (bfd_vma) 0); sym->st_value + addend, (bfd_vma) 0);
} }
@ -6435,9 +6461,15 @@ _bfd_elf_section_offset (abfd, info, sec, offset)
struct bfd_elf_section_data *sec_data; struct bfd_elf_section_data *sec_data;
sec_data = elf_section_data (sec); sec_data = elf_section_data (sec);
if (sec_data->stab_info != NULL) switch (sec_data->sec_info_type)
return _bfd_stab_section_offset {
(abfd, &elf_hash_table (info)->stab_info, case ELF_INFO_TYPE_STABS:
sec, &sec_data->stab_info, offset); return _bfd_stab_section_offset
return offset; (abfd, &elf_hash_table (info)->merge_info, sec, &sec_data->sec_info,
offset);
case ELF_INFO_TYPE_EH_FRAME:
return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
default:
return offset;
}
} }

View file

@ -3406,7 +3406,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
unless it has been done already. */ unless it has been done already. */
if ((sec->flags & SEC_MERGE) if ((sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION && ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& elf_section_data (sec)->merge_info && (elf_section_data (sec)->sec_info_type
== ELF_INFO_TYPE_MERGE)
&& (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0) && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0)
{ {
struct alpha_elf_got_entry *ent; struct alpha_elf_got_entry *ent;
@ -3421,7 +3422,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
ent->addend = ent->addend =
_bfd_merged_section_offset (output_bfd, &msec, _bfd_merged_section_offset (output_bfd, &msec,
elf_section_data (sec)-> elf_section_data (sec)->
merge_info, sec_info,
sym->st_value sym->st_value
+ ent->addend, + ent->addend,
(bfd_vma) 0); (bfd_vma) 0);

View file

@ -2214,7 +2214,7 @@ elf_link_add_object_symbols (abfd, info)
asection *stab, *stabstr; asection *stab, *stabstr;
stab = bfd_get_section_by_name (abfd, ".stab"); 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"); 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, if (! _bfd_link_section_stabs (abfd,
& hash_table->stab_info, & hash_table->stab_info,
stab, stabstr, stab, stabstr,
&secdata->stab_info)) &secdata->sec_info))
goto error_return; 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; asection *s;
for (s = abfd->sections; s != NULL; s = s->next) for (s = abfd->sections; s != NULL; s = s->next)
if ((s->flags & SEC_MERGE) if (s->flags & SEC_MERGE)
&& ! _bfd_merge_section (abfd, & hash_table->merge_info, s, {
& elf_section_data (s)->merge_info)) struct bfd_elf_section_data *secdata;
goto error_return;
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; return true;
@ -2300,6 +2310,16 @@ elf_link_create_dynamic_sections (abfd, info)
return false; 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 /* Create sections to hold version informations. These are removed
if they are not needed. */ if they are not needed. */
s = bfd_make_section (abfd, ".gnu.version_d"); s = bfd_make_section (abfd, ".gnu.version_d");
@ -5522,6 +5542,19 @@ elf_bfd_final_link (abfd, info)
goto error_return; 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) if (finfo.symstrtab != NULL)
_bfd_stringtab_free (finfo.symstrtab); _bfd_stringtab_free (finfo.symstrtab);
if (finfo.contents != NULL) if (finfo.contents != NULL)
@ -5671,14 +5704,14 @@ elf_link_sec_merge_syms (h, data)
if ((h->root.type == bfd_link_hash_defined if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak) || h->root.type == bfd_link_hash_defweak)
&& ((sec = h->root.u.def.section)->flags & SEC_MERGE) && ((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; bfd *output_bfd = (bfd *) data;
h->root.u.def.value = h->root.u.def.value =
_bfd_merged_section_offset (output_bfd, _bfd_merged_section_offset (output_bfd,
&h->root.u.def.section, &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); 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) else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
{ {
isec = section_from_elf_index (input_bfd, isym->st_shndx); 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) && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
isym->st_value = isym->st_value =
_bfd_merged_section_offset (output_bfd, &isec, _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); isym->st_value, (bfd_vma) 0);
} }
else if (isym->st_shndx == SHN_ABS) 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)
&& bfd_is_abs_section (h->root.u.def.section && bfd_is_abs_section (h->root.u.def.section
->output_section) ->output_section)
&& elf_section_data (h->root.u.def.section)->merge_info && (elf_section_data (h->root.u.def.section)
== NULL) ->sec_info_type != ELF_INFO_TYPE_MERGE))
{ {
#if BFD_VERSION_DATE < 20031005 #if BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0) if ((o->flags & SEC_DEBUGGING) != 0)
@ -6391,7 +6425,8 @@ elf_link_input_bfd (finfo, input_bfd)
if (sec != NULL if (sec != NULL
&& ! bfd_is_abs_section (sec) && ! bfd_is_abs_section (sec)
&& bfd_is_abs_section (sec->output_section) && 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 BFD_VERSION_DATE < 20031005
if ((o->flags & SEC_DEBUGGING) != 0 if ((o->flags & SEC_DEBUGGING) != 0
@ -6640,30 +6675,45 @@ elf_link_input_bfd (finfo, input_bfd)
{ {
/* Section written out. */ /* 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 if (! (_bfd_write_section_stabs
(output_bfd, &elf_hash_table (finfo->info)->stab_info, (output_bfd,
o, &elf_section_data (o)->stab_info, contents))) &elf_hash_table (finfo->info)->stab_info,
o, &elf_section_data (o)->sec_info, contents)))
return false; return false;
} break;
else if (elf_section_data (o)->merge_info) case ELF_INFO_TYPE_MERGE:
{
if (! (_bfd_write_merged_section if (! (_bfd_write_merged_section
(output_bfd, o, elf_section_data (o)->merge_info))) (output_bfd, o, elf_section_data (o)->sec_info)))
return false; return false;
} break;
else case ELF_INFO_TYPE_EH_FRAME:
{ {
bfd_size_type sec_size; asection *ehdrsec;
sec_size = (o->_cooked_size != 0 ? o->_cooked_size : o->_raw_size); ehdrsec
if (! (o->flags & SEC_EXCLUDE) = bfd_get_section_by_name (elf_hash_table (finfo->info)->dynobj,
&& ! bfd_set_section_contents (output_bfd, o->output_section, ".eh_frame_hdr");
contents, if (! (_bfd_elf_write_section_eh_frame (output_bfd, o, ehdrsec,
(file_ptr) o->output_offset, contents)))
sec_size)) return false;
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. */ which is true for all known assemblers. */
boolean boolean
elf_bfd_discard_info (info) elf_bfd_discard_info (output_bfd, info)
bfd *output_bfd;
struct bfd_link_info *info; struct bfd_link_info *info;
{ {
struct elf_reloc_cookie cookie; struct elf_reloc_cookie cookie;
asection *o; asection *stab, *eh, *ehdr;
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
Elf_External_Sym *freesyms; Elf_External_Sym *freesyms;
struct elf_backend_data *bed; struct elf_backend_data *bed;
bfd *abfd; bfd *abfd;
boolean ret = false; boolean ret = false;
boolean strip = info->strip == strip_all || info->strip == strip_debugger;
if (info->relocateable if (info->relocateable
|| info->traditional_format || info->traditional_format
|| info->hash->creator->flavour != bfd_target_elf_flavour || info->hash->creator->flavour != bfd_target_elf_flavour
|| ! is_elf_hash_table (info) || ! is_elf_hash_table (info))
|| info->strip == strip_all
|| info->strip == strip_debugger)
return false; 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) for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
{ {
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
@ -7909,8 +7963,18 @@ elf_bfd_discard_info (info)
if ((abfd->flags & DYNAMIC) != 0) if ((abfd->flags & DYNAMIC) != 0)
continue; continue;
o = bfd_get_section_by_name (abfd, ".stab"); eh = NULL;
if (! o && ! bed->elf_backend_discard_info) 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; continue;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 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) cookie.rels = (NAME(_bfd_elf,link_read_relocs)
(abfd, o, (PTR) NULL, (abfd, stab, (PTR) NULL,
(Elf_Internal_Rela *) NULL, (Elf_Internal_Rela *) NULL,
info->keep_memory)); info->keep_memory));
if (cookie.rels) if (cookie.rels)
{ {
cookie.rel = cookie.rels; cookie.rel = cookie.rels;
cookie.relend = cookie.relend =
cookie.rels + o->reloc_count * bed->s->int_rels_per_ext_rel; cookie.rels + stab->reloc_count * bed->s->int_rels_per_ext_rel;
if (_bfd_discard_section_stabs (abfd, o, if (_bfd_discard_section_stabs (abfd, stab,
elf_section_data (o)->stab_info, elf_section_data (stab)->sec_info,
elf_reloc_symbol_deleted_p, elf_reloc_symbol_deleted_p,
&cookie)) &cookie))
ret = true; 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)
{ {
if (bed->elf_backend_discard_info (abfd, &cookie, info)) if (bed->elf_backend_discard_info (abfd, &cookie, info))
@ -7985,6 +8073,11 @@ elf_bfd_discard_info (info)
if (freesyms) if (freesyms)
free (freesyms); free (freesyms);
} }
if (ehdr
&& _bfd_elf_discard_section_eh_frame_hdr (output_bfd,
info, ehdr))
ret = true;
return ret; return ret;
} }
@ -7992,13 +8085,19 @@ static boolean
elf_section_ignore_discarded_relocs (sec) elf_section_ignore_discarded_relocs (sec)
asection *sec; asection *sec;
{ {
if (strcmp (sec->name, ".stab") == 0) 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; return true;
else if ((get_elf_backend_data (sec->owner)
->elf_backend_ignore_discarded_relocs != NULL) return false;
&& (*get_elf_backend_data (sec->owner)
->elf_backend_ignore_discarded_relocs) (sec))
return true;
else
return false;
} }

View file

@ -3489,7 +3489,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel); value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
if ((sym_sec->flags & SEC_MERGE) if ((sym_sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION && ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& elf_section_data (sym_sec)->merge_info) && (elf_section_data (sym_sec)->sec_info_type
== ELF_INFO_TYPE_MERGE))
{ {
struct elfNN_ia64_local_hash_entry *loc_h; struct elfNN_ia64_local_hash_entry *loc_h;
@ -3505,7 +3506,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
dynent->addend = dynent->addend =
_bfd_merged_section_offset (output_bfd, &msec, _bfd_merged_section_offset (output_bfd, &msec,
elf_section_data (msec)-> elf_section_data (msec)->
merge_info, sec_info,
sym->st_value sym->st_value
+ dynent->addend, + dynent->addend,
(bfd_vma) 0); (bfd_vma) 0);

View file

@ -1,3 +1,7 @@
2001-12-13 Jakub Jelinek <jakub@redhat.com>
* readelf.c (get_segment_type): Support PT_GNU_EH_FRAME.
2001-12-11 Alan Modra <amodra@bigpond.net.au> 2001-12-11 Alan Modra <amodra@bigpond.net.au>
* readelf.c (process_file_header): Print extended e_shnum and * readelf.c (process_file_header): Print extended e_shnum and

View file

@ -1827,6 +1827,9 @@ get_segment_type (p_type)
case PT_SHLIB: return "SHLIB"; case PT_SHLIB: return "SHLIB";
case PT_PHDR: return "PHDR"; case PT_PHDR: return "PHDR";
case PT_GNU_EH_FRAME:
return "GNU_EH_FRAME";
default: default:
if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
{ {

View file

@ -1,3 +1,8 @@
2001-12-13 Jakub Jelinek <jakub@redhat.com>
* elf/common.h (PT_GNU_EH_FRAME): Define.
* bfdlink.h (struct bfd_link_info): Add eh_frame_hdr field.
2001-12-07 Geoffrey Keating <geoffk@redhat.com> 2001-12-07 Geoffrey Keating <geoffk@redhat.com>
* dis-asm.h (print_insn_xstormy16): Declare. * dis-asm.h (print_insn_xstormy16): Declare.

View file

@ -298,6 +298,10 @@ struct bfd_link_info
Setting this true may result in a non-sharable text segment. */ Setting this true may result in a non-sharable text segment. */
boolean nocopyreloc; boolean nocopyreloc;
/* True if .eh_frame_hdr section and PT_GNU_EH_FRAME ELF segment
should be created. */
boolean eh_frame_hdr;
/* How many spare .dynamic DT_NULL entries should be added? */ /* How many spare .dynamic DT_NULL entries should be added? */
unsigned int spare_dynamic_tags; unsigned int spare_dynamic_tags;
}; };

View file

@ -256,6 +256,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define PT_LOPROC 0x70000000 /* Processor-specific */ #define PT_LOPROC 0x70000000 /* Processor-specific */
#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */ #define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
/* Program segment permissions, in program header p_flags field. */ /* Program segment permissions, in program header p_flags field. */
#define PF_X (1 << 0) /* Segment is executable */ #define PF_X (1 << 0) /* Segment is executable */

View file

@ -1,3 +1,15 @@
2001-12-13 Jakub Jelinek <jakub@redhat.com>
* 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.
2001-12-13 Alan Modra <amodra@bigpond.net.au> 2001-12-13 Alan Modra <amodra@bigpond.net.au>
* lexsup.c (parse_args): Don't pass shortopts to second call to * lexsup.c (parse_args): Don't pass shortopts to second call to

View file

@ -1329,7 +1329,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
static void static void
gld${EMULATION_NAME}_finish () gld${EMULATION_NAME}_finish ()
{ {
if (bfd_elf${ELFSIZE}_discard_info (&link_info)) if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
{ {
/* Resize the sections. */ /* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section, lang_size_sections (stat_ptr->head, abs_output_section,
@ -1431,6 +1431,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
#define OPTION_DISABLE_NEW_DTAGS (400) #define OPTION_DISABLE_NEW_DTAGS (400)
#define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1) #define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1)
#define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1) #define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1)
#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1)
static struct option longopts[] = static struct option longopts[] =
{ {
@ -1444,6 +1445,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
{"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
{"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
{"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
{"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
{"Bgroup", no_argument, NULL, OPTION_GROUP}, {"Bgroup", no_argument, NULL, OPTION_GROUP},
{"Bgroup", no_argument, NULL, OPTION_GROUP}, {"Bgroup", no_argument, NULL, OPTION_GROUP},
EOF EOF
@ -1504,6 +1506,10 @@ cat >>e${EMULATION_NAME}.c <<EOF
link_info.new_dtags = true; link_info.new_dtags = true;
break; break;
case OPTION_EH_FRAME_HDR:
link_info.eh_frame_hdr = true;
break;
case OPTION_GROUP: case OPTION_GROUP:
link_info.flags_1 |= (bfd_vma) DF_1_GROUP; link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
/* Groups must be self-contained. */ /* Groups must be self-contained. */
@ -1579,6 +1585,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n")); fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n"));
fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n")); fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n"));
fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n")); fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n"));
fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n")); fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n")); fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n"));
fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n")); fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n"));

View file

@ -254,7 +254,7 @@ gld${EMULATION_NAME}_finish ()
ie. doesn't affect any code, so we can delay resizing the ie. doesn't affect any code, so we can delay resizing the
sections. It's likely we'll resize everything in the process of sections. It's likely we'll resize everything in the process of
adding stubs. */ adding stubs. */
if (bfd_elf${ELFSIZE}_discard_info (&link_info)) if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info))
need_laying_out = 1; need_laying_out = 1;
/* Call into the BFD backend to do the real work. */ /* Call into the BFD backend to do the real work. */

View file

@ -265,6 +265,7 @@ cat <<EOF
${CREATE_SHLIB-${SDATA2}} ${CREATE_SHLIB-${SDATA2}}
${CREATE_SHLIB-${SBSS2}} ${CREATE_SHLIB-${SBSS2}}
${OTHER_READONLY_SECTIONS} ${OTHER_READONLY_SECTIONS}
.eh_frame_hdr : { *(.eh_frame_hdr) }
/* Adjust the address for the data segment. We want to adjust up to /* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */ the same address within the page on the next page up. */