Sketch i386 relocations handling, from Roman Divacky.
authorBenjamin Kramer <benny.kra@googlemail.com>
Tue, 17 Aug 2010 18:20:28 +0000 (18:20 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Tue, 17 Aug 2010 18:20:28 +0000 (18:20 +0000)
Hello world builds & runs now on i386/ELF with -integrated-as.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111264 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/ELF.h
lib/MC/ELFObjectWriter.cpp

index f33aeb4188ad0b6b3478dd8b300e791521cc0e3b..83478b75cbc4d4b504623ce9e49da5c8cb4fca79 100644 (file)
@@ -216,6 +216,27 @@ enum {
   R_X86_64_TLSDESC    = 36
 };
 
+// i386 relocations.
+// TODO: this is just a subset
+enum {
+  R_386_NONE          = 0,
+  R_386_32            = 1,
+  R_386_PC32          = 2,
+  R_386_GOT32         = 3,
+  R_386_PLT32         = 4,
+  R_386_COPY          = 5,
+  R_386_GLOB_DAT      = 6,
+  R_386_JUMP_SLOT     = 7,
+  R_386_RELATIVE      = 8,
+  R_386_GOTOFF        = 9,
+  R_386_GOTPC         = 10,
+  R_386_32PLT         = 11,
+  R_386_16            = 20,
+  R_386_PC16          = 21,
+  R_386_8             = 22,
+  R_386_PC8           = 23
+};
+
 // Section header.
 struct Elf32_Shdr {
   Elf32_Word sh_name;      // Section name (index into string table)
index 23c2dd5c20703c93140b37a3a561c7a7b5ee4a18..9b98b8f89575b9a9a55c86fda99cae7e85031d7f 100644 (file)
@@ -487,7 +487,7 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F,
   }
 }
 
-// FIXME: this is currently X86_64 only
+// FIXME: this is currently X86/X86_64 only
 void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
                                            const MCAsmLayout &Layout,
                                            const MCFragment *Fragment,
@@ -495,8 +495,6 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
                                            MCValue Target,
                                            uint64_t &FixedValue) {
   unsigned IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
-  ELFRelocationEntry ERE;
-  struct ELF::Elf64_Rela ERE64;
 
   uint64_t FixupOffset =
     Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
@@ -508,7 +506,7 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
   Value = Target.getConstant();
 
   if (Target.isAbsolute()) {
-    Type = ELF::R_X86_64_NONE;
+    Type = Is64Bit ? ELF::R_X86_64_NONE : ELF::R_386_NONE;
     Index = 0;
   } else {
     const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
@@ -540,34 +538,57 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
   }
 
   // determine the type of the relocation
-  if (IsPCRel) {
-    Type = ELF::R_X86_64_PC32;
+  if (Is64Bit) {
+    if (IsPCRel) {
+      Type = ELF::R_X86_64_PC32;
+    } else {
+      switch ((unsigned)Fixup.getKind()) {
+      default: llvm_unreachable("invalid fixup kind!");
+      case FK_Data_8: Type = ELF::R_X86_64_64; break;
+      case X86::reloc_pcrel_4byte:
+      case FK_Data_4:
+        // check that the offset fits within a signed long
+        if (isInt<32>(Target.getConstant()))
+          Type = ELF::R_X86_64_32S;
+        else
+          Type = ELF::R_X86_64_32;
+        break;
+      case FK_Data_2: Type = ELF::R_X86_64_16; break;
+      case X86::reloc_pcrel_1byte:
+      case FK_Data_1: Type = ELF::R_X86_64_8; break;
+      }
+    }
   } else {
-    switch ((unsigned)Fixup.getKind()) {
-    default: llvm_unreachable("invalid fixup kind!");
-    case FK_Data_8: Type = ELF::R_X86_64_64; break;
-    case X86::reloc_pcrel_4byte:
-    case FK_Data_4:
-      // check that the offset fits within a signed long
-      if (isInt<32>(Target.getConstant()))
-        Type = ELF::R_X86_64_32S;
-      else
-        Type = ELF::R_X86_64_32;
-      break;
-    case FK_Data_2: Type = ELF::R_X86_64_16; break;
-    case X86::reloc_pcrel_1byte:
-    case FK_Data_1:
-      Type = ELF::R_X86_64_8;
-      break;
+    if (IsPCRel) {
+      Type = ELF::R_386_PC32;
+    } else {
+      switch ((unsigned)Fixup.getKind()) {
+      default: llvm_unreachable("invalid fixup kind!");
+      case X86::reloc_pcrel_4byte:
+      case FK_Data_4: Type = ELF::R_386_32; break;
+      case FK_Data_2: Type = ELF::R_386_16; break;
+      case X86::reloc_pcrel_1byte:
+      case FK_Data_1: Type = ELF::R_386_8; break;
+      }
     }
   }
 
   FixedValue = Value;
 
-  ERE64.setSymbolAndType(Index, Type);
+  ELFRelocationEntry ERE;
+
+  if (Is64Bit) {
+    struct ELF::Elf64_Rela ERE64;
+    ERE64.setSymbolAndType(Index, Type);
+    ERE.r_info = ERE64.r_info;
+  } else {
+    struct ELF::Elf32_Rela ERE32;
+    ERE32.setSymbolAndType(Index, Type);
+    ERE.r_info = ERE32.r_info;
+  }
 
   ERE.r_offset = FixupOffset;
-  ERE.r_info = ERE64.r_info;
+
   if (HasRelocationAddend)
     ERE.r_addend = Addend;
   else