From bc1d58a6b1cfe13e4b7f24de505bbb286febc73e Mon Sep 17 00:00:00 2001 From: George Rimar Date: Tue, 3 Apr 2018 12:19:04 +0000 Subject: [PATCH] [ELF] - Relax checks for R_386_8/R_386_16 relocations. 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. Patch changes the check to checkIntUInt to fix the issue. Differential revision: https://reviews.llvm.org/D45051 llvm-svn: 329061 --- lld/ELF/Arch/X86.cpp | 4 ++-- lld/test/ELF/i386-reloc-16-large-addend.s | 12 ++++++++++++ lld/test/ELF/i386-reloc-16.s | 2 +- lld/test/ELF/i386-reloc-8-large-addend.s | 12 ++++++++++++ lld/test/ELF/i386-reloc-8.s | 2 +- 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 lld/test/ELF/i386-reloc-16-large-addend.s create mode 100644 lld/test/ELF/i386-reloc-8-large-addend.s diff --git a/lld/ELF/Arch/X86.cpp b/lld/ELF/Arch/X86.cpp index 87c84ad..b2d9007 100644 --- a/lld/ELF/Arch/X86.cpp +++ b/lld/ELF/Arch/X86.cpp @@ -255,7 +255,7 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { // 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(Loc, Val, 8, Type); + checkIntUInt(Loc, Val, 8, Type); *Loc = Val; break; case R_386_PC8: @@ -263,7 +263,7 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { *Loc = Val; break; case R_386_16: - checkUInt(Loc, Val, 16, Type); + checkIntUInt(Loc, Val, 16, Type); write16le(Loc, Val); break; case R_386_PC16: diff --git a/lld/test/ELF/i386-reloc-16-large-addend.s b/lld/test/ELF/i386-reloc-16-large-addend.s new file mode 100644 index 0000000..ceb4862 --- /dev/null +++ b/lld/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 diff --git a/lld/test/ELF/i386-reloc-16.s b/lld/test/ELF/i386-reloc-16.s index e9d4fbb..33b6c44 100644 --- a/lld/test/ELF/i386-reloc-16.s +++ b/lld/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 [-32768, 32767] .short foo diff --git a/lld/test/ELF/i386-reloc-8-large-addend.s b/lld/test/ELF/i386-reloc-8-large-addend.s new file mode 100644 index 0000000..61d6380 --- /dev/null +++ b/lld/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 diff --git a/lld/test/ELF/i386-reloc-8.s b/lld/test/ELF/i386-reloc-8.s index e0e255b..9e9f0cc 100644 --- a/lld/test/ELF/i386-reloc-8.s +++ b/lld/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 [-128, 127] .byte foo -- 2.7.4