mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-31 03:10:03 +00:00
cleanup pass over elf parsing; base addr calculation?
This commit is contained in:
+1
-1
@@ -53,7 +53,7 @@ commands =
|
||||
.f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [scratch]
|
||||
.f2 = { .win = "raddbg_stable --ipc kill_all && build radbin && pushd build && radbin.exe mule_main.rdi --out:a.dump && popd", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f2 = { .win = "build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [textperf]
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
+81
-103
@@ -2,34 +2,25 @@
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal B32
|
||||
dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin)
|
||||
dw_is_dwarf_present_from_elf_bin(String8 data, ELF_Bin *bin)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
B32 is_dwarf_present = 0;
|
||||
|
||||
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr);
|
||||
|
||||
for (U64 i = 0; i < sections.count; ++i) {
|
||||
ELF_Shdr64 *shdr = §ions.v[i];
|
||||
String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr);
|
||||
|
||||
if (shdr->sh_type != ELF_SectionCode_ProgBits) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for EachIndex(idx, bin->shdrs.count)
|
||||
{
|
||||
ELF_Shdr64 *shdr = &bin->shdrs.v[idx];
|
||||
if(shdr->sh_type != ELF_SectionCode_ProgBits) { continue; }
|
||||
String8 name = elf_name_from_shdr64(data, bin, shdr);
|
||||
DW_SectionKind s = dw_section_kind_from_string(name);
|
||||
if (s == DW_Section_Null) {
|
||||
if(s == DW_Section_Null)
|
||||
{
|
||||
s = dw_section_dwo_kind_from_string(name);
|
||||
}
|
||||
|
||||
is_dwarf_present = s != DW_Section_Null;
|
||||
if (is_dwarf_present) {
|
||||
is_dwarf_present = (s != DW_Section_Null);
|
||||
if(is_dwarf_present)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return is_dwarf_present;
|
||||
}
|
||||
|
||||
@@ -37,99 +28,86 @@ dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin)
|
||||
#include "third_party/sinfl/sinfl.h"
|
||||
|
||||
internal DW_Input
|
||||
dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin)
|
||||
dw_input_from_elf_bin(Arena *arena, String8 data, ELF_Bin *bin)
|
||||
{
|
||||
DW_Input result = {0};
|
||||
B32 is_section_present[ArrayCount(result.sec)] = {0};
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
DW_Input result = {0};
|
||||
B32 sect_status[ArrayCount(result.sec)] = {0};
|
||||
|
||||
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_image, &bin->hdr);
|
||||
|
||||
for (U64 sect_idx = 1; sect_idx < sections.count; ++sect_idx) {
|
||||
ELF_Shdr64 *shdr = §ions.v[sect_idx];
|
||||
for(U64 section_idx = 1; section_idx < bin->shdrs.count; section_idx += 1)
|
||||
{
|
||||
ELF_Shdr64 *shdr = &bin->shdrs.v[section_idx];
|
||||
if(shdr->sh_type != ELF_SectionCode_ProgBits) { continue; } // skip BSS sections
|
||||
|
||||
// skip BSS sections
|
||||
if (shdr->sh_type != ELF_SectionCode_ProgBits) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String8 name = elf_name_from_shdr64(raw_image, &bin->hdr, bin->sh_name_range, shdr);
|
||||
|
||||
DW_SectionKind s = dw_section_kind_from_string(name);
|
||||
B32 is_dwo = 0;
|
||||
if (s == DW_Section_Null) {
|
||||
s = dw_section_dwo_kind_from_string(name);
|
||||
//- rjf: unpack section
|
||||
String8 section_name = elf_name_from_shdr64(data, bin, shdr);
|
||||
DW_SectionKind section_kind = dw_section_kind_from_string(section_name);
|
||||
String8 section_data__maybe_compressed = str8_substr(data, r1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size));
|
||||
B32 is_dwo = 0;
|
||||
if(section_kind == DW_Section_Null)
|
||||
{
|
||||
section_kind = dw_section_dwo_kind_from_string(section_name);
|
||||
is_dwo = 1;
|
||||
}
|
||||
|
||||
if (s != DW_Section_Null) {
|
||||
if (sect_status[s]) {
|
||||
Assert(!"too many debug sections with identical name, picking first");
|
||||
} else {
|
||||
Rng1U64 raw_data_range = rng_1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size);
|
||||
String8 data = str8_substr(raw_image, raw_data_range);
|
||||
|
||||
// ELF was compiled with compressed debug info
|
||||
if (shdr->sh_flags & ELF_Shf_Compressed) {
|
||||
String8 comp_data_with_header = data;
|
||||
|
||||
// read header
|
||||
ELF_Chdr64 chdr64 = {0};
|
||||
U64 chdr_size = 0;
|
||||
if (ELF_HdrIs64Bit(bin->hdr.e_ident)) {
|
||||
chdr_size = str8_deserial_read_struct(comp_data_with_header, 0, &chdr64);
|
||||
if (chdr_size != sizeof(chdr64)) {
|
||||
Assert(!"not enough bytes to read header");
|
||||
}
|
||||
} else if (ELF_HdrIs32Bit(bin->hdr.e_ident)) {
|
||||
ELF_Chdr32 chdr32 = {0};
|
||||
chdr_size = str8_deserial_read_struct(comp_data_with_header, 0, &chdr32);
|
||||
if (chdr_size == sizeof(chdr32)) {
|
||||
chdr64 = elf_chdr64_from_chdr32(chdr32);
|
||||
}
|
||||
}
|
||||
|
||||
AssertAlways(IsPow2(chdr64.ch_addr_align));
|
||||
|
||||
// skip header
|
||||
String8 comp_data = str8_skip(comp_data_with_header, chdr_size);
|
||||
|
||||
// push buffer for the decompressor
|
||||
U8 *decomp_buffer = push_array_no_zero_aligned(arena, U8, chdr64.ch_size, chdr64.ch_addr_align);
|
||||
U64 actual_decomp_size = 0;
|
||||
|
||||
// decompress
|
||||
switch (chdr64.ch_type) {
|
||||
case ELF_CompressType_None: {
|
||||
AssertAlways(!"unexpected compression type");
|
||||
} break;
|
||||
case ELF_CompressType_ZLib: {
|
||||
actual_decomp_size = zsinflate(decomp_buffer, chdr64.ch_size, comp_data.str, comp_data.size);
|
||||
} break;
|
||||
case ELF_CompressType_ZStd: {
|
||||
// TODO: zstd lib
|
||||
NotImplemented;
|
||||
} break;
|
||||
default: InvalidPath; break;
|
||||
}
|
||||
|
||||
// TODO: error handling
|
||||
AssertAlways(actual_decomp_size == chdr64.ch_size);
|
||||
|
||||
// set decompressed section data
|
||||
data = str8(decomp_buffer, actual_decomp_size);
|
||||
//- rjf: decompress section data if needed
|
||||
String8 section_data__uncompressed = {0};
|
||||
if(!(shdr->sh_flags & ELF_Shf_Compressed))
|
||||
{
|
||||
section_data__uncompressed = section_data__maybe_compressed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// rjf: read compressed-section header
|
||||
ELF_Chdr64 chdr64 = {0};
|
||||
U64 chdr_size = 0;
|
||||
if(ELF_HdrIs64Bit(bin->hdr.e_ident))
|
||||
{
|
||||
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr64);
|
||||
}
|
||||
else if(ELF_HdrIs32Bit(bin->hdr.e_ident))
|
||||
{
|
||||
ELF_Chdr32 chdr32 = {0};
|
||||
chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr32);
|
||||
if(chdr_size == sizeof(chdr32))
|
||||
{
|
||||
chdr64 = elf_chdr64_from_chdr32(chdr32);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: decompress
|
||||
{
|
||||
String8 section_data__compressed_contents = str8_skip(section_data__maybe_compressed, chdr_size);
|
||||
switch(chdr64.ch_type)
|
||||
{
|
||||
default:
|
||||
case ELF_CompressType_None:
|
||||
{
|
||||
section_data__uncompressed = section_data__compressed_contents;
|
||||
}break;
|
||||
case ELF_CompressType_ZLib:
|
||||
{
|
||||
U8 *section_data_uncompressed_buffer = push_array_no_zero_aligned(arena, U8, chdr64.ch_size, chdr64.ch_addr_align);
|
||||
U64 section_data_uncompressed_size = 0;
|
||||
section_data_uncompressed_size = zsinflate(section_data_uncompressed_buffer, chdr64.ch_size, section_data__compressed_contents.str, section_data__compressed_contents.size);
|
||||
section_data__uncompressed = str8(section_data_uncompressed_buffer, section_data_uncompressed_size);
|
||||
}break;
|
||||
case ELF_CompressType_ZStd:
|
||||
{
|
||||
NotImplemented;
|
||||
}break;
|
||||
}
|
||||
|
||||
sect_status[s] = 1;
|
||||
DW_Section *d = &result.sec[s];
|
||||
d->name = push_str8_copy(arena, name);
|
||||
d->data = data;
|
||||
d->is_dwo = is_dwo;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: store
|
||||
{
|
||||
is_section_present[section_kind] = 1;
|
||||
DW_Section *d = &result.sec[section_kind];
|
||||
d->name = push_str8_copy(arena, section_name);
|
||||
d->data = section_data__uncompressed;
|
||||
d->is_dwo = is_dwo;
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#ifndef DWARF_ELF_H
|
||||
#define DWARF_ELF_H
|
||||
|
||||
internal B32 dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin);
|
||||
internal DW_Input dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin);
|
||||
internal B32 dw_is_dwarf_present_from_elf_bin(String8 raw_image, ELF_Bin *bin);
|
||||
internal DW_Input dw_input_from_elf_bin(Arena *arena, String8 raw_image, ELF_Bin *bin);
|
||||
|
||||
#endif // DWARF_ELF_H
|
||||
|
||||
+3
-1
@@ -671,6 +671,9 @@ typedef enum ELF_Identifier
|
||||
ELF_Identifier_Max = 16,
|
||||
} ELF_Identifier;
|
||||
|
||||
read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'};
|
||||
read_only global String8 elf_magic_string = {elf_magic, sizeof(elf_magic)};
|
||||
|
||||
typedef U16 ELF_Type;
|
||||
typedef enum ELF_TypeEnum
|
||||
{
|
||||
@@ -993,4 +996,3 @@ internal String8 elf_string_from_class(Arena *arena, ELF_Class v);
|
||||
internal Arch arch_from_elf_machine(ELF_MachineKind machine);
|
||||
|
||||
#endif // ELF_H
|
||||
|
||||
|
||||
+128
-105
@@ -1,143 +1,166 @@
|
||||
// Copyright (c) 2025 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal B32
|
||||
elf_check_magic(String8 data)
|
||||
{
|
||||
U8 sig[ELF_Identifier_Max] = {0};
|
||||
str8_deserial_read(data, 0, &sig[0], sizeof(sig), 1);
|
||||
B32 is_magic_valid = (sig[ELF_Identifier_Mag0] == 0x7f && sig[ELF_Identifier_Mag1] == 'E' && sig[ELF_Identifier_Mag2] == 'L' && sig[ELF_Identifier_Mag3] == 'F');
|
||||
return is_magic_valid;
|
||||
}
|
||||
//- rjf: top-level binary parsing
|
||||
|
||||
internal ELF_BinInfo
|
||||
elf_bin_from_data(String8 data)
|
||||
internal ELF_Bin
|
||||
elf_bin_from_data(Arena *arena, String8 data)
|
||||
{
|
||||
ELF_Hdr64 hdr64 = {0};
|
||||
Rng1U64 sh_name_range = rng_1u64(0,0);
|
||||
|
||||
if (elf_check_magic(data)) {
|
||||
ELF_Bin bin = {0};
|
||||
if(str8_match(str8_prefix(data, elf_magic_string.size), elf_magic_string, 0) &&
|
||||
data.size >= ELF_Identifier_Max)
|
||||
{
|
||||
//- rjf: parse sig/header
|
||||
U8 sig[ELF_Identifier_Max] = {0};
|
||||
str8_deserial_read(data, 0, &sig[0], sizeof(sig), 1);
|
||||
|
||||
switch (sig[ELF_Identifier_Class]) {
|
||||
case ELF_Class_None: break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Hdr32 hdr32 = {0};
|
||||
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr32);
|
||||
if (hdr_size == sizeof(hdr32)) {
|
||||
hdr64 = elf_hdr64_from_hdr32(hdr32);
|
||||
|
||||
U64 shstr_off = hdr32.e_shoff + hdr32.e_shentsize*hdr32.e_shstrndx;
|
||||
ELF_Shdr32 shdr = {0};
|
||||
U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr);
|
||||
|
||||
if (shdr_size == sizeof(shdr)) {
|
||||
sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
|
||||
switch(sig[ELF_Identifier_Class])
|
||||
{
|
||||
default:
|
||||
case ELF_Class_None:{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Hdr32 hdr32 = {0};
|
||||
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr32);
|
||||
if(hdr_size == sizeof(hdr32))
|
||||
{
|
||||
bin.hdr = elf_hdr64_from_hdr32(hdr32);
|
||||
U64 shstr_off = hdr32.e_shoff + hdr32.e_shentsize*hdr32.e_shstrndx;
|
||||
ELF_Shdr32 shdr = {0};
|
||||
U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr);
|
||||
if(shdr_size == sizeof(shdr))
|
||||
{
|
||||
bin.sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
ELF_Hdr64 hdr64 = {0};
|
||||
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr64);
|
||||
if(hdr_size == sizeof(hdr64))
|
||||
{
|
||||
bin.hdr = hdr64;
|
||||
U64 shstr_off = hdr64.e_shoff + hdr64.e_shentsize*hdr64.e_shstrndx;
|
||||
ELF_Shdr64 shdr = {0};
|
||||
U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr);
|
||||
if(shdr_size == sizeof(shdr))
|
||||
{
|
||||
bin.sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
//- rjf: gather all shdrs
|
||||
{
|
||||
ELF_Hdr64 *hdr = &bin.hdr;
|
||||
bin.shdrs.count = hdr->e_shnum;
|
||||
bin.shdrs.v = push_array(arena, ELF_Shdr64, hdr->e_shnum);
|
||||
Rng1U64 shdr_range = rng_1u64(hdr->e_shoff, hdr->e_shoff + hdr->e_shentsize*hdr->e_shnum);
|
||||
String8 shdr_data = str8_substr(data, shdr_range);
|
||||
for EachIndex(shdr_idx, hdr->e_shnum)
|
||||
{
|
||||
switch(hdr->e_ident[ELF_Identifier_Class])
|
||||
{
|
||||
default:
|
||||
case ELF_Class_None:
|
||||
{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Shdr32 shdr32 = {0};
|
||||
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr32), &shdr32);
|
||||
bin.shdrs.v[shdr_idx] = elf_shdr64_from_shdr32(shdr32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr64), &bin.shdrs.v[shdr_idx]);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case ELF_Class_64: {
|
||||
U64 hdr_size = str8_deserial_read_struct(data, 0, &hdr64);
|
||||
if (hdr_size == sizeof(hdr64)) {
|
||||
U64 shstr_off = hdr64.e_shoff + hdr64.e_shentsize*hdr64.e_shstrndx;
|
||||
ELF_Shdr64 shdr = {0};
|
||||
U64 shdr_size = str8_deserial_read_struct(data, shstr_off, &shdr);
|
||||
|
||||
if (shdr_size == sizeof(shdr)) {
|
||||
sh_name_range = rng_1u64(shdr.sh_offset, shdr.sh_offset + shdr.sh_size);
|
||||
}
|
||||
|
||||
//- rjf: gather all phdrs
|
||||
{
|
||||
ELF_Hdr64 *hdr = &bin.hdr;
|
||||
bin.phdrs.count = hdr->e_phnum;
|
||||
bin.phdrs.v = push_array(arena, ELF_Phdr64, hdr->e_phnum);
|
||||
Rng1U64 phdr_range = rng_1u64(hdr->e_phoff, hdr->e_phoff + hdr->e_phentsize*hdr->e_phnum);
|
||||
String8 phdr_data = str8_substr(data, phdr_range);
|
||||
for EachIndex(phdr_idx, hdr->e_phnum)
|
||||
{
|
||||
switch(hdr->e_ident[ELF_Identifier_Class])
|
||||
{
|
||||
default:
|
||||
case ELF_Class_None:
|
||||
{}break;
|
||||
case ELF_Class_32:
|
||||
{
|
||||
ELF_Phdr32 phdr32 = {0};
|
||||
str8_deserial_read_struct(phdr_data, phdr_idx * sizeof(ELF_Phdr32), &phdr32);
|
||||
bin.phdrs.v[phdr_idx] = elf_phdr64_from_phdr32(phdr32);
|
||||
}break;
|
||||
case ELF_Class_64:
|
||||
{
|
||||
str8_deserial_read_struct(phdr_data, phdr_idx * sizeof(ELF_Phdr64), &bin.phdrs.v[phdr_idx]);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default: Assert(!"invalid elf header"); break;
|
||||
}
|
||||
}
|
||||
|
||||
ELF_BinInfo info = {0};
|
||||
info.hdr = hdr64;
|
||||
info.sh_name_range = sh_name_range;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
internal ELF_Shdr64Array
|
||||
elf_shdr64_array_from_bin(Arena *arena, String8 raw_data, ELF_Hdr64 *hdr)
|
||||
{
|
||||
Rng1U64 shdr_range = rng_1u64(hdr->e_shoff, hdr->e_shoff + hdr->e_shentsize*hdr->e_shnum);
|
||||
String8 shdr_data = str8_substr(raw_data, shdr_range);
|
||||
|
||||
ELF_Shdr64Array result = {0};
|
||||
result.count = hdr->e_shnum;
|
||||
result.v = push_array(arena, ELF_Shdr64, hdr->e_shnum);
|
||||
|
||||
for(U64 shdr_idx = 0; shdr_idx < hdr->e_shnum; ++shdr_idx) {
|
||||
switch (hdr->e_ident[ELF_Identifier_Class]) {
|
||||
case ELF_Class_None: break;
|
||||
case ELF_Class_32: {
|
||||
ELF_Shdr32 shdr32 = {0};
|
||||
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr32), &shdr32);
|
||||
result.v[shdr_idx] = elf_shdr64_from_shdr32(shdr32);
|
||||
} break;
|
||||
case ELF_Class_64: {
|
||||
str8_deserial_read_struct(shdr_data, shdr_idx * sizeof(ELF_Shdr64), &result.v[shdr_idx]);
|
||||
} break;
|
||||
default: InvalidPath; break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return bin;
|
||||
}
|
||||
|
||||
//- rjf: extra bin info extraction
|
||||
|
||||
internal String8
|
||||
elf_name_from_shdr64(String8 raw_data, ELF_Hdr64 *hdr, Rng1U64 sh_name_range, ELF_Shdr64 *shdr)
|
||||
elf_name_from_shdr64(String8 data, ELF_Bin *bin, ELF_Shdr64 *shdr)
|
||||
{
|
||||
String8 sh_names = str8_substr(raw_data, sh_name_range);
|
||||
String8 sh_names = str8_substr(data, bin->sh_name_range);
|
||||
String8 name = {0};
|
||||
str8_deserial_read_cstr(sh_names, shdr->sh_name, &name);
|
||||
return name;
|
||||
}
|
||||
|
||||
internal U64
|
||||
elf_base_addr_from_bin(ELF_Hdr64 *hdr)
|
||||
elf_base_addr_from_bin(ELF_Bin *bin)
|
||||
{
|
||||
NotImplemented;
|
||||
return 0;
|
||||
U64 base_vaddr = 0;
|
||||
for EachIndex(phdr_idx, bin->phdrs.count)
|
||||
{
|
||||
ELF_Phdr64 *phdr = &bin->phdrs.v[phdr_idx];
|
||||
if(phdr->p_type == ELF_PType_Load &&
|
||||
(base_vaddr == 0 || phdr->p_vaddr < base_vaddr))
|
||||
{
|
||||
base_vaddr = phdr->p_vaddr;
|
||||
}
|
||||
}
|
||||
return base_vaddr;
|
||||
}
|
||||
|
||||
internal B32
|
||||
elf_parse_debug_link(String8 raw_data, ELF_BinInfo *elf, ELF_GnuDebugLink *debug_link_out)
|
||||
internal ELF_GnuDebugLink
|
||||
elf_gnu_debug_link_from_bin(String8 raw_data, ELF_Bin *bin)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
B32 is_debug_link_present = 0;
|
||||
ELF_Shdr64Array sections = elf_shdr64_array_from_bin(scratch.arena, raw_data, &elf->hdr);
|
||||
for (U64 i = 0; i < sections.count; ++i) {
|
||||
ELF_Shdr64 *shdr = §ions.v[i];
|
||||
String8 name = elf_name_from_shdr64(raw_data, &elf->hdr, elf->sh_name_range, shdr);
|
||||
|
||||
if (str8_match(name, str8_lit(".gnu_debuglink"), 0)) {
|
||||
ELF_GnuDebugLink result = {0};
|
||||
for EachIndex(idx, bin->shdrs.count)
|
||||
{
|
||||
ELF_Shdr64 *shdr = &bin->shdrs.v[idx];
|
||||
String8 name = elf_name_from_shdr64(raw_data, bin, shdr);
|
||||
if(str8_match(name, str8_lit(".gnu_debuglink"), 0))
|
||||
{
|
||||
Rng1U64 raw_data_range = rng_1u64(shdr->sh_offset, shdr->sh_offset + shdr->sh_size);
|
||||
String8 data = str8_substr(raw_data, raw_data_range);
|
||||
|
||||
String8 path = {0};
|
||||
U32 checksum = 0;
|
||||
String8 data = str8_substr(raw_data, raw_data_range);
|
||||
String8 path = {0};
|
||||
U32 checksum = 0;
|
||||
{
|
||||
U64 cursor = 0;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &path);
|
||||
|
||||
cursor = AlignPow2(cursor, 4);
|
||||
cursor += str8_deserial_read_struct(data, cursor, &checksum);
|
||||
}
|
||||
|
||||
debug_link_out->path = path;
|
||||
debug_link_out->checksum = checksum;
|
||||
|
||||
is_debug_link_present = 1;
|
||||
result.path = path;
|
||||
result.checksum = checksum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return is_debug_link_present;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+33
-17
@@ -5,32 +5,48 @@
|
||||
#define ELF_PARSE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsed Structure Types
|
||||
|
||||
typedef struct ELF_BinInfo
|
||||
typedef struct ELF_Shdr64Array ELF_Shdr64Array;
|
||||
struct ELF_Shdr64Array
|
||||
{
|
||||
ELF_Shdr64 *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct ELF_Phdr64Array ELF_Phdr64Array;
|
||||
struct ELF_Phdr64Array
|
||||
{
|
||||
ELF_Phdr64 *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct ELF_Bin ELF_Bin;
|
||||
struct ELF_Bin
|
||||
{
|
||||
ELF_Hdr64 hdr;
|
||||
Rng1U64 sh_name_range;
|
||||
} ELF_BinInfo;
|
||||
Rng1U64 sh_name_range;
|
||||
ELF_Shdr64Array shdrs;
|
||||
ELF_Phdr64Array phdrs;
|
||||
};
|
||||
|
||||
typedef struct ELF_Shdr64Array
|
||||
{
|
||||
U64 count;
|
||||
ELF_Shdr64 *v;
|
||||
} ELF_Shdr64Array;
|
||||
|
||||
typedef struct ELF_GnuDebugLink
|
||||
typedef struct ELF_GnuDebugLink ELF_GnuDebugLink;
|
||||
struct ELF_GnuDebugLink
|
||||
{
|
||||
String8 path;
|
||||
U32 checksum;
|
||||
} ELF_GnuDebugLink;
|
||||
U32 checksum;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsing Functions
|
||||
|
||||
internal B32 elf_check_magic(String8 data);
|
||||
internal ELF_BinInfo elf_bin_from_data(String8 data);
|
||||
//- rjf: top-level binary parsing
|
||||
internal ELF_Bin elf_bin_from_data(Arena *arena, String8 data);
|
||||
|
||||
internal ELF_Shdr64Array elf_shdr64_array_from_bin(Arena *arena, String8 raw_data, ELF_Hdr64 *hdr);
|
||||
internal String8 elf_name_from_shdr64(String8 raw_data, ELF_Hdr64 *hdr, Rng1U64 sh_name_range, ELF_Shdr64 *shdr);
|
||||
internal U64 elf_base_addr_from_bin(ELF_Hdr64 *hdr);
|
||||
//- rjf: extra bin info extraction
|
||||
internal B32 elf_is_dwarf_present_from_bin(String8 data, ELF_Bin *bin);
|
||||
internal String8 elf_name_from_shdr64(String8 raw_data, ELF_Bin *bin, ELF_Shdr64 *shdr);
|
||||
internal U64 elf_base_addr_from_bin(ELF_Bin *bin);
|
||||
internal ELF_GnuDebugLink elf_gnu_debug_link_from_bin(String8 raw_data, ELF_Bin *bin);
|
||||
|
||||
#endif // ELF_PARSE_H
|
||||
|
||||
+10
-9
@@ -264,13 +264,14 @@ rb_entry_point(CmdLine *cmdline)
|
||||
if(file_format == RB_FileFormat_ELF32 ||
|
||||
file_format == RB_FileFormat_ELF64)
|
||||
{
|
||||
ELF_BinInfo elf = elf_bin_from_data(file_data);
|
||||
ELF_GnuDebugLink debug_link = {0};
|
||||
if(elf_parse_debug_link(file_data, &elf, &debug_link) &&
|
||||
debug_link.path.size != 0)
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
ELF_Bin bin = elf_bin_from_data(scratch.arena, file_data);
|
||||
ELF_GnuDebugLink debug_link = elf_gnu_debug_link_from_bin(file_data, &bin);
|
||||
if(debug_link.path.size != 0)
|
||||
{
|
||||
str8_list_push(arena, &input_file_path_tasks, debug_link.path);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
@@ -298,8 +299,8 @@ rb_entry_point(CmdLine *cmdline)
|
||||
file_format == RB_FileFormat_ELF64)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
ELF_BinInfo elf_bin = elf_bin_from_data(file_data);
|
||||
if(dw_is_dwarf_present_elf_section_table(file_data, &elf_bin))
|
||||
ELF_Bin elf_bin = elf_bin_from_data(scratch.arena, file_data);
|
||||
if(dw_is_dwarf_present_from_elf_bin(file_data, &elf_bin))
|
||||
{
|
||||
file_format_flags |= RB_FileFormatFlag_HasDWARF;
|
||||
}
|
||||
@@ -898,7 +899,7 @@ rb_entry_point(CmdLine *cmdline)
|
||||
//- rjf: unpack file parses
|
||||
Arch arch = Arch_Null;
|
||||
PE_BinInfo pe = {0};
|
||||
ELF_BinInfo elf = {0};
|
||||
ELF_Bin elf = {0};
|
||||
DW_Input dw = {0};
|
||||
{
|
||||
if(f->format == RB_FileFormat_PE)
|
||||
@@ -909,7 +910,7 @@ rb_entry_point(CmdLine *cmdline)
|
||||
if(f->format == RB_FileFormat_ELF32 ||
|
||||
f->format == RB_FileFormat_ELF64)
|
||||
{
|
||||
elf = elf_bin_from_data(f->data);
|
||||
elf = elf_bin_from_data(arena, f->data);
|
||||
arch = arch_from_elf_machine(elf.hdr.e_machine);
|
||||
}
|
||||
if(f->format_flags & RB_FileFormatFlag_HasDWARF)
|
||||
@@ -925,7 +926,7 @@ rb_entry_point(CmdLine *cmdline)
|
||||
else if(f->format == RB_FileFormat_ELF32 ||
|
||||
f->format == RB_FileFormat_ELF64)
|
||||
{
|
||||
dw = dw_input_from_elf_section_table(arena, f->data, &elf);
|
||||
dw = dw_input_from_elf_bin(arena, f->data, &elf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -110,8 +110,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
pe_name = input_n->string;
|
||||
is_pe_present = 1;
|
||||
} else if (elf_check_magic(input_data)) {
|
||||
ELF_BinInfo elf = elf_bin_from_data(input_data);
|
||||
B32 is_dwarf_present = dw_is_dwarf_present_elf_section_table(input_data, &elf);
|
||||
ELF_Bin elf = elf_bin_from_data(input_data);
|
||||
B32 is_dwarf_present = dw_is_dwarf_present_from_bin(input_data, &elf);
|
||||
if (is_dwarf_present) {
|
||||
if (is_elf_debug_present) {
|
||||
fprintf(stderr, "error: ambiguous input, both ELFs have DWARF debug sections, please use --elf:<path> --elf_debug:<path> to clarify inputs.\n");
|
||||
@@ -234,8 +234,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
//
|
||||
// Load image ELF
|
||||
//
|
||||
ELF_BinInfo elf = elf_bin_from_data(elf_data);
|
||||
B32 has_elf_dwarf = dw_is_dwarf_present_elf_section_table(elf_data, &elf);
|
||||
ELF_Bin elf = elf_bin_from_data(elf_data);
|
||||
B32 has_elf_dwarf = dw_is_dwarf_present_from_elf_bin(elf_data, &elf);
|
||||
|
||||
//
|
||||
// ELF doesn't have debug info and no .debug was specified on command line,
|
||||
@@ -252,8 +252,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
//
|
||||
// Load .debug ELF
|
||||
//
|
||||
ELF_BinInfo elf_debug = elf_bin_from_data(elf_debug_data);
|
||||
B32 has_elf_debug_dwarf = dw_is_dwarf_present_elf_section_table(elf_debug_data, &elf_debug);
|
||||
ELF_Bin elf_debug = elf_bin_from_data(elf_debug_data);
|
||||
B32 has_elf_debug_dwarf = dw_is_dwarf_present_from_elf_bin(elf_debug_data, &elf_debug);
|
||||
|
||||
//
|
||||
// Input is image ELF and .debug ELF
|
||||
|
||||
@@ -4078,9 +4078,9 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
ELF_BinInfo bin = elf_bin_from_data(raw_data);
|
||||
ELF_Bin bin = elf_bin_from_data(raw_data);
|
||||
Arch arch = arch_from_elf_machine(bin.hdr.e_machine);
|
||||
DW_Input dwarf_input = dw_input_from_elf_section_table(scratch.arena, raw_data, &bin);
|
||||
DW_Input dwarf_input = dw_input_from_elf_bin(scratch.arena, raw_data, &bin);
|
||||
ELF_Class elf_class = bin.hdr.e_ident[ELF_Identifier_Class];
|
||||
ExecutableImageKind image_type = elf_class == ELF_Class_32 ? ExecutableImageKind_Elf32 : elf_class == ELF_Class_64 ? ExecutableImageKind_Elf64 : ELF_Class_None;
|
||||
B32 relaxed = 1;
|
||||
|
||||
@@ -1097,44 +1097,23 @@ d2r_convert(Arena *arena, ASYNC_Root *async_root, D2R_ConvertParams *params)
|
||||
case ExecutableImageKind_CoffPe:
|
||||
{
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, params->exe_data);
|
||||
|
||||
// get image arch
|
||||
arch = pe.arch;
|
||||
|
||||
// get image base
|
||||
image_base = pe.image_base;
|
||||
|
||||
// get image sections
|
||||
String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range);
|
||||
U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader);
|
||||
String8 raw_sections = str8_substr(params->exe_data, pe.section_table_range);
|
||||
U64 section_count = raw_sections.size / sizeof(COFF_SectionHeader);
|
||||
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_sections.str;
|
||||
|
||||
// convert sections
|
||||
String8 string_table = str8_substr(params->exe_data, pe.string_table_range);
|
||||
binary_sections = c2r_rdi_binary_sections_from_coff_sections(arena, params->exe_data, string_table, section_count, section_table);
|
||||
|
||||
// make DWARF input
|
||||
input = dw_input_from_coff_section_table(scratch.arena, params->exe_data, string_table, section_count, section_table);
|
||||
}break;
|
||||
case ExecutableImageKind_Elf32:
|
||||
case ExecutableImageKind_Elf64:
|
||||
{
|
||||
ELF_BinInfo elf = elf_bin_from_data(params->dbg_data);
|
||||
|
||||
// get image arch
|
||||
arch = arch_from_elf_machine(elf.hdr.e_machine);
|
||||
|
||||
// get image base
|
||||
image_base = elf_base_addr_from_bin(&elf.hdr);
|
||||
|
||||
// get image sections
|
||||
ELF_Shdr64Array shdrs = elf_shdr64_array_from_bin(scratch.arena, params->dbg_data, &elf.hdr);
|
||||
|
||||
// convert sections
|
||||
binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, shdrs);
|
||||
|
||||
// make DWARF input
|
||||
input = dw_input_from_elf_section_table(scratch.arena, params->dbg_data, &elf);
|
||||
ELF_Bin bin = elf_bin_from_data(scratch.arena, params->dbg_data);
|
||||
arch = arch_from_elf_machine(bin.hdr.e_machine);
|
||||
image_base = elf_base_addr_from_bin(&bin);
|
||||
binary_sections = e2r_rdi_binary_sections_from_elf_section_table(arena, bin.shdrs);
|
||||
input = dw_input_from_elf_bin(scratch.arena, params->dbg_data, &bin);
|
||||
}break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user