Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 7 additions & 76 deletions src/Monkeypatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1625,79 +1625,6 @@ void Monkeypatcher::unpatch_dl_runtime_resolves(RecordTask* t) {
saved_dl_runtime_resolve_code.clear();
}

// https://documentation-service.arm.com/static/67581b3355451e3c38d97c22
static bool is_aarch64_bti(uint32_t instruction) {
if ((instruction >> 12) == 0b11010101000000110010 && (instruction & 0x1f) == 0b11111) {
// Hint instruction.
uint32_t crm = (instruction >> 8) & ((1 << 4) - 1);
uint32_t op2 = (instruction >> 5) & ((1 << 3) - 1);
return crm == 0b0100 && (op2 & 1) == 0;
}
return false;
}

static bool is_aarch64_adrp(uint32_t instruction, remote_ptr<void> pc, remote_ptr<void>* address) {
if ((instruction >> 31) == 1 && ((instruction >> 24) & 0x1f) == 0b10000) {
uint64_t base = (pc.as_int() >> 12) << 12;
uint64_t imm = ((instruction >> 29) & 0x3) +
(((instruction >> 5) & ((1 << 19) - 1)) << 2);
*address = remote_ptr<void>(base + (imm << 12));
return true;
}
return false;
}

static bool is_aarch64_ldrb(uint32_t instruction, uint32_t* offset) {
if ((instruction >> 22) == 0b0011100101) {
*offset = (instruction >> 10) & ((1 << 12) - 1);
return true;
}
return false;
}

/**
* Patch the __aarch64_have_lse_atomics variable to ensure that LSE atomics are
* always used even if init_lse_atomics
*/
void Monkeypatcher::patch_aarch64_have_lse_atomics(
RecordTask* t, ElfReader& reader, uintptr_t ldadd4_addr,
remote_ptr<void> map_start, size_t map_size, size_t map_offset,
uint64_t prot) {
ASSERT(t, t->arch() == aarch64);
remote_ptr<void> addr =
resolve_address(reader, ldadd4_addr, map_start, map_size, map_offset, prot);
if (!addr) {
return;
}

bool ok = true;
uint8_t instruction_bytes[12];
t->read_bytes_helper(addr, sizeof(instruction_bytes), instruction_bytes, &ok);
if (!ok) {
LOG(warn) << "Can't read ldadd4 instruction bytes at " << addr;
return;
}
uint32_t instructions[3];
memcpy(instructions, instruction_bytes, sizeof(instructions));
int index = 0;
if (is_aarch64_bti(instructions[0])) {
++index;
}
remote_ptr<void> adrp_address;
if (!is_aarch64_adrp(instructions[index], addr + index*4, &adrp_address)) {
LOG(warn) << "Instruction 0x" << HEX(instructions[index]) << " is not ADRP";
return;
}
uint32_t ldrb_offset;
if (!is_aarch64_ldrb(instructions[index + 1], &ldrb_offset)) {
LOG(warn) << "Instruction 0x" << HEX(instructions[index + 1]) << " is not LDRB";
return;
}
remote_ptr<void> have_lse_atomics_addr = adrp_address + ldrb_offset;
uint8_t enable = 1;
write_and_record_mem(t, have_lse_atomics_addr.cast<uint8_t>(), &enable, 1);
}

static bool file_may_need_instrumentation(const AddressSpace::Mapping& map) {
size_t file_part = map.map.fsname().rfind('/');
if (file_part == string::npos) {
Expand Down Expand Up @@ -1791,9 +1718,13 @@ void Monkeypatcher::patch_after_mmap(RecordTask* t, remote_ptr<void> start,
break;
case aarch64:
for (size_t i = 0; i < syms.size(); ++i) {
if (syms.is_name(i, "__aarch64_ldadd4_relax")) {
patch_aarch64_have_lse_atomics(t, reader, syms.addr(i), start, size,
offset_bytes, prot);
if (syms.is_name(i, "__aarch64_have_lse_atomics")) {
// Patch the __aarch64_have_lse_atomics variable to ensure that LSE
// atomics are always used even if init_lse_atomics hasn't been called
// yet (or at all).
static const char one = 1;
set_and_record_bytes(t, reader, syms.addr(i), &one, sizeof(one),
start, size, offset_bytes, prot);
}
}
break;
Expand Down
Loading