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.
This commit is contained in:
		
							parent
							
								
									b14ef0e24b
								
							
						
					
					
						commit
						6d055312a2
					
				
					 2 changed files with 54 additions and 10 deletions
				
			
		
							
								
								
									
										62
									
								
								tccelf.c
									
										
									
									
									
								
							
							
						
						
									
										62
									
								
								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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								tccrun.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue