Decipher '.debug_info'
This commit is contained in:
		
							parent
							
								
									283e372235
								
							
						
					
					
						commit
						ba4c5e691c
					
				@ -145,7 +145,7 @@ fn void compile_c(const CompileOptions *const options, char** envp)
 | 
				
			|||||||
        memcpy(vb_add(args, array_length(static_options)), static_options, sizeof(static_options));
 | 
					        memcpy(vb_add(args, array_length(static_options)), static_options, sizeof(static_options));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *vb_add(args, 1) = "-DSILENT";
 | 
					    // *vb_add(args, 1) = "-DSILENT";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (options->compiler == clang)
 | 
					    if (options->compiler == clang)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										653
									
								
								bootstrap/main.c
									
									
									
									
									
								
							
							
						
						
									
										653
									
								
								bootstrap/main.c
									
									
									
									
									
								
							@ -1091,6 +1091,11 @@ typedef enum DwarfUnitType : u8
 | 
				
			|||||||
    DW_UT_hi_user = 0xff, 
 | 
					    DW_UT_hi_user = 0xff, 
 | 
				
			||||||
} DwarfUnitType;
 | 
					} DwarfUnitType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum DwarfLanguage : u16
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DW_LANG_C11 = 0x001d,
 | 
				
			||||||
 | 
					} DwarfLanguage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum DwarfOperation : u8
 | 
					typedef enum DwarfOperation : u8
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    DW_OP_addr = 0x03, // Operands: 1
 | 
					    DW_OP_addr = 0x03, // Operands: 1
 | 
				
			||||||
@ -1474,6 +1479,19 @@ STRUCT(DwarfAddressTableHeader)
 | 
				
			|||||||
    u8 segment_selector_size;
 | 
					    u8 segment_selector_size;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum DwarfType : u8
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DW_ATE_void = 0x00,
 | 
				
			||||||
 | 
					    DW_ATE_address = 0x01,
 | 
				
			||||||
 | 
					    DW_ATE_boolean = 0x02,
 | 
				
			||||||
 | 
					    DW_ATE_complex_float = 0x03,
 | 
				
			||||||
 | 
					    DW_ATE_float = 0x04,
 | 
				
			||||||
 | 
					    DW_ATE_signed = 0x05,
 | 
				
			||||||
 | 
					    DW_ATE_signed_char = 0x06,
 | 
				
			||||||
 | 
					    DW_ATE_unsigned = 0x07,
 | 
				
			||||||
 | 
					    DW_ATE_unsigned_char = 0x08,
 | 
				
			||||||
 | 
					} DwarfType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum TypeId : u32
 | 
					typedef enum TypeId : u32
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Simple types
 | 
					    // Simple types
 | 
				
			||||||
