mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 16:27:35 +00:00
Kernel+LibCoreDump: Implement more x86_64 coredump functionality
This commit is contained in:
parent
d3127efc01
commit
2016354c12
4 changed files with 38 additions and 18 deletions
|
@ -78,7 +78,11 @@ KResult CoreDump::write_elf_header()
|
||||||
elf_file_header.e_ident[EI_MAG1] = 'E';
|
elf_file_header.e_ident[EI_MAG1] = 'E';
|
||||||
elf_file_header.e_ident[EI_MAG2] = 'L';
|
elf_file_header.e_ident[EI_MAG2] = 'L';
|
||||||
elf_file_header.e_ident[EI_MAG3] = 'F';
|
elf_file_header.e_ident[EI_MAG3] = 'F';
|
||||||
|
#if ARCH(I386)
|
||||||
elf_file_header.e_ident[EI_CLASS] = ELFCLASS32;
|
elf_file_header.e_ident[EI_CLASS] = ELFCLASS32;
|
||||||
|
#else
|
||||||
|
elf_file_header.e_ident[EI_CLASS] = ELFCLASS64;
|
||||||
|
#endif
|
||||||
elf_file_header.e_ident[EI_DATA] = ELFDATA2LSB;
|
elf_file_header.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||||
elf_file_header.e_ident[EI_VERSION] = EV_CURRENT;
|
elf_file_header.e_ident[EI_VERSION] = EV_CURRENT;
|
||||||
elf_file_header.e_ident[EI_OSABI] = 0; // ELFOSABI_NONE
|
elf_file_header.e_ident[EI_OSABI] = 0; // ELFOSABI_NONE
|
||||||
|
@ -90,7 +94,11 @@ KResult CoreDump::write_elf_header()
|
||||||
elf_file_header.e_ident[EI_PAD + 5] = 0;
|
elf_file_header.e_ident[EI_PAD + 5] = 0;
|
||||||
elf_file_header.e_ident[EI_PAD + 6] = 0;
|
elf_file_header.e_ident[EI_PAD + 6] = 0;
|
||||||
elf_file_header.e_type = ET_CORE;
|
elf_file_header.e_type = ET_CORE;
|
||||||
|
#if ARCH(I386)
|
||||||
elf_file_header.e_machine = EM_386;
|
elf_file_header.e_machine = EM_386;
|
||||||
|
#else
|
||||||
|
elf_file_header.e_machine = EM_X86_64;
|
||||||
|
#endif
|
||||||
elf_file_header.e_version = 1;
|
elf_file_header.e_version = 1;
|
||||||
elf_file_header.e_entry = 0;
|
elf_file_header.e_entry = 0;
|
||||||
elf_file_header.e_phoff = sizeof(ElfW(Ehdr));
|
elf_file_header.e_phoff = sizeof(ElfW(Ehdr));
|
||||||
|
|
|
@ -43,6 +43,10 @@ static const ELFObjectInfo* object_info_for_region(const ELF::Core::MemoryRegion
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto image = make<ELF::Image>(file_or_error.value()->bytes());
|
auto image = make<ELF::Image>(file_or_error.value()->bytes());
|
||||||
|
#if !ARCH(I386)
|
||||||
|
// FIXME: Fix LibDebug
|
||||||
|
return nullptr;
|
||||||
|
#endif
|
||||||
auto info = make<ELFObjectInfo>(file_or_error.release_value(), make<Debug::DebugInfo>(move(image)));
|
auto info = make<ELFObjectInfo>(file_or_error.release_value(), make<Debug::DebugInfo>(move(image)));
|
||||||
auto* info_ptr = info.ptr();
|
auto* info_ptr = info.ptr();
|
||||||
s_debug_info_cache.set(path, move(info));
|
s_debug_info_cache.set(path, move(info));
|
||||||
|
@ -52,30 +56,33 @@ static const ELFObjectInfo* object_info_for_region(const ELF::Core::MemoryRegion
|
||||||
Backtrace::Backtrace(const Reader& coredump, const ELF::Core::ThreadInfo& thread_info)
|
Backtrace::Backtrace(const Reader& coredump, const ELF::Core::ThreadInfo& thread_info)
|
||||||
: m_thread_info(move(thread_info))
|
: m_thread_info(move(thread_info))
|
||||||
{
|
{
|
||||||
|
FlatPtr* bp;
|
||||||
|
FlatPtr* ip;
|
||||||
#if ARCH(I386)
|
#if ARCH(I386)
|
||||||
uint32_t* ebp = (uint32_t*)m_thread_info.regs.ebp;
|
bp = (FlatPtr*)m_thread_info.regs.ebp;
|
||||||
uint32_t* eip = (uint32_t*)m_thread_info.regs.eip;
|
ip = (FlatPtr*)m_thread_info.regs.eip;
|
||||||
|
#else
|
||||||
|
bp = (FlatPtr*)m_thread_info.regs.rbp;
|
||||||
|
ip = (FlatPtr*)m_thread_info.regs.rip;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool first_frame = true;
|
bool first_frame = true;
|
||||||
while (ebp && eip) {
|
while (bp && ip) {
|
||||||
// We use eip - 1 because the return address from a function frame
|
// We use eip - 1 because the return address from a function frame
|
||||||
// is the instruction that comes after the 'call' instruction.
|
// is the instruction that comes after the 'call' instruction.
|
||||||
// However, because the first frame represents the faulting
|
// However, because the first frame represents the faulting
|
||||||
// instruction rather than the return address we don't subtract
|
// instruction rather than the return address we don't subtract
|
||||||
// 1 there.
|
// 1 there.
|
||||||
VERIFY((FlatPtr)eip > 0);
|
VERIFY((FlatPtr)ip > 0);
|
||||||
add_entry(coredump, (FlatPtr)eip - (first_frame ? 0 : 1));
|
add_entry(coredump, (FlatPtr)ip - (first_frame ? 0 : 1));
|
||||||
first_frame = false;
|
first_frame = false;
|
||||||
auto next_eip = coredump.peek_memory((FlatPtr)(ebp + 1));
|
auto next_ip = coredump.peek_memory((FlatPtr)(bp + 1));
|
||||||
auto next_ebp = coredump.peek_memory((FlatPtr)(ebp));
|
auto next_bp = coredump.peek_memory((FlatPtr)(bp));
|
||||||
if (!next_eip.has_value() || !next_ebp.has_value())
|
if (!next_ip.has_value() || !next_bp.has_value())
|
||||||
break;
|
break;
|
||||||
eip = (uint32_t*)next_eip.value();
|
ip = (FlatPtr*)next_ip.value();
|
||||||
ebp = (uint32_t*)next_ebp.value();
|
bp = (FlatPtr*)next_bp.value();
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
(void)coredump;
|
|
||||||
TODO();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace::~Backtrace()
|
Backtrace::~Backtrace()
|
||||||
|
@ -96,9 +103,14 @@ void Backtrace::add_entry(const Reader& coredump, FlatPtr eip)
|
||||||
if (!object_info)
|
if (!object_info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if ARCH(I386)
|
||||||
auto function_name = object_info->debug_info->elf().symbolicate(eip - region->region_start);
|
auto function_name = object_info->debug_info->elf().symbolicate(eip - region->region_start);
|
||||||
auto source_position = object_info->debug_info->get_source_position_with_inlines(eip - region->region_start);
|
auto source_position = object_info->debug_info->get_source_position_with_inlines(eip - region->region_start);
|
||||||
|
#else
|
||||||
|
// FIXME: Fix symbolication.
|
||||||
|
auto function_name = "";
|
||||||
|
Debug::DebugInfo::SourcePositionWithInlines source_position;
|
||||||
|
#endif
|
||||||
m_entries.append({ eip, object_name, function_name, source_position });
|
m_entries.append({ eip, object_name, function_name, source_position });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,7 @@ bool Reader::NotesEntryIterator::at_end() const
|
||||||
return type() == ELF::Core::NotesEntryHeader::Type::Null;
|
return type() == ELF::Core::NotesEntryHeader::Type::Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<uint32_t> Reader::peek_memory(FlatPtr address) const
|
Optional<FlatPtr> Reader::peek_memory(FlatPtr address) const
|
||||||
{
|
{
|
||||||
const auto* region = region_containing(address);
|
const auto* region = region_containing(address);
|
||||||
if (!region)
|
if (!region)
|
||||||
|
@ -114,7 +114,7 @@ Optional<uint32_t> Reader::peek_memory(FlatPtr address) const
|
||||||
|
|
||||||
FlatPtr offset_in_region = address - region->region_start;
|
FlatPtr offset_in_region = address - region->region_start;
|
||||||
const char* region_data = image().program_header(region->program_header_index).raw_data();
|
const char* region_data = image().program_header(region->program_header_index).raw_data();
|
||||||
return *(const uint32_t*)(®ion_data[offset_in_region]);
|
return *(const FlatPtr*)(®ion_data[offset_in_region]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonObject Reader::process_info() const
|
const JsonObject Reader::process_info() const
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
|
|
||||||
const ELF::Image& image() const { return m_coredump_image; }
|
const ELF::Image& image() const { return m_coredump_image; }
|
||||||
|
|
||||||
Optional<uint32_t> peek_memory(FlatPtr address) const;
|
Optional<FlatPtr> peek_memory(FlatPtr address) const;
|
||||||
const ELF::Core::MemoryRegionInfo* region_containing(FlatPtr address) const;
|
const ELF::Core::MemoryRegionInfo* region_containing(FlatPtr address) const;
|
||||||
|
|
||||||
struct LibraryData {
|
struct LibraryData {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue