[ARC] Add linker relaxation.

Add linker relaxation. The first relaxation added is converting
GOTPC32 to PCREL relocations. This relaxation doesn't change the size of
the binary.

bfd/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* elf32-arc.c (bfd_get_32_me): New function.
	(bfd_put_32_me): Likewise.
	(arc_elf_relax_section): Likewise.
	(bfd_elf32_bfd_relax_section): Define.

ld/testsuite/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* ld-arc/relax-local-pic.d: New test.
	* ld-arc/relax-local-pic.s: New file.
This commit is contained in:
Claudiu Zissulescu 2019-07-24 16:33:29 +03:00
parent c54e42531a
commit ef551643dc
5 changed files with 218 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2019-07-24 Claudiu Zissulescu <claziss@synopsys.com>
* elf32-arc.c (bfd_get_32_me): New function.
(bfd_put_32_me): Likewise.
(arc_elf_relax_section): Likewise.
(bfd_elf32_bfd_relax_section): Define.
2019-07-24 Alan Modra <amodra@gmail.com>
* elf-bfd.h (struct elf_backend_data): Return bfd_boolean from

View File

@ -96,6 +96,31 @@ reloc_type_to_name (unsigned int type)
#define USE_REL 1
static bfd_vma
bfd_get_32_me (bfd * abfd,const unsigned char * data)
{
bfd_vma value = 0;
if (bfd_big_endian(abfd)) {
value = bfd_get_32 (abfd, data);
}
else {
value = ((bfd_get_8 (abfd, data) & 255) << 16);
value |= ((bfd_get_8 (abfd, data + 1) & 255) << 24);
value |= (bfd_get_8 (abfd, data + 2) & 255);
value |= ((bfd_get_8 (abfd, data + 3) & 255) << 8);
}
return value;
}
static void
bfd_put_32_me (bfd *abfd, bfd_vma value,unsigned char *data)
{
bfd_put_16 (abfd, (value & 0xffff0000) >> 16, data);
bfd_put_16 (abfd, value & 0xffff, data + 2);
}
static ATTRIBUTE_UNUSED bfd_boolean
is_reloc_PC_relative (reloc_howto_type *howto)
{
@ -2968,6 +2993,156 @@ elf32_arc_section_from_shdr (bfd *abfd,
return TRUE;
}
/* Relaxation hook.
These are the current relaxing opportunities available:
* R_ARC_GOTPC32 => R_ARC_PCREL.
*/
static bfd_boolean
arc_elf_relax_section (bfd *abfd, asection *sec,
struct bfd_link_info *link_info, bfd_boolean *again)
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs;
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 (bfd_link_relocatable (link_info)
|| (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
|| (sec->flags & SEC_CODE) == 0)
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, NULL, 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++)
{
/* If this isn't something that can be relaxed, then ignore
this reloc. */
if (ELF32_R_TYPE (irel->r_info) != (int) R_ARC_GOTPC32)
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;
/* Go get them off disk. */
else 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;
}
struct elf_link_hash_entry *htop = NULL;
if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info)
{
/* An external symbol. */
unsigned int indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
htop = elf_sym_hashes (abfd)[indx];
}
if (ELF32_R_TYPE (irel->r_info) == (int) R_ARC_GOTPC32
&& SYMBOL_REFERENCES_LOCAL (link_info, htop))
{
unsigned int code;
/* Get the opcode. */
code = bfd_get_32_me (abfd, contents + irel->r_offset - 4);
/* 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;
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_ARC_PC32);
/* ld rA,[pcl,symbol@tgot] -> add rA,pcl,symbol@pcl. */
/* 0010 0bbb aa11 0ZZX DBBB 1111 10AA AAAA.
111 00 000 0111 xx xxxx*/
code &= ~0x27307F80;
BFD_ASSERT (code <= 62UL);
code |= 0x27007F80;
/* Write back the new instruction. */
bfd_put_32_me (abfd, code, contents + irel->r_offset - 4);
/* The size isn't changed, don't redo. */
*again = FALSE;
}
}
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;
}
#define TARGET_LITTLE_SYM arc_elf32_le_vec
#define TARGET_LITTLE_NAME "elf32-littlearc"
#define TARGET_BIG_SYM arc_elf32_be_vec
@ -2985,6 +3160,7 @@ elf32_arc_section_from_shdr (bfd *abfd,
#define bfd_elf32_bfd_set_private_flags arc_elf_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data arc_elf_print_private_bfd_data
#define bfd_elf32_bfd_copy_private_bfd_data arc_elf_copy_private_bfd_data
#define bfd_elf32_bfd_relax_section arc_elf_relax_section
#define elf_info_to_howto_rel arc_info_to_howto_rel
#define elf_backend_object_p arc_elf_object_p

View File

@ -1,3 +1,8 @@
2019-07-24 Claudiu Zissulescu <claziss@synopsys.com>
* ld-arc/relax-local-pic.d: New test.
* ld-arc/relax-local-pic.s: New file.
2019-07-22 Martin Liska <mliska@suse.cz>
* testsuite/ld-plugin/lto-3r.d: Remove.

View File

@ -0,0 +1,14 @@
#source: relax-local-pic.s
#as:
#ld: -q -A elf32-arclittle -relax
#objdump: -dr
[^:]+: file format elf32-.*arc
Disassembly of section \.text:
00000100 <__start>:
100: 2700 7f84 0000 [0-9a-f]+ add r4,pcl,0x[0-9a-f]+.*
104: R_ARC_PC32 a_in_other_thread
108: 1c00 [0-9a-f\s]+ st\s+.*

View File

@ -0,0 +1,16 @@
.section .text
.align 4
.global __start
.type __start, @function
__start:
ld r4,[pcl,@a_in_other_thread@gotpc]
st 1,[r4]
.size __start, .-__start
.global a_in_other_thread
.section .data
.align 4
.type a_in_other_thread, @object
.size a_in_other_thread, 4
a_in_other_thread:
.word -559038737