tinycc-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]