|
|
|
@ -56,10 +56,6 @@ static bfd_boolean m32r_elf_add_symbol_hook |
|
|
|
static bfd_boolean m32r_elf_relocate_section |
|
|
|
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
|
|
|
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
|
|
|
#if 0 /* not yet */
|
|
|
|
static bfd_boolean m32r_elf_relax_delete_bytes |
|
|
|
PARAMS ((bfd *, asection *, bfd_vma, int)); |
|
|
|
#endif |
|
|
|
static bfd_reloc_status_type m32r_elf_final_sda_base |
|
|
|
PARAMS ((bfd *, struct bfd_link_info *, const char **, bfd_vma *)); |
|
|
|
static bfd_boolean m32r_elf_object_p |
|
|
|
@ -3617,541 +3613,6 @@ printf("m32r_elf_finish_dynamic_sections()\n"); |
|
|
|
return TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if 0 /* relaxing not supported yet */
|
|
|
|
|
|
|
|
/* This function handles relaxing for the m32r.
|
|
|
|
Relaxing on the m32r is tricky because of instruction alignment |
|
|
|
requirements (4 byte instructions must be aligned on 4 byte boundaries). |
|
|
|
|
|
|
|
The following relaxing opportunities are handled: |
|
|
|
|
|
|
|
seth/add3/jl -> bl24 or bl8 |
|
|
|
seth/add3 -> ld24 |
|
|
|
|
|
|
|
It would be nice to handle bl24 -> bl8 but given: |
|
|
|
|
|
|
|
- 4 byte insns must be on 4 byte boundaries |
|
|
|
- branch instructions only branch to insns on 4 byte boundaries |
|
|
|
|
|
|
|
this isn't much of a win because the insn in the 2 "deleted" bytes |
|
|
|
must become a nop. With some complexity some real relaxation could be |
|
|
|
done but the frequency just wouldn't make it worth it; it's better to |
|
|
|
try to do all the code compaction one can elsewhere. |
|
|
|
When the chip supports parallel 16 bit insns, things may change. |
|
|
|
*/ |
|
|
|
|
|
|
|
static bfd_boolean |
|
|
|
m32r_elf_relax_section (abfd, sec, link_info, again) |
|
|
|
bfd *abfd; |
|
|
|
asection *sec; |
|
|
|
struct bfd_link_info *link_info; |
|
|
|
bfd_boolean *again; |
|
|
|
{ |
|
|
|
Elf_Internal_Shdr *symtab_hdr; |
|
|
|
/* The Rela structures are used here because that's what
|
|
|
|
_bfd_elf_link_read_relocs uses [for convenience - it sets the addend |
|
|
|
field to 0]. */ |
|
|
|
Elf_Internal_Rela *internal_relocs = NULL; |
|
|
|
Elf_Internal_Rela *irel, *irelend; |
|
|
|
bfd_byte *contents = NULL; |
|
|
|
Elf_Internal_Sym *isymbuf = NULL; |
|
|
|
|
|
|
|
/* Assume nothing changes. */ |
|
|
|
*again = FALSE; |
|
|
|
|
|
|
|
/* We don't have to do anything for a relocatable link, if
|
|
|
|
this section does not have relocs, or if this is not a |
|
|
|
code section. */ |
|
|
|
if (link_info->relocatable |
|
|
|
|| (sec->flags & SEC_RELOC) == 0 |
|
|
|
|| sec->reloc_count == 0 |
|
|
|
|| (sec->flags & SEC_CODE) == 0 |
|
|
|
|| 0 /* FIXME: check SHF_M32R_CAN_RELAX */) |
|
|
|
return TRUE; |
|
|
|
|
|
|
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
|
|
|
|
|
|
|
/* Get a copy of the native relocations. */ |
|
|
|
internal_relocs = (_bfd_elf_link_read_relocs |
|
|
|
(abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, |
|
|
|
link_info->keep_memory)); |
|
|
|
if (internal_relocs == NULL) |
|
|
|
goto error_return; |
|
|
|
|
|
|
|
/* Walk through them looking for relaxing opportunities. */ |
|
|
|
irelend = internal_relocs + sec->reloc_count; |
|
|
|
for (irel = internal_relocs; irel < irelend; irel++) |
|
|
|
{ |
|
|
|
bfd_vma symval; |
|
|
|
|
|
|
|
/* If this isn't something that can be relaxed, then ignore
|
|
|
|
this reloc. */ |
|
|
|
if (ELF32_R_TYPE (irel->r_info) != (int) R_M32R_HI16_SLO) |
|
|
|
continue; |
|
|
|
|
|
|
|
/* Get the section contents if we haven't done so already. */ |
|
|
|
if (contents == NULL) |
|
|
|
{ |
|
|
|
/* Get cached copy if it exists. */ |
|
|
|
if (elf_section_data (sec)->this_hdr.contents != NULL) |
|
|
|
contents = elf_section_data (sec)->this_hdr.contents; |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Go get them off disk. */ |
|
|
|
if (!bfd_malloc_and_get_section (abfd, sec, &contents)) |
|
|
|
goto error_return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Read this BFD's local symbols if we haven't done so already. */ |
|
|
|
if (isymbuf == NULL && symtab_hdr->sh_info != 0) |
|
|
|
{ |
|
|
|
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; |
|
|
|
if (isymbuf == NULL) |
|
|
|
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, |
|
|
|
symtab_hdr->sh_info, 0, |
|
|
|
NULL, NULL, NULL); |
|
|
|
if (isymbuf == NULL) |
|
|
|
goto error_return; |
|
|
|
} |
|
|
|
|
|
|
|
/* Get the value of the symbol referred to by the reloc. */ |
|
|
|
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) |
|
|
|
{ |
|
|
|
/* A local symbol. */ |
|
|
|
Elf_Internal_Sym *isym; |
|
|
|
asection *sym_sec; |
|
|
|
|
|
|
|
isym = isymbuf + ELF32_R_SYM (irel->r_info), |
|
|
|
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); |
|
|
|
symval = (isym->st_value |
|
|
|
+ sym_sec->output_section->vma |
|
|
|
+ sym_sec->output_offset); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
unsigned long indx; |
|
|
|
struct elf_link_hash_entry *h; |
|
|
|
|
|
|
|
/* An external symbol. */ |
|
|
|
indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; |
|
|
|
h = elf_sym_hashes (abfd)[indx]; |
|
|
|
BFD_ASSERT (h != NULL); |
|
|
|
if (h->root.type != bfd_link_hash_defined |
|
|
|
&& h->root.type != bfd_link_hash_defweak) |
|
|
|
{ |
|
|
|
/* This appears to be a reference to an undefined
|
|
|
|
symbol. Just ignore it--it will be caught by the |
|
|
|
regular reloc processing. */ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
symval = (h->root.u.def.value |
|
|
|
+ h->root.u.def.section->output_section->vma |
|
|
|
+ h->root.u.def.section->output_offset); |
|
|
|
} |
|
|
|
|
|
|
|
/* For simplicity of coding, we are going to modify the section
|
|
|
|
contents, the section relocs, and the BFD symbol table. We |
|
|
|
must tell the rest of the code not to free up this |
|
|
|
information. It would be possible to instead create a table |
|
|
|
of changes which have to be made, as is done in coff-mips.c; |
|
|
|
that would be more work, but would require less memory when |
|
|
|
the linker is run. */ |
|
|
|
|
|
|
|
/* Try to change a seth/add3/jl subroutine call to bl24 or bl8.
|
|
|
|
This sequence is generated by the compiler when compiling in |
|
|
|
32 bit mode. Also look for seth/add3 -> ld24. */ |
|
|
|
|
|
|
|
if (ELF32_R_TYPE (irel->r_info) == (int) R_M32R_HI16_SLO) |
|
|
|
{ |
|
|
|
Elf_Internal_Rela *nrel; |
|
|
|
bfd_vma pc = (sec->output_section->vma + sec->output_offset |
|
|
|
+ irel->r_offset); |
|
|
|
bfd_signed_vma pcrel_value = symval - pc; |
|
|
|
unsigned int code,reg; |
|
|
|
int addend,nop_p,bl8_p,to_delete; |
|
|
|
|
|
|
|
/* The tests are ordered so that we get out as quickly as possible
|
|
|
|
if this isn't something we can relax, taking into account that |
|
|
|
we are looking for two separate possibilities (jl/ld24). */ |
|
|
|
|
|
|
|
/* Do nothing if no room in the section for this to be what we're
|
|
|
|
looking for. */ |
|
|
|
if (irel->r_offset > sec->size - 8) |
|
|
|
continue; |
|
|
|
|
|
|
|
/* Make sure the next relocation applies to the next
|
|
|
|
instruction and that it's the add3's reloc. */ |
|
|
|
nrel = irel + 1; |
|
|
|
if (nrel == irelend |
|
|
|
|| irel->r_offset + 4 != nrel->r_offset |
|
|
|
|| ELF32_R_TYPE (nrel->r_info) != (int) R_M32R_LO16) |
|
|
|
continue; |
|
|
|
|
|
|
|
/* See if the instructions are seth/add3. */ |
|
|
|
/* FIXME: This is where macros from cgen can come in. */ |
|
|
|
code = bfd_get_16 (abfd, contents + irel->r_offset + 0); |
|
|
|
if ((code & 0xf0ff) != 0xd0c0) |
|
|
|
continue; /* not seth rN,foo */ |
|
|
|
reg = (code & 0x0f00) >> 8; |
|
|
|
code = bfd_get_16 (abfd, contents + irel->r_offset + 4); |
|
|
|
if (code != (0x80a0 | reg | (reg << 8))) |
|
|
|
continue; /* not add3 rN,rN,foo */ |
|
|
|
|
|
|
|
/* At this point we've confirmed we have seth/add3. Now check
|
|
|
|
whether the next insn is a jl, in which case try to change this |
|
|
|
to bl24 or bl8. */ |
|
|
|
|
|
|
|
/* Ensure the branch target is in range.
|
|
|
|
The bl24 instruction has a 24 bit operand which is the target |
|
|
|
address right shifted by 2, giving a signed range of 26 bits. |
|
|
|
Note that 4 bytes are added to the high value because the target |
|
|
|
will be at least 4 bytes closer if we can relax. It'll actually |
|
|
|
be 4 or 8 bytes closer, but we don't know which just yet and |
|
|
|
the difference isn't significant enough to worry about. */ |
|
|
|
#if !USE_REL /* put in for learning purposes */ |
|
|
|
pcrel_value += irel->r_addend; |
|
|
|
#else |
|
|
|
addend = bfd_get_signed_16 (abfd, contents + irel->r_offset + 2); |
|
|
|
pcrel_value += addend; |
|
|
|
#endif |
|
|
|
|
|
|
|
if (pcrel_value >= -(1 << 25) && pcrel_value < (1 << 25) + 4 |
|
|
|
/* Do nothing if no room in the section for this to be what we're
|
|
|
|
looking for. */ |
|
|
|
&& (irel->r_offset <= sec->size - 12) |
|
|
|
/* Ensure the next insn is "jl rN". */ |
|
|
|
&& ((code = bfd_get_16 (abfd, contents + irel->r_offset + 8)), |
|
|
|
code != (0x1ec0 | reg))) |
|
|
|
{ |
|
|
|
/* We can relax to bl24/bl8. */ |
|
|
|
|
|
|
|
/* See if there's a nop following the jl.
|
|
|
|
Also see if we can use a bl8 insn. */ |
|
|
|
code = bfd_get_16 (abfd, contents + irel->r_offset + 10); |
|
|
|
nop_p = (code & 0x7fff) == NOP_INSN; |
|
|
|
bl8_p = pcrel_value >= -0x200 && pcrel_value < 0x200; |
|
|
|
|
|
|
|
if (bl8_p) |
|
|
|
{ |
|
|
|
/* Change "seth rN,foo" to "bl8 foo || nop".
|
|
|
|
We OR in CODE just in case it's not a nop (technically, |
|
|
|
CODE currently must be a nop, but for cleanness we |
|
|
|
allow it to be anything). */ |
|
|
|
#if !USE_REL /* put in for learning purposes */ |
|
|
|
code = 0x7e000000 | MAKE_PARALLEL (code); |
|
|
|
#else |
|
|
|
code = (0x7e000000 + (((addend >> 2) & 0xff) << 16)) | MAKE_PARALLEL (code); |
|
|
|
#endif |
|
|
|
to_delete = 8; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Change the seth rN,foo to a bl24 foo. */ |
|
|
|
#if !USE_REL /* put in for learning purposes */ |
|
|
|
code = 0xfe000000; |
|
|
|
#else |
|
|
|
code = 0xfe000000 + ((addend >> 2) & 0xffffff); |
|
|
|
#endif |
|
|
|
to_delete = nop_p ? 8 : 4; |
|
|
|
} |
|
|
|
|
|
|
|
bfd_put_32 (abfd, code, contents + irel->r_offset); |
|
|
|
|
|
|
|
/* Set the new reloc type. */ |
|
|
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), |
|
|
|
bl8_p ? R_M32R_10_PCREL : R_M32R_26_PCREL); |
|
|
|
|
|
|
|
/* Delete the add3 reloc by making it a null reloc. */ |
|
|
|
nrel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), |
|
|
|
R_M32R_NONE); |
|
|
|
} |
|
|
|
else if (addend >= 0 |
|
|
|
&& symval + addend <= 0xffffff) |
|
|
|
{ |
|
|
|
/* We can relax to ld24. */ |
|
|
|
|
|
|
|
code = 0xe0000000 | (reg << 24) | (addend & 0xffffff); |
|
|
|
bfd_put_32 (abfd, code, contents + irel->r_offset); |
|
|
|
to_delete = 4; |
|
|
|
/* Tell the following code a nop filler isn't needed. */ |
|
|
|
nop_p = 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Can't do anything here. */ |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
/* Note that we've changed the relocs, section contents, etc. */ |
|
|
|
elf_section_data (sec)->relocs = internal_relocs; |
|
|
|
elf_section_data (sec)->this_hdr.contents = contents; |
|
|
|
symtab_hdr->contents = (unsigned char *) isymbuf; |
|
|
|
|
|
|
|
/* Delete TO_DELETE bytes of data. */ |
|
|
|
if (!m32r_elf_relax_delete_bytes (abfd, sec, |
|
|
|
irel->r_offset + 4, to_delete)) |
|
|
|
goto error_return; |
|
|
|
|
|
|
|
/* Now that the following bytes have been moved into place, see if
|
|
|
|
we need to replace the jl with a nop. This happens when we had |
|
|
|
to use a bl24 insn and the insn following the jl isn't a nop. |
|
|
|
Technically, this situation can't happen (since the insn can |
|
|
|
never be executed) but to be clean we do this. When the chip |
|
|
|
supports parallel 16 bit insns things may change. |
|
|
|
We don't need to do this in the case of relaxing to ld24, |
|
|
|
and the above code sets nop_p so this isn't done. */ |
|
|
|
if (! nop_p && to_delete == 4) |
|
|
|
bfd_put_16 (abfd, NOP_INSN, contents + irel->r_offset + 4); |
|
|
|
|
|
|
|
/* That will change things, so we should relax again.
|
|
|
|
Note that this is not required, and it may be slow. */ |
|
|
|
*again = TRUE; |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
/* loop to try the next reloc */ |
|
|
|
} |
|
|
|
|
|
|
|
if (isymbuf != NULL |
|
|
|
&& symtab_hdr->contents != (unsigned char *) isymbuf) |
|
|
|
{ |
|
|
|
if (! link_info->keep_memory) |
|
|
|
free (isymbuf); |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Cache the symbols for elf_link_input_bfd. */ |
|
|
|
symtab_hdr->contents = (unsigned char *) isymbuf; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (contents != NULL |
|
|
|
&& elf_section_data (sec)->this_hdr.contents != contents) |
|
|
|
{ |
|
|
|
if (! link_info->keep_memory) |
|
|
|
free (contents); |
|
|
|
else |
|
|
|
{ |
|
|
|
/* Cache the section contents for elf_link_input_bfd. */ |
|
|
|
elf_section_data (sec)->this_hdr.contents = contents; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (internal_relocs != NULL |
|
|
|
&& elf_section_data (sec)->relocs != internal_relocs) |
|
|
|
free (internal_relocs); |
|
|
|
|
|
|
|
return TRUE; |
|
|
|
|
|
|
|
error_return: |
|
|
|
if (isymbuf != NULL |
|
|
|
&& symtab_hdr->contents != (unsigned char *) isymbuf) |
|
|
|
free (isymbuf); |
|
|
|
if (contents != NULL |
|
|
|
&& elf_section_data (sec)->this_hdr.contents != contents) |
|
|
|
free (contents); |
|
|
|
if (internal_relocs != NULL |
|
|
|
&& elf_section_data (sec)->relocs != internal_relocs) |
|
|
|
free (internal_relocs); |
|
|
|
|
|
|
|
return FALSE; |
|
|
|
} |
|
|
|
|
|
|
|
/* Delete some bytes from a section while relaxing. */ |
|
|
|
|
|
|
|
static bfd_boolean |
|
|
|
m32r_elf_relax_delete_bytes (abfd, sec, addr, count) |
|
|
|
bfd *abfd; |
|
|
|
asection *sec; |
|
|
|
bfd_vma addr; |
|
|
|
int count; |
|
|
|
{ |
|
|
|
Elf_Internal_Shdr *symtab_hdr; |
|
|
|
int shndx; |
|
|
|
bfd_byte *contents; |
|
|
|
Elf_Internal_Rela *irel, *irelend; |
|
|
|
Elf_Internal_Rela *irelalign; |
|
|
|
bfd_vma toaddr; |
|
|
|
Elf_Internal_Sym *isym, *isymend; |
|
|
|
struct elf_link_hash_entry **sym_hashes; |
|
|
|
struct elf_link_hash_entry **end_hashes; |
|
|
|
unsigned int symcount; |
|
|
|
|
|
|
|
shndx = _bfd_elf_section_from_bfd_section (abfd, sec); |
|
|
|
|
|
|
|
contents = elf_section_data (sec)->this_hdr.contents; |
|
|
|
|
|
|
|
/* The deletion must stop at the next ALIGN reloc for an aligment
|
|
|
|
power larger than the number of bytes we are deleting. */ |
|
|
|
|
|
|
|
irelalign = NULL; |
|
|
|
toaddr = sec->size; |
|
|
|
|
|
|
|
irel = elf_section_data (sec)->relocs; |
|
|
|
irelend = irel + sec->reloc_count; |
|
|
|
|
|
|
|
/* Actually delete the bytes. */ |
|
|
|
memmove (contents + addr, contents + addr + count, toaddr - addr - count); |
|
|
|
sec->size -= count; |
|
|
|
|
|
|
|
/* Adjust all the relocs. */ |
|
|
|
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) |
|
|
|
{ |
|
|
|
/* Get the new reloc address. */ |
|
|
|
if ((irel->r_offset > addr |
|
|
|
&& irel->r_offset < toaddr)) |
|
|
|
irel->r_offset -= count; |
|
|
|
} |
|
|
|
|
|
|
|
/* Adjust the local symbols defined in this section. */ |
|
|
|
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
|
|
|
isym = (Elf_Internal_Sym *) symtab_hdr->contents; |
|
|
|
for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) |
|
|
|
{ |
|
|
|
if (isym->st_shndx == shndx |
|
|
|
&& isym->st_value > addr |
|
|
|
&& isym->st_value < toaddr) |
|
|
|
isym->st_value -= count; |
|
|
|
} |
|
|
|
|
|
|
|
/* Now adjust the global symbols defined in this section. */ |
|
|
|
symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) |
|
|
|
- symtab_hdr->sh_info); |
|
|
|
sym_hashes = elf_sym_hashes (abfd); |
|
|
|
end_hashes = sym_hashes + symcount; |
|
|
|
for (; sym_hashes < end_hashes; sym_hashes++) |
|
|
|
{ |
|
|
|
struct elf_link_hash_entry *sym_hash = *sym_hashes; |
|
|
|
|
|
|
|
if ((sym_hash->root.type == bfd_link_hash_defined |
|
|
|
|| sym_hash->root.type == bfd_link_hash_defweak) |
|
|
|
&& sym_hash->root.u.def.section == sec |
|
|
|
&& sym_hash->root.u.def.value > addr |
|
|
|
&& sym_hash->root.u.def.value < toaddr) |
|
|
|
{ |
|
|
|
sym_hash->root.u.def.value -= count; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
/* This is a version of bfd_generic_get_relocated_section_contents
|
|
|
|
which uses m32r_elf_relocate_section. */ |
|
|
|
|
|
|
|
static bfd_byte * |
|
|
|
m32r_elf_get_relocated_section_contents (output_bfd, link_info, link_order, |
|
|
|
data, relocatable, symbols) |
|
|
|
bfd *output_bfd; |
|
|
|
struct bfd_link_info *link_info; |
|
|
|
struct bfd_link_order *link_order; |
|
|
|
bfd_byte *data; |
|
|
|
bfd_boolean relocatable; |
|
|
|
asymbol **symbols; |
|
|
|
{ |
|
|
|
Elf_Internal_Shdr *symtab_hdr; |
|
|
|
asection *input_section = link_order->u.indirect.section; |
|
|
|
bfd *input_bfd = input_section->owner; |
|
|
|
asection **sections = NULL; |
|
|
|
Elf_Internal_Rela *internal_relocs = NULL; |
|
|
|
Elf_Internal_Sym *isymbuf = NULL; |
|
|
|
bfd_size_type amt; |
|
|
|
|
|
|
|
/* We only need to handle the case of relaxing, or of having a
|
|
|
|
particular set of section contents, specially. */ |
|
|
|
if (relocatable |
|
|
|
|| elf_section_data (input_section)->this_hdr.contents == NULL) |
|
|
|
return bfd_generic_get_relocated_section_contents (output_bfd, link_info, |
|
|
|
link_order, data, |
|
|
|
relocatable, |
|
|
|
symbols); |
|
|
|
|
|
|
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
|
|
|
|
|
|
|
memcpy (data, elf_section_data (input_section)->this_hdr.contents, |
|
|
|
input_section->size); |
|
|
|
|
|
|
|
if ((input_section->flags & SEC_RELOC) != 0 |
|
|
|
&& input_section->reloc_count > 0) |
|
|
|
{ |
|
|
|
Elf_Internal_Sym *isymp; |
|
|
|
asection **secpp; |
|
|
|
Elf32_External_Sym *esym, *esymend; |
|
|
|
|
|
|
|
internal_relocs = (_bfd_elf_link_read_relocs |
|
|
|
(input_bfd, input_section, (PTR) NULL, |
|
|
|
(Elf_Internal_Rela *) NULL, FALSE)); |
|
|
|
if (internal_relocs == NULL) |
|
|
|
goto error_return; |
|
|
|
|
|
|
|
if (symtab_hdr->sh_info != 0) |
|
|
|
{ |
|
|
|
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; |
|
|
|
if (isymbuf == NULL) |
|
|
|
isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, |
|
|
|
symtab_hdr->sh_info, 0, |
|
|
|
NULL, NULL, NULL); |
|
|
|
if (isymbuf == NULL) |
|
|
|
goto error_return; |
|
|
|
} |
|
|
|
|
|
|
|
amt = symtab_hdr->sh_info; |
|
|
|
amt *= sizeof (asection *); |
|
|
|
sections = (asection **) bfd_malloc (amt); |
|
|
|
if (sections == NULL && symtab_hdr->sh_info > 0) |
|
|
|
goto error_return; |
|
|
|
|
|
|
|
isymend = isymbuf + symtab_hdr->sh_info; |
|
|
|
for (isym = isymbuf, secpp = sections; isym < isymend; ++isym, ++secpp) |
|
|
|
{ |
|
|
|
asection *isec; |
|
|
|
|
|
|
|
if (isym->st_shndx == SHN_UNDEF) |
|
|
|
isec = bfd_und_section_ptr; |
|
|
|
else if (isym->st_shndx == SHN_ABS) |
|
|
|
isec = bfd_abs_section_ptr; |
|
|
|
else if (isym->st_shndx == SHN_COMMON) |
|
|
|
isec = bfd_com_section_ptr; |
|
|
|
else if (isym->st_shndx == SHN_M32R_SCOMMON) |
|
|
|
isec = &m32r_elf_scom_section; |
|
|
|
else |
|
|
|
isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx); |
|
|
|
|
|
|
|
*secpp = isec; |
|
|
|
} |
|
|
|
|
|
|
|
if (! m32r_elf_relocate_section (output_bfd, link_info, input_bfd, |
|
|
|
input_section, data, internal_relocs, |
|
|
|
isymbuf, sections)) |
|
|
|
goto error_return; |
|
|
|
|
|
|
|
if (sections != NULL) |
|
|
|
free (sections); |
|
|
|
if (isymbuf != NULL |
|
|
|
&& symtab_hdr->contents != (unsigned char *) isymbuf) |
|
|
|
free (isymbuf); |
|
|
|
if (elf_section_data (input_section)->relocs != internal_relocs) |
|
|
|
free (internal_relocs); |
|
|
|
} |
|
|
|
|
|
|
|
return data; |
|
|
|
|
|
|
|
error_return: |
|
|
|
if (sections != NULL) |
|
|
|
free (sections); |
|
|
|
if (isymbuf != NULL |
|
|
|
&& symtab_hdr->contents != (unsigned char *) isymbuf) |
|
|
|
free (isymbuf); |
|
|
|
if (internal_relocs != NULL |
|
|
|
&& elf_section_data (input_section)->relocs != internal_relocs) |
|
|
|
free (internal_relocs); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
#endif /* #if 0 */ |
|
|
|
|
|
|
|
/* Set the right machine number. */ |
|
|
|
static bfd_boolean |
|
|
|
@ -4832,13 +4293,6 @@ m32r_elf_reloc_type_class (rela) |
|
|
|
#define elf_backend_fake_sections m32r_elf_fake_sections |
|
|
|
#endif |
|
|
|
|
|
|
|
#if 0 /* not yet */
|
|
|
|
/* relax support */ |
|
|
|
#define bfd_elf32_bfd_relax_section m32r_elf_relax_section |
|
|
|
#define bfd_elf32_bfd_get_relocated_section_contents \ |
|
|
|
m32r_elf_get_relocated_section_contents |
|
|
|
#endif |
|
|
|
|
|
|
|
#define elf_backend_object_p m32r_elf_object_p |
|
|
|
#define elf_backend_final_write_processing m32r_elf_final_write_processing |
|
|
|
#define bfd_elf32_bfd_merge_private_bfd_data m32r_elf_merge_private_bfd_data |
|
|
|
|