llvmpipe: improvements to JIT assembly dump

Fix disassembly off-by-one instruction bug, add
Aarch64 support, add addresses to symbol names,
cleanup iostream usage.

Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30626>
This commit is contained in:
Aleksi Sapon 2024-08-13 10:35:27 -04:00 committed by Marge Bot
parent af8c680087
commit 6a3234ee3b
2 changed files with 35 additions and 26 deletions

View File

@ -104,7 +104,7 @@ def lookupMap(filename, matchSymbol):
def lookupAsm(filename, desiredFunction):
stream = open(filename + '.asm', 'rt')
while stream.readline() != desiredFunction + ':\n':
while not stream.readline().startswith(desiredFunction + ' '):
pass
asm = []

View File

@ -126,15 +126,22 @@ disassemble(const void* func, std::ostream &buffer)
* so that between runs.
*/
buffer << std::setw(6) << (unsigned long)pc << ":\t";
buffer << std::setw(6) << std::hex << (unsigned long)pc
<< std::setw(0) << std::dec << ":";
Size = LLVMDisasmInstruction(D, (uint8_t *)bytes + pc, extent - pc, 0, outline,
sizeof outline);
sizeof(outline));
if (!Size) {
buffer << "invalid\n";
pc += 1;
#if DETECT_ARCH_AARCH64
uint32_t invalid = bytes[pc + 0] << 0 | bytes[pc + 1] << 8 |
bytes[pc + 2] << 16 | bytes[pc + 3] << 24;
snprintf(outline, sizeof(outline), "\tinvalid %x", invalid);
Size = 4;
#else
buffer << "\tinvalid\n";
break;
#endif
}
/*
@ -145,10 +152,11 @@ disassemble(const void* func, std::ostream &buffer)
unsigned i;
for (i = 0; i < Size; ++i) {
buffer << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int> (bytes[pc + i]);
<< static_cast<int> (bytes[pc + i])
<< std::setw(0) << std::dec;
}
for (; i < 16; ++i) {
buffer << std::dec << " ";
buffer << " ";
}
}
@ -156,20 +164,7 @@ disassemble(const void* func, std::ostream &buffer)
* Print the instruction.
*/
buffer << std::setw(Size) << outline << '\n';
/*
* Stop disassembling on return statements, if there is no record of a
* jump to a successive address.
*
* XXX: This currently assumes x86
*/
#if DETECT_ARCH_X86 || DETECT_ARCH_X86_64
if (Size == 1 && bytes[pc] == 0xc3) {
break;
}
#endif
buffer << outline << '\n';
/*
* Advance.
@ -177,6 +172,21 @@ disassemble(const void* func, std::ostream &buffer)
pc += Size;
/*
* Stop disassembling on return statements
*/
#if DETECT_ARCH_X86 || DETECT_ARCH_X86_64
if (Size == 1 && bytes[pc - 1] == 0xc3) {
break;
}
#elif DETECT_ARCH_AARCH64
if (Size == 4 && bytes[pc - 1] == 0xD6 && bytes[pc - 2] == 0x5F &&
(bytes[pc - 3] & 0xFC) == 0 && (bytes[pc - 4] & 0x1F) == 0) {
break;
}
#endif
if (pc >= extent) {
buffer << "disassembly larger than " << extent << " bytes, aborting\n";
break;
@ -191,8 +201,8 @@ disassemble(const void* func, std::ostream &buffer)
* Print GDB command, useful to verify output.
*/
if (0) {
buffer << "disassemble " << static_cast<const void*>(bytes) << ' '
<< static_cast<const void*>(bytes + pc) << '\n';
buffer << "disassemble " << std::hex << static_cast<const void*>(bytes) << ' '
<< static_cast<const void*>(bytes + pc) << std::dec << '\n';
}
return pc;
@ -248,7 +258,8 @@ lp_profile(LLVMValueRef func, const void *code)
if (perf_map_file) {
const char *symbol = LLVMGetValueName(func);
unsigned long addr = (uintptr_t)code;
perf_asm_file << symbol << ":\n";
perf_asm_file << symbol << " " << std::hex
<< (uintptr_t)code << std::dec << ":\n";
unsigned long size = disassemble(code, perf_asm_file);
perf_asm_file.flush();
fprintf(perf_map_file, "%lx %lx %s\n", addr, size, symbol);
@ -259,5 +270,3 @@ lp_profile(LLVMValueRef func, const void *code)
(void)code;
#endif
}