@@ -1030,7 +1030,8 @@ bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const {
1030
1030
DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch,
1031
1031
const char *flavor_string)
1032
1032
: Disassembler(arch, flavor_string), m_exe_ctx(nullptr ), m_inst(nullptr ),
1033
- m_data_from_file(false ) {
1033
+ m_data_from_file(false ), m_adrp_address(LLDB_INVALID_ADDRESS),
1034
+ m_adrp_insn() {
1034
1035
if (!FlavorValidForArchSpec (arch, m_flavor.c_str ())) {
1035
1036
m_flavor.assign (" default" );
1036
1037
}
@@ -1310,6 +1311,46 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
1310
1311
Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr () : nullptr ;
1311
1312
Address value_so_addr;
1312
1313
Address pc_so_addr;
1314
+ if (target->GetArchitecture ().GetMachine () == llvm::Triple::aarch64 ||
1315
+ target->GetArchitecture ().GetMachine () == llvm::Triple::aarch64_be ||
1316
+ target->GetArchitecture ().GetMachine () == llvm::Triple::aarch64_32) {
1317
+ if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
1318
+ m_adrp_address = pc;
1319
+ m_adrp_insn = value;
1320
+ *name = nullptr ;
1321
+ *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1322
+ return nullptr ;
1323
+ }
1324
+ // If this instruction is an ADD and
1325
+ // the previous instruction was an ADRP and
1326
+ // the ADRP's register and this ADD's register are the same,
1327
+ // then this is a pc-relative address calculation.
1328
+ if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
1329
+ m_adrp_insn.hasValue () && m_adrp_address == pc - 4 &&
1330
+ (m_adrp_insn.getValue () & 0x1f ) == ((value >> 5 ) & 0x1f )) {
1331
+ uint32_t addxri_inst;
1332
+ uint64_t adrp_imm, addxri_imm;
1333
+ // Get immlo and immhi bits, OR them together to get the ADRP imm
1334
+ // value.
1335
+ adrp_imm = ((m_adrp_insn.getValue () & 0x00ffffe0 ) >> 3 ) |
1336
+ ((m_adrp_insn.getValue () >> 29 ) & 0x3 );
1337
+ // if high bit of immhi after right-shifting set, sign extend
1338
+ if (adrp_imm & (1ULL << 20 ))
1339
+ adrp_imm |= ~((1ULL << 21 ) - 1 );
1340
+
1341
+ addxri_inst = value;
1342
+ addxri_imm = (addxri_inst >> 10 ) & 0xfff ;
1343
+ // check if 'sh' bit is set, shift imm value up if so
1344
+ // (this would make no sense, ADRP already gave us this part)
1345
+ if ((addxri_inst >> (12 + 5 + 5 )) & 1 )
1346
+ addxri_imm <<= 12 ;
1347
+ value = (m_adrp_address & 0xfffffffffffff000LL ) + (adrp_imm << 12 ) +
1348
+ addxri_imm;
1349
+ }
1350
+ m_adrp_address = LLDB_INVALID_ADDRESS;
1351
+ m_adrp_insn.reset ();
1352
+ }
1353
+
1313
1354
if (m_inst->UsingFileAddress ()) {
1314
1355
ModuleSP module_sp (m_inst->GetAddress ().GetModule ());
1315
1356
if (module_sp) {
@@ -1371,6 +1412,12 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
1371
1412
}
1372
1413
}
1373
1414
1415
+ // TODO: llvm-objdump sets the type_ptr to the
1416
+ // LLVMDisassembler_ReferenceType_Out_* values
1417
+ // based on where value_so_addr is pointing, with
1418
+ // Mach-O specific augmentations in MachODump.cpp. e.g.
1419
+ // see what AArch64ExternalSymbolizer::tryAddingSymbolicOperand
1420
+ // handles.
1374
1421
*type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
1375
1422
*name = nullptr ;
1376
1423
return nullptr ;
0 commit comments