@ -7542,7 +7560,6 @@ fn Uleb128 uleb128_decode(String input)
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
fn void sleb128_encode(VirtualBuffer(u8)* buffer, s32 value)
 | 
					fn void sleb128_encode(VirtualBuffer(u8)* buffer, s32 value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto extra_bits = (u32)(value ^ (value >> 31)) >> 6;
 | 
					    auto extra_bits = (u32)(value ^ (value >> 31)) >> 6;
 | 
				
			||||||
@ -7570,6 +7587,275 @@ fn void uleb128_encode(VirtualBuffer(u8)* buffer, u32 value)
 | 
				
			|||||||
    *vb_add(buffer, 1) = out;
 | 
					    *vb_add(buffer, 1) = out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn void dwarf_playground(Thread* thread)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto file = file_read(thread->arena,
 | 
				
			||||||
 | 
					#ifdef __APPLE__
 | 
				
			||||||
 | 
					            strlit("/Users/david/minimal/main")
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					            strlit("/home/david/minimal/main")
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    auto* elf_header = (ELFHeader*)file.pointer;
 | 
				
			||||||
 | 
					    auto section_count = elf_header->section_header_count;
 | 
				
			||||||
 | 
					    auto section_header_offset = elf_header->section_header_offset;
 | 
				
			||||||
 | 
					    auto string_table_section_index = elf_header->section_header_string_table_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto debug_abbrev_section_index = -1;
 | 
				
			||||||
 | 
					    auto debug_info_section_index = -1;
 | 
				
			||||||
 | 
					    auto debug_addr_section_index = -1;
 | 
				
			||||||
 | 
					    auto debug_str_section_index = -1;
 | 
				
			||||||
 | 
					    auto debug_str_offsets_section_index = -1;
 | 
				
			||||||
 | 
					    auto rela_debug_str_offsets_section_index = -1;
 | 
				
			||||||
 | 
					    auto rela_debug_addr_section_index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto section_headers = (ELFSectionHeader*)(file.pointer + section_header_offset);
 | 
				
			||||||
 | 
					    auto* string_table_section_header = (ELFSectionHeader*)(file.pointer + section_header_offset) + string_table_section_index;
 | 
				
			||||||
 | 
					    auto string_table_offset = string_table_section_header->offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (u16 i = 0; i < section_count; i += 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto* section_header = section_headers + i;
 | 
				
			||||||
 | 
					        auto name_offset = string_table_offset + section_header->name_offset;
 | 
				
			||||||
 | 
					        auto* name = (char*)(file.pointer + name_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (strcmp(".debug_abbrev", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            debug_abbrev_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (strcmp(".debug_info", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            debug_info_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (strcmp(".debug_addr", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            debug_addr_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (strcmp(".debug_str", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            debug_str_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (strcmp(".debug_str_offsets", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            debug_str_offsets_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (strcmp(".rela.debug_addr", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            rela_debug_addr_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (strcmp(".rela.debug_str_offsets", name) == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            rela_debug_str_offsets_section_index = i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(debug_info_section_index != -1);
 | 
				
			||||||
 | 
					    assert(debug_abbrev_section_index != -1);
 | 
				
			||||||
 | 
					    assert(debug_addr_section_index != -1);
 | 
				
			||||||
 | 
					    assert(debug_str_section_index != -1);
 | 
				
			||||||
 | 
					    assert(debug_str_offsets_section_index != -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto* debug_abbrev_section_header = section_headers + debug_abbrev_section_index;
 | 
				
			||||||
 | 
					    auto* debug_info_section_header = section_headers + debug_info_section_index;
 | 
				
			||||||
 | 
					    auto* debug_addr_section_header = section_headers + debug_addr_section_index;
 | 
				
			||||||
 | 
					    auto* debug_str_section_header = section_headers + debug_str_section_index;
 | 
				
			||||||
 | 
					    auto* debug_str_offsets_section_header = section_headers + debug_str_offsets_section_index;
 | 
				
			||||||
 | 
					    auto* rela_debug_str_offsets_section_header = section_headers + rela_debug_str_offsets_section_index;
 | 
				
			||||||
 | 
					    auto* rela_debug_addr_section_header = section_headers + rela_debug_addr_section_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto* rela_debug_str_offsets = (ElfRelocation*)(file.pointer + rela_debug_str_offsets_section_header->offset);
 | 
				
			||||||
 | 
					    auto* rela_debug_addresses = (ElfRelocation*)(file.pointer + rela_debug_addr_section_header->offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto original_debug_info_bytes = (String) {
 | 
				
			||||||
 | 
					        .pointer = file.pointer + debug_info_section_header->offset,
 | 
				
			||||||
 | 
					        .length = debug_info_section_header->size,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    auto debug_info_bytes = original_debug_info_bytes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto* compile_unit_header = (DwarfCompilationUnit*)debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					    debug_info_bytes.pointer += sizeof(DwarfCompilationUnit);
 | 
				
			||||||
 | 
					    debug_info_bytes.length -= sizeof(DwarfCompilationUnit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto debug_abbrev_bytes = (String) {
 | 
				
			||||||
 | 
					        .pointer = file.pointer + debug_abbrev_section_header->offset,
 | 
				
			||||||
 | 
					        .length = debug_abbrev_section_header->size,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    auto* debug_addr_header = (DwarfAddressTableHeader*)(file.pointer + debug_addr_section_header->offset);
 | 
				
			||||||
 | 
					    assert(debug_addr_header->unit_length == debug_addr_section_header->size - sizeof(debug_addr_header->unit_length));
 | 
				
			||||||
 | 
					    assert(debug_addr_header->version == 5);
 | 
				
			||||||
 | 
					    assert(debug_addr_header->address_size == 8);
 | 
				
			||||||
 | 
					    auto* debug_addresses = (u64*)debug_addr_header + 1;
 | 
				
			||||||
 | 
					    auto* debug_str_offsets_header = (DwarfStringOffsetsTableHeader*)(file.pointer + debug_str_offsets_section_header->offset);
 | 
				
			||||||
 | 
					    assert(debug_str_offsets_header->unit_length == debug_str_offsets_section_header->size - sizeof(debug_str_offsets_header->unit_length));
 | 
				
			||||||
 | 
					    auto string_count = (debug_str_offsets_section_header->size - sizeof(DwarfStringOffsetsTableHeader)) / sizeof(u32);
 | 
				
			||||||
 | 
					    auto* string_index_offset_map = (u32*)(debug_str_offsets_header + 1);
 | 
				
			||||||
 | 
					    auto* string_table = file.pointer + debug_str_section_header->offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto debug_str_offset_base_guess = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto top = 0;
 | 
				
			||||||
 | 
					    while (debug_abbrev_bytes.length > 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto first = uleb128_decode(debug_abbrev_bytes);
 | 
				
			||||||
 | 
					        debug_abbrev_bytes.pointer += first.i;
 | 
				
			||||||
 | 
					        debug_abbrev_bytes.length -= first.i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (first.number != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto second = uleb128_decode(debug_abbrev_bytes);
 | 
				
			||||||
 | 
					            debug_abbrev_bytes.pointer += second.i;
 | 
				
			||||||
 | 
					            debug_abbrev_bytes.length -= second.i;
 | 
				
			||||||
 | 
					            auto children = debug_abbrev_bytes.pointer[0];
 | 
				
			||||||
 | 
					            debug_abbrev_bytes.pointer += 1;
 | 
				
			||||||
 | 
					            debug_abbrev_bytes.length -= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            auto di_abbrev_code = uleb128_decode(debug_info_bytes);
 | 
				
			||||||
 | 
					            debug_info_bytes.pointer += di_abbrev_code.i;
 | 
				
			||||||
 | 
					            debug_info_bytes.length -= di_abbrev_code.i;
 | 
				
			||||||
 | 
					            assert(di_abbrev_code.number == first.number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            print("======\nAbbreviation entry #{u64}: \"{s}\", (0x{u64:x})\n======\n", first.number, dwarf_tag_to_string((DwarfTag)second.number), second.number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while (1)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                auto first = uleb128_decode(debug_abbrev_bytes);
 | 
				
			||||||
 | 
					                debug_abbrev_bytes.pointer += first.i;
 | 
				
			||||||
 | 
					                debug_abbrev_bytes.length -= first.i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto second = uleb128_decode(debug_abbrev_bytes);
 | 
				
			||||||
 | 
					                debug_abbrev_bytes.pointer += second.i;
 | 
				
			||||||
 | 
					                debug_abbrev_bytes.length -= second.i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (first.number == 0 && second.number == 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto attribute = (DwarfAttribute)first.number;
 | 
				
			||||||
 | 
					                auto form = (DwarfForm)second.number;
 | 
				
			||||||
 | 
					                print("{u32}: Attribute: \"{s}\" (0x{u64:x}). Form: \"{s}\" (0x{u64:x})\n", (u32)(debug_info_bytes.pointer - original_debug_info_bytes.pointer), dwarf_attribute_to_string(attribute), (u64)attribute, dwarf_form_to_string(form), (u64)form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                switch (form)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // .debug_str_offsets
 | 
				
			||||||
 | 
					                    case DW_FORM_strx1:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto index = debug_info_bytes.pointer[0];
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += 1;
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if (rela_debug_str_offsets_section_index != -1)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                auto* relocation = &rela_debug_str_offsets[index];
 | 
				
			||||||
 | 
					                                auto offset = relocation->addend;
 | 
				
			||||||
 | 
					                                auto* c_string = &string_table[offset];
 | 
				
			||||||
 | 
					                                print("Index: {u32}. Offset: {u32}. String: \"{cstr}\"\n", (u32)index, offset, c_string);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_data1:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto data = *debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += 1;
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= 1;
 | 
				
			||||||
 | 
					                            print("Data1: 0x{u32:x}\n", (u32)data);
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_data2:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto data = *(u16*)debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += sizeof(u16);
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= sizeof(u16);
 | 
				
			||||||
 | 
					                            print("Data2: 0x{u32:x}\n", (u32)data);
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_data4:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto data = *(u32*)debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += sizeof(u32);
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= sizeof(u32);
 | 
				
			||||||
 | 
					                            print("Data4: 0x{u32:x}\n", data);
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_sec_offset:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto sec_offset = *(u32*)debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += sizeof(u32);
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= sizeof(u32);
 | 
				
			||||||
 | 
					                            print("Sec offset: 0x{u32:x}\n", sec_offset);
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_addrx:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto addrx = uleb128_decode(debug_info_bytes);
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += addrx.i;
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= addrx.i;
 | 
				
			||||||
 | 
					                            auto relocation_index = addrx.number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if (rela_debug_addr_section_index != -1)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                auto* relocation = &rela_debug_addresses[relocation_index];
 | 
				
			||||||
 | 
					                                auto index = relocation->addend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                switch (attribute)
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    case DW_AT_low_pc:
 | 
				
			||||||
 | 
					                                        {
 | 
				
			||||||
 | 
					                                            auto address = debug_addresses[index];
 | 
				
			||||||
 | 
					                                            print("Address: 0x{u64:x}\n", address);
 | 
				
			||||||
 | 
					                                        } break;
 | 
				
			||||||
 | 
					                                    default:
 | 
				
			||||||
 | 
					                                        todo();
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_exprloc:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto length = uleb128_decode(debug_info_bytes);
 | 
				
			||||||
 | 
					                            print("Length: {u64}\n", length.number);
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += length.i;
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= length.i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            switch (length.number)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                case 1:
 | 
				
			||||||
 | 
					                                    {
 | 
				
			||||||
 | 
					                                        switch (attribute)
 | 
				
			||||||
 | 
					                                        {
 | 
				
			||||||
 | 
					                                            case DW_AT_frame_base:
 | 
				
			||||||
 | 
					                                                {
 | 
				
			||||||
 | 
					                                                    auto b = *debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					                                                    debug_info_bytes.pointer += 1;
 | 
				
			||||||
 | 
					                                                    debug_info_bytes.length -= 1;
 | 
				
			||||||
 | 
					                                                    auto operation = (DwarfOperation)b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                                    print("Operation: {s}\n", dwarf_operation_to_string(operation));
 | 
				
			||||||
 | 
					                                                } break;
 | 
				
			||||||
 | 
					                                            default:
 | 
				
			||||||
 | 
					                                                todo();
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    } break;
 | 
				
			||||||
 | 
					                                default:
 | 
				
			||||||
 | 
					                                    todo();
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_flag_present:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            print("Flag present\n");
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    case DW_FORM_ref4:
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            auto ref4 = *(u32*)debug_info_bytes.pointer;
 | 
				
			||||||
 | 
					                            debug_info_bytes.pointer += sizeof(u32);
 | 
				
			||||||
 | 
					                            debug_info_bytes.length -= sizeof(u32);
 | 
				
			||||||
 | 
					                            print("Ref4: {u32:x}\n", ref4);
 | 
				
			||||||
 | 
					                        } break;
 | 
				
			||||||
 | 
					                    default:
 | 
				
			||||||
 | 
					                        todo();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(debug_abbrev_bytes.length == 0);
 | 
				
			||||||
 | 
					    assert(debug_info_bytes.length == 1);
 | 
				
			||||||
 | 
					    assert(*debug_info_bytes.pointer == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restrict options, char** envp)
 | 
					may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restrict options, char** envp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -9028,17 +9314,105 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        auto name = elf_get_section_name(builder, strlit(".debug_info"));
 | 
					        auto name = elf_get_section_name(builder, strlit(".debug_info"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        u8 data[] = {
 | 
					        // Compilation unit
 | 
				
			||||||
            0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1D, 0x00, 
 | 
					        // 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00,
 | 
				
			||||||
            0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 
 | 
					        DwarfCompilationUnit compilation_unit = {
 | 
				
			||||||
            0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x57, 0x03, 0x00, 0x01, 0x32, 0x00, 
 | 
					            .length = 0x33,
 | 
				
			||||||
            0x00, 0x00, 0x03, 0x04, 0x05, 0x04, 0x00, 
 | 
					            .version = 5,
 | 
				
			||||||
 | 
					            .type = DW_UT_compile,
 | 
				
			||||||
 | 
					            .address_size = 8,
 | 
				
			||||||
 | 
					            .debug_abbreviation_offset = 0,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        *vb_add_struct(&builder->file, typeof(compilation_unit)) = compilation_unit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto size = sizeof(data);
 | 
					        // COMPILATION UNIT
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            u32 abbrev_code = 1;
 | 
				
			||||||
 | 
					            uleb128_encode(&builder->file, abbrev_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        memcpy(vb_add(&builder->file, size), data, size);
 | 
					            // producer: strx1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // language: data2
 | 
				
			||||||
 | 
					            *(u16*)vb_add(&builder->file, sizeof(u16)) = DW_LANG_C11;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // name: strx1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // str_offsets_base: sec_offset
 | 
				
			||||||
 | 
					            *(u32*)vb_add(&builder->file, sizeof(u32)) = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // stmt_list: sec_offset
 | 
				
			||||||
 | 
					            *(u32*)vb_add(&builder->file, sizeof(u32)) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // comp_dir: strx1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // low_pc: addrx
 | 
				
			||||||
 | 
					            uleb128_encode(&builder->file, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // high_pc: data4
 | 
				
			||||||
 | 
					            *(u32*)vb_add(&builder->file, sizeof(u32)) = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // addr_base: sec_offset
 | 
				
			||||||
 | 
					            *(u32*)vb_add(&builder->file, sizeof(u32)) = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // end compilation unit attribute list
 | 
				
			||||||
 | 
					            // *(u32*)vb_add(&builder->file, sizeof(u32)) = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // SUBPROGRAM (main)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            u32 abbrev_code = 2;
 | 
				
			||||||
 | 
					            uleb128_encode(&builder->file, abbrev_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // low_pc: addrx
 | 
				
			||||||
 | 
					            uleb128_encode(&builder->file, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // high_pc: data4
 | 
				
			||||||
 | 
					            *(u32*)vb_add(&builder->file, sizeof(u32)) = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // frame_base: exprloc
 | 
				
			||||||
 | 
					            uleb128_encode(&builder->file, 1);
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = DW_OP_reg7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // call_all_calls: flag_present
 | 
				
			||||||
 | 
					            // not present in the debug_info section
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // name: strx1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 3;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // file: data1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 0;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // line: data1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // type: ref4
 | 
				
			||||||
 | 
					            *(u32*)vb_add(&builder->file, sizeof(u32)) = 0x32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // external: flag_present
 | 
				
			||||||
 | 
					            // not present in the debug_info section
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // base_type (s32)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            u32 abbrev_code = 3;
 | 
				
			||||||
 | 
					            uleb128_encode(&builder->file, abbrev_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // name: strx1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // encoding: data1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = DW_ATE_signed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // byte_size: data1
 | 
				
			||||||
 | 
					            *vb_add(&builder->file, 1) = 4;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *vb_add(&builder->file, 1) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto size = builder->file.length - offset;
 | 
				
			||||||
        *section_header = (ELFSectionHeader) {
 | 
					        *section_header = (ELFSectionHeader) {
 | 
				
			||||||
            .name_offset = name,
 | 
					            .name_offset = name,
 | 
				
			||||||
            .type = ELF_SECTION_PROGRAM,
 | 
					            .type = ELF_SECTION_PROGRAM,
 | 
				
			||||||
@ -9372,7 +9746,7 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr
 | 
				
			|||||||
                .name_offset = fini_string,
 | 
					                .name_offset = fini_string,
 | 
				
			||||||
                .type = ELF_SYMBOL_TYPE_FUNCTION,
 | 
					                .type = ELF_SYMBOL_TYPE_FUNCTION,
 | 
				
			||||||
                .binding = ELF_SYMBOL_BINDING_GLOBAL,
 | 
					                .binding = ELF_SYMBOL_BINDING_GLOBAL,
 | 
				
			||||||
                .visibility = ELF_SYMBOL_VISIBILITY_HIDDEN, // TODO: investigate this other field
 | 
					                .visibility = ELF_SYMBOL_VISIBILITY_HIDDEN,
 | 
				
			||||||
                .section_index = fini_section_index,
 | 
					                .section_index = fini_section_index,
 | 
				
			||||||
                .value = fini_offset,
 | 
					                .value = fini_offset,
 | 
				
			||||||
                .size = 0,
 | 
					                .size = 0,
 | 
				
			||||||
@ -13020,268 +13394,7 @@ fn void print_ir(Thread* restrict thread)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn void dwarf_playground(Thread* thread)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    auto file = file_read(thread->arena,
 | 
					 | 
				
			||||||
#ifdef __APPLE__
 | 
					 | 
				
			||||||
            strlit("/Users/david/dwarf/main.o")
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
            strlit("/home/david/dwarf/main.o")
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    auto* elf_header = (ELFHeader*)file.pointer;
 | 
					 | 
				
			||||||
    auto section_count = elf_header->section_header_count;
 | 
					 | 
				
			||||||
    auto section_header_offset = elf_header->section_header_offset;
 | 
					 | 
				
			||||||
    auto string_table_section_index = elf_header->section_header_string_table_index;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto debug_abbrev_section_index = -1;
 | 
					 | 
				
			||||||
    auto debug_info_section_index = -1;
 | 
					 | 
				
			||||||
    auto debug_addr_section_index = -1;
 | 
					 | 
				
			||||||
    auto debug_str_section_index = -1;
 | 
					 | 
				
			||||||
    auto debug_str_offsets_section_index = -1;
 | 
					 | 
				
			||||||
    auto rela_debug_str_offsets_section_index = -1;
 | 
					 | 
				
			||||||
    auto rela_debug_addr_section_index = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto section_headers = (ELFSectionHeader*)(file.pointer + section_header_offset);
 | 
					 | 
				
			||||||
    auto* string_table_section_header = (ELFSectionHeader*)(file.pointer + section_header_offset) + string_table_section_index;
 | 
					 | 
				
			||||||
    auto string_table_offset = string_table_section_header->offset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (u16 i = 0; i < section_count; i += 1)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        auto* section_header = section_headers + i;
 | 
					 | 
				
			||||||
        auto name_offset = string_table_offset + section_header->name_offset;
 | 
					 | 
				
			||||||
        auto* name = file.pointer + name_offset;
 | 
					 | 
				
			||||||
        print("Section #{u32}\t\"{cstr}\". Size: {u64}\n", i, name, section_header->size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (strcmp(".debug_abbrev", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            debug_abbrev_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (strcmp(".debug_info", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            debug_info_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (strcmp(".debug_addr", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            debug_addr_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (strcmp(".debug_str", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            debug_str_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (strcmp(".debug_str_offsets", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            debug_str_offsets_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (strcmp(".rela.debug_addr", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            rela_debug_addr_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (strcmp(".rela.debug_str_offsets", (char*)name) == 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            rela_debug_str_offsets_section_index = i;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert(debug_info_section_index != -1);
 | 
					 | 
				
			||||||
    assert(debug_abbrev_section_index != -1);
 | 
					 | 
				
			||||||
    assert(debug_addr_section_index != -1);
 | 
					 | 
				
			||||||
    assert(debug_str_section_index != -1);
 | 
					 | 
				
			||||||
    assert(debug_str_offsets_section_index != -1);
 | 
					 | 
				
			||||||
    assert(rela_debug_addr_section_index != -1);
 | 
					 | 
				
			||||||
    assert(rela_debug_str_offsets_section_index != -1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto* debug_abbrev_section_header = section_headers + debug_abbrev_section_index;
 | 
					 | 
				
			||||||
    auto* debug_info_section_header = section_headers + debug_info_section_index;
 | 
					 | 
				
			||||||
    auto* debug_addr_section_header = section_headers + debug_addr_section_index;
 | 
					 | 
				
			||||||
    auto* debug_str_section_header = section_headers + debug_str_section_index;
 | 
					 | 
				
			||||||
    auto* debug_str_offsets_section_header = section_headers + debug_str_offsets_section_index;
 | 
					 | 
				
			||||||
    auto* rela_debug_str_offsets_section_header = section_headers + rela_debug_str_offsets_section_index;
 | 
					 | 
				
			||||||
    auto* rela_debug_addr_section_header = section_headers + rela_debug_addr_section_index;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto* rela_debug_str_offsets = (ElfRelocation*)(file.pointer + rela_debug_str_offsets_section_header->offset);
 | 
					 | 
				
			||||||
    auto* rela_debug_addresses = (ElfRelocation*)(file.pointer + rela_debug_addr_section_header->offset);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto debug_info_bytes = (String) {
 | 
					 | 
				
			||||||
        .pointer = file.pointer + debug_info_section_header->offset,
 | 
					 | 
				
			||||||
        .length = debug_info_section_header->size,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto* compile_unit_header = (DwarfCompilationUnit*)debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
    debug_info_bytes.pointer += sizeof(DwarfCompilationUnit);
 | 
					 | 
				
			||||||
    debug_info_bytes.length -= sizeof(DwarfCompilationUnit);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto debug_abbrev_bytes = (String) {
 | 
					 | 
				
			||||||
        .pointer = file.pointer + debug_abbrev_section_header->offset,
 | 
					 | 
				
			||||||
        .length = debug_abbrev_section_header->size,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    auto* debug_addr_header = (DwarfAddressTableHeader*)(file.pointer + debug_addr_section_header->offset);
 | 
					 | 
				
			||||||
    assert(debug_addr_header->unit_length == debug_addr_section_header->size - sizeof(debug_addr_header->unit_length));
 | 
					 | 
				
			||||||
    assert(debug_addr_header->version == 5);
 | 
					 | 
				
			||||||
    assert(debug_addr_header->address_size == 8);
 | 
					 | 
				
			||||||
    auto* debug_addresses = (u64*)debug_addr_header + 1;
 | 
					 | 
				
			||||||
    auto* debug_str_offsets_header = (DwarfStringOffsetsTableHeader*)(file.pointer + debug_str_offsets_section_header->offset);
 | 
					 | 
				
			||||||
    assert(debug_str_offsets_header->unit_length == debug_str_offsets_section_header->size - sizeof(debug_str_offsets_header->unit_length));
 | 
					 | 
				
			||||||
    auto string_count = (debug_str_offsets_section_header->size - sizeof(DwarfStringOffsetsTableHeader)) / sizeof(u32);
 | 
					 | 
				
			||||||
    auto* string_index_offset_map = (u32*)(debug_str_offsets_header + 1);
 | 
					 | 
				
			||||||
    auto* string_table = file.pointer + debug_str_section_header->offset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto debug_str_offset_base_guess = 8;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto top = 0;
 | 
					 | 
				
			||||||
    while (debug_abbrev_bytes.length > 0)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        auto first = uleb128_decode(debug_abbrev_bytes);
 | 
					 | 
				
			||||||
        debug_abbrev_bytes.pointer += first.i;
 | 
					 | 
				
			||||||
        debug_abbrev_bytes.length -= first.i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (first.number != 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            auto second = uleb128_decode(debug_abbrev_bytes);
 | 
					 | 
				
			||||||
            debug_abbrev_bytes.pointer += second.i;
 | 
					 | 
				
			||||||
            debug_abbrev_bytes.length -= second.i;
 | 
					 | 
				
			||||||
            auto children = debug_abbrev_bytes.pointer[0];
 | 
					 | 
				
			||||||
            debug_abbrev_bytes.pointer += 1;
 | 
					 | 
				
			||||||
            debug_abbrev_bytes.length -= 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            auto di_abbrev_code = uleb128_decode(debug_info_bytes);
 | 
					 | 
				
			||||||
            debug_info_bytes.pointer += di_abbrev_code.i;
 | 
					 | 
				
			||||||
            debug_info_bytes.length -= di_abbrev_code.i;
 | 
					 | 
				
			||||||
            assert(di_abbrev_code.number == first.number);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            print("Abbreviation entry #{u64}: \"{s}\", (0x{u64:x})\n", first.number, dwarf_tag_to_string((DwarfTag)second.number), second.number);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            while (1)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                auto first = uleb128_decode(debug_abbrev_bytes);
 | 
					 | 
				
			||||||
                debug_abbrev_bytes.pointer += first.i;
 | 
					 | 
				
			||||||
                debug_abbrev_bytes.length -= first.i;
 | 
					 | 
				
			||||||
                auto second = uleb128_decode(debug_abbrev_bytes);
 | 
					 | 
				
			||||||
                debug_abbrev_bytes.pointer += second.i;
 | 
					 | 
				
			||||||
                debug_abbrev_bytes.length -= second.i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (first.number == 0 && second.number == 0)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                auto attribute = (DwarfAttribute)first.number;
 | 
					 | 
				
			||||||
                auto form = (DwarfForm)second.number;
 | 
					 | 
				
			||||||
                print("Attribute: \"{s}\" (0x{u64:x}). Form: \"{s}\" (0x{u64:x})\n", dwarf_attribute_to_string(attribute), (u64)attribute, dwarf_form_to_string(form), (u64)form);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                switch (form)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // .debug_str_offsets
 | 
					 | 
				
			||||||
                    case DW_FORM_strx1:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto index = debug_info_bytes.pointer[0];
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += 1;
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= 1;
 | 
					 | 
				
			||||||
                            auto* relocation = &rela_debug_str_offsets[index];
 | 
					 | 
				
			||||||
                            auto offset = relocation->addend;
 | 
					 | 
				
			||||||
                            auto* c_string = &string_table[offset];
 | 
					 | 
				
			||||||
                            print("Index: {u32}. Offset: {u32}. String: \"{cstr}\"\n", (u32)index, offset, c_string);
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_data1:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto data = *debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += 1;
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= 1;
 | 
					 | 
				
			||||||
                            print("Data1: 0x{u32:x}\n", (u32)data);
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_data2:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto data = *(u16*)debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += sizeof(u16);
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= sizeof(u16);
 | 
					 | 
				
			||||||
                            print("Data2: 0x{u32:x}\n", (u32)data);
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_data4:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto data = *(u32*)debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += sizeof(u32);
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= sizeof(u32);
 | 
					 | 
				
			||||||
                            print("Data4: 0x{u32:x}\n", data);
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_sec_offset:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto sec_offset = *(u32*)debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += sizeof(u32);
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= sizeof(u32);
 | 
					 | 
				
			||||||
                            print("Sec offset: 0x{u32:x}\n", sec_offset);
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_addrx:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto addrx = uleb128_decode(debug_info_bytes);
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += addrx.i;
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= addrx.i;
 | 
					 | 
				
			||||||
                            auto relocation_index = addrx.number;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            auto* relocation = &rela_debug_addresses[relocation_index];
 | 
					 | 
				
			||||||
                            auto index = relocation->addend;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            switch (attribute)
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                case DW_AT_low_pc:
 | 
					 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                        auto address = debug_addresses[index];
 | 
					 | 
				
			||||||
                                        print("Address: 0x{u64:x}\n", address);
 | 
					 | 
				
			||||||
                                    } break;
 | 
					 | 
				
			||||||
                                default:
 | 
					 | 
				
			||||||
                                    todo();
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_exprloc:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto length = uleb128_decode(debug_info_bytes);
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += length.i;
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= length.i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            switch (length.number)
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                case 1:
 | 
					 | 
				
			||||||
                                    {
 | 
					 | 
				
			||||||
                                        switch (attribute)
 | 
					 | 
				
			||||||
                                        {
 | 
					 | 
				
			||||||
                                            case DW_AT_frame_base:
 | 
					 | 
				
			||||||
                                                {
 | 
					 | 
				
			||||||
                                                    auto b = *debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
                                                    debug_info_bytes.pointer += 1;
 | 
					 | 
				
			||||||
                                                    debug_info_bytes.length -= 1;
 | 
					 | 
				
			||||||
                                                    auto operation = (DwarfOperation)b;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                                    print("Operation: {s}\n", dwarf_operation_to_string(operation));
 | 
					 | 
				
			||||||
                                                } break;
 | 
					 | 
				
			||||||
                                            default:
 | 
					 | 
				
			||||||
                                                todo();
 | 
					 | 
				
			||||||
                                        }
 | 
					 | 
				
			||||||
                                    } break;
 | 
					 | 
				
			||||||
                                default:
 | 
					 | 
				
			||||||
                                    todo();
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_flag_present:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            print("Flag present\n");
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    case DW_FORM_ref4:
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            auto ref4 = *(u32*)debug_info_bytes.pointer;
 | 
					 | 
				
			||||||
                            debug_info_bytes.pointer += sizeof(u32);
 | 
					 | 
				
			||||||
                            debug_info_bytes.length -= sizeof(u32);
 | 
					 | 
				
			||||||
                            print("Ref4: {u32:x}\n", ref4);
 | 
					 | 
				
			||||||
                        } break;
 | 
					 | 
				
			||||||
                    default:
 | 
					 | 
				
			||||||
                        todo();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assert(debug_abbrev_bytes.length == 0);
 | 
					 | 
				
			||||||
    assert(debug_info_bytes.length == 1);
 | 
					 | 
				
			||||||
    assert(*debug_info_bytes.pointer == 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn void entry_point(int argc, char* argv[], char* envp[])
 | 
					fn void entry_point(int argc, char* argv[], char* envp[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user