From 288c1cfd2adf6df80ff0738fcaac7fb7fdd6356a Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 22 Jun 2026 12:15:46 -0700 Subject: [PATCH] Simplify logic for setting __aarch64_have_lse_atomics When using a non-glibc loader (e.g. musl), __aarch64_ldadd4_relax will not necessarily be present, but the loader could still be using other outlined atomic functions, so the search for __aarch64_ldadd4_relax would not necessarily succeed. Therefore, remove the logic for disassembling __aarch64_ldadd4_relax, and replace it with code that sets __aarch64_have_lse_atomics directly. This logic was considered necessary because __aarch64_have_lse_atomics isn't exported. However, __aarch64_ldadd4_relax isn't exported either. So either way, the symbol should be findable via .symtab if it is present. It's possible that this wouldn't have worked before because of the bug fixed by #4035. --- src/Monkeypatcher.cc | 83 ++++---------------------------------------- 1 file changed, 7 insertions(+), 76 deletions(-) diff --git a/src/Monkeypatcher.cc b/src/Monkeypatcher.cc index 9bd920de425..cee83c0a63e 100644 --- a/src/Monkeypatcher.cc +++ b/src/Monkeypatcher.cc @@ -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 pc, remote_ptr* 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(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 map_start, size_t map_size, size_t map_offset, - uint64_t prot) { - ASSERT(t, t->arch() == aarch64); - remote_ptr 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 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 have_lse_atomics_addr = adrp_address + ldrb_offset; - uint8_t enable = 1; - write_and_record_mem(t, have_lse_atomics_addr.cast(), &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) { @@ -1791,9 +1718,13 @@ void Monkeypatcher::patch_after_mmap(RecordTask* t, remote_ptr 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;