diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -254,21 +254,15 @@ /// \param[in] abi /// An optional ABI plug-in that can be used to resolve register /// names. - void DumpLocation(Stream *s, lldb::offset_t offset, lldb::offset_t length, + void DumpLocation(Stream *s, const DataExtractor &data, lldb::DescriptionLevel level, ABI *abi) const; - bool GetLocation(lldb::addr_t func_load_addr, lldb::addr_t pc, - lldb::offset_t &offset, lldb::offset_t &len); + void RelocateLowHighPC(lldb::addr_t load_function_start, lldb::addr_t &low_pc, + lldb::addr_t &high_pc) const; - static bool AddressRangeForLocationListEntry( - const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data, - lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc); - - bool GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset, - lldb::offset_t &end_offset); - - void RelocateLowHighPC(lldb::addr_t base_address, lldb::addr_t func_load_addr, - lldb::addr_t &low_pc, lldb::addr_t &high_pc) const; + llvm::Optional + GetLocationExpression(lldb::addr_t load_function_start, + lldb::addr_t addr) const; /// Module which defined this expression. lldb::ModuleWP m_module_wp; diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -53,6 +53,25 @@ .GetMaxU64(&offset, index_size); } +static std::unique_ptr +GetLocationTable(DWARFExpression::LocationListFormat format, const DataExtractor &data) { + llvm::DWARFDataExtractor llvm_data( + toStringRef(data.GetData()), + data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize()); + + switch (format) { + case DWARFExpression::NonLocationList: + return nullptr; + case DWARFExpression::RegularLocationList: + return std::make_unique(llvm_data); + case DWARFExpression::SplitDwarfLocationList: + case DWARFExpression::LocLists: + return std::make_unique( + llvm_data, format == DWARFExpression::LocLists ? 5 : 4); + } + llvm_unreachable("Fully covered switch!"); +} + // DWARFExpression constructor DWARFExpression::DWARFExpression() : m_module_wp(), m_data(), m_dwarf_cu(nullptr), @@ -84,12 +103,11 @@ m_data.SetAddressByteSize(addr_byte_size); } -void DWARFExpression::DumpLocation(Stream *s, lldb::offset_t offset, - lldb::offset_t length, +void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data, lldb::DescriptionLevel level, ABI *abi) const { - llvm::DWARFExpression(DataExtractor(m_data, offset, length).GetAsLLVM(), - llvm::dwarf::DWARF_VERSION, m_data.GetAddressByteSize()) + llvm::DWARFExpression(data.GetAsLLVM(), llvm::dwarf::DWARF_VERSION, + data.GetAddressByteSize()) .print(s->AsRawOstream(), abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr); } @@ -109,53 +127,45 @@ return bool(m_loclist_addresses); } +namespace { +class DummyDWARFObject final: public llvm::DWARFObject { +public: + DummyDWARFObject(bool IsLittleEndian) : IsLittleEndian(IsLittleEndian) {} + + bool isLittleEndian() const override { return IsLittleEndian; } + + llvm::Optional find(const llvm::DWARFSection &Sec, + uint64_t Pos) const override { + return llvm::None; + } +private: + bool IsLittleEndian; +}; +} + void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level, addr_t location_list_base_addr, ABI *abi) const { if (IsLocationList()) { // We have a location list lldb::offset_t offset = 0; - uint32_t count = 0; - addr_t curr_base_addr = location_list_base_addr; - while (m_data.ValidOffset(offset)) { - addr_t begin_addr_offset = LLDB_INVALID_ADDRESS; - addr_t end_addr_offset = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, - begin_addr_offset, end_addr_offset)) - break; - - if (begin_addr_offset == 0 && end_addr_offset == 0) - break; - - if (begin_addr_offset < end_addr_offset) { - if (count > 0) - s->PutCString(", "); - VMRange addr_range(curr_base_addr + begin_addr_offset, - curr_base_addr + end_addr_offset); - addr_range.Dump(s, 0, 8); - s->PutChar('{'); - lldb::offset_t location_length = m_data.GetU16(&offset); - DumpLocation(s, offset, location_length, level, abi); - s->PutChar('}'); - offset += location_length; - } else { - if ((m_data.GetAddressByteSize() == 4 && - (begin_addr_offset == UINT32_MAX)) || - (m_data.GetAddressByteSize() == 8 && - (begin_addr_offset == UINT64_MAX))) { - curr_base_addr = end_addr_offset + location_list_base_addr; - // We have a new base address - if (count > 0) - s->PutCString(", "); - s->Format("base_addr = {0:x}", end_addr_offset); - } - } - - count++; - } + std::unique_ptr loctable_up = GetLocationTable( + m_dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(), m_data); + if (!loctable_up) + return; + + llvm::MCRegisterInfo *MRI = nullptr; + if (abi) + MRI = &abi->GetMCRegisterInfo(); + + loctable_up->dumpLocationList( + &offset, s->AsRawOstream(), + llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, MRI, + DummyDWARFObject(m_data.GetByteOrder() == eByteOrderLittle), nullptr, + llvm::DIDumpOptions(), s->GetIndentLevel() + 2); } else { // We have a normal location that contains DW_OP location opcodes - DumpLocation(s, 0, m_data.GetByteSize(), level, abi); + DumpLocation(s, m_data, level, abi); } } @@ -623,88 +633,21 @@ if (!IsLocationList()) return false; - lldb::offset_t offset = 0; - lldb::addr_t base_address = m_loclist_addresses->cu_file_addr; - while (m_data.ValidOffset(offset)) { - // We need to figure out what the value is for the location. - addr_t lo_pc = LLDB_INVALID_ADDRESS; - addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, - hi_pc)) - break; - - if (lo_pc == 0 && hi_pc == 0) - break; - - if ((m_data.GetAddressByteSize() == 4 && (lo_pc == UINT32_MAX)) || - (m_data.GetAddressByteSize() == 8 && (lo_pc == UINT64_MAX))) { - base_address = hi_pc; - continue; - } - RelocateLowHighPC(base_address, func_load_addr, lo_pc, hi_pc); - - if (lo_pc <= addr && addr < hi_pc) - return true; - - offset += m_data.GetU16(&offset); - } - return false; -} - -bool DWARFExpression::GetLocation(addr_t func_load_addr, addr_t pc, - lldb::offset_t &offset, - lldb::offset_t &length) { - offset = 0; - if (!IsLocationList()) { - length = m_data.GetByteSize(); - return true; - } - - if (func_load_addr != LLDB_INVALID_ADDRESS && pc != LLDB_INVALID_ADDRESS) { - addr_t base_address = m_loclist_addresses->cu_file_addr; - while (m_data.ValidOffset(offset)) { - // We need to figure out what the value is for the location. - addr_t lo_pc = LLDB_INVALID_ADDRESS; - addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, - hi_pc)) - break; - - if (lo_pc == 0 && hi_pc == 0) - break; - - if ((m_data.GetAddressByteSize() == 4 && (lo_pc == UINT32_MAX)) || - (m_data.GetAddressByteSize() == 8 && (lo_pc == UINT64_MAX))) { - base_address = hi_pc; - continue; - } - - RelocateLowHighPC(base_address, func_load_addr, lo_pc, hi_pc); - length = m_data.GetU16(&offset); - - if (length > 0 && lo_pc <= pc && pc < hi_pc) - return true; - - offset += length; - } - } - offset = LLDB_INVALID_OFFSET; - length = 0; - return false; + return bool(GetLocationExpression(func_load_addr, addr)); } bool DWARFExpression::DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level, addr_t func_load_addr, addr_t address, ABI *abi) { - lldb::offset_t offset = 0; - lldb::offset_t length = 0; - - if (GetLocation(func_load_addr, address, offset, length)) { - if (length > 0) { - DumpLocation(s, offset, length, level, abi); - return true; - } + if (!IsLocationList()) { + DumpLocation(s, m_data, level, abi); + return true; + } + if (llvm::Optional expr = + GetLocationExpression(func_load_addr, address)) { + DumpLocation(s, *expr, level, abi); + return true; } return false; } @@ -938,7 +881,6 @@ ModuleSP module_sp = m_module_wp.lock(); if (IsLocationList()) { - lldb::offset_t offset = 0; addr_t pc; StackFrame *frame = nullptr; if (reg_ctx) @@ -960,36 +902,11 @@ return false; } - addr_t base_address = m_loclist_addresses->cu_file_addr; - while (m_data.ValidOffset(offset)) { - // We need to figure out what the value is for the location. - addr_t lo_pc = LLDB_INVALID_ADDRESS; - addr_t hi_pc = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, - lo_pc, hi_pc)) - break; - - if (lo_pc == 0 && hi_pc == 0) - break; - - if ((m_data.GetAddressByteSize() == 4 && - (lo_pc == UINT32_MAX)) || - (m_data.GetAddressByteSize() == 8 && - (lo_pc == UINT64_MAX))) { - base_address = hi_pc; - continue; - } - - RelocateLowHighPC(base_address, func_load_addr, lo_pc, hi_pc); - uint16_t length = m_data.GetU16(&offset); - - if (length > 0 && lo_pc <= pc && pc < hi_pc) { - return DWARFExpression::Evaluate( - exe_ctx, reg_ctx, module_sp, - DataExtractor(m_data, offset, length), m_dwarf_cu, m_reg_kind, - initial_value_ptr, object_address_ptr, result, error_ptr); - } - offset += length; + if (llvm::Optional expr = + GetLocationExpression(func_load_addr, pc)) { + return DWARFExpression::Evaluate( + exe_ctx, reg_ctx, module_sp, *expr, m_dwarf_cu, m_reg_kind, + initial_value_ptr, object_address_ptr, result, error_ptr); } } if (error_ptr) @@ -2648,62 +2565,6 @@ return true; // Return true on success } -bool DWARFExpression::AddressRangeForLocationListEntry( - const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data, - lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) { - if (!debug_loc_data.ValidOffset(*offset_ptr)) - return false; - - DWARFExpression::LocationListFormat format = - dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(); - switch (format) { - case NonLocationList: - return false; - case RegularLocationList: - low_pc = debug_loc_data.GetAddress(offset_ptr); - high_pc = debug_loc_data.GetAddress(offset_ptr); - return true; - case SplitDwarfLocationList: - case LocLists: - switch (debug_loc_data.GetU8(offset_ptr)) { - case DW_LLE_end_of_list: - return false; - case DW_LLE_startx_endx: { - uint64_t index = debug_loc_data.GetULEB128(offset_ptr); - low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); - index = debug_loc_data.GetULEB128(offset_ptr); - high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); - return true; - } - case DW_LLE_startx_length: { - uint64_t index = debug_loc_data.GetULEB128(offset_ptr); - low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); - uint64_t length = (format == LocLists) - ? debug_loc_data.GetULEB128(offset_ptr) - : debug_loc_data.GetU32(offset_ptr); - high_pc = low_pc + length; - return true; - } - case DW_LLE_start_length: { - low_pc = debug_loc_data.GetAddress(offset_ptr); - high_pc = low_pc + debug_loc_data.GetULEB128(offset_ptr); - return true; - } - case DW_LLE_start_end: { - low_pc = debug_loc_data.GetAddress(offset_ptr); - high_pc = debug_loc_data.GetAddress(offset_ptr); - return true; - } - default: - // Not supported entry type - lldbassert(false && "Not supported location list type"); - return false; - } - } - assert(false && "Not supported location list type"); - return false; -} - static bool print_dwarf_exp_op(Stream &s, const DataExtractor &data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size) { @@ -2932,70 +2793,89 @@ } } -bool DWARFExpression::GetOpAndEndOffsets(StackFrame &frame, - lldb::offset_t &op_offset, - lldb::offset_t &end_offset) { - SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); - if (!sc.function) { - return false; - } - - addr_t loclist_base_file_addr = - sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) { - return false; - } - - addr_t pc_file_addr = frame.GetFrameCodeAddress().GetFileAddress(); - lldb::offset_t opcodes_offset, opcodes_length; - if (!GetLocation(loclist_base_file_addr, pc_file_addr, opcodes_offset, - opcodes_length)) { - return false; - } - - if (opcodes_length == 0) { - return false; - } +void DWARFExpression::RelocateLowHighPC(addr_t func_load_addr, addr_t &low_pc, + addr_t &high_pc) const { + // This relocates low_pc and high_pc by adding the difference between the + // function file address, and the actual address it is loaded in memory. + addr_t slide = func_load_addr - m_loclist_addresses->func_file_addr; + low_pc += slide; + high_pc += slide; +} - op_offset = opcodes_offset; - end_offset = opcodes_offset + opcodes_length; - return true; +static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc, + ByteOrder byte_order, uint32_t addr_size) { + auto buffer_sp = + std::make_shared(loc.Expr.data(), loc.Expr.size()); + return DataExtractor(buffer_sp, byte_order, addr_size); } -void DWARFExpression::RelocateLowHighPC(addr_t base_address, - addr_t func_load_addr, addr_t &low_pc, - addr_t &high_pc) const { - // How this works: - // base_address is the current base address, as known in the file. low_pc and - // high_pc are relative to that. First, we relocate the base address by - // applying the load bias (the difference between an address in the file and - // the actual address in memory). Then we relocate low_pc and high_pc based on - // that. - base_address += func_load_addr - m_loclist_addresses->func_file_addr; - low_pc += base_address; - high_pc += base_address; +llvm::Optional +DWARFExpression::GetLocationExpression(addr_t load_function_start, + addr_t addr) const { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); + + std::unique_ptr loctable_up = GetLocationTable( + m_dwarf_cu->GetSymbolFileDWARF().GetLocationListFormat(), m_data); + if (!loctable_up) + return llvm::None; + llvm::Optional result; + uint64_t offset = 0; + auto lookup_addr = [&](uint32_t index) { + return llvm::object::SectionedAddress{ + ReadAddressFromDebugAddrSection(m_dwarf_cu, index)}; + }; + auto process_list = [&](llvm::Expected loc) { + if (!loc) + LLDB_LOG_ERROR(log, loc.takeError(), "{0}"); + if (loc->Range) { + RelocateLowHighPC(load_function_start, loc->Range->LowPC, + loc->Range->HighPC); + if (loc->Range->LowPC <= addr && addr < loc->Range->HighPC) + result = ToDataExtractor(*loc, m_data.GetByteOrder(), + m_data.GetAddressByteSize()); + } + return !result; + }; + llvm::Error E = loctable_up->visitAbsoluteLocationList( + offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, + lookup_addr, process_list); + if (E) + LLDB_LOG_ERROR(log, std::move(E), "{0}"); + return result; } bool DWARFExpression::MatchesOperand(StackFrame &frame, const Instruction::Operand &operand) { using namespace OperandMatchers; - lldb::offset_t op_offset; - lldb::offset_t end_offset; - if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) { - return false; - } - - if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) { - return false; - } - RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); if (!reg_ctx_sp) { return false; } - DataExtractor opcodes = m_data; + DataExtractor opcodes; + if (IsLocationList()) { + SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); + if (!sc.function) + return false; + + addr_t load_function_start = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (load_function_start == LLDB_INVALID_ADDRESS) + return false; + + addr_t pc = frame.GetFrameCodeAddress().GetLoadAddress( + frame.CalculateTarget().get()); + + if (llvm::Optional expr = GetLocationExpression(load_function_start, pc)) + opcodes = std::move(*expr); + else + return false; + } else + opcodes = m_data; + + + lldb::offset_t op_offset = 0; uint8_t opcode = opcodes.GetU8(&op_offset); if (opcode == DW_OP_fbreg) { diff --git a/lldb/test/Shell/SymbolFile/DWARF/debug_loc.s b/lldb/test/Shell/SymbolFile/DWARF/debug_loc.s --- a/lldb/test/Shell/SymbolFile/DWARF/debug_loc.s +++ b/lldb/test/Shell/SymbolFile/DWARF/debug_loc.s @@ -1,24 +1,80 @@ -# Test debug_loc parsing, including the cases of invalid input. The exact +# Test location list handling, including the cases of invalid input. The exact # behavior in the invalid cases is not particularly important, but it should be # "reasonable". # REQUIRES: x86 -# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t -# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" -o exit \ -# RUN: | FileCheck %s +# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s --defsym LOC=0 > %t +# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \ +# RUN: -o "image dump symfile" -o exit | FileCheck %s + +# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s --defsym LOCLISTS=0 > %t +# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" \ +# RUN: -o "image dump symfile" -o exit | FileCheck %s # CHECK-LABEL: image lookup -v -a 0 # CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg5 RDI, # CHECK: Variable: {{.*}}, name = "x1", type = "int", location = , -# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = , # CHECK-LABEL: image lookup -v -a 2 # CHECK: Variable: {{.*}}, name = "x0", type = "int", location = DW_OP_reg0 RAX, # CHECK: Variable: {{.*}}, name = "x1", type = "int", location = , -# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = , # CHECK: Variable: {{.*}}, name = "x3", type = "int", location = DW_OP_reg1 RDX, +# CHECK-LABEL: image dump symfile +# CHECK: CompileUnit{0x00000000} +# CHECK: Function{ +# CHECK: Variable{{.*}}, name = "x0", {{.*}}, scope = parameter, location = +# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg5 RDI +# CHECK-NEXT: [0x0000000000000001, 0x0000000000000006): DW_OP_reg0 RAX +# CHECK: Variable{{.*}}, name = "x1", {{.*}}, scope = parameter +# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter, location = +# CHECK-NEXT: error: unexpected end of data +# CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location = +# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX + +.ifdef LOC +.macro OFFSET_PAIR lo hi + .quad \lo + .quad \hi +.endm + +.macro BASE_ADDRESS base + .quad -1 + .quad \base +.endm + +.macro EXPR_SIZE sz + .short \sz +.endm + +.macro END_OF_LIST + .quad 0 + .quad 0 +.endm +.endif + +.ifdef LOCLISTS +.macro OFFSET_PAIR lo hi + .byte 4 # DW_LLE_offset_pair + .uleb128 \lo + .uleb128 \hi +.endm + +.macro BASE_ADDRESS base + .byte 6 # DW_LLE_base_address + .quad \base +.endm + +.macro EXPR_SIZE sz + .uleb128 \sz +.endm + +.macro END_OF_LIST + .byte 0 # DW_LLE_end_of_list +.endm +.endif + .type f,@function f: # @f .Lfunc_begin0: @@ -44,33 +100,38 @@ .Linfo_string4: .asciz "int" +.ifdef LOC .section .debug_loc,"",@progbits +.endif +.ifdef LOCLISTS + .section .debug_loclists,"",@progbits + .long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0 # Length +.Ldebug_loclist_table_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 0 # Offset entry count +.endif .Ldebug_loc0: - .quad .Lfunc_begin0-.Lfunc_begin0 - .quad .Ltmp0-.Lfunc_begin0 - .short 1 # Loc expr size + OFFSET_PAIR .Lfunc_begin0-.Lfunc_begin0, .Ltmp0-.Lfunc_begin0 + EXPR_SIZE 1 .byte 85 # super-register DW_OP_reg5 - .quad .Ltmp0-.Lfunc_begin0 - .quad .Lfunc_end0-.Lfunc_begin0 - .short 1 # Loc expr size + OFFSET_PAIR .Ltmp0-.Lfunc_begin0, .Lfunc_end0-.Lfunc_begin0 + EXPR_SIZE 1 .byte 80 # super-register DW_OP_reg0 - .quad 0 - .quad 0 + END_OF_LIST .Ldebug_loc3: - .quad -1 # Select base address - .quad .Ltmp1 - .quad .Ltmp1-.Ltmp1 - .quad .Ltmp2-.Ltmp1 - .short 1 # Loc expr size + BASE_ADDRESS .Ltmp1 + OFFSET_PAIR .Ltmp1-.Ltmp1, .Ltmp2-.Ltmp1 + EXPR_SIZE 1 .byte 81 # super-register DW_OP_reg1 - .quad 0 - .quad 0 + END_OF_LIST .Ldebug_loc2: - .quad .Lfunc_begin0-.Lfunc_begin0 - .quad .Lfunc_end0-.Lfunc_begin0 - .short 0xdead # Loc expr size + OFFSET_PAIR .Lfunc_begin0-.Lfunc_begin0, .Lfunc_end0-.Lfunc_begin0 + EXPR_SIZE 0xdead +.Ldebug_loclist_table_end0: .section .debug_abbrev,"",@progbits .byte 1 # Abbreviation Code @@ -123,9 +184,17 @@ .Lcu_begin0: .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit .Ldebug_info_start0: +.ifdef LOC .short 4 # DWARF version number .long .debug_abbrev # Offset Into Abbrev. Section .byte 8 # Address Size (in bytes) +.endif +.ifdef LOCLISTS + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section +.endif .byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit .long .Linfo_string0 # DW_AT_producer .short 12 # DW_AT_language