Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -537,7 +537,17 @@ write16le(Loc, Val); break; case R_386_PC16: - checkInt<16>(Loc, Val, Type); + // 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 + // point from any 16 bit address to any other if the possibility + // of wrapping is included. + // The only restriction we have to check then is that the destination + // address fits in 16 bits. That is impossible to do here. The problem is + // that we are passed the final value, which already had the + // current location subtracted from it. + // We just check that Val fits in 17 bits. This misses some cases, but + // should have no false positives. + checkInt<17>(Loc, Val, Type); write16le(Loc, Val); break; default: Index: test/ELF/i386-reloc-large-addend.s =================================================================== --- /dev/null +++ test/ELF/i386-reloc-large-addend.s @@ -0,0 +1,15 @@ +// RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj + +// RUN: echo ".global foo; foo = 0x1" > %t1.s +// RUN: llvm-mc %t1.s -o %t1.o -triple i386-pc-linux -filetype=obj + +// RUN: ld.lld -Ttext 0x7000 %t.o %t1.o -o %t +// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t | FileCheck %s + +// CHECK: Disassembly of section .text: +// CHECK-NEXT: _start: +// CHECK-NEXT: 7000: e9 fe 1f jmp 8190 +// 0x1 + 0x9000 - 0x7003 == 8190 + .global _start +_start: +jmp foo + 0x9000 Index: test/ELF/i386-reloc-range.s =================================================================== --- test/ELF/i386-reloc-range.s +++ test/ELF/i386-reloc-range.s @@ -1,8 +1,8 @@ // RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj -// RUN: echo ".global foo; foo = 0x8202" > %t1.s +// RUN: echo ".global foo; foo = 0x10202" > %t1.s // RUN: llvm-mc %t1.s -o %t1.o -triple i386-pc-linux -filetype=obj -// RUN: echo ".global foo; foo = 0x8203" > %t2.s +// RUN: echo ".global foo; foo = 0x10203" > %t2.s // RUN: llvm-mc %t2.s -o %t2.o -triple i386-pc-linux -filetype=obj // RUN: ld.lld -Ttext 0x200 %t.o %t1.o -o %t1 @@ -10,8 +10,8 @@ // CHECK: Disassembly of section .text: // CHECK-NEXT: _start: -// CHECK-NEXT: 200: e9 ff 7f jmp 32767 -// 0x8202 - 0x203 == 32767 +// CHECK-NEXT: 200: {{.*}} jmp -1 +// 0x10202 - 0x203 == 0xffff // RUN: not ld.lld -Ttext 0x200 %t.o %t2.o -o %t2 2>&1 | FileCheck --check-prefix=ERR %s