mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 12:39:59 +00:00
ELF Section-level Garbage Collection.
This commit is contained in:
parent
d40d5880c2
commit
303b4cc64f
@ -1,3 +1,69 @@
|
||||
Thu Jun 25 18:31:41 1998 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
ELF Section-level Garbage Collection:
|
||||
* bfd.c (bfd_gc_sections): New.
|
||||
* aout-adobe.c: Hook to default implementation.
|
||||
* aout-target.h, aout-tic30.c, binary.c, bout.c: Likewise.
|
||||
* coff-alpha.c, coff-mips.c, coff-rs6000.c, coffcode.h: Likewise.
|
||||
* evax-alpha.c, i386msdos.c, i386os9k.c, ieee.c: Likewise.
|
||||
* ihex.c, nlm-target.h, oasys.c, ppcboot.c, srec.c: Likewise.
|
||||
* tekhex.c, versados.c: Likewise.
|
||||
* libbfd-in.h (_bfd_nolink_bfd_gc_sections): New.
|
||||
* targets.c (BFD_JUMP_TABLE_LINK): Add _bfd_gc_sections.
|
||||
|
||||
* reloc.c (BFD_RELOC_VTABLE_INHERIT, BFD_RELOC_VTABLE_ENTRY): New.
|
||||
(bfd_generic_gc_sections): New.
|
||||
* section.c (SEC_KEEP): New.
|
||||
(asection): Add gc_mark member.
|
||||
|
||||
* elfcode.h (elf_gc*): New name remappings.
|
||||
* elflink.h (elf_link_input_bfd): Don't set contents on stabs
|
||||
sections to be excluded.
|
||||
(elf_gc_mark, elf_gc_sweep, elf_gc_sweep_symbol): New.
|
||||
(elf_gc_propogate_vtable_entries_used): New.
|
||||
(elf_gc_smash_unused_vtentry_relocs): New.
|
||||
(elf_gc_sections, elf_gc_record_vtinherit, elf_gc_record_vtentry): New.
|
||||
(elf_gc_common_finalize_got_offsets): New.
|
||||
(elf_gc_allocate_got_offsets, elf_gc_common_final_link): New.
|
||||
* elfxx-target.h: Add and default gc hooks.
|
||||
|
||||
* elf-bfd.h (struct elf_link_hash_entry): Swap got_offset/plt_offset
|
||||
for unions.
|
||||
(struct elf_obj_tdata): Likewise for local_got_offsets.
|
||||
* elf.c, elf-i386.c, elf32-m68k.c, elf32-mips.c: Update all uses.
|
||||
* elf32-ppc.c, elf32-sparc.c, elf64-alpha.c: Likewise.
|
||||
* elf64-sparc.c, elflink.h: Likewise.
|
||||
|
||||
* elf-bfd.h (struct elf_link_hash_entry): Add vtable members.
|
||||
(ELF_LINK_HASH_MARK): Define.
|
||||
(struct elf_backend_data): Add GC hooks.
|
||||
* elf.c (_bfd_elf_link_hash_newfunc): Zero vtable members.
|
||||
|
||||
* elf-m10300.c (mn10300_elf_check_relocs): New.
|
||||
(mn10300_elf_gc_mark_hook): New.
|
||||
(R_MN10300_GNU_VTINHERIT, R_MN10300_GNU_VTENTRY): New.
|
||||
(elf_mn10300_howto, mn10300_reloc_map): Handle them.
|
||||
(mn10300_elf_final_link_relocate): Likewise.
|
||||
(mn10300_elf_relocate_section): Likewise.
|
||||
(elf_backend_can_gc_sections): Define.
|
||||
* elf32-mips.c (R_MIPS_GNU_VTINHERIT, R_MIPS_GNU_VTENTRY): New.
|
||||
(elf_mips_gnu_vtinherit_howto, elf_mips_gnu_vtentry_howto): New.
|
||||
(bfd_elf32_bfd_reloc_type_lookup): Handle them.
|
||||
(mips_info_to_howto_rel): Likewise.
|
||||
(mips_elf_relocate_section): Likewise.
|
||||
(mips_elf_check_relocs): Likewise.
|
||||
(mips_elf_gc_mark_hook, mips_elf_gc_sweep_hook): New.
|
||||
(elf_backend_can_gc_sections): Define.
|
||||
* elf32-ppc.c (R_PPC_GNU_VTINHERIT, R_PPC_GNU_VTENTRY): New.
|
||||
(ppc_elf_howto_raw): Handle them.
|
||||
(ppc_elf_reloc_type_lookup): Likewise.
|
||||
(ppc_elf_relocate_section): Likewise.
|
||||
(ppc_elf_check_relocs): Reference count .got and .plt entires.
|
||||
Handle new vtable relocs.
|
||||
(ppc_elf_adjust_dynamic_symbol): Recognize unused .plt entries.
|
||||
(ppc_elf_gc_mark_hook, ppc_elf_gc_sweep_hook): New.
|
||||
(elf_backend_can_gc_sections): Define.
|
||||
|
||||
Fri Jun 26 10:48:23 1998 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* archures.c (bfd_mach_mn10300): Define.
|
||||
|
@ -965,6 +965,9 @@ typedef struct sec
|
||||
else up the line will take care of it later. */
|
||||
#define SEC_LINKER_CREATED 0x800000
|
||||
|
||||
/* This section should not be subject to garbage collection. */
|
||||
#define SEC_KEEP 0x1000000
|
||||
|
||||
/* End of section flags. */
|
||||
|
||||
/* Some internal packed boolean fields. */
|
||||
@ -978,6 +981,9 @@ typedef struct sec
|
||||
/* A mark flag used by some of the linker backends. */
|
||||
unsigned int linker_mark : 1;
|
||||
|
||||
/* A mark flag used by some linker backends for garbage collection. */
|
||||
unsigned int gc_mark : 1;
|
||||
|
||||
/* End of internal packed boolean fields. */
|
||||
|
||||
/* The virtual memory address of the section - where it will be
|
||||
@ -2129,6 +2135,26 @@ instruction. */
|
||||
significant 8 bits of a 24 bit word are placed into the least
|
||||
significant 8 bits of the opcode. */
|
||||
BFD_RELOC_TIC30_LDP,
|
||||
|
||||
/* These two relocations are used by the linker to determine which of
|
||||
the entries in a C++ virtual function table are actually used. When
|
||||
the --gc-sections option is given, the linker will zero out the entries
|
||||
that are not used, so that the code for those functions need not be
|
||||
included in the output.
|
||||
|
||||
VTABLE_INHERIT is a zero-space relocation used to describe to the
|
||||
linker the inheritence tree of a C++ virtual function table. The
|
||||
relocation's symbol should be the parent class' vtable, and the
|
||||
relocation should be located at the child vtable.
|
||||
|
||||
VTABLE_ENTRY is a zero-space relocation that describes the use of a
|
||||
virtual function table entry. The reloc's symbol should refer to the
|
||||
table of the class mentioned in the code. Off of that base, an offset
|
||||
describes the entry that is being used. For Rela hosts, this offset
|
||||
is stored in the reloc's addend. For Rel hosts, we are forced to put
|
||||
this offset in the reloc's section offset. */
|
||||
BFD_RELOC_VTABLE_INHERIT,
|
||||
BFD_RELOC_VTABLE_ENTRY,
|
||||
BFD_RELOC_UNUSED };
|
||||
typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
|
||||
reloc_howto_type *
|
||||
@ -2577,6 +2603,9 @@ bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
|
||||
#define bfd_relax_section(abfd, section, link_info, again) \
|
||||
BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
|
||||
|
||||
#define bfd_gc_sections(abfd, link_info) \
|
||||
BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
|
||||
|
||||
#define bfd_link_hash_table_create(abfd) \
|
||||
BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
|
||||
|
||||
@ -2871,7 +2900,8 @@ CAT(NAME,_bfd_relax_section),\
|
||||
CAT(NAME,_bfd_link_hash_table_create),\
|
||||
CAT(NAME,_bfd_link_add_symbols),\
|
||||
CAT(NAME,_bfd_final_link),\
|
||||
CAT(NAME,_bfd_link_split_section)
|
||||
CAT(NAME,_bfd_link_split_section),\
|
||||
CAT(NAME,_bfd_gc_sections)
|
||||
int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
|
||||
bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
|
||||
struct bfd_link_info *, struct bfd_link_order *,
|
||||
@ -2895,7 +2925,10 @@ CAT(NAME,_bfd_link_split_section)
|
||||
/* Should this section be split up into smaller pieces during linking. */
|
||||
boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
|
||||
|
||||
/* Routines to handle dynamic symbols and relocs. */
|
||||
/* Remove sections that are not referenced from the output. */
|
||||
boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
|
||||
|
||||
/* Routines to handle dynamic symbols and relocs. */
|
||||
#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
|
||||
CAT(NAME,_get_dynamic_symtab_upper_bound),\
|
||||
CAT(NAME,_canonicalize_dynamic_symtab),\
|
||||
|
@ -3401,7 +3401,7 @@ coff_slurp_line_table (abfd, asect)
|
||||
|| (unsigned long) symndx >= obj_raw_syment_count (abfd))
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: warning: illegal symbol index %ld in line numbers",
|
||||
(_("%s: warning: illegal symbol index %ld in line numbers"),
|
||||
bfd_get_filename (abfd), dst.l_addr.l_symndx);
|
||||
symndx = 0;
|
||||
warned = true;
|
||||
@ -3415,7 +3415,7 @@ coff_slurp_line_table (abfd, asect)
|
||||
if (sym->lineno != NULL && ! warned)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: warning: duplicate line number information for `%s'",
|
||||
(_("%s: warning: duplicate line number information for `%s'"),
|
||||
bfd_get_filename (abfd),
|
||||
bfd_asymbol_name (&sym->symbol));
|
||||
}
|
||||
@ -3519,7 +3519,7 @@ coff_slurp_symbol_table (abfd)
|
||||
#ifdef COFF_WITH_PE
|
||||
/* PE uses storage class 0x68 to denote a section symbol */
|
||||
case C_SECTION:
|
||||
/* PE uses storage class 0x67 for a weak external symbol. */
|
||||
/* PE uses storage class 0x69 for a weak external symbol. */
|
||||
case C_NT_WEAK:
|
||||
#endif
|
||||
if ((src->u.syment.n_scnum) == 0)
|
||||
@ -3738,7 +3738,7 @@ coff_slurp_symbol_table (abfd)
|
||||
case C_HIDDEN: /* ext symbol in dmert public lib */
|
||||
default:
|
||||
(*_bfd_error_handler)
|
||||
("%s: Unrecognized storage class %d for %s symbol `%s'",
|
||||
(_("%s: Unrecognized storage class %d for %s symbol `%s'"),
|
||||
bfd_get_filename (abfd), src->u.syment.n_sclass,
|
||||
dst->symbol.section->name, dst->symbol.name);
|
||||
dst->symbol.flags = BSF_DEBUGGING;
|
||||
@ -3922,7 +3922,7 @@ coff_slurp_reloc_table (abfd, asect, symbols)
|
||||
if (dst.r_symndx < 0 || dst.r_symndx >= obj_conv_table_size (abfd))
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: warning: illegal symbol index %ld in relocs",
|
||||
(_("%s: warning: illegal symbol index %ld in relocs"),
|
||||
bfd_get_filename (abfd), dst.r_symndx);
|
||||
cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
|
||||
ptr = NULL;
|
||||
@ -3960,7 +3960,7 @@ coff_slurp_reloc_table (abfd, asect, symbols)
|
||||
if (cache_ptr->howto == NULL)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: illegal relocation type %d at address 0x%lx",
|
||||
(_("%s: illegal relocation type %d at address 0x%lx"),
|
||||
bfd_get_filename (abfd), dst.r_type, (long) dst.r_vaddr);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
@ -4299,3 +4299,7 @@ static CONST bfd_coff_backend_data bfd_coff_std_swap_table =
|
||||
#ifndef coff_bfd_relax_section
|
||||
#define coff_bfd_relax_section bfd_generic_relax_section
|
||||
#endif
|
||||
|
||||
#ifndef coff_bfd_gc_sections
|
||||
#define coff_bfd_gc_sections bfd_generic_gc_sections
|
||||
#endif
|
||||
|
165
bfd/elf-m10300.c
165
bfd/elf-m10300.c
@ -92,6 +92,12 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
|
||||
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
|
||||
static void mn10300_info_to_howto
|
||||
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
|
||||
static boolean mn10300_elf_check_relocs
|
||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||
const Elf_Internal_Rela *));
|
||||
static asection *mn10300_elf_gc_mark_hook
|
||||
PARAMS ((bfd *, struct bfd_link_info *info, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *));
|
||||
static boolean mn10300_elf_relax_delete_bytes
|
||||
PARAMS ((bfd *, asection *, bfd_vma, int));
|
||||
static boolean mn10300_elf_symbol_address_p
|
||||
@ -115,6 +121,11 @@ enum reloc_type
|
||||
R_MN10300_PCREL32,
|
||||
R_MN10300_PCREL16,
|
||||
R_MN10300_PCREL8,
|
||||
|
||||
/* These are GNU extensions to enable C++ vtable garbage collection. */
|
||||
R_MN10300_GNU_VTINHERIT,
|
||||
R_MN10300_GNU_VTENTRY,
|
||||
|
||||
R_MN10300_MAX
|
||||
};
|
||||
|
||||
@ -218,6 +229,36 @@ static reloc_howto_type elf_mn10300_howto_table[] =
|
||||
0xff,
|
||||
0xff,
|
||||
true),
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy */
|
||||
HOWTO (R_MN10300_GNU_VTINHERIT, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
0, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
NULL, /* special_function */
|
||||
"R_MN10300_GNU_VTINHERIT", /* name */
|
||||
false, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* GNU extension to record C++ vtable member usage */
|
||||
HOWTO (R_MN10300_GNU_VTENTRY, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
0, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
NULL, /* special_function */
|
||||
"R_MN10300_GNU_VTENTRY", /* name */
|
||||
false, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
};
|
||||
|
||||
struct mn10300_reloc_map
|
||||
@ -235,6 +276,8 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] =
|
||||
{ BFD_RELOC_32_PCREL, R_MN10300_PCREL32, },
|
||||
{ BFD_RELOC_16_PCREL, R_MN10300_PCREL16, },
|
||||
{ BFD_RELOC_8_PCREL, R_MN10300_PCREL8, },
|
||||
{ BFD_RELOC_VTABLE_INHERIT, R_MN10300_GNU_VTINHERIT },
|
||||
{ BFD_RELOC_VTABLE_ENTRY, R_MN10300_GNU_VTENTRY },
|
||||
};
|
||||
|
||||
static reloc_howto_type *
|
||||
@ -270,6 +313,109 @@ mn10300_info_to_howto (abfd, cache_ptr, dst)
|
||||
cache_ptr->howto = &elf_mn10300_howto_table[r_type];
|
||||
}
|
||||
|
||||
/* Look through the relocs for a section during the first phase.
|
||||
Since we don't do .gots or .plts, we just need to consider the
|
||||
virtual table relocs for gc. */
|
||||
|
||||
static boolean
|
||||
mn10300_elf_check_relocs (abfd, info, sec, relocs)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
asection *sec;
|
||||
const Elf_Internal_Rela *relocs;
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
|
||||
const Elf_Internal_Rela *rel;
|
||||
const Elf_Internal_Rela *rel_end;
|
||||
|
||||
if (info->relocateable)
|
||||
return true;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
|
||||
if (!elf_bad_symtab (abfd))
|
||||
sym_hashes_end -= symtab_hdr->sh_info;
|
||||
|
||||
rel_end = relocs + sec->reloc_count;
|
||||
for (rel = relocs; rel < rel_end; rel++)
|
||||
{
|
||||
struct elf_link_hash_entry *h;
|
||||
unsigned long r_symndx;
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = NULL;
|
||||
else
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
/* This relocation describes the C++ object vtable hierarchy.
|
||||
Reconstruct it for later use during GC. */
|
||||
case R_MN10300_GNU_VTINHERIT:
|
||||
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
/* This relocation describes which C++ vtable entries are actually
|
||||
used. Record for later use during GC. */
|
||||
case R_MN10300_GNU_VTENTRY:
|
||||
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return the section that should be marked against GC for a given
|
||||
relocation. */
|
||||
|
||||
static asection *
|
||||
mn10300_elf_gc_mark_hook (abfd, info, rel, h, sym)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
Elf_Internal_Rela *rel;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym *sym;
|
||||
{
|
||||
if (h != NULL)
|
||||
{
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_MN10300_GNU_VTINHERIT:
|
||||
case R_MN10300_GNU_VTENTRY:
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (h->root.type)
|
||||
{
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
return h->root.u.def.section;
|
||||
|
||||
case bfd_link_hash_common:
|
||||
return h->root.u.c.p->section;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(elf_bad_symtab (abfd)
|
||||
&& ELF_ST_BIND (sym->st_info) != STB_LOCAL)
|
||||
&& ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
|
||||
&& sym->st_shndx != SHN_COMMON))
|
||||
{
|
||||
return bfd_section_from_elf_index (abfd, sym->st_shndx);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Perform a relocation as part of a final link. */
|
||||
static bfd_reloc_status_type
|
||||
mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
|
||||
@ -292,7 +438,6 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
|
||||
case R_MN10300_NONE:
|
||||
return bfd_reloc_ok;
|
||||
|
||||
@ -352,6 +497,10 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
|
||||
bfd_put_32 (input_bfd, value, hit_data);
|
||||
return bfd_reloc_ok;
|
||||
|
||||
case R_MN10300_GNU_VTINHERIT:
|
||||
case R_MN10300_GNU_VTENTRY:
|
||||
return bfd_reloc_ok;
|
||||
|
||||
default:
|
||||
return bfd_reloc_notsupported;
|
||||
}
|
||||
@ -396,6 +545,11 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
howto = elf_mn10300_howto_table + r_type;
|
||||
|
||||
/* Just skip the vtable gc relocs. */
|
||||
if (r_type == R_MN10300_GNU_VTINHERIT
|
||||
|| r_type == R_MN10300_GNU_VTENTRY)
|
||||
continue;
|
||||
|
||||
if (info->relocateable)
|
||||
{
|
||||
/* This is a relocateable link. We don't have to change
|
||||
@ -2556,9 +2710,12 @@ _bfd_mn10300_elf_object_p (abfd)
|
||||
#define ELF_MACHINE_CODE EM_CYGNUS_MN10300
|
||||
#define ELF_MAXPAGESIZE 0x1000
|
||||
|
||||
#define elf_info_to_howto mn10300_info_to_howto
|
||||
#define elf_info_to_howto_rel 0
|
||||
#define elf_backend_relocate_section mn10300_elf_relocate_section
|
||||
#define elf_info_to_howto mn10300_info_to_howto
|
||||
#define elf_info_to_howto_rel 0
|
||||
#define elf_backend_can_gc_sections 1
|
||||
#define elf_backend_check_relocs mn10300_elf_check_relocs
|
||||
#define elf_backend_gc_mark_hook mn10300_elf_gc_mark_hook
|
||||
#define elf_backend_relocate_section mn10300_elf_relocate_section
|
||||
#define bfd_elf32_bfd_relax_section mn10300_elf_relax_section
|
||||
#define bfd_elf32_bfd_get_relocated_section_contents \
|
||||
mn10300_elf_get_relocated_section_contents
|
||||
|
@ -840,10 +840,12 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
|
||||
ret->dynindx = -1;
|
||||
ret->dynstr_index = 0;
|
||||
ret->weakdef = NULL;
|
||||
ret->got_offset = (bfd_vma) -1;
|
||||
ret->plt_offset = (bfd_vma) -1;
|
||||
ret->got.offset = (bfd_vma) -1;
|
||||
ret->plt.offset = (bfd_vma) -1;
|
||||
ret->linker_section_pointer = (elf_linker_section_pointers_t *)0;
|
||||
ret->verinfo.verdef = NULL;
|
||||
ret->vtable_entries_used = NULL;
|
||||
ret->vtable_parent = NULL;
|
||||
ret->type = STT_NOTYPE;
|
||||
ret->other = 0;
|
||||
/* Assume that we have been called by a non-ELF symbol reader.
|
||||
@ -2178,6 +2180,7 @@ map_sections_to_segments (abfd)
|
||||
if (phdr_size == 0)
|
||||
phdr_size = get_elf_backend_data (abfd)->s->sizeof_phdr;
|
||||
if ((abfd->flags & D_PAGED) == 0
|
||||
|| sections[0]->lma < phdr_size
|
||||
|| sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
|
||||
phdr_in_section = false;
|
||||
}
|
||||
|
145
bfd/elf32-m68k.c
145
bfd/elf32-m68k.c
@ -1,5 +1,5 @@
|
||||
/* Motorola 68k series support for 32-bit ELF
|
||||
Copyright 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Copyright 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
@ -38,6 +38,8 @@ static boolean elf_m68k_check_relocs
|
||||
const Elf_Internal_Rela *));
|
||||
static boolean elf_m68k_adjust_dynamic_symbol
|
||||
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
|
||||
static boolean elf_m68k_adjust_dynindx
|
||||
PARAMS ((struct elf_link_hash_entry *, PTR));
|
||||
static boolean elf_m68k_size_dynamic_sections
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static boolean elf_m68k_relocate_section
|
||||
@ -414,12 +416,12 @@ elf_m68k_check_relocs (abfd, info, sec, relocs)
|
||||
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->got_offset != (bfd_vma) -1)
|
||||
if (h->got.offset != (bfd_vma) -1)
|
||||
{
|
||||
/* We have already allocated space in the .got. */
|
||||
break;
|
||||
}
|
||||
h->got_offset = sgot->_raw_size;
|
||||
h->got.offset = sgot->_raw_size;
|
||||
|
||||
/* Make sure this symbol is output as a dynamic symbol. */
|
||||
if (h->dynindx == -1)
|
||||
@ -699,7 +701,7 @@ elf_m68k_adjust_dynamic_symbol (info, h)
|
||||
h->root.u.def.value = s->_raw_size;
|
||||
}
|
||||
|
||||
h->plt_offset = s->_raw_size;
|
||||
h->plt.offset = s->_raw_size;
|
||||
|
||||
/* Make room for this entry. */
|
||||
s->_raw_size += PLT_ENTRY_SIZE;
|
||||
@ -911,7 +913,8 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
|
||||
s->output_section);
|
||||
target = bfd_get_section_by_name (output_bfd, outname + 5);
|
||||
if (target != NULL
|
||||
&& (target->flags & SEC_READONLY) != 0)
|
||||
&& (target->flags & SEC_READONLY) != 0
|
||||
&& (target->flags & SEC_ALLOC) != 0)
|
||||
reltext = true;
|
||||
}
|
||||
|
||||
@ -984,6 +987,51 @@ elf_m68k_size_dynamic_sections (output_bfd, info)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we are generating a shared library, we generate a section
|
||||
symbol for each output section for which we might need to copy
|
||||
relocs. These are local symbols, which means that they must come
|
||||
first in the dynamic symbol table. That means we must increment
|
||||
the dynamic symbol index of every other dynamic symbol. */
|
||||
if (info->shared)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = 0;
|
||||
for (s = output_bfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
if ((s->flags & SEC_LINKER_CREATED) != 0
|
||||
|| (s->flags & SEC_ALLOC) == 0)
|
||||
continue;
|
||||
|
||||
elf_section_data (s)->dynindx = c + 1;
|
||||
|
||||
/* These symbols will have no names, so we don't need to
|
||||
fiddle with dynstr_index. */
|
||||
|
||||
++c;
|
||||
}
|
||||
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_m68k_adjust_dynindx,
|
||||
(PTR) &c);
|
||||
elf_hash_table (info)->dynsymcount += c;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Increment the index of a dynamic symbol by a given amount. Called
|
||||
via elf_link_hash_traverse. */
|
||||
|
||||
static boolean
|
||||
elf_m68k_adjust_dynindx (h, cparg)
|
||||
struct elf_link_hash_entry *h;
|
||||
PTR cparg;
|
||||
{
|
||||
int *cp = (int *) cparg;
|
||||
|
||||
if (h->dynindx != -1)
|
||||
h->dynindx += *cp;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1114,7 +1162,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|| r_type == R_68K_PLT8O
|
||||
|| r_type == R_68K_PLT16O
|
||||
|| r_type == R_68K_PLT32O)
|
||||
&& h->plt_offset != (bfd_vma) -1)
|
||||
&& h->plt.offset != (bfd_vma) -1)
|
||||
|| ((r_type == R_68K_GOT8O
|
||||
|| r_type == R_68K_GOT16O
|
||||
|| r_type == R_68K_GOT32O
|
||||
@ -1192,7 +1240,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
if (h != NULL)
|
||||
{
|
||||
off = h->got_offset;
|
||||
off = h->got.offset;
|
||||
BFD_ASSERT (off != (bfd_vma) -1);
|
||||
|
||||
if (!elf_hash_table (info)->dynamic_sections_created
|
||||
@ -1218,7 +1266,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
{
|
||||
bfd_put_32 (output_bfd, relocation,
|
||||
sgot->contents + off);
|
||||
h->got_offset |= 1;
|
||||
h->got.offset |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1286,7 +1334,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
if (h == NULL)
|
||||
break;
|
||||
|
||||
if (h->plt_offset == (bfd_vma) -1)
|
||||
if (h->plt.offset == (bfd_vma) -1)
|
||||
{
|
||||
/* We didn't make a PLT entry for this symbol. This
|
||||
happens when statically linking PIC code, or when
|
||||
@ -1302,7 +1350,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
relocation = (splt->output_section->vma
|
||||
+ splt->output_offset
|
||||
+ h->plt_offset);
|
||||
+ h->plt.offset);
|
||||
break;
|
||||
|
||||
case R_68K_PLT8O:
|
||||
@ -1310,7 +1358,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
case R_68K_PLT32O:
|
||||
/* Relocation is the offset of the entry for this symbol in
|
||||
the procedure linkage table. */
|
||||
BFD_ASSERT (h != NULL && h->plt_offset == (bfd_vma) -1);
|
||||
BFD_ASSERT (h != NULL && h->plt.offset != (bfd_vma) -1);
|
||||
|
||||
if (splt == NULL)
|
||||
{
|
||||
@ -1318,7 +1366,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
BFD_ASSERT (splt != NULL);
|
||||
}
|
||||
|
||||
relocation = h->plt_offset;
|
||||
relocation = h->plt.offset;
|
||||
|
||||
/* This relocation does not use the addend. */
|
||||
rel->r_addend = 0;
|
||||
@ -1442,8 +1490,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
osec = sec->output_section;
|
||||
indx = elf_section_data (osec)->dynindx;
|
||||
if (indx == 0)
|
||||
abort ();
|
||||
BFD_ASSERT (indx > 0);
|
||||
}
|
||||
|
||||
relocate = false;
|
||||
@ -1526,7 +1573,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
|
||||
if (h->plt_offset != (bfd_vma) -1)
|
||||
if (h->plt.offset != (bfd_vma) -1)
|
||||
{
|
||||
asection *splt;
|
||||
asection *sgot;
|
||||
@ -1549,7 +1596,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
corresponds to this symbol. This is the index of this symbol
|
||||
in all the symbols for which we are making plt entries. The
|
||||
first entry in the procedure linkage table is reserved. */
|
||||
plt_index = h->plt_offset / PLT_ENTRY_SIZE - 1;
|
||||
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
|
||||
|
||||
/* Get the offset into the .got table of the entry that
|
||||
corresponds to this function. Each .got entry is 4 bytes.
|
||||
@ -1557,7 +1604,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
got_offset = (plt_index + 3) * 4;
|
||||
|
||||
/* Fill in the entry in the procedure linkage table. */
|
||||
memcpy (splt->contents + h->plt_offset, elf_m68k_plt_entry,
|
||||
memcpy (splt->contents + h->plt.offset, elf_m68k_plt_entry,
|
||||
PLT_ENTRY_SIZE);
|
||||
/* The offset is relative to the first extension word. */
|
||||
bfd_put_32 (output_bfd,
|
||||
@ -1565,19 +1612,19 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
+ sgot->output_offset
|
||||
+ got_offset
|
||||
- (splt->output_section->vma
|
||||
+ h->plt_offset + 2)),
|
||||
splt->contents + h->plt_offset + 4);
|
||||
+ h->plt.offset + 2)),
|
||||
splt->contents + h->plt.offset + 4);
|
||||
|
||||
bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
|
||||
splt->contents + h->plt_offset + 10);
|
||||
bfd_put_32 (output_bfd, - (h->plt_offset + 16),
|
||||
splt->contents + h->plt_offset + 16);
|
||||
splt->contents + h->plt.offset + 10);
|
||||
bfd_put_32 (output_bfd, - (h->plt.offset + 16),
|
||||
splt->contents + h->plt.offset + 16);
|
||||
|
||||
/* Fill in the entry in the global offset table. */
|
||||
bfd_put_32 (output_bfd,
|
||||
(splt->output_section->vma
|
||||
+ splt->output_offset
|
||||
+ h->plt_offset
|
||||
+ h->plt.offset
|
||||
+ 8),
|
||||
sgot->contents + got_offset);
|
||||
|
||||
@ -1599,7 +1646,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
}
|
||||
}
|
||||
|
||||
if (h->got_offset != (bfd_vma) -1)
|
||||
if (h->got.offset != (bfd_vma) -1)
|
||||
{
|
||||
asection *sgot;
|
||||
asection *srela;
|
||||
@ -1614,7 +1661,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
|
||||
rela.r_offset = (sgot->output_section->vma
|
||||
+ sgot->output_offset
|
||||
+ (h->got_offset &~ 1));
|
||||
+ (h->got.offset &~ 1));
|
||||
|
||||
/* If this is a -Bsymbolic link, and the symbol is defined
|
||||
locally, we just want to emit a RELATIVE reloc. Likewise if
|
||||
@ -1628,12 +1675,12 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
|
||||
rela.r_addend = bfd_get_signed_32 (output_bfd,
|
||||
(sgot->contents
|
||||
+ (h->got_offset & ~1)));
|
||||
+ (h->got.offset & ~1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, (bfd_vma) 0,
|
||||
sgot->contents + (h->got_offset & ~1));
|
||||
sgot->contents + (h->got.offset & ~1));
|
||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT);
|
||||
rela.r_addend = 0;
|
||||
}
|
||||
@ -1796,6 +1843,50 @@ elf_m68k_finish_dynamic_sections (output_bfd, info)
|
||||
|
||||
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
|
||||
|
||||
if (info->shared)
|
||||
{
|
||||
asection *sdynsym;
|
||||
asection *s;
|
||||
Elf_Internal_Sym sym;
|
||||
int c;
|
||||
|
||||
/* Set up the section symbols for the output sections. */
|
||||
|
||||
sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
|
||||
BFD_ASSERT (sdynsym != NULL);
|
||||
|
||||
sym.st_size = 0;
|
||||
sym.st_name = 0;
|
||||
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
|
||||
sym.st_other = 0;
|
||||
|
||||
c = 0;
|
||||
for (s = output_bfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
int indx;
|
||||
|
||||
if (elf_section_data (s)->dynindx == 0)
|
||||
continue;
|
||||
|
||||
sym.st_value = s->vma;
|
||||
|
||||
indx = elf_section_data (s)->this_idx;
|
||||
BFD_ASSERT (indx > 0);
|
||||
sym.st_shndx = indx;
|
||||
|
||||
bfd_elf32_swap_symbol_out (output_bfd, &sym,
|
||||
(PTR) (((Elf32_External_Sym *)
|
||||
sdynsym->contents)
|
||||
+ elf_section_data (s)->dynindx));
|
||||
|
||||
++c;
|
||||
}
|
||||
|
||||
/* Set the sh_info field of the output .dynsym section to the
|
||||
index of the first global symbol. */
|
||||
elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
265
bfd/elf32-mips.c
265
bfd/elf32-mips.c
@ -317,12 +317,15 @@ enum reloc_type
|
||||
R_MIPS_max,
|
||||
/* These relocs are used for the mips16. */
|
||||
R_MIPS16_26 = 100,
|
||||
R_MIPS16_GPREL = 101
|
||||
R_MIPS16_GPREL = 101,
|
||||
/* start-sanitize-sky */
|
||||
/* These relocs are for the dvp. */
|
||||
, R_MIPS_DVP_11_PCREL = 120,
|
||||
R_MIPS_DVP_27_S4 = 121
|
||||
R_MIPS_DVP_11_PCREL = 120,
|
||||
R_MIPS_DVP_27_S4 = 121,
|
||||
/* end-sanitize-sky */
|
||||
/* These are GNU extensions to enable C++ vtable garbage collection. */
|
||||
R_MIPS_GNU_VTINHERIT = 253,
|
||||
R_MIPS_GNU_VTENTRY = 254
|
||||
};
|
||||
|
||||
static reloc_howto_type elf_mips_howto_table[] =
|
||||
@ -814,6 +817,38 @@ static reloc_howto_type elf_mips_dvp_27_s4_howto =
|
||||
false); /* pcrel_offset */
|
||||
/* end-sanitize-sky */
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy */
|
||||
static reloc_howto_type elf_mips_gnu_vtinherit_howto =
|
||||
HOWTO (R_MIPS_GNU_VTINHERIT, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
0, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
NULL, /* special_function */
|
||||
"R_MIPS_GNU_VTINHERIT", /* name */
|
||||
false, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
false); /* pcrel_offset */
|
||||
|
||||
/* GNU extension to record C++ vtable member usage */
|
||||
static reloc_howto_type elf_mips_gnu_vtentry_howto =
|
||||
HOWTO (R_MIPS_GNU_VTENTRY, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
0, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
NULL, /* special_function */
|
||||
"R_MIPS_GNU_VTENTRY", /* name */
|
||||
false, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
false); /* pcrel_offset */
|
||||
|
||||
/* Do a R_MIPS_HI16 relocation. This has to be done in combination
|
||||
with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
|
||||
the HI16. Here we just save the information we need; we do the
|
||||
@ -1662,30 +1697,32 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
|
||||
return &elf_mips_howto_table[(int) mips_reloc_map[i].elf_reloc_val];
|
||||
}
|
||||
|
||||
/* We need to handle BFD_RELOC_CTOR specially.
|
||||
|
||||
Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
|
||||
size of addresses on this architecture. */
|
||||
if (code == BFD_RELOC_CTOR)
|
||||
switch (code)
|
||||
{
|
||||
case BFD_RELOC_CTOR:
|
||||
/* We need to handle BFD_RELOC_CTOR specially.
|
||||
Select the right relocation (R_MIPS_32 or R_MIPS_64) based on the
|
||||
size of addresses on this architecture. */
|
||||
if (bfd_arch_bits_per_address (abfd) == 32)
|
||||
return &elf_mips_howto_table[(int) R_MIPS_32];
|
||||
else
|
||||
return &elf_mips_ctor64_howto;
|
||||
}
|
||||
|
||||
/* Special handling for the MIPS16 relocs, since they are made up
|
||||
reloc types with a large value. */
|
||||
if (code == BFD_RELOC_MIPS16_JMP)
|
||||
return &elf_mips16_jump_howto;
|
||||
else if (code == BFD_RELOC_MIPS16_GPREL)
|
||||
return &elf_mips16_gprel_howto;
|
||||
case BFD_RELOC_MIPS16_JMP:
|
||||
return &elf_mips16_jump_howto;
|
||||
case BFD_RELOC_MIPS16_GPREL:
|
||||
return &elf_mips16_gprel_howto;
|
||||
/* start-sanitize-sky */
|
||||
else if (code == BFD_RELOC_MIPS_DVP_11_PCREL)
|
||||
return &elf_mips_dvp_11_pcrel_howto;
|
||||
else if (code == BFD_RELOC_MIPS_DVP_27_S4)
|
||||
return &elf_mips_dvp_27_s4_howto;
|
||||
case BFD_RELOC_MIPS_DVP_11_PCREL:
|
||||
return &elf_mips_dvp_11_pcrel_howto;
|
||||
case BFD_RELOC_MIPS_DVP_27_S4:
|
||||
return &elf_mips_dvp_27_s4_howto;
|
||||
/* end-sanitize-sky */
|
||||
case BFD_RELOC_VTABLE_INHERIT:
|
||||
return &elf_mips_gnu_vtinherit_howto;
|
||||
case BFD_RELOC_VTABLE_ENTRY:
|
||||
return &elf_mips_gnu_vtentry_howto;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -1701,20 +1738,33 @@ mips_info_to_howto_rel (abfd, cache_ptr, dst)
|
||||
unsigned int r_type;
|
||||
|
||||
r_type = ELF32_R_TYPE (dst->r_info);
|
||||
if (r_type == R_MIPS16_26)
|
||||
cache_ptr->howto = &elf_mips16_jump_howto;
|
||||
else if (r_type == R_MIPS16_GPREL)
|
||||
cache_ptr->howto = &elf_mips16_gprel_howto;
|
||||
/* start-sanitize-sky */
|
||||
else if (r_type == R_MIPS_DVP_11_PCREL)
|
||||
cache_ptr->howto = &elf_mips_dvp_11_pcrel_howto;
|
||||
else if (r_type == R_MIPS_DVP_27_S4)
|
||||
cache_ptr->howto = &elf_mips_dvp_27_s4_howto;
|
||||
/* end-sanitize-sky */
|
||||
else
|
||||
switch (r_type)
|
||||
{
|
||||
case R_MIPS16_26:
|
||||
cache_ptr->howto = &elf_mips16_jump_howto;
|
||||
break;
|
||||
case R_MIPS16_GPREL:
|
||||
cache_ptr->howto = &elf_mips16_gprel_howto;
|
||||
break;
|
||||
/* start-sanitize-sky */
|
||||
case R_MIPS_DVP_11_PCREL:
|
||||
cache_ptr->howto = &elf_mips_dvp_11_pcrel_howto;
|
||||
break;
|
||||
case R_MIPS_DVP_27_S4:
|
||||
cache_ptr->howto = &elf_mips_dvp_27_s4_howto;
|
||||
break;
|
||||
/* end-sanitize-sky */
|
||||
case R_MIPS_GNU_VTINHERIT:
|
||||
cache_ptr->howto = &elf_mips_gnu_vtinherit_howto;
|
||||
break;
|
||||
case R_MIPS_GNU_VTENTRY:
|
||||
cache_ptr->howto = &elf_mips_gnu_vtentry_howto;
|
||||
break;
|
||||
|
||||
default:
|
||||
BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
|
||||
cache_ptr->howto = &elf_mips_howto_table[r_type];
|
||||
break;
|
||||
}
|
||||
|
||||
/* The addend for a GPREL16 or LITERAL relocation comes from the GP
|
||||
@ -2558,7 +2608,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec)
|
||||
else if (strcmp (name, SHNAME_DVP_OVERLAY_TABLE) == 0)
|
||||
{
|
||||
hdr->sh_type = SHT_DVP_OVERLAY_TABLE;
|
||||
hdr->sh_entsize = sizeof (Elf64_Dvp_External_Overlay);
|
||||
hdr->sh_entsize = sizeof (Elf32_Dvp_External_Overlay);
|
||||
/* The sh_link field is set in final_write_processing. */
|
||||
}
|
||||
else if (strcmp (name, SHNAME_DVP_OVERLAY_STRTAB) == 0)
|
||||
@ -3792,7 +3842,7 @@ mips_elf_output_extsym (h, data)
|
||||
{
|
||||
output_section = sec->output_section;
|
||||
if (output_section != NULL)
|
||||
h->esym.asym.value = (h->root.plt_offset
|
||||
h->esym.asym.value = (h->root.plt.offset
|
||||
+ sec->output_offset
|
||||
+ output_section->vma);
|
||||
else
|
||||
@ -4815,6 +4865,9 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
bfd_reloc_status_type r;
|
||||
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
if (r_type == R_MIPS_GNU_VTINHERIT
|
||||
|| r_type == R_MIPS_GNU_VTENTRY)
|
||||
continue;
|
||||
if ((r_type < 0 || r_type >= (int) R_MIPS_max)
|
||||
/* start-sanitize-sky */
|
||||
&& r_type != R_MIPS_DVP_11_PCREL
|
||||
@ -5239,7 +5292,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
/* This symbol must be registered as a global symbol
|
||||
having the corresponding got entry. */
|
||||
BFD_ASSERT (h->got_offset != (bfd_vma) -1);
|
||||
BFD_ASSERT (h->got.offset != (bfd_vma) -1);
|
||||
|
||||
offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
|
||||
BFD_ASSERT (g->local_gotno <= offset
|
||||
@ -5259,7 +5312,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
/* This must be a global symbol with a got entry. The
|
||||
next reloc must be the corresponding LO16 reloc. */
|
||||
BFD_ASSERT (h != NULL && h->got_offset != (bfd_vma) -1);
|
||||
BFD_ASSERT (h != NULL && h->got.offset != (bfd_vma) -1);
|
||||
BFD_ASSERT ((rel + 1) < relend);
|
||||
BFD_ASSERT ((int) ELF32_R_TYPE ((rel + 1)->r_info)
|
||||
== (r_type == R_MIPS_CALL_HI16
|
||||
@ -6210,7 +6263,7 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (h->got_offset != (bfd_vma) -1)
|
||||
if (h->got.offset != (bfd_vma) -1)
|
||||
{
|
||||
/* We have already allocated space in the .got. */
|
||||
break;
|
||||
@ -6222,7 +6275,7 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
g->global_gotsym = h->dynindx;
|
||||
|
||||
/* Make this symbol to have the corresponding got entry. */
|
||||
h->got_offset = 0;
|
||||
h->got.offset = 0;
|
||||
|
||||
/* We need a stub, not a plt entry for the undefined
|
||||
function. But we record it as if it needs plt. See
|
||||
@ -6246,7 +6299,7 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (h->got_offset != (bfd_vma) -1)
|
||||
if (h->got.offset != (bfd_vma) -1)
|
||||
{
|
||||
/* We have already allocated space in the .got. */
|
||||
break;
|
||||
@ -6258,7 +6311,7 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
g->global_gotsym = h->dynindx;
|
||||
|
||||
/* Make this symbol to be the global got symbol. */
|
||||
h->got_offset = 0;
|
||||
h->got.offset = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -6329,6 +6382,20 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
sizeof (Elf32_External_crinfo);
|
||||
break;
|
||||
|
||||
/* This relocation describes the C++ object vtable hierarchy.
|
||||
Reconstruct it for later use during GC. */
|
||||
case R_MIPS_GNU_VTINHERIT:
|
||||
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
/* This relocation describes which C++ vtable entries are actually
|
||||
used. Record for later use during GC. */
|
||||
case R_MIPS_GNU_VTENTRY:
|
||||
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -6355,6 +6422,98 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return the section that should be marked against GC for a given
|
||||
relocation. */
|
||||
|
||||
static asection *
|
||||
mips_elf_gc_mark_hook (abfd, info, rel, h, sym)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
Elf_Internal_Rela *rel;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym *sym;
|
||||
{
|
||||
/* ??? Do mips16 stub sections need to be handled special? */
|
||||
|
||||
if (h != NULL)
|
||||
{
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_MIPS_GNU_VTINHERIT:
|
||||
case R_MIPS_GNU_VTENTRY:
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (h->root.type)
|
||||
{
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
return h->root.u.def.section;
|
||||
|
||||
case bfd_link_hash_common:
|
||||
return h->root.u.c.p->section;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(elf_bad_symtab (abfd)
|
||||
&& ELF_ST_BIND (sym->st_info) != STB_LOCAL)
|
||||
&& ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
|
||||
&& sym->st_shndx != SHN_COMMON))
|
||||
{
|
||||
return bfd_section_from_elf_index (abfd, sym->st_shndx);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Update the got entry reference counts for the section being removed. */
|
||||
|
||||
static boolean
|
||||
mips_elf_gc_sweep_hook (abfd, info, sec, relocs)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
asection *sec;
|
||||
const Elf_Internal_Rela *relocs;
|
||||
{
|
||||
#if 0
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes;
|
||||
bfd_signed_vma *local_got_refcounts;
|
||||
const Elf_Internal_Rela *rel, *relend;
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
local_got_refcounts = elf_local_got_refcounts (abfd);
|
||||
|
||||
relend = relocs + sec->reloc_count;
|
||||
for (rel = relocs; rel < relend; rel++)
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_MIPS_GOT16:
|
||||
case R_MIPS_CALL16:
|
||||
case R_MIPS_CALL_HI16:
|
||||
case R_MIPS_CALL_LO16:
|
||||
case R_MIPS_GOT_HI16:
|
||||
case R_MIPS_GOT_LO16:
|
||||
/* ??? It would seem that the existing MIPS code does no sort
|
||||
of reference counting or whatnot on its GOT and PLT entries,
|
||||
so it is not possible to garbage collect them at this time. */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Adjust a symbol defined by a dynamic object and referenced by a
|
||||
regular object. The current definition is in some section of the
|
||||
dynamic object, but we're not including those sections. We have to
|
||||
@ -6424,7 +6583,7 @@ mips_elf_adjust_dynamic_symbol (info, h)
|
||||
h->root.u.def.value = s->_raw_size;
|
||||
|
||||
/* XXX Write this stub address somewhere. */
|
||||
h->plt_offset = s->_raw_size;
|
||||
h->plt.offset = s->_raw_size;
|
||||
|
||||
/* Make room for this stub code. */
|
||||
s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
|
||||
@ -6608,7 +6767,18 @@ mips_elf_size_dynamic_sections (output_bfd, info)
|
||||
if (strncmp (name, ".rel", 4) == 0)
|
||||
{
|
||||
if (s->_raw_size == 0)
|
||||
strip = true;
|
||||
{
|
||||
/* We only strip the section if the output section name
|
||||
has the same name. Otherwise, there might be several
|
||||
input sections for this output section. FIXME: This
|
||||
code is probably not needed these days anyhow, since
|
||||
the linker now does not create empty output sections. */
|
||||
if (s->output_section != NULL
|
||||
&& strcmp (name,
|
||||
bfd_get_section_name (s->output_section->owner,
|
||||
s->output_section)) == 0)
|
||||
strip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *outname;
|
||||
@ -6917,7 +7087,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
gval = sym->st_value;
|
||||
|
||||
if (h->plt_offset != (bfd_vma) -1)
|
||||
if (h->plt.offset != (bfd_vma) -1)
|
||||
{
|
||||
asection *s;
|
||||
bfd_byte *p;
|
||||
@ -6945,17 +7115,17 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, STUB_LI16 + h->dynindx, p);
|
||||
|
||||
BFD_ASSERT (h->plt_offset <= s->_raw_size);
|
||||
memcpy (s->contents + h->plt_offset, stub, MIPS_FUNCTION_STUB_SIZE);
|
||||
BFD_ASSERT (h->plt.offset <= s->_raw_size);
|
||||
memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
|
||||
|
||||
/* Mark the symbol as undefined. plt_offset != -1 occurs
|
||||
/* Mark the symbol as undefined. plt.offset != -1 occurs
|
||||
only for the referenced symbol. */
|
||||
sym->st_shndx = SHN_UNDEF;
|
||||
|
||||
/* The run-time linker uses the st_value field of the symbol
|
||||
to reset the global offset table entry for this external
|
||||
to its stub address when unlinking a shared object. */
|
||||
gval = s->output_section->vma + s->output_offset + h->plt_offset;
|
||||
gval = s->output_section->vma + s->output_offset + h->plt.offset;
|
||||
sym->st_value = gval;
|
||||
}
|
||||
|
||||
@ -6973,7 +7143,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
|
||||
/* This symbol has an entry in the global offset table. Set its
|
||||
value to the corresponding got entry, if needed. */
|
||||
if (h->got_offset == (bfd_vma) -1)
|
||||
if (h->got.offset == (bfd_vma) -1)
|
||||
{
|
||||
offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
|
||||
BFD_ASSERT (g->local_gotno * 4 <= offset
|
||||
@ -7612,6 +7782,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap =
|
||||
|
||||
#define elf_backend_collect true
|
||||
#define elf_backend_type_change_ok true
|
||||
#define elf_backend_can_gc_sections true
|
||||
#define elf_info_to_howto 0
|
||||
#define elf_info_to_howto_rel mips_info_to_howto_rel
|
||||
#define elf_backend_sym_is_global mips_elf_sym_is_global
|
||||
@ -7658,5 +7829,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap =
|
||||
mips_elf_finish_dynamic_symbol
|
||||
#define elf_backend_finish_dynamic_sections \
|
||||
mips_elf_finish_dynamic_sections
|
||||
#define elf_backend_gc_mark_hook mips_elf_gc_mark_hook
|
||||
#define elf_backend_gc_sweep_hook mips_elf_gc_sweep_hook
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
562
bfd/elflink.h
562
bfd/elflink.h
@ -1459,12 +1459,12 @@ elf_link_add_object_symbols (abfd, info)
|
||||
/* Copy over the global table offset entry.
|
||||
This may have been already set up by a
|
||||
check_relocs routine. */
|
||||
if (ht->got_offset == (bfd_vma) -1)
|
||||
if (ht->got.offset == (bfd_vma) -1)
|
||||
{
|
||||
ht->got_offset = hi->got_offset;
|
||||
hi->got_offset = (bfd_vma) -1;
|
||||
ht->got.offset = hi->got.offset;
|
||||
hi->got.offset = (bfd_vma) -1;
|
||||
}
|
||||
BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
|
||||
BFD_ASSERT (hi->got.offset == (bfd_vma) -1);
|
||||
|
||||
if (ht->dynindx == -1)
|
||||
{
|
||||
@ -1560,12 +1560,12 @@ elf_link_add_object_symbols (abfd, info)
|
||||
/* Copy over the global table offset entry.
|
||||
This may have been already set up by a
|
||||
check_relocs routine. */
|
||||
if (h->got_offset == (bfd_vma) -1)
|
||||
if (h->got.offset == (bfd_vma) -1)
|
||||
{
|
||||
h->got_offset = hi->got_offset;
|
||||
hi->got_offset = (bfd_vma) -1;
|
||||
h->got.offset = hi->got.offset;
|
||||
hi->got.offset = (bfd_vma) -1;
|
||||
}
|
||||
BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
|
||||
BFD_ASSERT (hi->got.offset == (bfd_vma) -1);
|
||||
|
||||
if (h->dynindx == -1)
|
||||
{
|
||||
@ -4884,7 +4884,8 @@ elf_link_input_bfd (finfo, input_bfd)
|
||||
/* Write out the modified section contents. */
|
||||
if (elf_section_data (o)->stab_info == NULL)
|
||||
{
|
||||
if (! bfd_set_section_contents (output_bfd, o->output_section,
|
||||
if (! (o->flags & SEC_EXCLUDE) &&
|
||||
! bfd_set_section_contents (output_bfd, o->output_section,
|
||||
contents, o->output_offset,
|
||||
(o->_cooked_size != 0
|
||||
? o->_cooked_size
|
||||
@ -5298,3 +5299,546 @@ elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, reloca
|
||||
processing. */
|
||||
return relocation - linker_section_ptr->addend;
|
||||
}
|
||||
|
||||
/* Garbage collect unused sections. */
|
||||
|
||||
static boolean elf_gc_mark
|
||||
PARAMS ((struct bfd_link_info *info, asection *sec,
|
||||
asection * (*gc_mark_hook)
|
||||
PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *))));
|
||||
|
||||
static boolean elf_gc_sweep
|
||||
PARAMS ((struct bfd_link_info *info,
|
||||
boolean (*gc_sweep_hook)
|
||||
PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *o,
|
||||
const Elf_Internal_Rela *relocs))));
|
||||
|
||||
static boolean elf_gc_sweep_symbol
|
||||
PARAMS ((struct elf_link_hash_entry *h, PTR idxptr));
|
||||
|
||||
static boolean elf_gc_allocate_got_offsets
|
||||
PARAMS ((struct elf_link_hash_entry *h, PTR offarg));
|
||||
|
||||
static boolean elf_gc_propogate_vtable_entries_used
|
||||
PARAMS ((struct elf_link_hash_entry *h, PTR dummy));
|
||||
|
||||
static boolean elf_gc_smash_unused_vtentry_relocs
|
||||
PARAMS ((struct elf_link_hash_entry *h, PTR dummy));
|
||||
|
||||
/* The mark phase of garbage collection. For a given section, mark
|
||||
it, and all the sections which define symbols to which it refers. */
|
||||
|
||||
static boolean
|
||||
elf_gc_mark (info, sec, gc_mark_hook)
|
||||
struct bfd_link_info *info;
|
||||
asection *sec;
|
||||
asection * (*gc_mark_hook)
|
||||
PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *));
|
||||
{
|
||||
boolean ret = true;
|
||||
|
||||
sec->gc_mark = 1;
|
||||
|
||||
/* Look through the section relocs. */
|
||||
|
||||
if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
|
||||
{
|
||||
Elf_Internal_Rela *relstart, *rel, *relend;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes;
|
||||
size_t nlocsyms;
|
||||
size_t extsymoff;
|
||||
Elf_External_Sym *locsyms, *freesyms = NULL;
|
||||
bfd *input_bfd = sec->owner;
|
||||
|
||||
/* GCFIXME: how to arrange so that relocs and symbols are not
|
||||
reread continually? */
|
||||
|
||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||
sym_hashes = elf_sym_hashes (input_bfd);
|
||||
|
||||
/* Read the local symbols. */
|
||||
if (elf_bad_symtab (input_bfd))
|
||||
{
|
||||
nlocsyms = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
|
||||
extsymoff = 0;
|
||||
}
|
||||
else
|
||||
extsymoff = nlocsyms = symtab_hdr->sh_info;
|
||||
if (symtab_hdr->contents)
|
||||
locsyms = (Elf_External_Sym *) symtab_hdr->contents;
|
||||
else if (nlocsyms == 0)
|
||||
locsyms = NULL;
|
||||
else
|
||||
{
|
||||
locsyms = freesyms =
|
||||
bfd_malloc (nlocsyms * sizeof (Elf_External_Sym));
|
||||
if (freesyms == NULL
|
||||
|| bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
|
||||
|| (bfd_read (locsyms, sizeof (Elf_External_Sym),
|
||||
nlocsyms, input_bfd)
|
||||
!= nlocsyms * sizeof (Elf_External_Sym)))
|
||||
{
|
||||
ret = false;
|
||||
goto out1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the relocations. */
|
||||
relstart = (NAME(_bfd_elf,link_read_relocs)
|
||||
(sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL,
|
||||
info->keep_memory));
|
||||
if (relstart == NULL)
|
||||
{
|
||||
ret = false;
|
||||
goto out1;
|
||||
}
|
||||
relend = relstart + sec->reloc_count;
|
||||
|
||||
for (rel = relstart; rel < relend; rel++)
|
||||
{
|
||||
unsigned long r_symndx;
|
||||
asection *rsec;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym s;
|
||||
|
||||
r_symndx = ELF_R_SYM (rel->r_info);
|
||||
if (r_symndx == 0)
|
||||
continue;
|
||||
|
||||
if (elf_bad_symtab (sec->owner))
|
||||
{
|
||||
elf_swap_symbol_in (input_bfd, &locsyms[r_symndx], &s);
|
||||
if (ELF_ST_BIND (s.st_info) == STB_LOCAL)
|
||||
rsec = (*gc_mark_hook)(sec->owner, info, rel, NULL, &s);
|
||||
else
|
||||
{
|
||||
h = sym_hashes[r_symndx - extsymoff];
|
||||
rsec = (*gc_mark_hook)(sec->owner, info, rel, h, NULL);
|
||||
}
|
||||
}
|
||||
else if (r_symndx >= nlocsyms)
|
||||
{
|
||||
h = sym_hashes[r_symndx - extsymoff];
|
||||
rsec = (*gc_mark_hook)(sec->owner, info, rel, h, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
elf_swap_symbol_in (input_bfd, &locsyms[r_symndx], &s);
|
||||
rsec = (*gc_mark_hook)(sec->owner, info, rel, NULL, &s);
|
||||
}
|
||||
|
||||
if (rsec && !rsec->gc_mark)
|
||||
if (!elf_gc_mark (info, rsec, gc_mark_hook))
|
||||
{
|
||||
ret = false;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
|
||||
out2:
|
||||
if (!info->keep_memory)
|
||||
free (relstart);
|
||||
out1:
|
||||
if (freesyms)
|
||||
free (freesyms);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The sweep phase of garbage collection. Remove all garbage sections. */
|
||||
|
||||
static boolean
|
||||
elf_gc_sweep (info, gc_sweep_hook)
|
||||
struct bfd_link_info *info;
|
||||
boolean (*gc_sweep_hook)
|
||||
PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *o,
|
||||
const Elf_Internal_Rela *relocs));
|
||||
{
|
||||
bfd *sub;
|
||||
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
|
||||
{
|
||||
asection *o;
|
||||
|
||||
for (o = sub->sections; o != NULL; o = o->next)
|
||||
{
|
||||
/* Keep special sections. Keep .debug sections. */
|
||||
if ((o->flags & SEC_LINKER_CREATED)
|
||||
|| (o->flags & SEC_DEBUGGING))
|
||||
o->gc_mark = 1;
|
||||
|
||||
if (o->gc_mark)
|
||||
continue;
|
||||
|
||||
/* Skip sweeping sections already excluded. */
|
||||
if (o->flags & SEC_EXCLUDE)
|
||||
continue;
|
||||
|
||||
/* Since this is early in the link process, it is simple
|
||||
to remove a section from the output. */
|
||||
o->flags |= SEC_EXCLUDE;
|
||||
|
||||
/* But we also have to update some of the relocation
|
||||
info we collected before. */
|
||||
if (gc_sweep_hook
|
||||
&& (o->flags & SEC_RELOC) && o->reloc_count > 0)
|
||||
{
|
||||
Elf_Internal_Rela *internal_relocs;
|
||||
boolean r;
|
||||
|
||||
internal_relocs = (NAME(_bfd_elf,link_read_relocs)
|
||||
(o->owner, o, NULL, NULL, info->keep_memory));
|
||||
if (internal_relocs == NULL)
|
||||
return false;
|
||||
|
||||
r = (*gc_sweep_hook)(o->owner, info, o, internal_relocs);
|
||||
|
||||
if (!info->keep_memory)
|
||||
free (internal_relocs);
|
||||
|
||||
if (!r)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the symbols that were in the swept sections from the dynamic
|
||||
symbol table. GCFIXME: Anyone know how to get them out of the
|
||||
static symbol table as well? */
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_gc_sweep_symbol,
|
||||
(PTR) &i);
|
||||
|
||||
elf_hash_table (info)->dynsymcount = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */
|
||||
|
||||
static boolean
|
||||
elf_gc_sweep_symbol (h, idxptr)
|
||||
struct elf_link_hash_entry *h;
|
||||
PTR idxptr;
|
||||
{
|
||||
int *idx = (int *) idxptr;
|
||||
|
||||
if (h->dynindx != -1
|
||||
&& ((h->root.type != bfd_link_hash_defined
|
||||
&& h->root.type != bfd_link_hash_defweak)
|
||||
|| h->root.u.def.section->gc_mark))
|
||||
h->dynindx = (*idx)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Propogate collected vtable information. This is called through
|
||||
elf_link_hash_traverse. */
|
||||
|
||||
static boolean
|
||||
elf_gc_propogate_vtable_entries_used (h, okp)
|
||||
struct elf_link_hash_entry *h;
|
||||
PTR okp;
|
||||
{
|
||||
/* Those that are not vtables. */
|
||||
if (h->vtable_parent == NULL)
|
||||
return true;
|
||||
|
||||
/* Those vtables that do not have parents, we cannot merge. */
|
||||
if (h->vtable_parent == (struct elf_link_hash_entry *) -1)
|
||||
return true;
|
||||
|
||||
/* If we've already been done, exit. */
|
||||
if (h->vtable_entries_used && h->vtable_entries_used[-1])
|
||||
return true;
|
||||
|
||||
/* Make sure the parent's table is up to date. */
|
||||
elf_gc_propogate_vtable_entries_used (h->vtable_parent, okp);
|
||||
|
||||
if (h->vtable_entries_used == NULL)
|
||||
{
|
||||
/* None of this table's entries were referenced. Re-use the
|
||||
parent's table. */
|
||||
h->vtable_entries_used = h->vtable_parent->vtable_entries_used;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t n;
|
||||
boolean *cu, *pu;
|
||||
|
||||
/* Or the parent's entries into ours. */
|
||||
cu = h->vtable_entries_used;
|
||||
cu[-1] = true;
|
||||
pu = h->vtable_parent->vtable_entries_used;
|
||||
if (pu != NULL)
|
||||
{
|
||||
n = h->vtable_parent->size / FILE_ALIGN;
|
||||
while (--n != 0)
|
||||
{
|
||||
if (*pu) *cu = true;
|
||||
pu++, cu++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
elf_gc_smash_unused_vtentry_relocs (h, okp)
|
||||
struct elf_link_hash_entry *h;
|
||||
PTR okp;
|
||||
{
|
||||
asection *sec;
|
||||
bfd_vma hstart, hend;
|
||||
Elf_Internal_Rela *relstart, *relend, *rel;
|
||||
|
||||
/* Take care of both those symbols that do not describe vtables as
|
||||
well as those that are not loaded. */
|
||||
if (h->vtable_parent == NULL)
|
||||
return true;
|
||||
|
||||
BFD_ASSERT (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak);
|
||||
|
||||
sec = h->root.u.def.section;
|
||||
hstart = h->root.u.def.value;
|
||||
hend = hstart + h->size;
|
||||
|
||||
relstart = (NAME(_bfd_elf,link_read_relocs)
|
||||
(sec->owner, sec, NULL, (Elf_Internal_Rela *) NULL, true));
|
||||
if (!relstart)
|
||||
return *(boolean *)okp = false;
|
||||
relend = relstart + sec->reloc_count;
|
||||
|
||||
for (rel = relstart; rel < relend; ++rel)
|
||||
if (rel->r_offset >= hstart && rel->r_offset < hend)
|
||||
{
|
||||
/* If the entry is in use, do nothing. */
|
||||
if (h->vtable_entries_used)
|
||||
{
|
||||
bfd_vma entry = (rel->r_offset - hstart) / FILE_ALIGN;
|
||||
if (h->vtable_entries_used[entry])
|
||||
continue;
|
||||
}
|
||||
/* Otherwise, kill it. */
|
||||
rel->r_offset = rel->r_info = rel->r_addend = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Do mark and sweep of unused sections. */
|
||||
|
||||
boolean
|
||||
elf_gc_sections (abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
boolean ok = true;
|
||||
bfd *sub;
|
||||
asection * (*gc_mark_hook)
|
||||
PARAMS ((bfd *abfd, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *h, Elf_Internal_Sym *));
|
||||
|
||||
if (!get_elf_backend_data (abfd)->can_gc_sections
|
||||
|| info->relocateable)
|
||||
return true;
|
||||
|
||||
/* Apply transitive closure to the vtable entry usage info. */
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_gc_propogate_vtable_entries_used,
|
||||
(PTR) &ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
/* Kill the vtable relocations that were not used. */
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_gc_smash_unused_vtentry_relocs,
|
||||
(PTR) &ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
/* Grovel through relocs to find out who stays ... */
|
||||
|
||||
gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
|
||||
{
|
||||
asection *o;
|
||||
for (o = sub->sections; o != NULL; o = o->next)
|
||||
{
|
||||
if (o->flags & SEC_KEEP)
|
||||
if (!elf_gc_mark (info, o, gc_mark_hook))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ... and mark SEC_EXCLUDE for those that go. */
|
||||
if (!elf_gc_sweep(info, get_elf_backend_data (abfd)->gc_sweep_hook))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Called from check_relocs to record the existance of a VTINHERIT reloc. */
|
||||
|
||||
boolean
|
||||
elf_gc_record_vtinherit (abfd, sec, h, offset)
|
||||
bfd *abfd;
|
||||
asection *sec;
|
||||
struct elf_link_hash_entry *h;
|
||||
bfd_vma offset;
|
||||
{
|
||||
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
|
||||
struct elf_link_hash_entry **search, *child;
|
||||
bfd_size_type extsymcount;
|
||||
|
||||
/* The sh_info field of the symtab header tells us where the
|
||||
external symbols start. We don't care about the local symbols at
|
||||
this point. */
|
||||
extsymcount = elf_tdata (abfd)->symtab_hdr.sh_size/sizeof (Elf_External_Sym);
|
||||
if (!elf_bad_symtab (abfd))
|
||||
extsymcount -= elf_tdata (abfd)->symtab_hdr.sh_info;
|
||||
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
sym_hashes_end = sym_hashes + extsymcount;
|
||||
|
||||
/* Hunt down the child symbol, which is in this section at the same
|
||||
offset as the relocation. */
|
||||
for (search = sym_hashes; search != sym_hashes_end; ++search)
|
||||
{
|
||||
if ((child = *search) != NULL
|
||||
&& (child->root.type == bfd_link_hash_defined
|
||||
|| child->root.type == bfd_link_hash_defweak)
|
||||
&& child->root.u.def.section == sec
|
||||
&& child->root.u.def.value == offset)
|
||||
goto win;
|
||||
}
|
||||
|
||||
(*_bfd_error_handler) ("%s: %s+%lu: No symbol found for INHERIT",
|
||||
bfd_get_filename (abfd), sec->name,
|
||||
(unsigned long)offset);
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return false;
|
||||
|
||||
win:
|
||||
if (!h)
|
||||
{
|
||||
/* This *should* only be the absolute section. It could potentially
|
||||
be that someone has defined a non-global vtable though, which
|
||||
would be bad. It isn't worth paging in the local symbols to be
|
||||
sure though; that case should simply be handled by the assembler. */
|
||||
|
||||
child->vtable_parent = (struct elf_link_hash_entry *) -1;
|
||||
}
|
||||
else
|
||||
child->vtable_parent = h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Called from check_relocs to record the existance of a VTENTRY reloc. */
|
||||
|
||||
boolean
|
||||
elf_gc_record_vtentry (abfd, sec, h, addend)
|
||||
bfd *abfd;
|
||||
asection *sec;
|
||||
struct elf_link_hash_entry *h;
|
||||
bfd_vma addend;
|
||||
{
|
||||
if (h->vtable_entries_used == NULL)
|
||||
{
|
||||
/* Allocate one extra entry for use as a "done" flag for the
|
||||
consolidation pass. */
|
||||
size_t size = (h->size / FILE_ALIGN + 1) * sizeof(boolean);
|
||||
h->vtable_entries_used = (boolean *) bfd_alloc (abfd, size);
|
||||
if (h->vtable_entries_used == NULL)
|
||||
return false;
|
||||
|
||||
/* And arrange for that done flag to be at index -1. */
|
||||
memset (h->vtable_entries_used++, 0, size);
|
||||
}
|
||||
h->vtable_entries_used[addend / FILE_ALIGN] = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* And an accompanying bit to work out final got entry offsets once
|
||||
we're done. Should be called from final_link. */
|
||||
|
||||
boolean
|
||||
elf_gc_common_finalize_got_offsets (abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfd *i;
|
||||
bfd_vma off[2], gotoff = 0;
|
||||
|
||||
/* Do the local .got entries first. */
|
||||
for (i = info->input_bfds; i; i = i->link_next)
|
||||
{
|
||||
bfd_signed_vma *local_got = elf_local_got_refcounts (i);
|
||||
bfd_size_type j, locsymcount;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
|
||||
if (!local_got)
|
||||
continue;
|
||||
|
||||
symtab_hdr = &elf_tdata (i)->symtab_hdr;
|
||||
if (elf_bad_symtab (i))
|
||||
locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
|
||||
else
|
||||
locsymcount = symtab_hdr->sh_info;
|
||||
|
||||
for (j = 0; j < locsymcount; ++j)
|
||||
local_got[j] = (local_got[j] > 0 ? gotoff++ : (bfd_vma) - 1);
|
||||
}
|
||||
|
||||
/* Then the global .got and .plt entries. */
|
||||
off[0] = gotoff;
|
||||
off[1] = 0;
|
||||
elf_link_hash_traverse (elf_hash_table (info),
|
||||
elf_gc_allocate_got_offsets,
|
||||
(PTR) off);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We need a special top-level link routine to convert got reference counts
|
||||
to real got offsets. */
|
||||
|
||||
static boolean
|
||||
elf_gc_allocate_got_offsets (h, offarg)
|
||||
struct elf_link_hash_entry *h;
|
||||
PTR offarg;
|
||||
{
|
||||
bfd_vma *off = (bfd_vma *) offarg;
|
||||
|
||||
h->got.offset = (h->got.refcount > 0 ? off[0]++ : (bfd_vma) - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Many folk need no more in the way of final link than this, once
|
||||
got entry reference counting is enabled. */
|
||||
|
||||
boolean
|
||||
elf_gc_common_final_link (abfd, info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
if (!elf_gc_common_finalize_got_offsets (abfd, info))
|
||||
return false;
|
||||
|
||||
/* Invoke the regular ELF backend linker to do all the work. */
|
||||
return elf_bfd_final_link (abfd, info);
|
||||
}
|
||||
|
@ -105,6 +105,8 @@ static bfd_byte *evax_bfd_get_relocated_section_contents
|
||||
static boolean evax_bfd_relax_section
|
||||
PARAMS ((bfd *abfd, asection *section, struct bfd_link_info *link_info,
|
||||
boolean *again));
|
||||
static boolean evax_bfd_gc_sections
|
||||
PARAMS ((bfd *abfd, struct bfd_link_info *link_info));
|
||||
static struct bfd_link_hash_table *evax_bfd_link_hash_table_create
|
||||
PARAMS ((bfd *abfd));
|
||||
static boolean evax_bfd_link_add_symbols
|
||||
@ -1657,6 +1659,18 @@ evax_bfd_relax_section (abfd, section, link_info, again)
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
evax_bfd_gc_sections (abfd, link_info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *link_info;
|
||||
const char *entry;
|
||||
{
|
||||
#if EVAX_DEBUG
|
||||
evax_debug (1, "evax_bfd_gc_sections(%p, %p)\n", abfd, link_info);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Create a hash table for the linker. Different backends store
|
||||
different information in this table. */
|
||||
|
200
bfd/ieee.c
200
bfd/ieee.c
@ -1,5 +1,7 @@
|
||||
/* BFD back-end for ieee-695 objects.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97, 1998
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Written by Steve Chamberlain of Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
@ -30,6 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "ieee.h"
|
||||
#include "libieee.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static boolean ieee_write_byte PARAMS ((bfd *, int));
|
||||
static boolean ieee_write_2bytes PARAMS ((bfd *, int));
|
||||
static boolean ieee_write_int PARAMS ((bfd *, bfd_vma));
|
||||
@ -160,7 +164,7 @@ ieee_write_id (abfd, id)
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: string too long (%d chars, max 65535)",
|
||||
(_("%s: string too long (%d chars, max 65535)"),
|
||||
bfd_get_filename (abfd), length);
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return false;
|
||||
@ -290,7 +294,7 @@ ieee_write_expression (abfd, value, symbol, pcrel, index)
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: unrecognized symbol `%s' flags 0x%x",
|
||||
(_("%s: unrecognized symbol `%s' flags 0x%x"),
|
||||
bfd_get_filename (abfd), bfd_asymbol_name (symbol),
|
||||
symbol->flags);
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
@ -786,7 +790,7 @@ ieee_slurp_external_symbols (abfd)
|
||||
break;
|
||||
default:
|
||||
(*_bfd_error_handler)
|
||||
("%s: unimplemented ATI record %u for symbol %u",
|
||||
(_("%s: unimplemented ATI record %u for symbol %u"),
|
||||
bfd_get_filename (abfd), symbol_attribute_def,
|
||||
symbol_name_index);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
@ -1239,15 +1243,18 @@ ieee_archive_p (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
char *library;
|
||||
boolean loop;
|
||||
unsigned int i;
|
||||
unsigned char buffer[512];
|
||||
file_ptr buffer_offset = 0;
|
||||
ieee_ar_data_type *save = abfd->tdata.ieee_ar_data;
|
||||
ieee_ar_data_type *ieee;
|
||||
abfd->tdata.ieee_ar_data = (ieee_ar_data_type *) bfd_alloc (abfd, sizeof (ieee_ar_data_type));
|
||||
unsigned int alc_elts;
|
||||
ieee_ar_obstack_type *elts = NULL;
|
||||
|
||||
abfd->tdata.ieee_ar_data =
|
||||
(ieee_ar_data_type *) bfd_alloc (abfd, sizeof (ieee_ar_data_type));
|
||||
if (!abfd->tdata.ieee_ar_data)
|
||||
return NULL;
|
||||
goto error_return;
|
||||
ieee = IEEE_AR_DATA (abfd);
|
||||
|
||||
/* FIXME: Check return value. I'm not sure whether it needs to read
|
||||
@ -1262,7 +1269,7 @@ ieee_archive_p (abfd)
|
||||
if (this_byte (&(ieee->h)) != Module_Beginning)
|
||||
{
|
||||
abfd->tdata.ieee_ar_data = save;
|
||||
return (const bfd_target *) NULL;
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
next_byte (&(ieee->h));
|
||||
@ -1271,7 +1278,7 @@ ieee_archive_p (abfd)
|
||||
{
|
||||
bfd_release (abfd, ieee);
|
||||
abfd->tdata.ieee_ar_data = save;
|
||||
return (const bfd_target *) NULL;
|
||||
goto error_return;
|
||||
}
|
||||
/* Throw away the filename */
|
||||
read_id (&(ieee->h));
|
||||
@ -1283,43 +1290,65 @@ ieee_archive_p (abfd)
|
||||
must_parse_int (&(ieee->h)); /* And the two dummy numbers */
|
||||
must_parse_int (&(ieee->h));
|
||||
|
||||
loop = true;
|
||||
alc_elts = 10;
|
||||
elts = (ieee_ar_obstack_type *) bfd_malloc (alc_elts * sizeof *elts);
|
||||
if (elts == NULL)
|
||||
goto error_return;
|
||||
|
||||
/* Read the index of the BB table */
|
||||
while (loop)
|
||||
while (1)
|
||||
{
|
||||
ieee_ar_obstack_type t;
|
||||
int rec = read_2bytes (&(ieee->h));
|
||||
if (rec == (int) ieee_assign_value_to_variable_enum)
|
||||
int rec;
|
||||
ieee_ar_obstack_type *t;
|
||||
|
||||
rec = read_2bytes (&(ieee->h));
|
||||
if (rec != (int) ieee_assign_value_to_variable_enum)
|
||||
break;
|
||||
|
||||
if (ieee->element_count >= alc_elts)
|
||||
{
|
||||
must_parse_int (&(ieee->h));
|
||||
t.file_offset = must_parse_int (&(ieee->h));
|
||||
t.abfd = (bfd *) NULL;
|
||||
ieee->element_count++;
|
||||
ieee_ar_obstack_type *n;
|
||||
|
||||
bfd_alloc_grow (abfd, (PTR) &t, sizeof t);
|
||||
|
||||
/* Make sure that we don't go over the end of the buffer */
|
||||
|
||||
if ((size_t) ieee_pos (abfd) > sizeof (buffer) / 2)
|
||||
{
|
||||
/* Past half way, reseek and reprime */
|
||||
buffer_offset += ieee_pos (abfd);
|
||||
if (bfd_seek (abfd, buffer_offset, SEEK_SET) != 0)
|
||||
return NULL;
|
||||
/* FIXME: Check return value. I'm not sure whether it
|
||||
needs to read the entire buffer or not. */
|
||||
bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
|
||||
ieee->h.first_byte = buffer;
|
||||
ieee->h.input_p = buffer;
|
||||
}
|
||||
alc_elts *= 2;
|
||||
n = ((ieee_ar_obstack_type *)
|
||||
bfd_realloc (elts, alc_elts * sizeof *elts));
|
||||
if (n == NULL)
|
||||
goto error_return;
|
||||
elts = n;
|
||||
}
|
||||
|
||||
t = &elts[ieee->element_count];
|
||||
ieee->element_count++;
|
||||
|
||||
must_parse_int (&(ieee->h));
|
||||
t->file_offset = must_parse_int (&(ieee->h));
|
||||
t->abfd = (bfd *) NULL;
|
||||
|
||||
/* Make sure that we don't go over the end of the buffer */
|
||||
|
||||
if ((size_t) ieee_pos (abfd) > sizeof (buffer) / 2)
|
||||
{
|
||||
/* Past half way, reseek and reprime */
|
||||
buffer_offset += ieee_pos (abfd);
|
||||
if (bfd_seek (abfd, buffer_offset, SEEK_SET) != 0)
|
||||
goto error_return;
|
||||
/* FIXME: Check return value. I'm not sure whether it needs
|
||||
to read the entire buffer or not. */
|
||||
bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
|
||||
ieee->h.first_byte = buffer;
|
||||
ieee->h.input_p = buffer;
|
||||
}
|
||||
else
|
||||
loop = false;
|
||||
}
|
||||
|
||||
ieee->elements = (ieee_ar_obstack_type *) bfd_alloc_finish (abfd);
|
||||
if (!ieee->elements)
|
||||
return (const bfd_target *) NULL;
|
||||
ieee->elements = ((ieee_ar_obstack_type *)
|
||||
bfd_alloc (abfd,
|
||||
ieee->element_count * sizeof *ieee->elements));
|
||||
if (ieee->elements == NULL)
|
||||
goto error_return;
|
||||
memcpy (ieee->elements, elts,
|
||||
ieee->element_count * sizeof *ieee->elements);
|
||||
free (elts);
|
||||
elts = NULL;
|
||||
|
||||
/* Now scan the area again, and replace BB offsets with file */
|
||||
/* offsets */
|
||||
@ -1327,7 +1356,7 @@ ieee_archive_p (abfd)
|
||||
for (i = 2; i < ieee->element_count; i++)
|
||||
{
|
||||
if (bfd_seek (abfd, ieee->elements[i].file_offset, SEEK_SET) != 0)
|
||||
return NULL;
|
||||
goto error_return;
|
||||
/* FIXME: Check return value. I'm not sure whether it needs to
|
||||
read the entire buffer or not. */
|
||||
bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
|
||||
@ -1348,8 +1377,14 @@ ieee_archive_p (abfd)
|
||||
}
|
||||
}
|
||||
|
||||
/* abfd->has_armap = ;*/
|
||||
/* abfd->has_armap = ;*/
|
||||
|
||||
return abfd->xvec;
|
||||
|
||||
error_return:
|
||||
if (elts != NULL)
|
||||
free (elts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static boolean
|
||||
@ -1407,7 +1442,70 @@ ieee_object_p (abfd)
|
||||
/* Determine the architecture and machine type of the object file.
|
||||
*/
|
||||
{
|
||||
const bfd_arch_info_type *arch = bfd_scan_arch (processor);
|
||||
const bfd_arch_info_type *arch;
|
||||
char family[10];
|
||||
|
||||
/* IEEE does not specify the format of the processor identificaton
|
||||
string, so the compiler is free to put in it whatever it wants.
|
||||
We try here to recognize different processors belonging to the
|
||||
m68k family. Code for other processors can be added here. */
|
||||
if ((processor[0] == '6') && (processor[1] == '8'))
|
||||
{
|
||||
if (processor[2] == '3') /* 683xx integrated processors */
|
||||
{
|
||||
switch (processor[3])
|
||||
{
|
||||
case '0': /* 68302, 68306, 68307 */
|
||||
case '2': /* 68322, 68328 */
|
||||
case '5': /* 68356 */
|
||||
strcpy (family, "68000"); /* MC68000-based controllers */
|
||||
break;
|
||||
|
||||
case '3': /* 68330, 68331, 68332, 68333,
|
||||
68334, 68335, 68336, 68338 */
|
||||
case '6': /* 68360 */
|
||||
case '7': /* 68376 */
|
||||
strcpy (family, "68332"); /* CPU32 and CPU32+ */
|
||||
break;
|
||||
|
||||
case '4':
|
||||
if (processor[4] == '9') /* 68349 */
|
||||
strcpy (family, "68030"); /* CPU030 */
|
||||
else /* 68340, 68341 */
|
||||
strcpy (family, "68332"); /* CPU32 and CPU32+ */
|
||||
break;
|
||||
|
||||
default: /* Does not exist yet */
|
||||
strcpy (family, "68332"); /* Guess it will be CPU32 */
|
||||
}
|
||||
}
|
||||
else if (toupper (processor[3]) == 'F') /* 68F333 */
|
||||
strcpy (family, "68332"); /* CPU32 */
|
||||
else if ((toupper (processor[3]) == 'C') /* Embedded controllers */
|
||||
&& ((toupper (processor[2]) == 'E')
|
||||
|| (toupper (processor[2]) == 'H')
|
||||
|| (toupper (processor[2]) == 'L')))
|
||||
{
|
||||
strcpy (family, "68");
|
||||
strncat (family, processor + 4, 7);
|
||||
family[9] = '\0';
|
||||
}
|
||||
else /* "Regular" processors */
|
||||
{
|
||||
strncpy (family, processor, 9);
|
||||
family[9] = '\0';
|
||||
}
|
||||
}
|
||||
else if ((strncmp (processor, "cpu32", 5) == 0) /* CPU32 and CPU32+ */
|
||||
|| (strncmp (processor, "CPU32", 5) == 0))
|
||||
strcpy (family, "68332");
|
||||
else
|
||||
{
|
||||
strncpy (family, processor, 9);
|
||||
family[9] = '\0';
|
||||
}
|
||||
|
||||
arch = bfd_scan_arch (family);
|
||||
if (arch == 0)
|
||||
goto got_wrong_format;
|
||||
abfd->arch_info = arch;
|
||||
@ -1613,10 +1711,8 @@ do_one (ieee, current_map, location_ptr, s, iterations)
|
||||
s->flags |= SEC_RELOC;
|
||||
s->owner->flags |= HAS_RELOC;
|
||||
s->reloc_count++;
|
||||
if (r->relent.sym_ptr_ptr == 0)
|
||||
{
|
||||
r->relent.sym_ptr_ptr = section->symbol_ptr_ptr;
|
||||
}
|
||||
if (r->relent.sym_ptr_ptr == NULL && section != NULL)
|
||||
r->relent.sym_ptr_ptr = section->symbol_ptr_ptr;
|
||||
|
||||
if (this_byte (&(ieee->h)) == (int) ieee_comma)
|
||||
{
|
||||
@ -1954,8 +2050,9 @@ ieee_canonicalize_reloc (abfd, section, relptr, symbols)
|
||||
symbols + src->symbol.index + ieee->external_reference_base_offset;
|
||||
break;
|
||||
case 0:
|
||||
src->relent.sym_ptr_ptr =
|
||||
src->relent.sym_ptr_ptr[0]->section->symbol_ptr_ptr;
|
||||
if (src->relent.sym_ptr_ptr != NULL)
|
||||
src->relent.sym_ptr_ptr =
|
||||
src->relent.sym_ptr_ptr[0]->section->symbol_ptr_ptr;
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -3609,9 +3706,11 @@ ieee_generic_stat_arch_elt (abfd, buf)
|
||||
bfd *abfd;
|
||||
struct stat *buf;
|
||||
{
|
||||
ieee_ar_data_type *ar = abfd->my_archive->tdata.ieee_ar_data;
|
||||
ieee_ar_data_type *ar = (ieee_ar_data_type *) NULL;
|
||||
ieee_data_type *ieee;
|
||||
|
||||
if (abfd->my_archive != NULL)
|
||||
ar = abfd->my_archive->tdata.ieee_ar_data;
|
||||
if (ar == (ieee_ar_data_type *) NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
@ -3724,7 +3823,7 @@ ieee_bfd_debug_info_accumulate (abfd, section)
|
||||
#define ieee_update_armap_timestamp bfd_true
|
||||
#define ieee_get_elt_at_index _bfd_generic_get_elt_at_index
|
||||
|
||||
#define ieee_bfd_is_local_label bfd_generic_is_local_label
|
||||
#define ieee_bfd_is_local_label_name bfd_generic_is_local_label_name
|
||||
#define ieee_get_lineno _bfd_nosymbols_get_lineno
|
||||
#define ieee_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
|
||||
#define ieee_read_minisymbols _bfd_generic_read_minisymbols
|
||||
@ -3739,6 +3838,7 @@ ieee_bfd_debug_info_accumulate (abfd, section)
|
||||
#define ieee_bfd_get_relocated_section_contents \
|
||||
bfd_generic_get_relocated_section_contents
|
||||
#define ieee_bfd_relax_section bfd_generic_relax_section
|
||||
#define ieee_bfd_gc_sections bfd_generic_gc_sections
|
||||
#define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
|
||||
#define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
|
||||
#define ieee_bfd_final_link _bfd_generic_final_link
|
||||
|
36
bfd/libbfd.h
36
bfd/libbfd.h
@ -23,31 +23,6 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
#include <libintl.h>
|
||||
/* FIXME: We might want to use dgettext instead, in some cases.
|
||||
This is still under investigation. */
|
||||
#define _(String) gettext (String)
|
||||
#ifdef gettext_noop
|
||||
#define N_(String) gettext_noop (String)
|
||||
#else
|
||||
#define N_(String) (String)
|
||||
#endif
|
||||
#else
|
||||
/* Stubs that do something close enough. */
|
||||
#define textdomain(String) (String)
|
||||
#define gettext(String) (String)
|
||||
#define dgettext(Domain,Message) (Message)
|
||||
#define dcgettext(Domain,Message,Type) (Message)
|
||||
#define bindtextdomain(Domain,Directory) (Domain)
|
||||
#define _(String) (String)
|
||||
#define N_(String) (String)
|
||||
/* In this case we don't care about the value. */
|
||||
#ifndef LC_MESSAGES
|
||||
#define LC_MESSAGES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Align an address upward to a boundary, expressed as a number of bytes.
|
||||
E.g. align to an 8-byte boundary with argument of 8. Take care never
|
||||
to wrap around if the address is within boundary-1 of the end of the
|
||||
@ -342,6 +317,10 @@ extern boolean _bfd_generic_set_section_contents
|
||||
((boolean (*) \
|
||||
PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *))) \
|
||||
bfd_false)
|
||||
#define _bfd_nolink_bfd_gc_sections \
|
||||
((boolean (*) \
|
||||
PARAMS ((struct bfd_link_info *))) \
|
||||
bfd_false)
|
||||
#define _bfd_nolink_bfd_link_hash_table_create \
|
||||
((struct bfd_link_hash_table *(*) PARAMS ((bfd *))) bfd_nullvoidptr)
|
||||
#define _bfd_nolink_bfd_link_add_symbols \
|
||||
@ -670,6 +649,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_SPARC_M44",
|
||||
"BFD_RELOC_SPARC_L44",
|
||||
"BFD_RELOC_SPARC_REGISTER",
|
||||
"BFD_RELOC_SPARC_32LE",
|
||||
"BFD_RELOC_ALPHA_GPDISP_HI16",
|
||||
"BFD_RELOC_ALPHA_GPDISP_LO16",
|
||||
"BFD_RELOC_ALPHA_GPDISP",
|
||||
@ -842,6 +822,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_MN10300_32_PCREL",
|
||||
"BFD_RELOC_MN10300_16_PCREL",
|
||||
"BFD_RELOC_TIC30_LDP",
|
||||
"BFD_RELOC_VTABLE_INHERIT",
|
||||
"BFD_RELOC_VTABLE_ENTRY",
|
||||
"@@overflow: BFD_RELOC_UNUSED@@",
|
||||
};
|
||||
#endif
|
||||
@ -857,6 +839,10 @@ bfd_generic_relax_section
|
||||
struct bfd_link_info *,
|
||||
boolean *));
|
||||
|
||||
boolean
|
||||
bfd_generic_gc_sections
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
|
||||
bfd_byte *
|
||||
|
||||
bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd,
|
||||
|
50
bfd/reloc.c
50
bfd/reloc.c
@ -1868,6 +1868,11 @@ ENUMX
|
||||
ENUMDOC
|
||||
SPARC64 relocations
|
||||
|
||||
ENUM
|
||||
BFD_RELOC_SPARC_32LE
|
||||
ENUMDOC
|
||||
SPARC little endian relocation
|
||||
|
||||
ENUM
|
||||
BFD_RELOC_ALPHA_GPDISP_HI16
|
||||
ENUMDOC
|
||||
@ -2477,6 +2482,29 @@ ENUMDOC
|
||||
significant 8 bits of a 24 bit word are placed into the least
|
||||
significant 8 bits of the opcode.
|
||||
|
||||
ENUM
|
||||
BFD_RELOC_VTABLE_INHERIT
|
||||
ENUMX
|
||||
BFD_RELOC_VTABLE_ENTRY
|
||||
ENUMDOC
|
||||
These two relocations are used by the linker to determine which of
|
||||
the entries in a C++ virtual function table are actually used. When
|
||||
the --gc-sections option is given, the linker will zero out the entries
|
||||
that are not used, so that the code for those functions need not be
|
||||
included in the output.
|
||||
|
||||
VTABLE_INHERIT is a zero-space relocation used to describe to the
|
||||
linker the inheritence tree of a C++ virtual function table. The
|
||||
relocation's symbol should be the parent class' vtable, and the
|
||||
relocation should be located at the child vtable.
|
||||
|
||||
VTABLE_ENTRY is a zero-space relocation that describes the use of a
|
||||
virtual function table entry. The reloc's symbol should refer to the
|
||||
table of the class mentioned in the code. Off of that base, an offset
|
||||
describes the entry that is being used. For Rela hosts, this offset
|
||||
is stored in the reloc's addend. For Rel hosts, we are forced to put
|
||||
this offset in the reloc's section offset.
|
||||
|
||||
ENDSENUM
|
||||
BFD_RELOC_UNUSED
|
||||
CODE_FRAGMENT
|
||||
@ -2603,6 +2631,28 @@ bfd_generic_relax_section (abfd, section, link_info, again)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
INTERNAL_FUNCTION
|
||||
bfd_generic_gc_sections
|
||||
|
||||
SYNOPSIS
|
||||
boolean bfd_generic_gc_sections
|
||||
(bfd *, struct bfd_link_info *);
|
||||
|
||||
DESCRIPTION
|
||||
Provides default handling for relaxing for back ends which
|
||||
don't do section gc -- i.e., does nothing.
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
boolean
|
||||
bfd_generic_gc_sections (abfd, link_info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *link_info;
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
INTERNAL_FUNCTION
|
||||
bfd_generic_get_relocated_section_contents
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Object file "section" support for the BFD library.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997
|
||||
Free Software Foundation, Inc.
|
||||
Written by Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
@ -214,7 +215,7 @@ CODE_FRAGMENT
|
||||
. standard data. *}
|
||||
.#define SEC_CONSTRUCTOR 0x100
|
||||
.
|
||||
. {* The section is a constuctor, and should be placed at the
|
||||
. {* The section is a constructor, and should be placed at the
|
||||
. end of the text, data, or bss section(?). *}
|
||||
.#define SEC_CONSTRUCTOR_TEXT 0x1100
|
||||
.#define SEC_CONSTRUCTOR_DATA 0x2100
|
||||
@ -303,6 +304,9 @@ CODE_FRAGMENT
|
||||
. else up the line will take care of it later. *}
|
||||
.#define SEC_LINKER_CREATED 0x800000
|
||||
.
|
||||
. {* This section should not be subject to garbage collection. *}
|
||||
.#define SEC_KEEP 0x1000000
|
||||
.
|
||||
. {* End of section flags. *}
|
||||
.
|
||||
. {* Some internal packed boolean fields. *}
|
||||
@ -316,6 +320,9 @@ CODE_FRAGMENT
|
||||
. {* A mark flag used by some of the linker backends. *}
|
||||
. unsigned int linker_mark : 1;
|
||||
.
|
||||
. {* A mark flag used by some linker backends for garbage collection. *}
|
||||
. unsigned int gc_mark : 1;
|
||||
.
|
||||
. {* End of internal packed boolean fields. *}
|
||||
.
|
||||
. {* The virtual memory address of the section - where it will be
|
||||
@ -558,7 +565,7 @@ DESCRIPTION
|
||||
o <<bfd_error_invalid_operation>> -
|
||||
If output has already started for this BFD.
|
||||
o <<bfd_error_no_memory>> -
|
||||
If obstack alloc fails.
|
||||
If memory allocation fails.
|
||||
|
||||
*/
|
||||
|
||||
@ -590,7 +597,7 @@ DESCRIPTION
|
||||
|
||||
Return <<NULL>> and set <<bfd_error>> on error; possible errors are:
|
||||
o <<bfd_error_invalid_operation>> - If output has already started for @var{abfd}.
|
||||
o <<bfd_error_no_memory>> - If obstack alloc fails.
|
||||
o <<bfd_error_no_memory>> - If memory allocation fails.
|
||||
*/
|
||||
|
||||
sec_ptr
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Generic target-file-type support for the BFD library.
|
||||
Copyright 1990, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
|
||||
Free Software Foundation, Inc.
|
||||
Written by Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
@ -412,7 +413,8 @@ The general target vector.
|
||||
.CAT(NAME,_bfd_link_hash_table_create),\
|
||||
.CAT(NAME,_bfd_link_add_symbols),\
|
||||
.CAT(NAME,_bfd_final_link),\
|
||||
.CAT(NAME,_bfd_link_split_section)
|
||||
.CAT(NAME,_bfd_link_split_section),\
|
||||
.CAT(NAME,_bfd_gc_sections)
|
||||
. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
|
||||
. bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
|
||||
. struct bfd_link_info *, struct bfd_link_order *,
|
||||
@ -436,7 +438,10 @@ The general target vector.
|
||||
. {* Should this section be split up into smaller pieces during linking. *}
|
||||
. boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
|
||||
.
|
||||
. {* Routines to handle dynamic symbols and relocs. *}
|
||||
. {* Remove sections that are not referenced from the output. *}
|
||||
. boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
|
||||
.
|
||||
. {* Routines to handle dynamic symbols and relocs. *}
|
||||
.#define BFD_JUMP_TABLE_DYNAMIC(NAME)\
|
||||
.CAT(NAME,_get_dynamic_symtab_upper_bound),\
|
||||
.CAT(NAME,_canonicalize_dynamic_symtab),\
|
||||
@ -588,6 +593,7 @@ extern const bfd_target tic30_coff_vec;
|
||||
/* start-sanitize-tic80 */
|
||||
extern const bfd_target tic80coff_vec;
|
||||
/* end-sanitize-tic80 */
|
||||
extern const bfd_target vaxnetbsd_vec;
|
||||
extern const bfd_target versados_vec;
|
||||
extern const bfd_target we32kcoff_vec;
|
||||
extern const bfd_target w65_vec;
|
||||
@ -674,6 +680,7 @@ const bfd_target * const bfd_target_vector[] = {
|
||||
&bfd_elf32_m88k_vec,
|
||||
&bfd_elf32_sparc_vec,
|
||||
&bfd_elf32_powerpc_vec,
|
||||
&bfd_elf32_powerpcle_vec,
|
||||
&bfd_elf32_v850_vec,
|
||||
#ifdef BFD64 /* No one seems to use this. */
|
||||
&bfd_elf64_big_generic_vec,
|
||||
@ -803,8 +810,9 @@ const bfd_target * const bfd_target_vector[] = {
|
||||
/* start-sanitize-tic80 */
|
||||
&tic80coff_vec,
|
||||
/* end-sanitize-tic80 */
|
||||
&we32kcoff_vec,
|
||||
&vaxnetbsd_vec,
|
||||
&versados_vec,
|
||||
&we32kcoff_vec,
|
||||
&z8kcoff_vec,
|
||||
|
||||
#endif /* not SELECT_VECS */
|
||||
@ -833,6 +841,9 @@ const bfd_target * const bfd_target_vector[] = {
|
||||
#ifdef IRIX_CORE
|
||||
&irix_core_vec,
|
||||
#endif
|
||||
#ifdef NETBSD_CORE
|
||||
&netbsd_core_vec,
|
||||
#endif
|
||||
#ifdef OSF_CORE
|
||||
&osf_core_vec,
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user