Line 73... |
Line 73... |
/* Offset of next stub during relocation. Somewhat redundant with the
|
/* Offset of next stub during relocation. Somewhat redundant with the
|
above: error coverage is easier and we don't have to reset the
|
above: error coverage is easier and we don't have to reset the
|
stubs_size_sum for relocation. */
|
stubs_size_sum for relocation. */
|
bfd_size_type stub_offset;
|
bfd_size_type stub_offset;
|
} pjs;
|
} 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) \
|
#define mmix_elf_section_data(sec) \
|
((struct _mmix_elf_section_data *) elf_section_data (sec))
|
((struct _mmix_elf_section_data *) elf_section_data (sec))
|
|
|
Line 188... |
Line 195... |
static bfd_boolean mmix_elf_relocate_section
|
static bfd_boolean mmix_elf_relocate_section
|
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
|
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
|
|
|
static bfd_reloc_status_type mmix_final_link_relocate
|
static bfd_reloc_status_type mmix_final_link_relocate
|
PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
|
(reloc_howto_type *, asection *, bfd_byte *, bfd_vma, bfd_signed_vma,
|
bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
|
bfd_vma, const char *, asection *, char **);
|
|
|
static bfd_reloc_status_type mmix_elf_perform_relocation
|
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
|
static bfd_boolean mmix_elf_section_from_bfd_section
|
PARAMS ((bfd *, asection *, int *));
|
PARAMS ((bfd *, asection *, int *));
|
|
|
static bfd_boolean mmix_elf_add_symbol_hook
|
static bfd_boolean mmix_elf_add_symbol_hook
|
Line 932... |
Line 939... |
GO $255,$255,0
|
GO $255,$255,0
|
|
|
R_MMIX_ADDR19 and R_MMIX_ADDR27 are just filled in. */
|
R_MMIX_ADDR19 and R_MMIX_ADDR27 are just filled in. */
|
|
|
static bfd_reloc_status_type
|
static bfd_reloc_status_type
|
mmix_elf_perform_relocation (isec, howto, datap, addr, value)
|
mmix_elf_perform_relocation (asection *isec, reloc_howto_type *howto,
|
asection *isec;
|
void *datap, bfd_vma addr, bfd_vma value,
|
reloc_howto_type *howto;
|
char **error_message)
|
PTR datap;
|
|
bfd_vma addr;
|
|
bfd_vma value;
|
|
{
|
{
|
bfd *abfd = isec->owner;
|
bfd *abfd = isec->owner;
|
bfd_reloc_status_type flag = bfd_reloc_ok;
|
bfd_reloc_status_type flag = bfd_reloc_ok;
|
bfd_reloc_status_type r;
|
bfd_reloc_status_type r;
|
int offs = 0;
|
int offs = 0;
|
Line 1011... |
Line 1015... |
- (addr - (isec->output_section->vma + isec->output_offset))
|
- (addr - (isec->output_section->vma + isec->output_offset))
|
+ size
|
+ size
|
+ mmix_elf_section_data (isec)->pjs.stub_offset);
|
+ mmix_elf_section_data (isec)->pjs.stub_offset);
|
bfd_vma stubaddr;
|
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
|
/* The address doesn't fit, so redirect the PUSHJ to the
|
location of the stub. */
|
location of the stub. */
|
r = mmix_elf_perform_relocation (isec,
|
r = mmix_elf_perform_relocation (isec,
|
&elf_mmix_howto_table
|
&elf_mmix_howto_table
|
[R_MMIX_ADDR19],
|
[R_MMIX_ADDR19],
|
Line 1023... |
Line 1057... |
isec->output_section->vma
|
isec->output_section->vma
|
+ isec->output_offset
|
+ isec->output_offset
|
+ size
|
+ size
|
+ (mmix_elf_section_data (isec)
|
+ (mmix_elf_section_data (isec)
|
->pjs.stub_offset)
|
->pjs.stub_offset)
|
- addr);
|
- addr,
|
|
error_message);
|
if (r != bfd_reloc_ok)
|
if (r != bfd_reloc_ok)
|
return r;
|
return r;
|
|
|
stubaddr
|
stubaddr
|
= (isec->output_section->vma
|
= (isec->output_section->vma
|
Line 1047... |
Line 1082... |
r = mmix_elf_perform_relocation (isec,
|
r = mmix_elf_perform_relocation (isec,
|
&elf_mmix_howto_table
|
&elf_mmix_howto_table
|
[R_MMIX_ADDR27],
|
[R_MMIX_ADDR27],
|
stubcontents,
|
stubcontents,
|
stubaddr,
|
stubaddr,
|
value + addr - stubaddr);
|
value + addr - stubaddr,
|
|
error_message);
|
mmix_elf_section_data (isec)->pjs.stub_offset += 4;
|
mmix_elf_section_data (isec)->pjs.stub_offset += 4;
|
|
|
if (size + mmix_elf_section_data (isec)->pjs.stub_offset
|
if (size + mmix_elf_section_data (isec)->pjs.stub_offset
|
> isec->size)
|
> isec->size)
|
abort ();
|
abort ();
|
Line 1159... |
Line 1195... |
|
|
case R_MMIX_BASE_PLUS_OFFSET:
|
case R_MMIX_BASE_PLUS_OFFSET:
|
{
|
{
|
struct bpo_reloc_section_info *bpodata
|
struct bpo_reloc_section_info *bpodata
|
= mmix_elf_section_data (isec)->bpo.reloc;
|
= mmix_elf_section_data (isec)->bpo.reloc;
|
asection *bpo_greg_section
|
asection *bpo_greg_section;
|
= bpodata->bpo_greg_section;
|
struct bpo_greg_section_info *gregdata;
|
struct bpo_greg_section_info *gregdata
|
size_t bpo_index;
|
= mmix_elf_section_data (bpo_greg_section)->bpo.greg;
|
|
size_t bpo_index
|
if (bpodata == NULL)
|
= gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
|
{
|
|
/* 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
|
/* A consistency check: The value we now have in "relocation" must
|
be the same as the value we stored for that relocation. It
|
be the same as the value we stored for that relocation. It
|
doesn't cost much, so can be left in at all times. */
|
doesn't cost much, so can be left in at all times. */
|
if (value != gregdata->reloc_request[bpo_index].value)
|
if (value != gregdata->reloc_request[bpo_index].value)
|
Line 1258... |
Line 1325... |
arelent *reloc_entry;
|
arelent *reloc_entry;
|
asymbol *symbol;
|
asymbol *symbol;
|
PTR data;
|
PTR data;
|
asection *input_section;
|
asection *input_section;
|
bfd *output_bfd;
|
bfd *output_bfd;
|
char **error_message ATTRIBUTE_UNUSED;
|
char **error_message;
|
{
|
{
|
bfd_vma relocation;
|
bfd_vma relocation;
|
bfd_reloc_status_type r;
|
bfd_reloc_status_type r;
|
asection *reloc_target_output_section;
|
asection *reloc_target_output_section;
|
bfd_reloc_status_type flag = bfd_reloc_ok;
|
bfd_reloc_status_type flag = bfd_reloc_ok;
|
Line 1320... |
Line 1387... |
|
|
return mmix_final_link_relocate (reloc_entry->howto, input_section,
|
return mmix_final_link_relocate (reloc_entry->howto, input_section,
|
data, reloc_entry->address,
|
data, reloc_entry->address,
|
reloc_entry->addend, relocation,
|
reloc_entry->addend, relocation,
|
bfd_asymbol_name (symbol),
|
bfd_asymbol_name (symbol),
|
reloc_target_output_section);
|
reloc_target_output_section,
|
|
error_message);
|
}
|
}
|
|
|
/* Relocate an MMIX ELF section. Modified from elf32-fr30.c; look to it
|
/* Relocate an MMIX ELF section. Modified from elf32-fr30.c; look to it
|
for guidance if you're thinking of copying this. */
|
for guidance if you're thinking of copying this. */
|
|
|
Line 1452... |
Line 1520... |
->output_section->vma
|
->output_section->vma
|
+ input_section->output_offset
|
+ input_section->output_offset
|
+ size
|
+ size
|
+ mmix_elf_section_data (input_section)
|
+ mmix_elf_section_data (input_section)
|
->pjs.stub_offset,
|
->pjs.stub_offset,
|
NULL, NULL) != bfd_reloc_ok)
|
NULL, NULL, NULL) != bfd_reloc_ok)
|
return FALSE;
|
return FALSE;
|
|
|
/* Put a JMP insn at the stub; it goes with the
|
/* Put a JMP insn at the stub; it goes with the
|
R_MMIX_JMP reloc. */
|
R_MMIX_JMP reloc. */
|
bfd_put_32 (output_bfd, JMP_INSN_BYTE << 24,
|
bfd_put_32 (output_bfd, JMP_INSN_BYTE << 24,
|
Line 1492... |
Line 1560... |
continue;
|
continue;
|
}
|
}
|
|
|
r = mmix_final_link_relocate (howto, input_section,
|
r = mmix_final_link_relocate (howto, input_section,
|
contents, rel->r_offset,
|
contents, rel->r_offset,
|
rel->r_addend, relocation, name, sec);
|
rel->r_addend, relocation, name, sec, NULL);
|
|
|
if (r != bfd_reloc_ok)
|
if (r != bfd_reloc_ok)
|
{
|
{
|
bfd_boolean check_ok = TRUE;
|
bfd_boolean check_ok = TRUE;
|
const char * msg = (const char *) NULL;
|
const char * msg = (const char *) NULL;
|
Line 1549... |
Line 1617... |
|
|
/* Perform a single relocation. By default we use the standard BFD
|
/* Perform a single relocation. By default we use the standard BFD
|
routines. A few relocs we have to do ourselves. */
|
routines. A few relocs we have to do ourselves. */
|
|
|
static bfd_reloc_status_type
|
static bfd_reloc_status_type
|
mmix_final_link_relocate (howto, input_section, contents,
|
mmix_final_link_relocate (reloc_howto_type *howto, asection *input_section,
|
r_offset, r_addend, relocation, symname, symsec)
|
bfd_byte *contents, bfd_vma r_offset,
|
reloc_howto_type *howto;
|
bfd_signed_vma r_addend, bfd_vma relocation,
|
asection *input_section;
|
const char *symname, asection *symsec,
|
bfd_byte *contents;
|
char **error_message)
|
bfd_vma r_offset;
|
|
bfd_signed_vma r_addend;
|
|
bfd_vma relocation;
|
|
const char *symname;
|
|
asection *symsec;
|
|
{
|
{
|
bfd_reloc_status_type r = bfd_reloc_ok;
|
bfd_reloc_status_type r = bfd_reloc_ok;
|
bfd_vma addr
|
bfd_vma addr
|
= (input_section->output_section->vma
|
= (input_section->output_section->vma
|
+ input_section->output_offset
|
+ input_section->output_offset
|
Line 1585... |
Line 1648... |
srel -= (input_section->output_section->vma
|
srel -= (input_section->output_section->vma
|
+ input_section->output_offset
|
+ input_section->output_offset
|
+ r_offset);
|
+ r_offset);
|
|
|
r = mmix_elf_perform_relocation (input_section, howto, contents,
|
r = mmix_elf_perform_relocation (input_section, howto, contents,
|
addr, srel);
|
addr, srel, error_message);
|
break;
|
break;
|
|
|
case R_MMIX_BASE_PLUS_OFFSET:
|
case R_MMIX_BASE_PLUS_OFFSET:
|
if (symsec == NULL)
|
if (symsec == NULL)
|
return bfd_reloc_undefined;
|
return bfd_reloc_undefined;
|
Line 1667... |
Line 1730... |
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
}
|
}
|
do_mmix_reloc:
|
do_mmix_reloc:
|
contents += r_offset;
|
contents += r_offset;
|
r = mmix_elf_perform_relocation (input_section, howto, contents,
|
r = mmix_elf_perform_relocation (input_section, howto, contents,
|
addr, srel);
|
addr, srel, error_message);
|
break;
|
break;
|
|
|
case R_MMIX_LOCAL:
|
case R_MMIX_LOCAL:
|
/* This isn't a real relocation, it's just an assertion that the
|
/* This isn't a real relocation, it's just an assertion that the
|
final relocation value corresponds to a local register. We
|
final relocation value corresponds to a local register. We
|