[ELF] - Implemented R_386_16 and R_386PC16 relocations
authorGeorge Rimar <grimar@accesssoftek.com>
Sat, 3 Dec 2016 07:30:30 +0000 (07:30 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Sat, 3 Dec 2016 07:30:30 +0000 (07:30 +0000)
A program or object file using R_386_8, R_386_16, R_386_PC16 or R_386_PC8
relocations is not conformant to latest ABI. The R_386_16, and R_386_8
relocations truncate the computed value to 16 - bits and 8 - bits
respectively. R_386_PC16 and R_386_16 are used by some
applications, for example by FreeBSD loaders.

Previously we did not take addend in account for these relocation,
counting it as 0, what is wrong and was a reason of hangs.

This patch needed for example for FreeBSD pmbr (protective mbr).

Differential revision: https://reviews.llvm.org/D27303

llvm-svn: 288581

lld/ELF/Target.cpp
lld/test/ELF/i386-pc16.test [new file with mode: 0644]

index 2a61205..97c2900 100644 (file)
@@ -329,6 +329,7 @@ RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
     return R_TLSLD;
   case R_386_PLT32:
     return R_PLT_PC;
+  case R_386_PC16:
   case R_386_PC32:
     return R_PC;
   case R_386_GOTPC:
@@ -437,11 +438,13 @@ uint64_t X86TargetInfo::getImplicitAddend(const uint8_t *Buf,
   switch (Type) {
   default:
     return 0;
+  case R_386_16:
   case R_386_32:
   case R_386_GOT32:
   case R_386_GOT32X:
   case R_386_GOTOFF:
   case R_386_GOTPC:
+  case R_386_PC16:
   case R_386_PC32:
   case R_386_PLT32:
   case R_386_TLS_LE:
@@ -452,6 +455,13 @@ uint64_t X86TargetInfo::getImplicitAddend(const uint8_t *Buf,
 void X86TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
                                 uint64_t Val) const {
   checkInt<32>(Loc, Val, Type);
+
+  // R_386_PC16 and R_386_16 are not part of the current i386 psABI. They are
+  // used by 16-bit x86 objects, like boot loaders.
+  if (Type == R_386_16 || Type == R_386_PC16) {
+    write16le(Loc, Val);
+    return;
+  }
   write32le(Loc, Val);
 }
 
diff --git a/lld/test/ELF/i386-pc16.test b/lld/test/ELF/i386-pc16.test
new file mode 100644 (file)
index 0000000..46c54eb
--- /dev/null
@@ -0,0 +1,40 @@
+# REQUIRES: x86
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: ld.lld %t.o -o %t.exe
+# RUN: llvm-objdump -s -section=.text %t.exe 2>&1 | FileCheck %s
+
+# CHECK:      Contents of section .text:
+# CHECK-NEXT:  11000 56441111 52341111
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_386
+Sections:
+  - Type:            SHT_PROGBITS
+    Name:            .text
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x04
+    Content:         "1111111111111111"
+  - Type:            SHT_REL
+    Name:            .rel.text
+    Link:            .symtab
+    Info:            .text
+    AddressAlign:    0x04
+    Relocations:
+      - Offset:          0
+        Symbol:          _start
+        Type:            R_386_16
+      - Offset:          4
+        Symbol:          _start
+        Type:            R_386_PC16
+Symbols:
+  Global:
+    - Name:     _start
+      Type:     STT_FUNC
+      Section:  .text
+      Value:    0x12345
+      Size:     4