[PATCH] D45051: [ELF] - Relax checks for R_386_8/R_386_16 relocations.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 29 09:31:16 PDT 2018


grimar created this revision.
grimar added reviewers: ruiu, espindola.
Herald added subscribers: arichardson, emaste.

This fixes PR36927.

The issue is next. Imagine we have -Ttext 0x7c and code below.

.code16
.global _start
_start:
 movb $_start+0x83,%ah

So we have R_386_8 relocation and _start at 0x7C.
Addend is 0x83 == 131. We will sign extend it to 0xffffffffffffff83.

Now, 0xffffffffffffff83 + 0x7c gives us 0xFFFFFFFFFFFFFFFF.
Techically 0x83 + 0x7c == 0xFF, we do not exceed 1 byte value, but
currently LLD errors out, because we use checkUInt<8>.

Let's try to use checkInt<8> now and the following code to see if it can help (no):
main.s:
.byte foo

input.s:
.globl foo
.hidden foo
foo = 0xff

Here, foo is 0xFF. And addend is 0x0. Final value is 0x00000000000000FF.
Again, it fits one byte well, but with checkInt<8>,
we would error out it, so we can't use it.

What we want to do is to check that the result fits 1 byte well.

For R_386_PC16 we have a comment about using checkInt<16 + 1>. I think that
is the approach we can use for R_386_8 too. With the use of checkInt<9>,
we will check that value is in [-256, 256). It would work for both cases above.
(It will skip some cases, but we already do the same for R_386_PC16
and I think it is not so critical probably since 8/16 bits relocations are not very
common).

Patch do such change for R_386_8 and R_386_16.


https://reviews.llvm.org/D45051

Files:
  ELF/Arch/X86.cpp
  test/ELF/i386-reloc-16-large-addend.s
  test/ELF/i386-reloc-16.s
  test/ELF/i386-reloc-8-large-addend.s
  test/ELF/i386-reloc-8.s


Index: test/ELF/i386-reloc-8.s
===================================================================
--- test/ELF/i386-reloc-8.s
+++ test/ELF/i386-reloc-8.s
@@ -10,6 +10,6 @@
 // CHECK-NEXT:   1000 ff
 
 // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s
-// ERROR: relocation R_386_8 out of range: 256 is not in [0, 255]
+// ERROR: relocation R_386_8 out of range: 256 is not in [-256, 255]
 
 .byte foo
Index: test/ELF/i386-reloc-8-large-addend.s
===================================================================
--- test/ELF/i386-reloc-8-large-addend.s
+++ test/ELF/i386-reloc-8-large-addend.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t
+# RUN: ld.lld -Ttext 0x7c %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck %s
+
+# CHECK:       Contents of section .text:
+# CHECK-NEXT:  007c b4ff
+
+.code16
+.global _start
+_start:
+ movb $_start+0x83,%ah
Index: test/ELF/i386-reloc-16.s
===================================================================
--- test/ELF/i386-reloc-16.s
+++ test/ELF/i386-reloc-16.s
@@ -10,6 +10,6 @@
 // CHECK-NEXT:   1000 42
 
 // RUN: not ld.lld -shared %t %t2 -o %t4 2>&1 | FileCheck --check-prefix=ERROR %s
-// ERROR: relocation R_386_16 out of range: 65536 is not in [0, 65535]
+// ERROR: relocation R_386_16 out of range: 65536 is not in [-65536, 65535]
 
 .short foo
Index: test/ELF/i386-reloc-16-large-addend.s
===================================================================
--- test/ELF/i386-reloc-16-large-addend.s
+++ test/ELF/i386-reloc-16-large-addend.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t
+# RUN: ld.lld -Ttext 0x7c00 %t -o %t2
+# RUN: llvm-objdump -s %t2 | FileCheck %s
+
+# CHECK:       Contents of section .text:
+# CHECK-NEXT:  7c00 b800ff
+
+.code16
+.global _start
+_start:
+ movw $_start+0x8300,%ax
Index: ELF/Arch/X86.cpp
===================================================================
--- ELF/Arch/X86.cpp
+++ ELF/Arch/X86.cpp
@@ -252,20 +252,14 @@
 void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
   switch (Type) {
   case R_386_8:
+  case R_386_PC8:
     // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are
     // being used for some 16-bit programs such as boot loaders, so
     // we want to support them.
-    checkUInt<8>(Loc, Val, Type);
-    *Loc = Val;
-    break;
-  case R_386_PC8:
-    checkInt<8>(Loc, Val, Type);
+    checkInt<9>(Loc, Val, Type);
     *Loc = Val;
     break;
   case R_386_16:
-    checkUInt<16>(Loc, Val, Type);
-    write16le(Loc, Val);
-    break;
   case R_386_PC16:
     // R_386_PC16 is normally used with 16 bit code. In that situation
     // the PC is 16 bits, just like the addend. This means that it can


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D45051.140273.patch
Type: text/x-patch
Size: 2786 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180329/45734000/attachment-0001.bin>


More information about the llvm-commits mailing list