aboutsummaryrefslogtreecommitdiff
path: root/i386-link.c
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2016-11-12 23:16:06 +0800
committerThomas Preud'homme <robotux@celest.fr>2016-12-03 17:26:51 +0000
commitcb273fdad891d312c15110cd4eab95f5db39dcb2 (patch)
treeb5cfe985f0ba556bca2e1e6e278db51972c7b862 /i386-link.c
parent60374d01ae56e59308d1b5441bc1986295507ec6 (diff)
downloadtinycc-cb273fdad891d312c15110cd4eab95f5db39dcb2.tar.gz
tinycc-cb273fdad891d312c15110cd4eab95f5db39dcb2.tar.bz2
Do section relocation in architecture backend
Diffstat (limited to 'i386-link.c')
-rw-r--r--i386-link.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/i386-link.c b/i386-link.c
new file mode 100644
index 0000000..b33882f
--- /dev/null
+++ b/i386-link.c
@@ -0,0 +1,90 @@
+#include "tcc.h"
+#define HAVE_SECTION_RELOC
+
+static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
+
+void relocate_init(Section *sr)
+{
+ qrel = (ElfW_Rel *) sr->data;
+}
+
+void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val)
+{
+ int sym_index, esym_index;
+
+ sym_index = ELFW(R_SYM)(rel->r_info);
+
+ switch (type) {
+ case R_386_32:
+ if (s1->output_type == TCC_OUTPUT_DLL) {
+ esym_index = s1->symtab_to_dynsym[sym_index];
+ qrel->r_offset = rel->r_offset;
+ if (esym_index) {
+ qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
+ qrel++;
+ return;
+ } else {
+ qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
+ qrel++;
+ }
+ }
+ add32le(ptr, val);
+ return;
+ case R_386_PC32:
+ if (s1->output_type == TCC_OUTPUT_DLL) {
+ /* DLL relocation */
+ esym_index = s1->symtab_to_dynsym[sym_index];
+ if (esym_index) {
+ qrel->r_offset = rel->r_offset;
+ qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
+ qrel++;
+ return;
+ }
+ }
+ add32le(ptr, val - addr);
+ return;
+ case R_386_PLT32:
+ add32le(ptr, val - addr);
+ return;
+ case R_386_GLOB_DAT:
+ case R_386_JMP_SLOT:
+ write32le(ptr, val);
+ return;
+ case R_386_GOTPC:
+ add32le(ptr, s1->got->sh_addr - addr);
+ return;
+ case R_386_GOTOFF:
+ add32le(ptr, val - s1->got->sh_addr);
+ return;
+ case R_386_GOT32:
+ case R_386_GOT32X:
+ /* we load the got offset */
+ add32le(ptr, s1->sym_attrs[sym_index].got_offset);
+ return;
+ case R_386_16:
+ if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
+ output_file:
+ tcc_error("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:
+ /* do nothing */
+ return;
+ case R_386_COPY:
+ /* This reloction must copy initialized data from the library
+ to the program .bss segment. Currently made like for ARM
+ (to remove noise of defaukt case). Is this true?
+ */
+ return;
+ default:
+ fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
+ type, (unsigned)addr, ptr, (unsigned)val);
+ return;
+ }
+}