summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/armv7/arch_armv7.cpp68
1 files changed, 66 insertions, 2 deletions
diff --git a/arch/armv7/arch_armv7.cpp b/arch/armv7/arch_armv7.cpp
index df659dd4..08191de5 100644
--- a/arch/armv7/arch_armv7.cpp
+++ b/arch/armv7/arch_armv7.cpp
@@ -2409,6 +2409,70 @@ public:
mov->imm4 = (newTarget >> 28) & 0xf;
break;
}
+ case R_ARM_THM_MOVW_ABS_NC:
+ case R_ARM_THM_MOVT_ABS:
+ {
+ /*
+ MOVW<c> <Rd>,#<imm16>
+ |15 14 13 12 11|10 |9 8 |7 |6 |5 |4 |3 2 1 0 |15|14 13 12|11 10 9 8 |7 6 5 4 3 2 1 0|
+ |1 1 1 1 0 |i |1 0 |0 |1 |0 |0 |imm4 |0 |imm3 |Rd |imm8 |
+ MOVT<c> <Rd>,#<imm16>
+ |15 14 13 12 11|10 |9 8 |7 |6 |5 |4 |3 2 1 0 |15|14 13 12|11 10 9 8 |7 6 5 4 3 2 1 0|
+ |1 1 1 1 0 |i |1 0 |1 |1 |0 |0 |imm4 |0 |imm3 |Rd |imm8 |
+ imm16 = imm4:i:imm3:imm8
+ i = imm16[11] = upper_insn[10]
+ imm4 = imm16[12:15] = upper_insn[3:0]
+ imm3 = imm16[8:10] = lower_insn[14:12]
+ imm8 = imm16[0:7] = lower_insn[7:0]
+ */
+ #pragma pack(push, 1)
+ // TODO: not portable
+ // see PE_IMAGE_REL_THUMB_MOV32 for a slightly different approach to structuring this
+ struct _mov {
+ // lower word
+ uint32_t imm4:4;
+ uint32_t group2:6;
+ uint32_t i:1;
+ // bit 3 of group3 (bit 7 of the lower word) determines if it's movt or movw:
+ // MOVT: 0b101100
+ // MOVW: 0b100100
+ uint32_t group3:5;
+ // upper word
+ uint32_t imm8:8;
+ uint32_t rd:4;
+ uint32_t imm3:3;
+ uint32_t group1_15:1;
+ };
+ union _target {
+ // XXX: endianness?
+ struct {
+ uint16_t imm8:8;
+ uint16_t imm3:3;
+ uint16_t i:1;
+ uint16_t imm4:4;
+ };
+ uint16_t word;
+ };
+ #pragma pack(pop)
+ _mov* mov = (_mov*)dest32;
+ int16_t addend = mov->imm8 | (mov->imm3 << 8) | (mov->i << (8 + 3)) | (mov->imm4 << (8 + 3 + 1));
+ int64_t newTarget = target + addend;
+ _target t;
+ if (info.nativeType == R_ARM_THM_MOVW_ABS_NC) {
+ // MOVW takes the lower 16-bit word
+ t.word = (newTarget & 0xffff);
+ }
+ else // if (info.nativeType == R_ARM_THM_MOVT_ABS)
+ {
+ // MOVT takes the upper 16-bit word
+ t.word = (newTarget >> 16) & 0xffff;
+ }
+ mov->imm8 = t.imm8;
+ mov->imm3 = t.imm3;
+ mov->imm4 = t.imm4;
+ mov->i = t.i;
+ break;
+ }
case R_ARM_TLS_DTPMOD32:
/* Default to module index 0. */
dest32[0] = 0;
@@ -2465,6 +2529,8 @@ public:
case R_ARM_JUMP_SLOT:
reloc.type = ELFJumpSlotRelocationType;
break;
+ case R_ARM_THM_MOVW_ABS_NC:
+ case R_ARM_THM_MOVT_ABS:
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS:
break;
@@ -2544,8 +2610,6 @@ public:
case R_ARM_THM_PC8:
case R_ARM_THM_SWI8:
case R_ARM_THM_XPC22:
- case R_ARM_THM_MOVW_ABS_NC:
- case R_ARM_THM_MOVT_ABS:
case R_ARM_THM_MOVW_PREL_NC:
case R_ARM_THM_MOVT_PREL:
case R_ARM_THM_JUMP19: