Skip to content

Commit

Permalink
Differentiate modifyData() processing for ADR/ADRP variants and LDR/L…
Browse files Browse the repository at this point in the history
…DRSW variants.
  • Loading branch information
ssunny7 committed Apr 7, 2017
1 parent cc15c55 commit 83bdf66
Showing 1 changed file with 43 additions and 28 deletions.
71 changes: 43 additions & 28 deletions dyninstAPI/src/codegen-aarch64.C
Expand Up @@ -628,34 +628,49 @@ bool insnCodeGen::modifyData(Address target,
NS_aarch64::instruction &insn,
codeGen &gen) {
int raw = insn.asInt();

//Get the immhi and immlo values from the original instruction
int immhi = ((raw >> 5) & 0x7FFFF), immlo = ((raw >> 29) & 0x3);
//Get the original offset
int imm = ((immhi << 2) | immlo);

//Sign extend the original offset to the size of an Address
Address referTarget = ((((Address)imm ) << (sizeof(Address) - 21)) >> (sizeof(Address) - 21)) + gen.currAddr();
//Get offset of target from the instruction's new location
Address offset = abs(target - referTarget);

//If offset is within +/- 1 MB, modify the instruction (ADR/ADRP) with the new offset
if(offset <= (1 << 20))
{
int _offset = (offset & 0x1FFFFF);

instruction newInsn(insn);

INSN_SET(newInsn, 5, 23, ((_offset >> 2) & 0x7FFFF));
INSN_SET(insn, 29, 30, (_offset & 0x3));

generate(gen, newInsn);
}
//Else, generate move instructions to move the value to the same register
else
{
Register rd = raw & 0x1F;
loadImmIntoReg(gen, rd, offset);
bool isneg = false;

if(target < gen.currAddr())
isneg = true;
Address offset = !isneg ? (target - gen.currAddr()) : (gen.currAddr() - target);

if(((raw >> 24) & 0x1F) == 0x10) {
int shiftamt = ((raw >> 31) & 0x1) ? 12 : 0;

//If offset is within +/- 1 MB, modify the instruction (ADR/ADRP) with the new offset
if (offset <= (1 << 20)) {
instruction newInsn(insn);

signed long imm = isneg ? -(offset >> shiftamt) : (offset >> shiftamt);

INSN_SET(newInsn, 5, 23, ((imm >> 2) & 0x7FFFF));
INSN_SET(newInsn, 29, 30, (imm & 0x3));

generate(gen, newInsn);
}
//Else, generate move instructions to move the value to the same register
else {
Register rd = raw & 0x1F;
loadImmIntoReg(gen, rd, offset);
}
} else if(((raw >> 24) & 0x3F) == 0x18) {
//If offset is within +/- 1 MB, modify the instruction (LDR/LDRSW) with the new offset
if(offset <= (1 << 20)) {
instruction newInsn(insn);

isneg ? (offset += 4) : (offset -= 4);
signed long imm = isneg ? -(offset >> 2) : (offset >> 2);
INSN_SET(newInsn, 5, 23, (imm & 0x7FFFF));

generate(gen, newInsn);
}
//Else, generate move instructions to move the value to the same register
else {
Register rt = raw & 0x1F;
loadImmIntoReg(gen, rt, offset);
}
} else {
assert(!"Got an instruction other than ADR/ADRP/LDR(literal)/LDRSW(literal) in PC-relative data access!");
}

return true;
Expand Down

0 comments on commit 83bdf66

Please sign in to comment.