mirror of
https://github.com/torvalds/linux.git
synced 2026-11-12 20:54:48 +01:00
perf llvm: Fix arm64 adrp instruction disassembly mismatch with objdump
The operands of 'adrp' instructions parsed by libllvm are currently represented as raw immediates rather than the "address <symbol+offset>" format used by objdump. This inconsistency causes arm64_mov__parse() to fail when parsing these instructions during post-processing. Example of the mismatch: Current: adrp x18, 8014 Objdump: adrp x18, ffff800081f5f000 <this_cpu_vector> Fix this by manually extracting the target address from the raw adrp instruction via symbol_lookup_callback(). The address is then converted to a specific symbol during symbol__disassemble_llvm() and formatted to match objdump's output, ensuring compatibility with existing parsers. Reviewed-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Tengda Wu <wutengda@huaweicloud.com> Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
268d5c3979
commit
705390bdcf
|
|
@ -9,8 +9,10 @@
|
|||
#include "symbol.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/zalloc.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#ifdef HAVE_LIBLLVM_SUPPORT
|
||||
#include "llvm-c-helpers.h"
|
||||
|
|
@ -108,6 +110,16 @@ symbol_lookup_callback(void *disinfo, uint64_t value,
|
|||
storage->branch_addr = value;
|
||||
else if (*ref_type == LLVMDisassembler_ReferenceType_In_PCrel_Load)
|
||||
storage->pcrel_load_addr = value;
|
||||
else if (*ref_type == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
|
||||
uint64_t adrp_imm;
|
||||
|
||||
/* immhi (bits 23:5) and immlo (bits 30:29) */
|
||||
adrp_imm = ((value & 0x00ffffe0) >> 3) | ((value >> 29) & 0x3);
|
||||
adrp_imm = sign_extend64(adrp_imm, 20);
|
||||
|
||||
/* Calculate the target page address */
|
||||
storage->pcrel_load_addr = (address & ~0xfffULL) + (adrp_imm << 12);
|
||||
}
|
||||
*ref_type = LLVMDisassembler_ReferenceType_InOut_None;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -228,12 +240,42 @@ int symbol__disassemble_llvm(const char *filename, struct symbol *sym,
|
|||
}
|
||||
}
|
||||
if (storage.pcrel_load_addr != 0) {
|
||||
char *name = llvm_name_for_data(dso, filename,
|
||||
char *name;
|
||||
|
||||
if (arch__is_arm64(args->arch)) {
|
||||
/*
|
||||
* For arm64, replace the immediate operand with
|
||||
* the resolved address to match objdump's output.
|
||||
*
|
||||
* Example conversion:
|
||||
* From: adrp x18, 8014
|
||||
* To: adrp x18, ffff800081f5f000
|
||||
*/
|
||||
char *s = strchr(disasm_buf, ',');
|
||||
|
||||
if (s == NULL)
|
||||
goto err;
|
||||
|
||||
s++;
|
||||
*s = '\0';
|
||||
disasm_len = strlen(disasm_buf);
|
||||
disasm_len += scnprintf(disasm_buf + disasm_len,
|
||||
sizeof(disasm_buf) - disasm_len,
|
||||
" %"PRIx64,
|
||||
storage.pcrel_load_addr);
|
||||
disasm_len += scnprintf(disasm_buf + disasm_len,
|
||||
sizeof(disasm_buf) - disasm_len,
|
||||
" # %#"PRIx64,
|
||||
storage.pcrel_load_addr);
|
||||
} else {
|
||||
/*
|
||||
* For other archs, append the resolved address
|
||||
* as an inline comment.
|
||||
*/
|
||||
disasm_len += scnprintf(disasm_buf + disasm_len,
|
||||
sizeof(disasm_buf) - disasm_len,
|
||||
" # %#"PRIx64,
|
||||
storage.pcrel_load_addr);
|
||||
}
|
||||
|
||||
/* Append the resolved symbol name if available */
|
||||
name = llvm_name_for_data(dso, filename, storage.pcrel_load_addr);
|
||||
if (name) {
|
||||
disasm_len += scnprintf(disasm_buf + disasm_len,
|
||||
sizeof(disasm_buf) -
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user