Replace pointer casts with calls to (read|write)(16|32|64)le.

This stops UBSan from giving runtime misaligned address errors
and might eventually allow building on a non-little-endian host.
This commit is contained in:
Edmund Grimley Evans 2015-11-19 18:21:14 +00:00
parent 5d496b1695
commit 553242c18a
5 changed files with 185 additions and 170 deletions

View File

@ -110,7 +110,7 @@ ST_FUNC void o(unsigned int c)
int ind1 = ind + 4;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
*(uint32_t *)(cur_text_section->data + ind) = c;
write32le(cur_text_section->data + ind, c);
ind = ind1;
}
@ -237,12 +237,12 @@ ST_FUNC void gsym_addr(int t_, int a_)
uint32_t t = t_;
uint32_t a = a_;
while (t) {
uint32_t *ptr = (uint32_t *)(cur_text_section->data + t);
uint32_t next = *ptr;
unsigned char *ptr = cur_text_section->data + t;
uint32_t next = read32le(ptr);
if (a - t + 0x8000000 >= 0x10000000)
tcc_error("branch out of range");
*ptr = (a - t == 4 ? 0xd503201f : // nop
0x14000000 | ((a - t) >> 2 & 0x3ffffff)); // b
write32le(ptr, (a - t == 4 ? 0xd503201f : // nop
0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b
t = next;
}
}
@ -1177,8 +1177,7 @@ ST_FUNC void gen_va_arg(CType *t)
o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
b2 = ind; o(0x14000000); // b lab2
// lab1:
*(uint32_t *)(cur_text_section->data + b1) =
(0x5400000d | (ind - b1) << 3);
write32le(cur_text_section->data + b1, 0x5400000d | (ind - b1) << 3);
o(0xb9001c00 | r1 | r0 << 5); // str w(r1),[x(r0),#28] // __vr_offs
o(0xf9400800 | r1 | r0 << 5); // ldr x(r1),[x(r0),#16] // __vr_top
if (hfa == 1 || fsize == 16)
@ -1198,8 +1197,7 @@ ST_FUNC void gen_va_arg(CType *t)
(uint32_t)(hfa != 3) << 21); // st(hfa) {v28.(s|d),...}[0],[x(r1)]
}
// lab2:
*(uint32_t *)(cur_text_section->data + b2) =
(0x14000000 | (ind - b2) >> 2);
write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2);
}
}
@ -1259,14 +1257,13 @@ ST_FUNC void gfunc_epilog(void)
{
if (loc) {
// Insert instructions to subtract size of stack frame from SP.
uint32_t *ptr =
(uint32_t *)(cur_text_section->data + arm64_func_sub_sp_offset);
unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
uint64_t diff = (-loc + 15) & ~15;
if (!(diff >> 24)) {
if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff)
ptr[0] = 0xd10003ff | (diff & 0xfff) << 10;
write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10);
if (diff >> 12) // sub sp,sp,#(diff >> 12),lsl #12
ptr[1] = 0xd14003ff | (diff >> 12) << 10;
write32le(ptr + 4, 0xd14003ff | (diff >> 12) << 10);
}
else {
// In this case we may subtract more than necessary,
@ -1281,9 +1278,9 @@ ST_FUNC void gfunc_epilog(void)
diff = (diff + 1) >> 1;
++j;
}
ptr[0] = 0xd2800010 | diff << 5 | i << 21;
write32le(ptr, 0xd2800010 | diff << 5 | i << 21);
// mov x16,#(diff),lsl #(16 * i)
ptr[1] = 0xcb3063ff | j << 10;
write32le(ptr + 4, 0xcb3063ff | j << 10);
// sub sp,sp,x16,lsl #(j)
}
}
@ -1805,8 +1802,7 @@ ST_FUNC void gen_clear_cache(void)
lab1 = ind;
o(0xd50b7b20 | p); // dc cvau,x(p)
o(0x8b000000 | p | p << 5 | dsz << 16); // add x(p),x(p),x(dsz)
*(uint32_t *)(cur_text_section->data + b1) =
(0x14000000 | (ind - b1) >> 2);
write32le(cur_text_section->data + b1, 0x14000000 | (ind - b1) >> 2);
o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end)
o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1
o(0xd5033b9f); // dsb ish
@ -1816,8 +1812,7 @@ ST_FUNC void gen_clear_cache(void)
lab1 = ind;
o(0xd50b7520 | p); // ic ivau,x(p)
o(0x8b000000 | p | p << 5 | isz << 16); // add x(p),x(p),x(isz)
*(uint32_t *)(cur_text_section->data + b1) =
(0x14000000 | (ind - b1) >> 2);
write32le(cur_text_section->data + b1, 0x14000000 | (ind - b1) >> 2);
o(0xeb00001f | p << 5 | end << 16); // cmp x(p),x(end)
o(0x54ffffa3 | ((lab1 - ind) << 3 & 0xffffe0)); // b.cc lab1
o(0xd5033b9f); // dsb ish

