#include #include "cc/cc.h" #if 0 void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) { int sym_index; sym_index = ELFW(R_SYM)(rel->r_info); switch (type) { case R_386_32: add32le(ptr, val); return; case R_386_PC32: add32le(ptr, val - addr); return; case R_386_GLOB_DAT: case R_386_JMP_SLOT: write32le(ptr, val); return; case R_386_16: if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) { output_file: tcc_error_noabort("can only produce 16-bit binary files"); } write16le(ptr, read16le(ptr) + val); return; case R_386_PC16: if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) goto output_file; write16le(ptr, read16le(ptr) + val - addr); return; case R_386_RELATIVE: #ifdef TCC_TARGET_PE add32le(ptr, val - s1->pe_imagebase); #endif /* do nothing */ return; case R_386_COPY: /* This relocation must copy initialized data from the library to the program .bss segment. Currently made like for ARM (to remove noise of default case). Is this true? */ return; case R_386_TLS_GD: { static const unsigned char expect[] = { /* lea 0(,%ebx,1),%eax */ 0x8d, 0x04, 0x1d, 0x00, 0x00, 0x00, 0x00, /* call __tls_get_addr@PLT */ 0xe8, 0xfc, 0xff, 0xff, 0xff }; static const unsigned char replace[] = { /* mov %gs:0,%eax */ 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* sub 0,%eax */ 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 }; if (memcmp (ptr-3, expect, sizeof(expect)) == 0) { ElfW(Sym) *sym; Section *sec; int32_t x; memcpy(ptr-3, replace, sizeof(replace)); rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE); sym = &((ElfW(Sym) *)s1->symtab_section->data)[sym_index]; sec = s1->sections[sym->st_shndx]; x = sym->st_value - sec->sh_addr - sec->data_offset; add32le(ptr + 5, -x); } else tcc_error_noabort("unexpected R_386_TLS_GD pattern"); } return; case R_386_TLS_LDM: { static const unsigned char expect[] = { /* lea 0(%ebx),%eax */ 0x8d, 0x83, 0x00, 0x00, 0x00, 0x00, /* call __tls_get_addr@PLT */ 0xe8, 0xfc, 0xff, 0xff, 0xff }; static const unsigned char replace[] = { /* mov %gs:0,%eax */ 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* nop */ 0x90, /* lea 0(%esi,%eiz,1),%esi */ 0x8d, 0x74, 0x26, 0x00 }; if (memcmp (ptr-2, expect, sizeof(expect)) == 0) { memcpy(ptr-2, replace, sizeof(replace)); rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE); } else tcc_error_noabort("unexpected R_386_TLS_LDM pattern"); } return; case R_386_TLS_LDO_32: case R_386_TLS_LE: { ElfW(Sym) *sym; Section *sec; int32_t x; sym = &((ElfW(Sym) *)s1->symtab_section->data)[sym_index]; sec = s1->sections[sym->st_shndx]; x = val - sec->sh_addr - sec->data_offset; add32le(ptr, x); } return; case R_386_NONE: return; default: fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n", type, (unsigned)addr, ptr, (unsigned)val); return; } } #endif