[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Tinycc-devel] [PATCH] TCC arm64 back end
From: |
Michael Matz |
Subject: |
Re: [Tinycc-devel] [PATCH] TCC arm64 back end |
Date: |
Sun, 22 Feb 2015 06:13:21 +0100 (CET) |
User-agent: |
Alpine 2.00 (LNX 1167 2008-08-23) |
Hi,
On Thu, 19 Feb 2015, Edmund Grimley Evans wrote:
It's not finished, but a lot of things seem to work, and there's a
problem with the linker that perhaps someone could help me with.
See README.arm64 for details.
That's quite cool. Below is a patch on top of your's (slightly amended to
resolve the conflicts with top-of-mob of your recent commits) which fixes
-run. Obviously quite more stuff is missing, most of which will be
necessary for generating real shared libs (or even psABI compliant exes).
And the codegen should sometimes use different strategies. One thing I
noticed is for instance that gen_addr uses non-GOT relocs for accessing
the address of a symbol. That's generally not correct, at least for weak
symbols one has to go via a GOT entry (or some in-.text slot with a ABS64
reloc). I've hacked around this in the patch, but eventually such things
need cleanup.
And I pulled my hair out again when tracing the different paths the
linker can go through in different modes, and how the relocs and symbol
values change over the course of compilation. One of those days ... :-)
Ciao,
Michael.
---------------------
From c2274760caed058d53a94e161c34ea7ea49bfdca Mon Sep 17 00:00:00 2001
From: Michael Matz <address@hidden>
Date: Sun, 22 Feb 2015 05:59:06 +0100
Subject: [PATCH] aarch64: Fix -run.
This adds some more support for properly transfering some
offsets over the different stages of a relocations life.
Still not at all psABI compliant and DSOs can't yet be generated.
But it runs the testsuite in qemu-arm64.
---
tccelf.c | 62 +++++++++++++++++++++++++++++++++++++++++-------
tccrun.c | 2 +-
tests/Makefile | 2 +-
tests/tests2/Makefile | 20 ---------------
4 files changed, 55 insertions(+), 31 deletions(-)
diff --git a/tccelf.c b/tccelf.c
index 4f89224..2b07f60 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -451,7 +451,7 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
if (addr) {
sym->st_value = (addr_t)addr;
#ifdef DEBUG_RELOC
- printf ("relocate_sym: %s -> 0x%x\n", name, sym->st_value);
+ printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
#endif
goto found;
}
@@ -797,8 +797,21 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break;
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
+ /* This check must match the one in build_got_entries, testing
+ if we really need a PLT slot. */
+ if (sym->st_shndx == SHN_UNDEF)
+ /* We've put the PLT slot offset into r_addend when generating
+ it, and that's what we must use as relocation value (adjusted
+ by section offset of course). */
+ val = s1->plt->sh_addr + rel->r_addend;
+#ifdef DEBUG_RELOC
+ printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
+ (char *) symtab_section->link->data + sym->st_name);
+#endif
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
- tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed");
+ {
+ tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx,
addr=%lx)", addr, val);
+ }
*(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 |
((val - addr) >> 2 & 0x3ffffff);
break;
@@ -818,7 +831,17 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
& 0xff8) << 7;
break;
case R_AARCH64_COPY:
- break;
+ break;
+ case R_AARCH64_GLOB_DAT:
+ case R_AARCH64_JUMP_SLOT:
+ /* They don't need addend */
+#ifdef DEBUG_RELOC
+ printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
+ val - rel->r_addend,
+ (char *) symtab_section->link->data + sym->st_name);
+#endif
+ *(addr_t *)ptr = val - rel->r_addend;
+ break;
default:
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
type, (unsigned)addr, ptr, (unsigned)val);
@@ -1211,6 +1234,7 @@ static unsigned long put_got_entry(TCCState *s1,
plt = s1->plt;
if (plt->data_offset == 0)
section_ptr_add(plt, 32);
+ symattr->plt_offset = plt->data_offset;
p = section_ptr_add(plt, 16);
put32(p, s1->got->data_offset);
put32(p + 4, (uint64_t)s1->got->data_offset >> 32);
@@ -1372,6 +1396,23 @@ ST_FUNC void build_got_entries(TCCState *s1)
put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
sym_index);
break;
+
+ case R_AARCH64_JUMP26:
+ case R_AARCH64_CALL26:
+ if (!s1->got)
+ build_got(s1);
+ sym_index = ELFW(R_SYM)(rel->r_info);
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
+ if (sym->st_shndx == SHN_UNDEF) {
+ unsigned long ofs;
+ reloc_type = R_AARCH64_JUMP_SLOT;
+ ofs = put_got_entry(s1, reloc_type, sym->st_size,
+ sym->st_info, sym_index);
+ /* We store the place of the generated PLT slot
+ in our addend. */
+ rel->r_addend += ofs;
+ }
+ break;
#elif defined(TCC_TARGET_C67)
case R_C60_GOT32:
case R_C60_GOTOFF:
@@ -1895,8 +1936,8 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t plt = s1->plt->sh_addr;
uint64_t got = s1->got->sh_addr;
uint64_t off = (got >> 12) - (plt >> 12);
- if ((off + ((uint64_t)1 << 20)) >> 21)
- tcc_error("Failed relocating PLT");
+ if ((off + ((uint32_t)1 << 20)) >> 21)
+ tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx,
plt=0x%lx)", off, got, plt);
put32(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
put32(p + 4, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
@@ -1914,8 +1955,8 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t addr = got +
(get32(p) | (uint64_t)get32(p + 4) << 32);
uint32_t off = (addr >> 12) - (pc >> 12);
- if ((off + ((uint64_t)1 << 20)) >> 21)
- tcc_error("Failed relocating PLT");
+ if ((off + ((uint32_t)1 << 20)) >> 21)
+ tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx,
pc=0x%lx)", off, addr, pc);
put32(p, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
put32(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
@@ -2590,9 +2631,12 @@ static int elf_output_file(TCCState *s1, const char
*filename)
/* relocate symbols in .dynsym now that final addresses are known
*/
for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
- /* relocate to PLT if symbol corresponds to a PLT entry */
if (sym->st_shndx == SHN_UNDEF) {
- if (sym->st_value)
+ /* relocate to PLT if symbol corresponds to a PLT entry,
+ but not if it's a weak symbol */
+ if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
+ sym->st_value = 0;
+ else if (sym->st_value)
sym->st_value += s1->plt->sh_addr;
} else if (sym->st_shndx < SHN_LORESERVE) {
/* do symbol relocation */
diff --git a/tccrun.c b/tccrun.c
index 13c2012..8b9e719 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -196,7 +196,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
if (0 == (s->sh_flags & SHF_ALLOC))
continue;
length = s->data_offset;
- // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
+ // printf("%-12s %08lx %04x\n", s->name, s->sh_addr, length);
ptr = (void*)s->sh_addr;
if (NULL == s->data || s->sh_type == SHT_NOBITS)
memset(ptr, 0, length);
diff --git a/tests/Makefile b/tests/Makefile
index 5a9f559..fc7a42f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -49,7 +49,7 @@ endif
# Temporary work-arounds for arm64:
ifeq ($(ARCH),arm64)
- TESTS := $(filter-out test3 abitest,$(TESTS))
+ TESTS := $(filter-out abitest,$(TESTS))
TESTS := test0 $(TESTS)
endif
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index 2ec64fb..a04ad6e 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -99,16 +99,6 @@ TESTS = \
72_long_long_constant.test \
-# On arm64 some tests currently don't work with -run:
-NORUN =
-ifeq ($(ARCH),arm64)
-22_floating_point.test : NORUN = 1
-24_math_library.test : NORUN = 1
-28_strings.test : NORUN = 1
-40_stdio.test : NORUN = 1
-46_grep.test : NORUN = 1
-endif
-
# 34_array_assignment.test -- array assignment is not in C standard
SKIP = 34_array_assignment.test
@@ -132,21 +122,11 @@ all test: $(filter-out $(SKIP),$(TESTS))
%.test: %.c
@echo Test: $*...
-ifeq ($(ARCH),arm64)
- @( if [ -z "$(NORUN)" ] ; then \
- $(TCC) -run $< $(ARGS) ; else \
- $(TCC) $< -o $*.exe && ./$*.exe $(ARGS) ; \
- fi ) 2>&1 | cat >$*.output
-else
@$(TCC) -run $< $(ARGS) 2>&1 | grep -v 'warning: soft float ABI currently
not supported: default to softfp' >$*.output || true
-endif
@diff -Nbu $*.expect $*.output && rm -f $*.output
-ifeq ($(ARCH),arm64)
-else
@($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) 2>&1 | grep -v 'warning: soft
float ABI currently not supported: default to softfp' >$*.output2 || true
@diff -Nbu $*.expect $*.output2 && rm -f $*.output2 $*.exe
-endif
clean:
rm -vf fred.txt *.output* *.exe
--
1.7.3.4