119 lines
No EOL
4.1 KiB
C
119 lines
No EOL
4.1 KiB
C
#include <tcc.h>
|
|
#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
|