/* MMIX-specific support for 64-bit ELF.
- Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Hans-Peter Nilsson <hp@bitrange.com>
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ 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., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-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. */
/* No specific ABI or "processor-specific supplement" defined. */
- GETA stub relaxation (call a stub for out of range new
R_MMIX_GETA_STUBBABLE). */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/mmix.h"
stubs_size_sum for relocation. */
bfd_size_type stub_offset;
} pjs;
+
+ /* Whether there has been a warning that this section could not be
+ linked due to a specific cause. FIXME: a way to access the
+ linker info or output section, then stuff the limiter guard
+ there. */
+ bfd_boolean has_warned_bpo;
+ bfd_boolean has_warned_pushj;
};
#define mmix_elf_section_data(sec) \
struct bpo_reloc_request *reloc_request;
};
-static bfd_boolean mmix_elf_link_output_symbol_hook
+static int mmix_elf_link_output_symbol_hook
PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
asection *, struct elf_link_hash_entry *));
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static asection * mmix_elf_gc_mark_hook
- PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
- struct elf_link_hash_entry *, Elf_Internal_Sym *));
-
-static bfd_boolean mmix_elf_gc_sweep_hook
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- const Elf_Internal_Rela *));
-
static bfd_reloc_status_type mmix_final_link_relocate
- PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
- bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
+ (reloc_howto_type *, asection *, bfd_byte *, bfd_vma, bfd_signed_vma,
+ bfd_vma, const char *, asection *, char **);
static bfd_reloc_status_type mmix_elf_perform_relocation
- PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma));
+ (asection *, reloc_howto_type *, void *, bfd_vma, bfd_vma, char **);
static bfd_boolean mmix_elf_section_from_bfd_section
PARAMS ((bfd *, asection *, int *));
static bfd_boolean mmix_elf_add_symbol_hook
- PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+ PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
const char **, flagword *, asection **, bfd_vma *));
static bfd_boolean mmix_elf_is_local_label_name
mmix_set_relaxable_size
PARAMS ((bfd *, asection *, void *));
-static bfd_boolean
-mmix_elf_get_section_contents
- PARAMS ((bfd *, sec_ptr, void *, file_ptr, bfd_size_type));
-
/* Watch out: this currently needs to have elements with the same index as
their R_MMIX_ number. */
return NULL;
}
+static reloc_howto_type *
+bfd_elf64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (elf_mmix_howto_table) / sizeof (elf_mmix_howto_table[0]);
+ i++)
+ if (elf_mmix_howto_table[i].name != NULL
+ && strcasecmp (elf_mmix_howto_table[i].name, r_name) == 0)
+ return &elf_mmix_howto_table[i];
+
+ return NULL;
+}
+
static bfd_boolean
mmix_elf_new_section_hook (abfd, sec)
bfd *abfd;
asection *sec;
{
- struct _mmix_elf_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ if (!sec->used_by_bfd)
+ {
+ struct _mmix_elf_section_data *sdata;
+ bfd_size_type amt = sizeof (*sdata);
- sdata = (struct _mmix_elf_section_data *) bfd_zalloc (abfd, amt);
- if (sdata == NULL)
- return FALSE;
- sec->used_by_bfd = (PTR) sdata;
+ sdata = bfd_zalloc (abfd, amt);
+ if (sdata == NULL)
+ return FALSE;
+ sec->used_by_bfd = sdata;
+ }
return _bfd_elf_new_section_hook (abfd, sec);
}
R_MMIX_ADDR19 and R_MMIX_ADDR27 are just filled in. */
static bfd_reloc_status_type
-mmix_elf_perform_relocation (isec, howto, datap, addr, value)
- asection *isec;
- reloc_howto_type *howto;
- PTR datap;
- bfd_vma addr;
- bfd_vma value;
+mmix_elf_perform_relocation (asection *isec, reloc_howto_type *howto,
+ void *datap, bfd_vma addr, bfd_vma value,
+ char **error_message)
{
bfd *abfd = isec->owner;
bfd_reloc_status_type flag = bfd_reloc_ok;
goto pcrel_mmix_reloc_fits;
else
{
- bfd_size_type raw_size
- = (isec->_raw_size
- - mmix_elf_section_data (isec)->pjs.n_pushj_relocs
- * MAX_PUSHJ_STUB_SIZE);
+ bfd_size_type size = isec->rawsize ? isec->rawsize : isec->size;
/* We have the bytes at the PUSHJ insn and need to get the
position for the stub. There's supposed to be room allocated
for the stub. */
bfd_byte *stubcontents
- = ((char *) datap
+ = ((bfd_byte *) datap
- (addr - (isec->output_section->vma + isec->output_offset))
- + raw_size
+ + size
+ mmix_elf_section_data (isec)->pjs.stub_offset);
bfd_vma stubaddr;
+ if (mmix_elf_section_data (isec)->pjs.n_pushj_relocs == 0)
+ {
+ /* This shouldn't happen when linking to ELF or mmo, so
+ this is an attempt to link to "binary", right? We
+ can't access the output bfd, so we can't verify that
+ assumption. We only know that the critical
+ mmix_elf_check_common_relocs has not been called,
+ which happens when the output format is different
+ from the input format (and is not mmo). */
+ if (! mmix_elf_section_data (isec)->has_warned_pushj)
+ {
+ /* For the first such error per input section, produce
+ a verbose message. */
+ *error_message
+ = _("invalid input relocation when producing"
+ " non-ELF, non-mmo format output."
+ "\n Please use the objcopy program to convert from"
+ " ELF or mmo,"
+ "\n or assemble using"
+ " \"-no-expand\" (for gcc, \"-Wa,-no-expand\"");
+ mmix_elf_section_data (isec)->has_warned_pushj = TRUE;
+ return bfd_reloc_dangerous;
+ }
+
+ /* For subsequent errors, return this one, which is
+ rate-limited but looks a little bit different,
+ hopefully without affecting user-friendliness. */
+ return bfd_reloc_overflow;
+ }
+
/* The address doesn't fit, so redirect the PUSHJ to the
location of the stub. */
r = mmix_elf_perform_relocation (isec,
addr,
isec->output_section->vma
+ isec->output_offset
- + raw_size
+ + size
+ (mmix_elf_section_data (isec)
->pjs.stub_offset)
- - addr);
+ - addr,
+ error_message);
if (r != bfd_reloc_ok)
return r;
stubaddr
= (isec->output_section->vma
+ isec->output_offset
- + raw_size
+ + size
+ mmix_elf_section_data (isec)->pjs.stub_offset);
/* We generate a simple JMP if that suffices, else the whole 5
[R_MMIX_ADDR27],
stubcontents,
stubaddr,
- value + addr - stubaddr);
+ value + addr - stubaddr,
+ error_message);
mmix_elf_section_data (isec)->pjs.stub_offset += 4;
- if (raw_size
- + mmix_elf_section_data (isec)->pjs.stub_offset
- > isec->_cooked_size)
+ if (size + mmix_elf_section_data (isec)->pjs.stub_offset
+ > isec->size)
abort ();
return r;
{
struct bpo_reloc_section_info *bpodata
= mmix_elf_section_data (isec)->bpo.reloc;
- asection *bpo_greg_section
- = bpodata->bpo_greg_section;
- struct bpo_greg_section_info *gregdata
- = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
- size_t bpo_index
- = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
+ asection *bpo_greg_section;
+ struct bpo_greg_section_info *gregdata;
+ size_t bpo_index;
+
+ if (bpodata == NULL)
+ {
+ /* This shouldn't happen when linking to ELF or mmo, so
+ this is an attempt to link to "binary", right? We
+ can't access the output bfd, so we can't verify that
+ assumption. We only know that the critical
+ mmix_elf_check_common_relocs has not been called, which
+ happens when the output format is different from the
+ input format (and is not mmo). */
+ if (! mmix_elf_section_data (isec)->has_warned_bpo)
+ {
+ /* For the first such error per input section, produce
+ a verbose message. */
+ *error_message
+ = _("invalid input relocation when producing"
+ " non-ELF, non-mmo format output."
+ "\n Please use the objcopy program to convert from"
+ " ELF or mmo,"
+ "\n or compile using the gcc-option"
+ " \"-mno-base-addresses\".");
+ mmix_elf_section_data (isec)->has_warned_bpo = TRUE;
+ return bfd_reloc_dangerous;
+ }
+
+ /* For subsequent errors, return this one, which is
+ rate-limited but looks a little bit different,
+ hopefully without affecting user-friendliness. */
+ return bfd_reloc_overflow;
+ }
+
+ bpo_greg_section = bpodata->bpo_greg_section;
+ gregdata = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
+ bpo_index = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
/* A consistency check: The value we now have in "relocation" must
be the same as the value we stored for that relocation. It
PTR data;
asection *input_section;
bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
+ char **error_message;
{
bfd_vma relocation;
bfd_reloc_status_type r;
asection *reloc_target_output_section;
bfd_reloc_status_type flag = bfd_reloc_ok;
bfd_vma output_base = 0;
- bfd_vma addr;
r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd, error_message);
return bfd_reloc_undefined;
/* Is the address of the relocation really within the section? */
- if (reloc_entry->address > input_section->_cooked_size)
+ if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
return bfd_reloc_outofrange;
/* Work out which section the relocation is targeted at and the
relocation += output_base + symbol->section->output_offset;
- /* Get position of relocation. */
- addr = (reloc_entry->address + input_section->output_section->vma
- + input_section->output_offset);
if (output_bfd != (bfd *) NULL)
{
/* Add in supplied addend. */
data, reloc_entry->address,
reloc_entry->addend, relocation,
bfd_asymbol_name (symbol),
- reloc_target_output_section);
+ reloc_target_output_section,
+ error_message);
}
\f
/* Relocate an MMIX ELF section. Modified from elf32-fr30.c; look to it
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- bfd_size_type raw_size
- = (input_section->_raw_size
- - mmix_elf_section_data (input_section)->pjs.n_pushj_relocs
- * MAX_PUSHJ_STUB_SIZE);
+ bfd_size_type size;
size_t pjsno = 0;
+ size = input_section->rawsize ? input_section->rawsize : input_section->size;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
relend = relocs + input_section->reloc_count;
+ /* Zero the stub area before we start. */
+ if (input_section->rawsize != 0
+ && input_section->size > input_section->rawsize)
+ memset (contents + input_section->rawsize, 0,
+ input_section->size - input_section->rawsize);
+
for (rel = relocs; rel < relend; rel ++)
{
reloc_howto_type *howto;
r_symndx = ELF64_R_SYM (rel->r_info);
+ howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections [r_symndx];
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ name = bfd_section_name (input_bfd, sec);
+ }
+ else
+ {
+ bfd_boolean unresolved_reloc;
+
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, undefined_signalled);
+ name = h->root.root.string;
+ }
+
+ if (sec != NULL && elf_discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, relend, howto, contents);
+
if (info->relocatable)
{
/* This is a relocatable link. For most relocs we don't have to
change anything, unless the reloc is against a section
symbol, in which case we have to adjust according to where
the section symbol winds up in the output section. */
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
-
- if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- sec = local_sections [r_symndx];
- rel->r_addend += sec->output_offset + sym->st_value;
- }
- }
+ if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ rel->r_addend += sec->output_offset;
/* For PUSHJ stub relocs however, we may need to change the
reloc and the section contents, if the reloc doesn't reach
input_section
->output_section->vma
+ input_section->output_offset
- + raw_size
+ + size
+ mmix_elf_section_data (input_section)
->pjs.stub_offset,
- NULL, NULL) != bfd_reloc_ok)
+ NULL, NULL, NULL) != bfd_reloc_ok)
return FALSE;
/* Put a JMP insn at the stub; it goes with the
R_MMIX_JMP reloc. */
bfd_put_32 (output_bfd, JMP_INSN_BYTE << 24,
contents
- + raw_size
+ + size
+ mmix_elf_section_data (input_section)
->pjs.stub_offset);
R_MMIX_JMP reloc. */
rel->r_info = ELF64_R_INFO (r_symndx, R_MMIX_JMP);
rel->r_offset
- = (raw_size
+ = (size
+ mmix_elf_section_data (input_section)
->pjs.stub_offset);
continue;
}
- /* This is a final link. */
- howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
- h = NULL;
- sym = NULL;
- sec = NULL;
-
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- sec = local_sections [r_symndx];
- relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-
- name = bfd_elf_string_from_elf_section
- (input_bfd, symtab_hdr->sh_link, sym->st_name);
- name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
- }
- else
- {
- bfd_boolean unresolved_reloc;
-
- RELOC_FOR_GLOBAL_SYMBOL (h, sym_hashes, r_symndx, symtab_hdr,
- relocation, sec, unresolved_reloc,
- info, undefined_signalled);
- }
-
r = mmix_final_link_relocate (howto, input_section,
contents, rel->r_offset,
- rel->r_addend, relocation, name, sec);
+ rel->r_addend, relocation, name, sec, NULL);
if (r != bfd_reloc_ok)
{
{
case bfd_reloc_overflow:
check_ok = info->callbacks->reloc_overflow
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset);
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
break;
case bfd_reloc_undefined:
routines. A few relocs we have to do ourselves. */
static bfd_reloc_status_type
-mmix_final_link_relocate (howto, input_section, contents,
- r_offset, r_addend, relocation, symname, symsec)
- reloc_howto_type *howto;
- asection *input_section;
- bfd_byte *contents;
- bfd_vma r_offset;
- bfd_signed_vma r_addend;
- bfd_vma relocation;
- const char *symname;
- asection *symsec;
+mmix_final_link_relocate (reloc_howto_type *howto, asection *input_section,
+ bfd_byte *contents, bfd_vma r_offset,
+ bfd_signed_vma r_addend, bfd_vma relocation,
+ const char *symname, asection *symsec,
+ char **error_message)
{
bfd_reloc_status_type r = bfd_reloc_ok;
bfd_vma addr
+ r_offset);
r = mmix_elf_perform_relocation (input_section, howto, contents,
- addr, srel);
+ addr, srel, error_message);
break;
case R_MMIX_BASE_PLUS_OFFSET:
do_mmix_reloc:
contents += r_offset;
r = mmix_elf_perform_relocation (input_section, howto, contents,
- addr, srel);
+ addr, srel, error_message);
break;
case R_MMIX_LOCAL:
relocation. */
static asection *
-mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
- asection *sec;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *rel;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+mmix_elf_gc_mark_hook (asection *sec,
+ struct bfd_link_info *info,
+ Elf_Internal_Rela *rel,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
if (h != NULL)
- {
- switch (ELF64_R_TYPE (rel->r_info))
- {
- case R_MMIX_GNU_VTINHERIT:
- case R_MMIX_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;
-
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+ switch (ELF64_R_TYPE (rel->r_info))
+ {
+ case R_MMIX_GNU_VTINHERIT:
+ case R_MMIX_GNU_VTENTRY:
+ return NULL;
+ }
- return NULL;
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Update relocation info for a GC-excluded section. We could supposedly
present. Better to waste some memory and (perhaps) a little time. */
static bfd_boolean
-mmix_elf_gc_sweep_hook (abfd, info, sec, relocs)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+mmix_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *sec,
+ const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
{
struct bpo_reloc_section_info *bpodata
= mmix_elf_section_data (sec)->bpo.reloc;
if (allocated_gregs_section == NULL)
{
allocated_gregs_section
- = bfd_make_section (bpo_greg_owner,
- MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+ = bfd_make_section_with_flags (bpo_greg_owner,
+ MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME,
+ (SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED));
/* Setting both SEC_ALLOC and SEC_LOAD means the section is
treated like any other section, and we'd get errors for
address overlap with the text section. Let's set none of
those flags, as that is what currently happens for usual
GREG allocations, and that works. */
if (allocated_gregs_section == NULL
- || !bfd_set_section_flags (bpo_greg_owner,
- allocated_gregs_section,
- (SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (bpo_greg_owner,
allocated_gregs_section,
3))
const Elf_Internal_Rela *relocs;
{
Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym);
- if (!elf_bad_symtab (abfd))
- sym_hashes_end -= symtab_hdr->sh_info;
/* First we sort the relocs so that any register relocs come before
expansion-relocs to the same insn. FIXME: Not done for mmo. */
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ }
switch (ELF64_R_TYPE (rel->r_info))
{
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_MMIX_GNU_VTINHERIT:
- if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+ if (!bfd_elf_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_MMIX_GNU_VTENTRY:
- if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+ BFD_ASSERT (h != NULL);
+ if (h != NULL
+ && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
}
the register section, and scale them down to correspond to the register
number. */
-static bfd_boolean
+static int
mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
struct bfd_link_info *info ATTRIBUTE_UNUSED;
const char *name ATTRIBUTE_UNUSED;
sym->st_shndx = SHN_REGISTER;
}
- return TRUE;
+ return 1;
}
/* We fake a register section that holds values that are register numbers.
mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
bfd *abfd;
struct bfd_link_info *info ATTRIBUTE_UNUSED;
- const Elf_Internal_Sym *sym;
+ Elf_Internal_Sym *sym;
const char **namep ATTRIBUTE_UNUSED;
flagword *flagsp ATTRIBUTE_UNUSED;
asection **secp;
bfd_vma *valp ATTRIBUTE_UNUSED;
{
if (sym->st_shndx == SHN_REGISTER)
- *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
+ {
+ *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
+ (*secp)->flags |= SEC_LINKER_CREATED;
+ }
else if ((*namep)[0] == '_' && (*namep)[1] == '_' && (*namep)[2] == '.'
- && strncmp (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
- strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)) == 0)
+ && CONST_STRNEQ (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX))
{
/* See if we have another one. */
struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash,
/* We never output a register section, though we create one for
temporary measures. Check that nobody entered contents into it. */
asection *reg_section;
- asection **secpp;
reg_section = bfd_get_section_by_name (abfd, MMIX_REG_SECTION_NAME);
if (bfd_get_section_flags (abfd, reg_section) & SEC_HAS_CONTENTS)
_bfd_abort (__FILE__, __LINE__, _("Register section has contents\n"));
- /* Really remove the section. */
- for (secpp = &abfd->sections;
- *secpp != reg_section;
- secpp = &(*secpp)->next)
- ;
- bfd_section_list_remove (abfd, secpp);
- --abfd->section_count;
+ /* Really remove the section, if it hasn't already been done. */
+ if (!bfd_section_removed_from_list (abfd, reg_section))
+ {
+ bfd_section_list_remove (abfd, reg_section);
+ --abfd->section_count;
+ }
}
- if (! bfd_elf64_bfd_final_link (abfd, info))
+ if (! bfd_elf_final_link (abfd, info))
return FALSE;
/* Since this section is marked SEC_LINKER_CREATED, it isn't output by
greg_section->output_section,
greg_section->contents,
(file_ptr) greg_section->output_offset,
- greg_section->_cooked_size))
+ greg_section->size))
return FALSE;
}
return TRUE;
}
/* We need to include the maximum size of PUSHJ-stubs in the initial
- section size. This is expected to shrink during linker relaxation.
-
- You might think that we should set *only* _cooked_size, but that won't
- work: section contents allocation will be using _raw_size in mixed
- format linking and not enough storage will be allocated. FIXME: That's
- a major bug, including the name bfd_get_section_size_before_reloc; it
- should be bfd_get_section_size_before_relax. The relaxation functions
- set _cooked size. Relaxation happens before relocation. All functions
- *after relaxation* should be using _cooked size. */
+ section size. This is expected to shrink during linker relaxation. */
static void
mmix_set_relaxable_size (abfd, sec, ptr)
if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0)
return;
- sec->_cooked_size
- = (sec->_raw_size
- + mmix_elf_section_data (sec)->pjs.n_pushj_relocs
- * MAX_PUSHJ_STUB_SIZE);
- sec->_raw_size = sec->_cooked_size;
+ sec->rawsize = sec->size;
+ sec->size += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
+ * MAX_PUSHJ_STUB_SIZE);
/* For use in relocatable link, we start with a max stubs size. See
mmix_elf_relax_section. */
n_gregs = gregdata->n_allocated_bpo_gregs;
- /* We need to have a _raw_size contents even though there's only
- _cooked_size worth of data, since the generic relocation machinery
- will allocate and copy that much temporarily. */
bpo_gregs_section->contents
- = contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->_raw_size);
+ = contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->size);
if (contents == NULL)
return FALSE;
when the last such reloc is done, an index-array is sorted according to
the values and iterated over to produce register numbers (indexed by 0
from the first allocated register number) and offsets for use in real
- relocation.
+ relocation. (N.B.: Relocatable runs are handled, not just punted.)
PUSHJ stub accounting is also done here.
spot a missing actual initialization. */
size_t bpono = (size_t) -1;
size_t pjsno = 0;
- bfd *bpo_greg_owner;
Elf_Internal_Sym *isymbuf = NULL;
- bfd_size_type raw_size
- = (sec->_raw_size
- - mmix_elf_section_data (sec)->pjs.n_pushj_relocs
- * MAX_PUSHJ_STUB_SIZE);
+ bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
mmix_elf_section_data (sec)->pjs.stubs_size_sum = 0;
/* Assume nothing changes. */
*again = FALSE;
- /* If this is the first time we have been called for this section,
- initialize the cooked size. */
- if (sec->_cooked_size == 0 && sec->_raw_size != 0)
- abort ();
-
/* We don't have to do anything if this section does not have relocs, or
if this is not a code section. */
if ((sec->flags & SEC_RELOC) == 0
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- bpo_greg_owner = (bfd *) link_info->base_file;
-
if (bpodata != NULL)
{
bpo_gregs_section = bpodata->bpo_greg_section;
0,
bfd_arch_bits_per_address (abfd),
/* Output-stub location. */
- sec->output_section->_cooked_size
+ sec->output_section->rawsize
+ (mmix_elf_section_data (sec
->output_section)
->pjs.stubs_size_sum)
bfd_vma stubaddr
= (sec->output_section->vma
+ sec->output_offset
- + raw_size
+ + size
+ mmix_elf_section_data (sec)->pjs.stubs_size_sum);
if ((value & 3) == 0
*again = TRUE;
}
- bpo_gregs_section->_cooked_size = (regindex + 1) * 8;
+ bpo_gregs_section->size = (regindex + 1) * 8;
}
if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
&& elf_section_data (sec)->relocs != internal_relocs)
free (internal_relocs);
- if (sec->_cooked_size
- < raw_size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
+ if (sec->size < size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
abort ();
- if (sec->_cooked_size
- > raw_size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
+ if (sec->size > size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
{
- sec->_cooked_size
- = raw_size + mmix_elf_section_data (sec)->pjs.stubs_size_sum;
+ sec->size = size + mmix_elf_section_data (sec)->pjs.stubs_size_sum;
*again = TRUE;
}
free (internal_relocs);
return FALSE;
}
-
-/* Because we set _raw_size to include the max size of pushj stubs,
- i.e. larger than the actual section input size (see
- mmix_set_relaxable_raw_size), we have to take care of that when reading
- the section. */
-
-static bfd_boolean
-mmix_elf_get_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- void *location;
- file_ptr offset;
- bfd_size_type count;
-{
- bfd_size_type raw_size
- = (section->_raw_size
- - mmix_elf_section_data (section)->pjs.n_pushj_relocs
- * MAX_PUSHJ_STUB_SIZE);
-
- if (offset + count > section->_raw_size)
- {
- abort();
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
- }
-
- /* Check bounds against the faked raw_size. */
- if (offset + count > raw_size)
- {
- /* Clear the part in the faked area. */
- memset (location + raw_size - offset, 0, count - (raw_size - offset));
-
- /* If there's no initial part within the "real" contents, we're
- done. */
- if ((bfd_size_type) offset >= raw_size)
- return TRUE;
-
- /* Else adjust the count and fall through to call the generic
- function. */
- count = raw_size - offset;
- }
-
- return
- _bfd_generic_get_section_contents (abfd, section, location, offset,
- count);
-}
-
\f
#define ELF_ARCH bfd_arch_mmix
#define ELF_MACHINE_CODE EM_MMIX
#define elf_backend_check_relocs mmix_elf_check_relocs
#define elf_backend_symbol_processing mmix_elf_symbol_processing
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define bfd_elf64_bfd_is_local_label_name \
mmix_elf_is_local_label_name
#define bfd_elf64_new_section_hook mmix_elf_new_section_hook
#define bfd_elf64_bfd_final_link mmix_elf_final_link
#define bfd_elf64_bfd_relax_section mmix_elf_relax_section
-#define bfd_elf64_get_section_contents mmix_elf_get_section_contents
#include "elf64-target.h"