Index: COFF/Chunks.cpp =================================================================== --- COFF/Chunks.cpp +++ COFF/Chunks.cpp @@ -131,16 +131,22 @@ write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff)); } -static uint16_t readMOV(uint8_t *Off) { +static uint16_t readMOV(uint8_t *Off, bool MOVT) { uint16_t Op1 = read16le(Off); + if ((Op1 & 0xfbf0) != (MOVT ? 0xf2c0 : 0xf240)) + error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") + + " instruction in MOV32T relocation"); uint16_t Op2 = read16le(Off + 2); + if ((Op2 & 0x8000) != 0) + error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") + + " instruction in MOV32T relocation"); return (Op2 & 0x00ff) | ((Op2 >> 4) & 0x0700) | ((Op1 << 1) & 0x0800) | ((Op1 & 0x000f) << 12); } void applyMOV32T(uint8_t *Off, uint32_t V) { - uint16_t ImmW = readMOV(Off); // read MOVW operand - uint16_t ImmT = readMOV(Off + 4); // read MOVT operand + uint16_t ImmW = readMOV(Off, false); // read MOVW operand + uint16_t ImmT = readMOV(Off + 4, true); // read MOVT operand uint32_t Imm = ImmW | (ImmT << 16); V += Imm; // add the immediate offset applyMOV(Off, V); // set MOVW operand Index: test/COFF/broken-arm-reloc.s =================================================================== --- /dev/null +++ test/COFF/broken-arm-reloc.s @@ -0,0 +1,20 @@ +# REQUIRES: arm + +# RUN: llvm-mc -triple=armv7-windows-gnu %s -filetype=obj -o %t.obj +# RUN: not lld-link -out:%t.exe -entry:main %t.obj 2>&1 | FileCheck %s + +# CHECK: error: unexpected instruction in MOVT instruction in MOV32T relocation + + .global main + .global variable + .text + .thumb +main: + movw r0, :lower16:variable + nop + movt r0, :upper16:variable + ldr r0, [r0] + bx lr + .data +variable: + .long 42