View File

@ -138,11 +138,10 @@ ST_FUNC void gen_le32(int c)
/* output a symbol and patch all calls to it */
ST_FUNC void gsym_addr(int t, int a)
{
int n, *ptr;
while (t) {
ptr = (int *)(cur_text_section->data + t);
n = *ptr; /* next value */
*ptr = a - t - 4;
unsigned char *ptr = cur_text_section->data + t;
uint32_t n = read32le(ptr); /* next value */
write32le(ptr, a - t - 4);
t = n;
}
}
@ -165,7 +164,7 @@ ST_FUNC int oad(int c, int s)
ind1 = ind + 4;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
*(int *)(cur_text_section->data + ind) = s;
write32le(cur_text_section->data + ind, s);
s = ind;
ind = ind1;
return s;
@ -671,9 +670,7 @@ ST_FUNC void gjmp_addr(int a)
/* generate a test. set 'inv' to invert test. Stack entry is popped */
ST_FUNC int gtst(int inv, int t)
{
int v, t1, *p;
v = vtop->r & VT_VALMASK;
int v = vtop->r & VT_VALMASK;
if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */
g(0x0f);
@ -681,14 +678,12 @@ ST_FUNC int gtst(int inv, int t)
} else if (v == VT_JMP || v == VT_JMPI) {
/* && or || optimization */
if ((v & 1) == inv) {
uint32_t n1, n = vtop->c.i;
/* insert vtop->c jump list in t */
t1 = vtop->c.i;
p = &t1;
while (*p != 0)
p = (int *)(cur_text_section->data + *p);
*p = t;
vtop->c.i = t1;
t = t1;
while ((n1 = read32le(cur_text_section->data + n)))
n = n1;
write32le(cur_text_section->data + n, t);
t = vtop->c.i;
} else {
t = gjmp(t);
gsym(vtop->c.i);

45
tcc.h
View File

@ -131,6 +131,51 @@
#include "stab.h"
#include "libtcc.h"
static inline uint16_t read16le(unsigned char *p)
{
return p[0] | (uint16_t)p[1] << 8;
}
static inline void write16le(unsigned char *p, uint16_t x)
{
p[0] = x & 255;
p[1] = x >> 8 & 255;
}
static inline uint32_t read32le(unsigned char *p)
{
return (p[0] | (uint32_t)p[1] << 8 |
(uint32_t)p[2] << 16 | (uint32_t)p[3] << 24);
}
static inline void write32le(unsigned char *p, uint32_t x)
{
p[0] = x & 255;
p[1] = x >> 8 & 255;
p[2] = x >> 16 & 255;
p[3] = x >> 24 & 255;
}
static inline uint64_t read64le(unsigned char *p)
{
return (p[0] | (uint64_t)p[1] << 8 |
(uint64_t)p[2] << 16 | (uint64_t)p[3] << 24 |
(uint64_t)p[4] << 32 | (uint64_t)p[5] << 40 |
(uint64_t)p[6] << 48 | (uint64_t)p[7] << 56);
}
static inline void write64le(unsigned char *p, uint64_t x)
{
p[0] = x & 255;
p[1] = x >> 8 & 255;
p[2] = x >> 16 & 255;
p[3] = x >> 24 & 255;
p[4] = x >> 32 & 255;
p[5] = x >> 40 & 255;
p[6] = x >> 48 & 255;
p[7] = x >> 56 & 255;
}
/* parser debug */
/* #define PARSE_DEBUG */
/* preprocessor debug */

213
tccelf.c
View File

@ -528,7 +528,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
qrel++;
}
}
*(int *)ptr += val;
write32le(ptr, read32le(ptr) + val);
break;
case R_386_PC32:
if (s1->output_type == TCC_OUTPUT_DLL) {
@ -541,36 +541,36 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break;
}
}
*(int *)ptr += val - addr;
write32le(ptr, read32le(ptr) + val - addr);
break;
case R_386_PLT32:
*(int *)ptr += val - addr;
write32le(ptr, read32le(ptr) + val - addr);
break;
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
*(int *)ptr = val;
write32le(ptr, val);
break;
case R_386_GOTPC:
*(int *)ptr += s1->got->sh_addr - addr;
write32le(ptr, read32le(ptr) + s1->got->sh_addr - addr);
break;
case R_386_GOTOFF:
*(int *)ptr += val - s1->got->sh_addr;
write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
break;
case R_386_GOT32:
/* we load the got offset */
*(int *)ptr += s1->sym_attrs[sym_index].got_offset;
write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
break;
case R_386_16:
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
output_file:
tcc_error("can only produce 16-bit binary files");
}
*(short *)ptr += val;
write16le(ptr, read16le(ptr) + val);
break;
case R_386_PC16:
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
goto output_file;
*(short *)ptr += val - addr;
write16le(ptr, read16le(ptr) + val - addr);
break;
#elif defined(TCC_TARGET_ARM)
case R_ARM_PC24:
@ -762,38 +762,38 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break;
#elif defined(TCC_TARGET_ARM64)
case R_AARCH64_ABS64:
*(uint64_t *)ptr = val;
write64le(ptr, val);
break;
case R_AARCH64_ABS32:
*(uint32_t *)ptr = val;
write32le(ptr, val);
break;
case R_AARCH64_MOVW_UABS_G0_NC:
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
(val & 0xffff) << 5;
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
(val & 0xffff) << 5));
break;
case R_AARCH64_MOVW_UABS_G1_NC:
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
(val >> 16 & 0xffff) << 5;
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
(val >> 16 & 0xffff) << 5));
break;
case R_AARCH64_MOVW_UABS_G2_NC:
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
(val >> 32 & 0xffff) << 5;
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
(val >> 32 & 0xffff) << 5));
break;
case R_AARCH64_MOVW_UABS_G3:
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffe0001f) |
(val >> 48 & 0xffff) << 5;
write32le(ptr, ((read32le(ptr) & 0xffe0001f) |
(val >> 48 & 0xffff) << 5));
break;
case R_AARCH64_ADR_PREL_PG_HI21: {
uint64_t off = (val >> 12) - (addr >> 12);
if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29;
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29));
break;
}
case R_AARCH64_ADD_ABS_LO12_NC:
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0xffc003ff) |
(val & 0xfff) << 10;
write32le(ptr, ((read32le(ptr) & 0xffc003ff) |
(val & 0xfff) << 10));
break;
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
@ -812,9 +812,9 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
{
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val);
}
*(uint32_t *)ptr = 0x14000000 |
write32le(ptr, (0x14000000 |
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
((val - addr) >> 2 & 0x3ffffff);
((val - addr) >> 2 & 0x3ffffff)));
break;
case R_AARCH64_ADR_GOT_PAGE: {
uint64_t off =
@ -822,14 +822,15 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
s1->sym_attrs[sym_index].got_offset) >> 12) - (addr >> 12));
if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29;
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29));
break;
}
case R_AARCH64_LD64_GOT_LO12_NC:
*(uint32_t *)ptr = (*(uint32_t *)ptr & 0xfff803ff) |
((s1->got->sh_addr + s1->sym_attrs[sym_index].got_offset)
& 0xff8) << 7;
write32le(ptr,
((read32le(ptr) & 0xfff803ff) |
((s1->got->sh_addr +
s1->sym_attrs[sym_index].got_offset) & 0xff8) << 7));
break;
case R_AARCH64_COPY:
break;
@ -841,7 +842,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
val - rel->r_addend,
(char *) symtab_section->link->data + sym->st_name);
#endif
*(addr_t *)ptr = val - rel->r_addend;
write64le(ptr, val - rel->r_addend);
break;
default:
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
@ -885,11 +886,11 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break;
} else {
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
qrel->r_addend = *(long long *)ptr + val;
qrel->r_addend = read64le(ptr) + val;
qrel++;
}
}
*(long long *)ptr += val;
write64le(ptr, read64le(ptr) + val);
break;
case R_X86_64_32:
case R_X86_64_32S:
@ -897,10 +898,10 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_X86_64_32 even for a 64bit pointer */
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
qrel->r_addend = *(int *)ptr + val;
qrel->r_addend = read32le(ptr) + val;
qrel++;
}
*(int *)ptr += val;
write32le(ptr, read32le(ptr) + val);
break;
case R_X86_64_PC32:
@ -910,7 +911,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
qrel->r_addend = *(int *)ptr;
qrel->r_addend = read32le(ptr);
qrel++;
break;
}
@ -931,24 +932,25 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
if (diff < -2147483648LL || diff > 2147483647LL) {
tcc_error("internal error: relocation failed");
}
*(int *)ptr += diff;
write32le(ptr, read32le(ptr) + diff);
}
break;
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT:
/* They don't need addend */
*(addr_t *)ptr = val - rel->r_addend;
write64le(ptr, val - rel->r_addend);
break;
case R_X86_64_GOTPCREL:
*(int *)ptr += (s1->got->sh_addr - addr +
s1->sym_attrs[sym_index].got_offset - 4);
write32le(ptr, read32le(ptr) +
(s1->got->sh_addr - addr +
s1->sym_attrs[sym_index].got_offset - 4));
break;
case R_X86_64_GOTTPOFF:
*(int *)ptr += val - s1->got->sh_addr;
write32le(ptr, read32le(ptr) + val - s1->got->sh_addr);
break;
case R_X86_64_GOT32:
/* we load the got offset */
*(int *)ptr += s1->sym_attrs[sym_index].got_offset;
write32le(ptr, read32le(ptr) + s1->sym_attrs[sym_index].got_offset);
break;
#else
#error unsupported processor
@ -1032,23 +1034,6 @@ static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
return &s1->sym_attrs[index];
}
/* XXX: suppress that */
static void put32(unsigned char *p, uint32_t val)
{
p[0] = val;
p[1] = val >> 8;
p[2] = val >> 16;
p[3] = val >> 24;
}
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
static uint32_t get32(unsigned char *p)
{
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
#endif
static void build_got(TCCState *s1)
{
unsigned char *ptr;
@ -1061,19 +1046,19 @@ static void build_got(TCCState *s1)
ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
#if PTR_SIZE == 4
/* keep space for _DYNAMIC pointer, if present */
put32(ptr, 0);
write32le(ptr, 0);
/* two dummy got entries */
put32(ptr + 4, 0);
put32(ptr + 8, 0);
write32le(ptr + 4, 0);
write32le(ptr + 8, 0);
#else
/* keep space for _DYNAMIC pointer, if present */
put32(ptr, 0);
put32(ptr + 4, 0);
write32le(ptr, 0);
write32le(ptr + 4, 0);
/* two dummy got entries */
put32(ptr + 8, 0);
put32(ptr + 12, 0);
put32(ptr + 16, 0);
put32(ptr + 20, 0);
write32le(ptr + 8, 0);
write32le(ptr + 12, 0);
write32le(ptr + 16, 0);
write32le(ptr + 20, 0);
#endif
}
@ -1155,10 +1140,10 @@ static unsigned long put_got_entry(TCCState *s1,
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* pushl got + PTR_SIZE */
p[1] = modrm + 0x10;
put32(p + 2, PTR_SIZE);
write32le(p + 2, PTR_SIZE);
p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
p[7] = modrm;
put32(p + 8, PTR_SIZE * 2);
write32le(p + 8, PTR_SIZE * 2);
}
/* The PLT slot refers to the relocation entry it needs
@ -1169,16 +1154,16 @@ static unsigned long put_got_entry(TCCState *s1,
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* jmp *(got + x) */
p[1] = modrm;
put32(p + 2, s1->got->data_offset);
write32le(p + 2, s1->got->data_offset);
p[6] = 0x68; /* push $xxx */
#ifdef TCC_TARGET_X86_64
/* On x86-64, the relocation is referred to by _index_. */
put32(p + 7, relofs / sizeof (ElfW_Rel));
write32le(p + 7, relofs / sizeof (ElfW_Rel));
#else
put32(p + 7, relofs);
write32le(p + 7, relofs);
#endif
p[11] = 0xe9; /* jmp plt_start */
put32(p + 12, -(plt->data_offset));
write32le(p + 12, -(plt->data_offset));
/* If this was an UNDEF symbol set the offset in the
dynsymtab to the PLT slot, so that PC32 relocs to it
@ -1200,24 +1185,24 @@ static unsigned long put_got_entry(TCCState *s1,
if (plt->data_offset == 0) {
/* first plt entry */
p = section_ptr_add(plt, 16);
put32(p, 0xe52de004); /* push {lr} */
put32(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
put32(p+8, 0xe08fe00e); /* add lr, pc, lr */
put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
write32le(p, 0xe52de004); /* push {lr} */
write32le(p+4, 0xe59fe010); /* ldr lr, [pc, #16] */
write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
write32le(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */
}
symattr->plt_offset = plt->data_offset;
if (symattr->plt_thumb_stub) {
p = section_ptr_add(plt, 20);
put32(p, 0x4778); /* bx pc */
put32(p+2, 0x46c0); /* nop */
write32le(p, 0x4778); /* bx pc */
write32le(p+2, 0x46c0); /* nop */
p += 4;
} else
p = section_ptr_add(plt, 16);
put32(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
put32(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
put32(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
put32(p+12, s1->got->data_offset); /* GOT entry off once patched */
write32le(p, 0xe59fc004); /* ldr ip, [pc, #4] ; GOT entry offset */
write32le(p+4, 0xe08fc00c); /* add ip, pc, ip ; addr of GOT entry */
write32le(p+8, 0xe59cf000); /* ldr pc, [ip] ; jump to GOT entry */
write32le(p+12, s1->got->data_offset); /* GOT entry off once patched */
/* the symbol is modified so that it will be relocated to
the PLT */
@ -1237,8 +1222,8 @@ static unsigned long put_got_entry(TCCState *s1,
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);
write32le(p, s1->got->data_offset);
write32le(p + 4, (uint64_t)s1->got->data_offset >> 32);
if (sym->st_shndx == SHN_UNDEF)
offset = plt->data_offset - 16;
@ -1381,9 +1366,9 @@ ST_FUNC void build_got_entries(TCCState *s1)
text_section->data_offset + 4, R_ARM_JUMP24,
sym_index);
p = section_ptr_add(text_section, 8);
put32(p, 0x4778); /* bx pc */
put32(p+2, 0x46c0); /* nop */
put32(p+4, 0xeafffffe); /* b $sym */
write32le(p, 0x4778); /* bx pc */
write32le(p+2, 0x46c0); /* nop */
write32le(p+4, 0xeafffffe); /* b $sym */
}
#elif defined(TCC_TARGET_ARM64)
//xx Other cases may be required here:
@ -1595,7 +1580,7 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1)
Section *init_section = find_section(s1, ".init");
unsigned char *pinit = section_ptr_add(init_section, 5);
pinit[0] = 0xe8;
put32(pinit + 1, -4);
write32le(pinit + 1, -4);
put_elf_reloc(symtab_section, init_section,
init_section->data_offset - 4, R_386_PC32, sym_index);
}
@ -1761,9 +1746,9 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
section_reserve(s1->got, offset + PTR_SIZE);
#ifdef TCC_TARGET_X86_64
/* only works for x86-64 */
put32(s1->got->data + offset + 4, sym->st_value >> 32);
write32le(s1->got->data + offset + 4, sym->st_value >> 32);
#endif
put32(s1->got->data + offset, sym->st_value & 0xffffffff);
write32le(s1->got->data + offset, sym->st_value & 0xffffffff);
}
/* Perform relocation to GOT or PLT entries */
@ -1930,20 +1915,20 @@ ST_FUNC void relocate_plt(TCCState *s1)
p_end = p + s1->plt->data_offset;
if (p < p_end) {
#if defined(TCC_TARGET_I386)
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
put32(p + 8, get32(p + 8) + s1->got->sh_addr);
write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
write32le(p + 8, read32le(p + 8) + s1->got->sh_addr);
p += 16;
while (p < p_end) {
put32(p + 2, get32(p + 2) + s1->got->sh_addr);
write32le(p + 2, read32le(p + 2) + s1->got->sh_addr);
p += 16;
}
#elif defined(TCC_TARGET_X86_64)
int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
put32(p + 2, get32(p + 2) + x);
put32(p + 8, get32(p + 8) + x - 6);
write32le(p + 2, read32le(p + 2) + x);
write32le(p + 8, read32le(p + 8) + x - 6);
p += 16;
while (p < p_end) {
put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
write32le(p + 2, read32le(p + 2) + x + s1->plt->data - p);
p += 16;
}
#elif defined(TCC_TARGET_ARM)
@ -1951,9 +1936,9 @@ ST_FUNC void relocate_plt(TCCState *s1)
x=s1->got->sh_addr - s1->plt->sh_addr - 12;
p += 16;
while (p < p_end) {
if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
p += 4;
put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
write32le(p + 12, x + read32le(p + 12) + s1->plt->data - p);
p += 16;
}
#elif defined(TCC_TARGET_ARM64)
@ -1962,32 +1947,32 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t off = (got >> 12) - (plt >> 12);
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,...
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
write32le(p + 4, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
put32(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
write32le(p + 8, (0xf9400211 | // ldr x17,[x16,#...]
(got & 0xff8) << 7));
put32(p + 12, (0x91000210 | // add x16,x16,#...
write32le(p + 12, (0x91000210 | // add x16,x16,#...
(got & 0xfff) << 10));
put32(p + 16, 0xd61f0220); // br x17
put32(p + 20, 0xd503201f); // nop
put32(p + 24, 0xd503201f); // nop
put32(p + 28, 0xd503201f); // nop
write32le(p + 16, 0xd61f0220); // br x17
write32le(p + 20, 0xd503201f); // nop
write32le(p + 24, 0xd503201f); // nop
write32le(p + 28, 0xd503201f); // nop
p += 32;
while (p < p_end) {
uint64_t pc = plt + (p - s1->plt->data);
uint64_t addr = got +
(get32(p) | (uint64_t)get32(p + 4) << 32);
(read32le(p) | (uint64_t)read32le(p + 4) << 32);
uint32_t off = (addr >> 12) - (pc >> 12);
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,...
write32le(p, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
put32(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
(addr & 0xff8) << 7));
put32(p + 8, (0x91000210 | // add x16,x16,#...
write32le(p + 8, (0x91000210 | // add x16,x16,#...
(addr & 0xfff) << 10));
put32(p + 12, 0xd61f0220); // br x17
write32le(p + 12, 0xd61f0220); // br x17
p += 16;
}
#elif defined(TCC_TARGET_C67)
@ -2654,7 +2639,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
fill_dynamic(s1, &dyninf);
/* put in GOT the dynamic section address and relocate PLT */
put32(s1->got->data, dynamic->sh_addr);
write32le(s1->got->data, dynamic->sh_addr);
if (file_type == TCC_OUTPUT_EXE
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
|| file_type == TCC_OUTPUT_DLL

View File

@ -214,11 +214,10 @@ void orex(int ll, int r, int r2, int b)
/* output a symbol and patch all calls to it */
void gsym_addr(int t, int a)
{
int n, *ptr;
while (t) {
ptr = (int *)(cur_text_section->data + t);
n = *ptr; /* next value */
*ptr = a - t - 4;
unsigned char *ptr = cur_text_section->data + t;
uint32_t n = read32le(ptr); /* next value */
write32le(ptr, a - t - 4);
t = n;
}
}
@ -248,7 +247,7 @@ ST_FUNC int oad(int c, int s)
ind1 = ind + 4;
if (ind1 > cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1);
*(int *)(cur_text_section->data + ind) = s;
write32le(cur_text_section->data + ind, s);
s = ind;
ind = ind1;
return s;
@ -1691,9 +1690,7 @@ void gjmp_addr(int a)
/* generate a test. set 'inv' to invert test. Stack entry is popped */
int gtst(int inv, int t)
{
int v, t1, *p;
v = vtop->r & VT_VALMASK;
int v = vtop->r & VT_VALMASK;
if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */
if (vtop->c.i & 0x100)
@ -1719,14 +1716,12 @@ int gtst(int inv, int t)
} else if (v == VT_JMP || v == VT_JMPI) {
/* && or || optimization */
if ((v & 1) == inv) {
uint32_t n1, n = vtop->c.i;
/* insert vtop->c jump list in t */
t1 = vtop->c.i;
p = &t1;
while (*p != 0)
p = (int *)(cur_text_section->data + *p);
*p = t;
vtop->c.i = t1;
t = t1;
while ((n1 = read32le(cur_text_section->data + n)))
n = n1;
write32le(cur_text_section->data + n, t);
t = vtop->c.i;
} else {
t = gjmp(t);
gsym(vtop->c.i);