ELF Section-level Garbage Collection.

This commit is contained in:
Richard Henderson 1998-06-30 10:02:22 +00:00
parent d40d5880c2
commit 303b4cc64f
14 changed files with 1418 additions and 179 deletions

View File

@ -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.

View File

@ -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),\

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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"

View File

@ -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);
}

View File

@ -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. */

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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