summaryrefslogtreecommitdiffstats
path: root/lld/COFF/Chunks.cpp
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2018-08-27 06:04:36 +0000
committerMartin Storsjo <martin@martin.st>2018-08-27 06:04:36 +0000
commitc4b0061c0525ff268947e35c1dc9eefced26c083 (patch)
treebc8b094e37c2c3f39edbe84507367463e49f4ec3 /lld/COFF/Chunks.cpp
parent266b858705f96b24f16909ab4471b6f1514af1ca (diff)
downloadbcm5719-llvm-c4b0061c0525ff268947e35c1dc9eefced26c083.tar.gz
bcm5719-llvm-c4b0061c0525ff268947e35c1dc9eefced26c083.zip
[COFF] Check the instructions in ARM MOV32T relocations
For this relocation, which applies to two consecutive instructions, it's plausible that the second instruction might not actually be the right one. Differential Revision: https://reviews.llvm.org/D50998 llvm-svn: 340715
Diffstat (limited to 'lld/COFF/Chunks.cpp')
-rw-r--r--lld/COFF/Chunks.cpp12
1 files changed, 9 insertions, 3 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index d7f4f43c8d5..fc5998f3945 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -124,16 +124,22 @@ static void applyMOV(uint8_t *Off, uint16_t V) {
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
OpenPOWER on IntegriCloud