Files
raddebugger/src/rdi_from_dwarf/rdi_from_dwarf.c
T
2024-10-18 16:40:25 -07:00

899 lines
32 KiB
C

// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Build Options
#define BUILD_VERSION_MAJOR 0
#define BUILD_VERSION_MINOR 9
#define BUILD_VERSION_PATCH 13
#define BUILD_RELEASE_PHASE_STRING_LITERAL "ALPHA"
#define BUILD_TITLE "rdi_from_dwarf"
#define BUILD_CONSOLE_INTERFACE 1
////////////////////////////////
//~ rjf: Includes
//- rjf: [lib]
#include "lib_rdi_format/rdi_format.h"
#include "lib_rdi_format/rdi_format.c"
#include "third_party/rad_lzb_simple/rad_lzb_simple.h"
#include "third_party/rad_lzb_simple/rad_lzb_simple.c"
//- rjf: [h]
#include "base/base_inc.h"
#include "os/os_inc.h"
#include "rdi_make/rdi_make_local.h"
#include "rdi_elf.h"
#include "rdi_dwarf.h"
#include "rdi_dwarf_stringize.h"
#include "rdi_from_dwarf.h"
//- rjf: [c]
#include "base/base_inc.c"
#include "os/os_inc.c"
#include "rdi_make/rdi_make_local.c"
#include "rdi_elf.c"
#include "rdi_dwarf.c"
#include "rdi_dwarf_stringize.c"
// TODO(allen):
// [ ] need sample data for .debug_names
////////////////////////////////
//~ Program Parameters Parser
static DWARFCONV_Params*
dwarf_convert_params_from_cmd_line(Arena *arena, CmdLine *cmdline){
DWARFCONV_Params *result = push_array(arena, DWARFCONV_Params, 1);
result->unit_idx_max = ~0ull;
// get input pdb
{
String8 input_name = cmd_line_string(cmdline, str8_lit("elf"));
if (input_name.size == 0){
str8_list_push(arena, &result->errors,
str8_lit("missing required parameter '--elf:<elf_file>'"));
}
if (input_name.size > 0){
String8 input_data = os_data_from_file_path(arena, input_name);
if (input_data.size == 0){
str8_list_pushf(arena, &result->errors,
"could not load input file '%.*s'", str8_varg(input_name));
}
if (input_data.size != 0){
result->input_elf_name = input_name;
result->input_elf_data = input_data;
}
}
}
// get output name
{
result->output_name = cmd_line_string(cmdline, str8_lit("out"));
}
// error options
if (cmd_line_has_flag(cmdline, str8_lit("hide_errors"))){
String8List vals = cmd_line_strings(cmdline, str8_lit("hide_errors"));
// if no values - set all to hidden
if (vals.node_count == 0){
B8 *ptr = (B8*)&result->hide_errors;
B8 *opl = ptr + sizeof(result->hide_errors);
for (;ptr < opl; ptr += 1){
*ptr = 1;
}
}
// for each explicit value set the corresponding flag to hidden
for (String8Node *node = vals.first;
node != 0;
node = node->next){
if (str8_match(node->string, str8_lit("input"), 0)){
result->hide_errors.input = 1;
}
}
}
// unit idx selector
if (cmd_line_has_flag(cmdline, str8_lit("unit_idx"))){
String8List vals = cmd_line_strings(cmdline, str8_lit("unit_idx"));
// single value unit index
if (vals.node_count == 1){
U64 idx = u64_from_str8(vals.first->string, 10);
result->unit_idx_min = idx;
result->unit_idx_max = idx;
}
// range value unit index
else if (vals.node_count >= 2){
U64 idx_a = u64_from_str8(vals.first->string, 10);
U64 idx_b = u64_from_str8(vals.first->next->string, 10);
result->unit_idx_min = Min(idx_a, idx_b);
result->unit_idx_max = Max(idx_a, idx_b);
}
}
// dump options
if (cmd_line_has_flag(cmdline, str8_lit("dump"))){
result->dump = 1;
String8List vals = cmd_line_strings(cmdline, str8_lit("dump"));
if (vals.first == 0){
B8 *ptr = &result->dump__first;
for (; ptr < &result->dump__last; ptr += 1){
*ptr = 1;
}
}
else{
for (String8Node *node = vals.first;
node != 0;
node = node->next){
if (str8_match(node->string, str8_lit("header"), 0)){
result->dump_header = 1;
}
else if (str8_match(node->string, str8_lit("sections"), 0)){
result->dump_sections = 1;
}
else if (str8_match(node->string, str8_lit("segments"), 0)){
result->dump_segments = 1;
}
else if (str8_match(node->string, str8_lit("symtab"), 0)){
result->dump_symtab = 1;
}
else if (str8_match(node->string, str8_lit("dynsym"), 0)){
result->dump_dynsym = 1;
}
else if (str8_match(node->string, str8_lit("debug_sections"), 0)){
result->dump_debug_sections = 1;
}
else if (str8_match(node->string, str8_lit("debug_info"), 0)){
result->dump_debug_info = 1;
}
else if (str8_match(node->string, str8_lit("debug_abbrev"), 0)){
result->dump_debug_abbrev = 1;
}
else if (str8_match(node->string, str8_lit("debug_pubnames"), 0)){
result->dump_debug_pubnames = 1;
}
else if (str8_match(node->string, str8_lit("debug_pubtypes"), 0)){
result->dump_debug_pubtypes = 1;
}
else if (str8_match(node->string, str8_lit("debug_names"), 0)){
result->dump_debug_names = 1;
}
else if (str8_match(node->string, str8_lit("debug_aranges"), 0)){
result->dump_debug_aranges = 1;
}
else if (str8_match(node->string, str8_lit("debug_addr"), 0)){
result->dump_debug_addr = 1;
}
}
}
}
return(result);
}
////////////////////////////////
//~ Entry Point
static void
dump_symtab(Arena *arena, String8List *out, ELF_SymArray *symbols, String8 strtab,
U32 indent){
static char spaces[] = " ";
U8 *str_first = strtab.str;
U8 *str_opl = strtab.str + strtab.size;
ELF_Sym64 *symbol = symbols->symbols;
U64 count = symbols->count;
for (U64 i = 0; i < count; i += 1, symbol += 1){
U8 *name_first = str_first + symbol->st_name;
U8 *name_opl = name_first;
for (;name_opl < str_opl && *name_opl != 0;) name_opl += 1;
String8 name = str8_range(name_first, name_opl);
ELF_SymbolBinding binding = ELF_SymBindingFromInfo(symbol->st_info);
String8 binding_string = elf_string_from_symbol_binding(binding);
ELF_SymbolType type = ELF_SymTypeFromInfo(symbol->st_info);
String8 type_string = elf_string_from_symbol_type(type);
ELF_SymbolVisibility vis = ELF_SymVisibilityFromOther(symbol->st_other);
String8 vis_string = elf_string_from_symbol_visibility(vis);
str8_list_pushf(arena, out,
"%.*ssymbol[%5llu] %6.*s %7.*s %9.*s 0x%08llx size=%-5llu sec=%-5u "
"%.*s\n",
indent, spaces, i,
str8_varg(binding_string), str8_varg(type_string),
str8_varg(vis_string),
symbol->st_value, symbol->st_size,
symbol->st_shndx, str8_varg(name));
}
}
#if 0
static void
dump_entry_tree(Arena *arena, String8List *out,
DWARF_Parsed *dwarf, DWARF_InfoUnit *unit,
DWARF_InfoEntry *entry, U32 indent){
static char spaces[] = " ";
DWARF_AbbrevDecl *abbrev_decl = entry->abbrev_decl;
// tag
DWARF_Tag tag = abbrev_decl->tag;
String8 tag_string = dwarf_string_from_tag(tag);
str8_list_pushf(arena, out, "%.*sentry(@%llx) TAG %.*s\n",
indent, spaces, entry->info_offset, str8_varg(tag_string));
// attributes
U32 attrib_count = abbrev_decl->attrib_count;
DWARF_AbbrevAttribSpec *attrib_spec = abbrev_decl->attrib_specs;
DWARF_InfoAttribVal *attrib_val = entry->attrib_vals;
for (U32 i = 0; i < attrib_count; i += 1, attrib_spec += 1, attrib_val += 1){
// attribute name
DWARF_AttributeName name = attrib_spec->name;
String8 name_string = dwarf_string_from_attribute_name(name);
str8_list_pushf(arena, out, "%.*sATTR %.*s ", indent + 4, spaces, str8_varg(name_string));
// attribute value
switch (attrib_spec->form){
default:
{
String8 form_string = dwarf_string_from_attribute_form(attrib_spec->form);
str8_list_pushf(arena, out, "<form: %.*s> {%llu, 0x%p}\n",
str8_varg(form_string), attrib_val->val, attrib_val->dataptr);
}break;
case DWARF_AttributeForm_strp:
{
String8 str = {0};
String8 data = dwarf->debug_data[DWARF_SectionCode_Str];
U64 off = attrib_val->val;
if (off < data.size){
U8 *start = data.str + off;
U8 *opl = data.str + data.size;
U8 *ptr = start;
for (;ptr < opl && *ptr != 0;) ptr += 1;
str = str8_range(start, ptr);
}
str8_list_pushf(arena, out, "'%.*s'\n", str8_varg(str));
}break;
case DWARF_AttributeForm_sec_offset:
{
DWARF_AttributeClassFlags attr_classes1 = dwarf_attribute_class_from_name(name);
DWARF_AttributeClassFlags attr_classes2 = DWARF_AttributeClassFlag_sec_offset_classes;
DWARF_AttributeClassFlags attr_classes = attr_classes1&attr_classes2;
DWARF_SectionCode sec_code = DWARF_SectionCode_Null;
if (unit->dwarf_version == 5){
switch (attr_classes){
case DWARF_AttributeClassFlag_addrptr: sec_code = DWARF_SectionCode_Addr; break;
case DWARF_AttributeClassFlag_lineptr: sec_code = DWARF_SectionCode_Line; break;
case DWARF_AttributeClassFlag_loclist: sec_code = DWARF_SectionCode_LocLists; break;
case DWARF_AttributeClassFlag_loclistsptr: sec_code = DWARF_SectionCode_LocLists; break;
case DWARF_AttributeClassFlag_macptr: sec_code = DWARF_SectionCode_Macro; break;
case DWARF_AttributeClassFlag_rnglist: sec_code = DWARF_SectionCode_RngLists; break;
case DWARF_AttributeClassFlag_rnglistsptr: sec_code = DWARF_SectionCode_RngLists; break;
case DWARF_AttributeClassFlag_stroffsetsptr: sec_code = DWARF_SectionCode_StrOffsets; break;
}
}
else if (unit->dwarf_version == 4){
switch (attr_classes){
case DWARF_AttributeClassFlag_lineptr: sec_code = DWARF_SectionCode_Line; break;
case DWARF_AttributeClassFlag_loclist: sec_code = DWARF_SectionCode_Loc; break;
case DWARF_AttributeClassFlag_macptr: sec_code = DWARF_SectionCode_MacInfo; break;
case DWARF_AttributeClassFlag_rnglist: sec_code = DWARF_SectionCode_Ranges; break;
}
}
String8 sec_name = dwarf_name_from_debug_section(dwarf, sec_code);
str8_list_pushf(arena, out, "sec(%.*s) + %llu\n", str8_varg(sec_name), attrib_val->val);
}break;
case DWARF_AttributeForm_ref1:
case DWARF_AttributeForm_ref2:
case DWARF_AttributeForm_ref4:
case DWARF_AttributeForm_ref8:
case DWARF_AttributeForm_ref_udata:
{
str8_list_pushf(arena, out, "entry(@%llx)\n", attrib_val->val);
}break;
case DWARF_AttributeForm_addr:
{
str8_list_pushf(arena, out, "0x%llx\n", attrib_val->val);
}break;
case DWARF_AttributeForm_exprloc:
{
str8_list_pushf(arena, out, "expression\n");
// TODO(allen): dwarf expression dumping
}break;
case DWARF_AttributeForm_strx1:
case DWARF_AttributeForm_strx2:
case DWARF_AttributeForm_strx3:
case DWARF_AttributeForm_strx4:
{
String8 str = {0};
U32 idx = attrib_val->val;
U64 str_offsets_off = unit->str_offsets_base + idx*unit->offset_size;
String8 str_offsets = dwarf->debug_data[DWARF_SectionCode_StrOffsets];
if (str_offsets_off + unit->offset_size < str_offsets.size){
U64 off = 0;
MemoryCopy(&off, str_offsets.str + str_offsets_off, unit->offset_size);
String8 data = dwarf->debug_data[DWARF_SectionCode_Str];
if (off < data.size){
U8 *start = data.str + off;
U8 *opl = data.str + data.size;
U8 *ptr = start;
for (;ptr < opl && *ptr != 0;) ptr += 1;
str = str8_range(start, ptr);
}
}
str8_list_pushf(arena, out, "'%.*s'\n", str8_varg(str));
}break;
case DWARF_AttributeForm_addrx:
case DWARF_AttributeForm_addrx1:
case DWARF_AttributeForm_addrx2:
case DWARF_AttributeForm_addrx3:
case DWARF_AttributeForm_addrx4:
{
U64 address = 0;
U32 idx = attrib_val->val;
U64 address_off = unit->addr_base + idx*unit->address_size;
String8 data = dwarf->debug_data[DWARF_SectionCode_Addr];
if (address_off + unit->address_size < data.size){
MemoryCopy(&address, data.str + address_off, unit->address_size);
}
str8_list_pushf(arena, out, "0x%x\n", address);
}break;
case DWARF_AttributeForm_rnglistx:
{
U64 rnglist_off = unit->rnglists_base + attrib_val->val;
int x = 0;
}break;
case DWARF_AttributeForm_data1:
case DWARF_AttributeForm_data2:
case DWARF_AttributeForm_data4:
case DWARF_AttributeForm_data8:
case DWARF_AttributeForm_data16:
case DWARF_AttributeForm_udata:
case DWARF_AttributeForm_implicit_const:
case DWARF_AttributeForm_flag:
case DWARF_AttributeForm_flag_present:
{
str8_list_pushf(arena, out, "%llu\n", attrib_val->val);
}break;
case DWARF_AttributeForm_sdata:
{
str8_list_pushf(arena, out, "%lld\n", (S64)attrib_val->val);
}break;
case DWARF_AttributeForm_string:
{
str8_list_pushf(arena, out, "'%.*s'\n", (int)attrib_val->val, attrib_val->dataptr);
}break;
}
}
// dump children
for (DWARF_InfoEntry *child = entry->first_child;
child != 0;
child = child->next_sibling){
dump_entry_tree(arena, out, dwarf, unit, child, indent + 1);
}
}
#endif
internal void
entry_point(CmdLine *cmd_line)
{
Arena *arena = arena_alloc();
// parse arguments
DWARFCONV_Params *params = dwarf_convert_params_from_cmd_line(arena, cmd_line);
// show input errors
if (params->errors.node_count > 0 &&
!params->hide_errors.input){
for (String8Node *node = params->errors.first;
node != 0;
node = node->next){
fprintf(stdout, "error(input): %.*s\n", str8_varg(node->string));
}
}
// will we try to parse an input file?
B32 try_parse_input = (params->errors.node_count == 0);
// track parse success
B32 successful_parse = 1;
#define PARSE_CHECK_ERROR(p,fmt,...) do{ if ((p) == 0){ \
successful_parse = 0; \
fprintf(stdout, "error(parsing): " fmt "\n", __VA_ARGS__); \
} }while(0)
// parse elf
ELF_Parsed *elf = 0;
if (try_parse_input) ProfScope("parse elf"){
elf = elf_parsed_from_data(arena, params->input_elf_data);
PARSE_CHECK_ERROR(elf, "ELF");
}
// parse strtab
String8 strtab = {0};
if (elf != 0) ProfScope("parse strtab"){
strtab = elf_section_data_from_idx(elf, elf->strtab_idx);
}
// parse symtab
ELF_SymArray symtab = {0};
if (elf != 0) ProfScope("parse symtab"){
String8 data = elf_section_data_from_idx(elf, elf->symtab_idx);
symtab = elf_sym_array_from_data(arena, elf->elf_class, data);
}
// parse dynsym
ELF_SymArray dynsym = {0};
if (elf != 0) ProfScope("parse dynsym"){
String8 data = elf_section_data_from_idx(elf, elf->dynsym_idx);
dynsym = elf_sym_array_from_data(arena, elf->elf_class, data);
}
// parse dwarf
DWARF_Parsed *dwarf = 0;
if (elf != 0) ProfScope("parse dwarf"){
dwarf = dwarf_parsed_from_elf(arena, elf);
PARSE_CHECK_ERROR(dwarf, "DWARF");
}
// parse info
DWARF_InfoParsed *info = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_Info];
if (data.size > 0) ProfScope("parse .debug_info"){
info = dwarf_info_from_data(arena, data);
PARSE_CHECK_ERROR(info, "DEBUG INFO");
}
}
// parse pubnames
DWARF_PubNamesParsed *pubnames = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_PubNames];
if (data.size) ProfScope("parse .debug_pubnames"){
pubnames = dwarf_pubnames_from_data(arena, data);
PARSE_CHECK_ERROR(pubnames, "DEBUG PUBNAMES");
}
}
// parse pubtypes
DWARF_PubNamesParsed *pubtypes = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_PubTypes];
if (data.size) ProfScope("parse .debug_pubtypes"){
pubtypes = dwarf_pubnames_from_data(arena, data);
PARSE_CHECK_ERROR(pubtypes, "DEBUG PUBTYPES");
}
}
// parse names
DWARF_NamesParsed *names = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_Names];
if (data.size) ProfScope("parse .debug_names"){
names = dwarf_names_from_data(arena, data);
PARSE_CHECK_ERROR(names, "DEBUG NAMES");
}
}
// parse aranges
DWARF_ArangesParsed *aranges = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_Aranges];
if (data.size) ProfScope("parse .debug_aranges"){
aranges = dwarf_aranges_from_data(arena, data);
PARSE_CHECK_ERROR(aranges, "DEBUG ARANGES");
}
}
// parse addr
DWARF_AddrParsed *addr = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_Addr];
if (data.size) ProfScope("parse .debug_addr"){
addr = dwarf_addr_from_data(arena, data);
PARSE_CHECK_ERROR(addr, "DEBUG ADDR");
}
}
#if 0
// parse abbrev
DWARF_AbbrevParsed *abbrev = 0;
if (dwarf != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_Abbrev];
if (data.size > 0) ProfScope("parse .debug_abbrev"){
DWARF_AbbrevParams abbrev_params = {0};
abbrev_params.unit_idx_min = params->unit_idx_min;
abbrev_params.unit_idx_max = params->unit_idx_max;
abbrev = dwarf_abbrev_from_data(arena, data, &abbrev_params);
PARSE_CHECK_ERROR(abbrev, "DEBUG ABBREV");
}
}
// parse info
DWARF_InfoParsed *info = 0;
if (abbrev != 0){
String8 data = dwarf->debug_data[DWARF_SectionCode_Info];
if (data.size > 0) ProfScope("parse .debug_info"){
DWARF_InfoParams info_params = {0};
info_params.unit_idx_min = params->unit_idx_min;
info_params.unit_idx_max = params->unit_idx_max;
info = dwarf_info_from_data(arena, data, &info_params, abbrev);
PARSE_CHECK_ERROR(info, "DEBUG INFO");
}
}
#endif
// dump
if (params->dump) ProfScope("dump"){
String8List dump = {0};
// ELF
if (params->dump_header){
if (elf != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"ELF:\n"));
// TODO: better stringizers for fields here
str8_list_pushf(arena, &dump, " elf_class=%u\n", elf->elf_class);
str8_list_pushf(arena, &dump, " arch=%u\n", elf->arch);
str8_list_pushf(arena, &dump, " section_count=%llu\n", elf->section_count);
str8_list_pushf(arena, &dump, " segment_count=%llu\n", elf->segment_count);
str8_list_pushf(arena, &dump, " vbase=0x%llx\n", elf->vbase);
str8_list_pushf(arena, &dump, " entry_vaddr=0x%llx\n", elf->vbase);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
// SECTIONS
if (params->dump_sections){
if (elf != 0){
ELF_SectionArray section_array = elf_section_array_from_elf(elf);
String8Array section_name_array = elf_section_name_array_from_elf(elf);
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"SECTIONS:\n"));
ELF_Shdr64 *sec = section_array.sections;
String8 *sec_name = section_name_array.v;
U64 count = section_array.count;
for (U64 i = 0 ; i < count; i += 1, sec += 1, sec_name += 1){
String8 type_string = elf_string_from_section_type(sec->sh_type);
// TODO: better stringizers for fields here
str8_list_pushf(arena, &dump, " section[%llu]:\n", i);
str8_list_pushf(arena, &dump, " name='%.*s'\n", str8_varg(*sec_name));
str8_list_pushf(arena, &dump, " type=%.*s\n", str8_varg(type_string));
str8_list_pushf(arena, &dump, " flags=0x%llx\n", sec->sh_flags);
str8_list_pushf(arena, &dump, " addr=0x%llx\n", sec->sh_addr);
str8_list_pushf(arena, &dump, " offset=0x%llx\n", sec->sh_offset);
str8_list_pushf(arena, &dump, " size=%llu\n", sec->sh_size);
str8_list_pushf(arena, &dump, " link=%u\n", sec->sh_link);
str8_list_pushf(arena, &dump, " info=%u\n", sec->sh_info);
str8_list_pushf(arena, &dump, " addralign=0x%llx\n", sec->sh_addralign);
str8_list_pushf(arena, &dump, " entsize=%llu\n", sec->sh_entsize);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// SYMTAB
if (symtab.count > 0 && params->dump_symtab){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"SYMTAB:\n"));
str8_list_pushf(arena, &dump, " section: %llu\n", elf->symtab_idx);
dump_symtab(arena, &dump, &symtab, strtab, 1);
str8_list_push(arena, &dump, str8_lit("\n"));
}
// DYNSYM
if (dynsym.count > 0 && params->dump_dynsym){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DYNSYM:\n"));
str8_list_pushf(arena, &dump, " section: %llu\n", elf->dynsym_idx);
dump_symtab(arena, &dump, &dynsym, strtab, 1);
str8_list_push(arena, &dump, str8_lit("\n"));
}
// SEGMENTS
if (params->dump_segments){
if (elf != 0){
ELF_SegmentArray segment_array = elf_segment_array_from_elf(elf);
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"SEGMENTS:\n"));
ELF_Phdr64 *segments = segment_array.segments;
U64 count = segment_array.count;
for (U64 i = 0 ; i < count; i += 1){
ELF_Phdr64 *seg = segments + i;
// TODO: better stringizers for fields here
str8_list_pushf(arena, &dump, " segment[%llu]:\n", i);
str8_list_pushf(arena, &dump, " p_type=%u\n", seg->p_type);
str8_list_pushf(arena, &dump, " p_flags=0x%x\n", seg->p_flags);
str8_list_pushf(arena, &dump, " p_offset=0x%llx\n", seg->p_offset);
str8_list_pushf(arena, &dump, " p_vaddr=0x%llx\n", seg->p_vaddr);
str8_list_pushf(arena, &dump, " p_paddr=0x%llx\n", seg->p_paddr);
str8_list_pushf(arena, &dump, " p_filesz=%llu\n", seg->p_filesz);
str8_list_pushf(arena, &dump, " p_memsz=%llu\n", seg->p_memsz);
str8_list_pushf(arena, &dump, " p_align=%llu\n", seg->p_align);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// DEBUG SECTIONS
if (params->dump_debug_sections){
if (dwarf != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG SECTIONS:\n"));
U32 *debug_section_idx = dwarf->debug_section_idx;
String8 *debug_data = dwarf->debug_data;
for (U32 i = 1; i < DWARF_SectionCode_COUNT; i += 1, debug_data += 1){
U32 idx = debug_section_idx[i];
String8 name = dwarf_string_from_section_code(i);
str8_list_pushf(arena, &dump, " %-10.*s section_idx=%u\n", str8_varg(name), idx);
}
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
// DEBUG INFO
if (params->dump_debug_info){
if (info != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG INFO:\n"));
U32 i = 0;
for (DWARF_InfoUnit *unit = info->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
dwarf_stringize_info(arena, &dump, unit, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// DEBUG PUBNAMES
if (params->dump_debug_pubnames){
if (pubnames != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG PUBNAMES:\n"));
U32 i = 0;
for (DWARF_PubNamesUnit *unit = pubnames->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
dwarf_stringize_pubnames(arena, &dump, unit, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// DEBUG PUBTYPES
if (params->dump_debug_pubtypes){
if (pubtypes != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG PUBTYPES:\n"));
U32 i = 0;
for (DWARF_PubNamesUnit *unit = pubtypes->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
dwarf_stringize_pubnames(arena, &dump, unit, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// DEBUG NAMES
if (params->dump_debug_names){
if (names != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG NAMES:\n"));
U32 i = 0;
for (DWARF_NamesUnit *unit = names->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
dwarf_stringize_names(arena, &dump, unit, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// DEBUG ARANGES
if (params->dump_debug_aranges){
if (aranges != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG ARANGES:\n"));
U32 i = 0;
for (DWARF_ArangesUnit *unit = aranges->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
dwarf_stringize_aranges(arena, &dump, unit, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
// DEBUG ADDR
if (params->dump_debug_addr){
if (addr != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG ADDR:\n"));
U32 i = 0;
for (DWARF_AddrUnit *unit = addr->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
dwarf_stringize_addr(arena, &dump, unit, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
#if 0
// DEBUG ABBREV
if (params->dump_debug_abbrev){
if (abbrev != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG ABBREV:\n"));
U32 i = 0;
for (DWARF_AbbrevUnit *unit = abbrev->unit_first;
unit != 0;
unit = unit->next, i += 1){
U32 j = 0;
for (DWARF_AbbrevDecl *abbrev_decl = unit->first;
abbrev_decl != 0;
abbrev_decl = abbrev_decl->next, j += 1){
String8 tag_string = dwarf_string_from_tag(abbrev_decl->tag);
str8_list_pushf(arena, &dump, " unit[%u],abbrev[%u]:\n", i, j);
str8_list_pushf(arena, &dump, " code=%llu\n", abbrev_decl->abbrev_code);
str8_list_pushf(arena, &dump, " tag=%.*s\n", str8_varg(tag_string));
str8_list_pushf(arena, &dump, " has_children=%u\n", abbrev_decl->has_children);
str8_list_pushf(arena, &dump, " attrib_count=%u\n", abbrev_decl->attrib_count);
str8_list_pushf(arena, &dump, " attribs:\n", abbrev_decl->attrib_count);
U32 attrib_count = abbrev_decl->attrib_count;
DWARF_AbbrevAttribSpec *attrib_spec = abbrev_decl->attrib_specs;
for (U32 k = 0; k < attrib_count; k += 1, attrib_spec += 1){
String8 name_string = dwarf_string_from_attribute_name(attrib_spec->name);
String8 form_string = dwarf_string_from_attribute_form(attrib_spec->form);
str8_list_pushf(arena, &dump, " [%-14.*s %-10.*s]\n",
str8_varg(name_string), str8_varg(form_string));
}
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
}
#endif
#if 0
// DEBUG INFO
if (params->dump_debug_info){
if (info != 0){
str8_list_push(arena, &dump,
str8_lit("################################"
"################################\n"
"DEBUG INFO:\n"));
U32 i = 0;
for (DWARF_InfoUnit *unit = info->unit_first;
unit != 0;
unit = unit->next, i += 1){
str8_list_pushf(arena, &dump, " unit[%u]:\n", i);
str8_list_pushf(arena, &dump, " [header]\n");
str8_list_pushf(arena, &dump, " version=%u\n", unit->dwarf_version);
str8_list_pushf(arena, &dump, " offset_size=%u\n", unit->offset_size);
str8_list_pushf(arena, &dump, " address_size=%u\n", unit->address_size);
str8_list_pushf(arena, &dump, " [extracted attributes]\n");
str8_list_pushf(arena, &dump, " langauge=%u\n", (U32)unit->language);
str8_list_pushf(arena, &dump, " line_info_offset=%llu\n", unit->line_info_offset);
str8_list_pushf(arena, &dump, " vbase=0x%llx\n", unit->vbase);
str8_list_pushf(arena, &dump, " str_offsets_base=%llu\n", unit->str_offsets_base);
str8_list_pushf(arena, &dump, " addr_base=%llu\n", unit->addr_base);
str8_list_pushf(arena, &dump, " rnglists_base=%llu\n", unit->rnglists_base);
str8_list_pushf(arena, &dump, " loclists_base=%llu\n", unit->loclists_base);
dump_entry_tree(arena, &dump, dwarf, unit, unit->entry_root, 2);
str8_list_push(arena, &dump, str8_lit("\n"));
}
}
}
#endif
// print dump
for (String8Node *node = dump.first;
node != 0;
node = node->next){
fwrite(node->string.str, 1, node->string.size, stdout);
}
}
}