Index: include/llvm/BinaryFormat/Dwarf.def =================================================================== --- include/llvm/BinaryFormat/Dwarf.def +++ include/llvm/BinaryFormat/Dwarf.def @@ -856,6 +856,7 @@ // TODO: Add Mach-O and COFF names. // Official DWARF sections. HANDLE_DWARF_SECTION(DebugAbbrev, ".debug_abbrev", "debug-abbrev") +HANDLE_DWARF_SECTION(DebugAddr, ".debug_addr", "debug-addr") HANDLE_DWARF_SECTION(DebugAranges, ".debug_aranges", "debug-aranges") HANDLE_DWARF_SECTION(DebugInfo, ".debug_info", "debug-info") HANDLE_DWARF_SECTION(DebugTypes, ".debug_types", "debug-types") Index: include/llvm/DebugInfo/DIContext.h =================================================================== --- include/llvm/DebugInfo/DIContext.h +++ include/llvm/DebugInfo/DIContext.h @@ -154,6 +154,8 @@ struct DIDumpOptions { unsigned DumpType = DIDT_All; unsigned RecurseDepth = -1U; + uint16_t Version = 0; // DWARF version to assume when extracting. + uint8_t AddrSize = 4; // Address byte size to assume when extracting. bool ShowAddresses = true; bool ShowChildren = false; bool ShowParents = false; Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -323,6 +323,10 @@ /// have initialized the relevant target descriptions. Error loadRegisterInfo(const object::ObjectFile &Obj); + /// Get address size from CUs. + /// TODO: refactor compile_units() to make this const. + uint8_t getCUAddrSize(); + private: /// Return the compile unit which contains instruction with provided /// address. Index: include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -51,6 +51,8 @@ /// reflect the absolute address of this pointer. Optional getEncodedPointer(uint32_t *Offset, uint8_t Encoding, uint64_t AbsPosOffset = 0) const; + + size_t size() const { return Section == nullptr ? 0 : Section->Data.size(); } }; } // end namespace llvm Index: include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h @@ -0,0 +1,98 @@ +//===- DWARFDebugAddr.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGADDR_H +#define LLVM_DEBUGINFO_DWARFDEBUGADDR_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Error.h" +#include +#include +#include + +namespace llvm { + +class Error; +class raw_ostream; + +/// A class representing an address table as specified in DWARF v5. +/// The table consists of a header followed by an array of address values from +/// .debug_addr section. +class DWARFDebugAddrTable { +public: + struct Header { + /// The total length of the entries for this table, not including the length + /// field itself. + uint32_t Length = 0; + /// The DWARF version number. + uint16_t Version = 5; + /// The size in bytes of an address on the target architecture. For + /// segmented addressing, this is the size of the offset portion of the + /// address. + uint8_t AddrSize; + /// The size in bytes of a segment selector on the target architecture. + /// If the target system uses a flat address space, this value is 0. + uint8_t SegSize = 0; + }; + +private: + dwarf::DwarfFormat Format; + uint32_t HeaderOffset; + Header HeaderData; + uint32_t DataSize = 0; + std::vector Addrs; + +public: + void clear(); + + /// Extract an entire table, including all addresses. + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr, + uint16_t Version, uint8_t AddrSize, + std::function WarnCallback); + + uint32_t getHeaderOffset() const { return HeaderOffset; } + uint8_t getAddrSize() const { return HeaderData.AddrSize; } + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + + /// Return the address based on a given index. + Expected getAddrEntry(uint32_t Index) const; + + /// Return the size of the table header including the length + /// but not including the addresses. + uint8_t getHeaderSize() const { + switch (Format) { + case dwarf::DwarfFormat::DWARF32: + return 8; // 4 + 2 + 1 + 1 + case dwarf::DwarfFormat::DWARF64: + return 16; // 12 + 2 + 1 + 1 + } + llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64)"); + } + + /// Returns the length of this table, including the length field, or 0 if the + /// length has not been determined (e.g. because the table has not yet been + /// parsed, or there was a problem in parsing). + uint32_t getLength() const; + + /// Verify that the given length is valid for this table. + bool hasValidLength() const { return getLength() != 0; } + + /// Invalidate Length field to stop further processing. + void invalidateLength() { HeaderData.Length = 0; } + + /// Returns the length of the array of addresses. + uint32_t getDataSize() const; +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGADDR_H Index: lib/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- lib/DebugInfo/DWARF/CMakeLists.txt +++ lib/DebugInfo/DWARF/CMakeLists.txt @@ -6,6 +6,7 @@ DWARFContext.cpp DWARFDataExtractor.cpp DWARFDebugAbbrev.cpp + DWARFDebugAddr.cpp DWARFDebugArangeSet.cpp DWARFDebugAranges.cpp DWARFDebugFrame.cpp Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -17,6 +17,7 @@ #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" @@ -249,6 +250,35 @@ } } +// Dump the .debug_addr section. +static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, + DIDumpOptions DumpOpts) { + // TODO: Make this more general: add callback types to Error.h, create + // implementation and make all DWARF classes use them. + static auto WarnCallback = [](Error Warn) { + handleAllErrors(std::move(Warn), [](ErrorInfoBase &Info) { + WithColor::warning() << Info.message() << '\n'; + }); + }; + uint32_t Offset = 0; + while (AddrData.isValidOffset(Offset)) { + DWARFDebugAddrTable AddrTable; + uint32_t TableOffset = Offset; + if (Error Err = AddrTable.extract(AddrData, &Offset, DumpOpts.Version, + DumpOpts.AddrSize, WarnCallback)) { + WithColor::error() << toString(std::move(Err)) << '\n'; + // Keep going after an error, if we can, assuming that the length field + // could be read. If it couldn't, stop reading the section. + if (!AddrTable.hasValidLength()) + break; + uint64_t Length = AddrTable.getLength(); + Offset = TableOffset + Length; + } else { + AddrTable.dump(OS, DumpOpts); + } + } +} + // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). static void dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, @@ -455,18 +485,18 @@ } } + if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr, + DObj->getAddrSection().Data)) { + DWARFDataExtractor AddrData(*DObj, DObj->getAddrSection(), + isLittleEndian(), 0); + DumpOpts.Version = getMaxVersion(); + DumpOpts.AddrSize = getCUAddrSize(); + dumpAddrSection(OS, AddrData, DumpOpts); + } + if (shouldDump(Explicit, ".debug_ranges", DIDT_ID_DebugRanges, DObj->getRangeSection().Data)) { - // In fact, different compile units may have different address byte - // sizes, but for simplicity we just use the address byte size of the - // last compile unit (there is no easy and fast way to associate address - // range list and the compile unit it describes). - // FIXME: savedAddressByteSize seems sketchy. - uint8_t savedAddressByteSize = 0; - for (const auto &CU : compile_units()) { - savedAddressByteSize = CU->getAddressByteSize(); - break; - } + uint8_t savedAddressByteSize = getCUAddrSize(); DWARFDataExtractor rangesData(*DObj, DObj->getRangeSection(), isLittleEndian(), savedAddressByteSize); uint32_t offset = 0; @@ -1584,3 +1614,17 @@ RegInfo.reset(TheTarget->createMCRegInfo(TT.str())); return Error::success(); } + +uint8_t DWARFContext::getCUAddrSize() { + // In theory, different compile units may have different address byte + // sizes, but for simplicity we just use the address byte size of the + // last compile unit. In practice the address size field is repeated across + // various DWARF headers (at least in version 5) to make it easier to dump + // them independently, not to enable varying the address size. + uint8_t Addr = 0; + for (const auto &CU : compile_units()) { + Addr = CU->getAddressByteSize(); + break; + } + return Addr; +} Index: lib/DebugInfo/DWARF/DWARFDebugAddr.cpp =================================================================== --- /dev/null +++ lib/DebugInfo/DWARF/DWARFDebugAddr.cpp @@ -0,0 +1,200 @@ +//===- DWARFDebugAddr.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" + +using namespace llvm; + +void DWARFDebugAddrTable::clear() { + HeaderData = {}; + Addrs.clear(); + invalidateLength(); +} + +Error DWARFDebugAddrTable::extract(DWARFDataExtractor Data, + uint32_t *OffsetPtr, + uint16_t Version, + uint8_t AddrSize, + std::function WarnCallback) { + clear(); + HeaderOffset = *OffsetPtr; + // Read and verify the length field. + if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) + return createStringError(errc::invalid_argument, + "section is not large enough to contain a " + ".debug_addr table length at offset 0x%" + PRIx32, *OffsetPtr); + uint16_t UnitVersion; + if (Version == 0) { + WarnCallback(createStringError(errc::invalid_argument, + "DWARF version is not defined in CU," + " assuming version 5")); + UnitVersion = 5; + } else { + UnitVersion = Version; + } + // TODO: Add support for DWARF64. + Format = dwarf::DwarfFormat::DWARF32; + if (UnitVersion >= 5) { + HeaderData.Length = Data.getU32(OffsetPtr); + if (HeaderData.Length == 0xffffffffu) { + invalidateLength(); + return createStringError(errc::not_supported, + "DWARF64 is not supported in .debug_addr at offset 0x%" PRIx32, + HeaderOffset); + } + if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) { + uint32_t TmpLength = getLength(); + invalidateLength(); + return createStringError(errc::invalid_argument, + ".debug_addr table at offset 0x%" PRIx32 + " has too small length (0x%" PRIx32 + ") to contain a complete header", + HeaderOffset, TmpLength); + } + uint32_t End = HeaderOffset + getLength(); + if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) { + uint32_t TmpLength = getLength(); + invalidateLength(); + return createStringError(errc::invalid_argument, + "section is not large enough to contain a .debug_addr table " + "of length 0x%" PRIx32 " at offset 0x%" PRIx32, + TmpLength, HeaderOffset); + } + + HeaderData.Version = Data.getU16(OffsetPtr); + HeaderData.AddrSize = Data.getU8(OffsetPtr); + HeaderData.SegSize = Data.getU8(OffsetPtr); + DataSize = getDataSize(); + } else { + HeaderData.Version = UnitVersion; + HeaderData.AddrSize = AddrSize; + // TODO: Support for non-zero SegSize. + HeaderData.SegSize = 0; + DataSize = Data.size(); + } + + // Perform basic validation of the remaining header fields. + + // We support DWARF version 5 for now as well as pre-DWARF5 + // implementations of .debug_addr table, which doesn't contain a header + // and consists only of a series of addresses. + if (HeaderData.Version > 5) { + return createStringError(errc::not_supported, "version %" PRIu16 + " of .debug_addr section at offset 0x%" PRIx32 " is not supported", + HeaderData.Version, HeaderOffset); + } + // FIXME: For now we just treat version mismatch as error, + // however the correct way to associate a .debug_addr table + // with a .debug_info table is to look at the DW_AT_addr_base + // attribute in the info table. + // In this case, each of the two .debug_info tables would point + // at different .debug_addr tables. + if (HeaderData.Version != UnitVersion) + return createStringError(errc::invalid_argument, + ".debug_addr table at offset 0x%" PRIx32 + " has version %" PRIu16 + " which is different from the version suggested" + " by the DWARF unit header: %" PRIu16, + HeaderOffset, HeaderData.Version, UnitVersion); + if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) + return createStringError(errc::not_supported, + ".debug_addr table at offset 0x%" PRIx32 + " has unsupported address size %" PRIu8, + HeaderOffset, HeaderData.AddrSize); + if (HeaderData.AddrSize != AddrSize && AddrSize != 0) + return createStringError(errc::invalid_argument, + ".debug_addr table at offset 0x%" PRIx32 + " has address size %" PRIu8 + " which is different from CU address size %" PRIu8, + HeaderOffset, HeaderData.AddrSize, AddrSize); + + // TODO: add support for non-zero segment selector size. + if (HeaderData.SegSize != 0) + return createStringError(errc::not_supported, + ".debug_addr table at offset 0x%" PRIx32 + " has unsupported segment selector size %" PRIu8, + HeaderOffset, HeaderData.SegSize); + if (DataSize % HeaderData.AddrSize != 0) { + invalidateLength(); + return createStringError(errc::invalid_argument, + ".debug_addr table at offset 0x%" PRIx32 + " contains data of size %" PRIu32 + " which is not a multiple of addr size %" PRIu8, + HeaderOffset, DataSize, HeaderData.AddrSize); + } + Data.setAddressSize(HeaderData.AddrSize); + uint32_t AddrCount = DataSize / HeaderData.AddrSize; + for (uint32_t I = 0; I < AddrCount; ++I) + if (HeaderData.AddrSize == 4) + Addrs.push_back(Data.getU32(OffsetPtr)); + else + Addrs.push_back(Data.getU64(OffsetPtr)); + return Error::success(); +} + +void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { + if (DumpOpts.Verbose) + OS << format("0x%8.8" PRIx32 ": ", HeaderOffset); + OS << format("Addr Section: length = 0x%8.8" PRIx32 + ", version = 0x%4.4" PRIx16 ", " + "addr_size = 0x%2.2" PRIx8 ", seg_size = 0x%2.2" PRIx8 "\n", + HeaderData.Length, HeaderData.Version, HeaderData.AddrSize, + HeaderData.SegSize); + + static const char *Fmt32 = "0x%8.8" PRIx32; + static const char *Fmt64 = "0x%16.16" PRIx64; + std::string AddrFmt = "\n"; + std::string AddrFmtVerbose = " => "; + if (HeaderData.AddrSize == 4) { + AddrFmt.append(Fmt32); + AddrFmtVerbose.append(Fmt32); + } + else { + AddrFmt.append(Fmt64); + AddrFmtVerbose.append(Fmt64); + } + + if (Addrs.size() > 0) { + OS << "Addrs: ["; + for (uint64_t Addr : Addrs) { + OS << format(AddrFmt.c_str(), Addr); + if (DumpOpts.Verbose) + OS << format(AddrFmtVerbose.c_str(), + Addr + HeaderOffset + sizeof(HeaderData)); + } + OS << "\n]\n"; + } +} + +Expected DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const { + if (Index < Addrs.size()) + return Addrs[Index]; + return createStringError(errc::invalid_argument, + "Index %" PRIu32 " is out of range of the " + ".debug_addr table at offset 0x%" PRIx32, + Index, HeaderOffset); +} + +uint32_t DWARFDebugAddrTable::getLength() const { + if (HeaderData.Length == 0) + return 0; + // TODO: DWARF64 support. + return HeaderData.Length + sizeof(uint32_t); +} + +uint32_t DWARFDebugAddrTable::getDataSize() const { + if (DataSize != 0) + return DataSize; + if (getLength() == 0) + return 0; + return getLength() - getHeaderSize(); +} Index: test/tools/llvm-dwarfdump/X86/debug_addr.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr.s @@ -0,0 +1,38 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o %t.o +# RUN: llvm-dwarfdump -debug-addr %t.o | FileCheck %s + +# CHECK: .debug_addr contents + +# CHECK-NEXT: length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00 +# CHECK-NEXT: Addrs: [ +# CHECK-NEXT: 0x00000000 +# CHECK-NEXT: 0x00000001 +# CHECK-NEXT: ] +# CHECK-NEXT: length = 0x00000004, version = 0x0005, addr_size = 0x04, seg_size = 0x00 +# CHECK-NOT: {{.}} + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .section .debug_info,"",@progbits +.Lcu_begin0: + .long 8 # Length of Unit + .short 5 # DWARF version number + .byte 1 # DWARF unit type + .byte 4 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 + + .section .debug_addr,"",@progbits +.Ldebug_addr1: + .long 4 # unit_length = .short + .byte + .byte + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size Index: test/tools/llvm-dwarfdump/X86/debug_addr_64bit_address.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_64bit_address.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o +# RUN: llvm-dwarfdump -debug-addr %t.o | FileCheck %s + +# CHECK: .debug_addr contents +# CHECK-NEXT: length = 0x00000014, version = 0x0005, addr_size = 0x08, seg_size = 0x00 +# CHECK-NEXT: Addrs: [ +# CHECK-NEXT: 0x0000000100000000 +# CHECK-NEXT: 0x0000000100000001 +# CHECK-NEXT: ] +# CHECK-NOT: {{.}} + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .section .debug_info,"",@progbits +.Lcu_begin0: + .long 8 # Length of Unit + .short 5 # DWARF version number + .byte 1 # DWARF unit type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 20 # unit_length = .short + .byte + .byte + .quad + .quad + .short 5 # version + .byte 8 # address_size + .byte 0 # segment_selector_size + .quad 0x0000000100000000 + .quad 0x0000000100000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_absent.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_absent.s @@ -0,0 +1,4 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2>&1 | FileCheck %s +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} Index: test/tools/llvm-dwarfdump/X86/debug_addr_address_size_mismatch.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_address_size_mismatch.s @@ -0,0 +1,42 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# ERR: .debug_addr table at offset 0x0 has address size 8 which is different from CU address size 4 +# ERR-NOT: {{.}} + +# CHECK: .debug_addr contents +# CHECK-NEXT: length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00 +# CHECK-NEXT: Addrs: [ +# CHECK-NEXT: 0x00000000 +# CHECK-NEXT: 0x00000001 +# CHECK-NEXT: ] +# CHECK-NOT: {{.}} + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .section .debug_info,"",@progbits +.Lcu_begin0: + .long 8 # Length of Unit + .short 5 # DWARF version number + .byte 1 # DWARF unit type + .byte 4 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 5 # version + .byte 8 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 + + .section .debug_addr,"",@progbits +.Ldebug_addr1: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_address_size_not_multiple.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_address_size_not_multiple.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: .debug_addr table at offset 0x0 contains data of size 7 which is not a multiple of addr size 4 +# ERR-NOT: {{.}} + +# data size is not multiple of address_size + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 11 # unit_length = .short + .byte + .byte + .long + .long - 1 + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_dwarf4.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_dwarf4.s @@ -0,0 +1,20 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o %t.o +# RUN: llvm-dwarfdump --debug-addr %t.o | FileCheck %s + +# CHECK: .debug_addr contents +# CHECK-NEXT: length = 0x00000000, version = 0x0004, addr_size = 0x04, seg_size = 0x00 +# CHECK-NEXT: Addrs: [ +# CHECK-NEXT: 0x00000000 +# CHECK-NEXT: 0x00000001 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .section .debug_info,"",@progbits +.Lcu_begin0: + .long 7 # Length of Unit + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 4 # Address Size (in bytes) + .section .debug_addr,"",@progbits + .long 0x00000000 + .long 0x00000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_dwarf64.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_dwarf64.s @@ -0,0 +1,19 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: DWARF64 is not supported in .debug_addr at offset 0x0 +# ERR-NOT: {{.}} + +# DWARF64 table + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 0xffffffff # unit_length DWARF64 mark + .quad 12 # unit_length + .short 5 # version + .byte 3 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_empty.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_empty.s @@ -0,0 +1,7 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - | FileCheck %s +# CHECK: .debug_addr contents: +# CHECK-NOT: Addr +# CHECK-NOT: error: + +.section .debug_addr,"",@progbits Index: test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_invalid_addr_size.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: unsupported address size 3 +# ERR-NOT: {{.}} + +# invalid addr size + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 5 # version + .byte 3 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_segment_selector.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_segment_selector.s @@ -0,0 +1,17 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: .debug_addr table at offset 0x0 has unsupported segment selector size 1 +# ERR-NOT: {{.}} + +# non-zero segment_selector_size +# TODO: make this valid + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 4 # unit_length = .short + .byte + .byte + .short 5 # version + .byte 4 # address_size + .byte 1 # segment_selector_size Index: test/tools/llvm-dwarfdump/X86/debug_addr_small_length_field.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_small_length_field.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: .debug_addr table at offset 0x0 has too small length (0x5) to contain a complete header +# ERR-NOT: {{.}} + +# too small length value + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 1 # unit_length + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 Index: test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_length_field.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_length_field.s @@ -0,0 +1,13 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: section is not large enough to contain a .debug_addr table length at offset 0x0 +# ERR-NOT: {{.}} + +# too small section to contain length field + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .short 1 # unit_length Index: test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_section.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_too_small_for_section.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# CHECK: .debug_addr contents: +# CHECK-NOT: {{.}} +# ERR: section is not large enough to contain a .debug_addr table of length 0x10 at offset 0x0 +# ERR-NOT: {{.}} + +# too small section to contain section of given length + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 12 # unit_length + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size Index: test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_unsupported_version.s @@ -0,0 +1,42 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# ERR: version 6 of .debug_addr section at offset 0x0 is not supported +# ERR-NOT: {{.}} + +# CHECK: .debug_addr contents +# CHECK-NEXT: length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00 +# CHECK-NEXT: Addrs: [ +# CHECK-NEXT: 0x00000002 +# CHECK-NEXT: 0x00000003 +# CHECK-NEXT: ] +# CHECK-NOT: {{.}} + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .section .debug_info,"",@progbits +.Lcu_begin0: + .long 8 # Length of Unit + .short 5 # DWARF version number + .byte 1 # DWARF unit type + .byte 4 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 6 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 + + .section .debug_addr,"",@progbits +.Ldebug_addr1: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000002 + .long 0x00000003 Index: test/tools/llvm-dwarfdump/X86/debug_addr_version_mismatch.s =================================================================== --- /dev/null +++ test/tools/llvm-dwarfdump/X86/debug_addr_version_mismatch.s @@ -0,0 +1,42 @@ +# RUN: llvm-mc %s -filetype obj -triple i386-pc-linux -o - | \ +# RUN: llvm-dwarfdump -debug-addr - 2> %t.err | FileCheck %s +# RUN: FileCheck %s -input-file %t.err -check-prefix=ERR + +# ERR: .debug_addr table at offset 0x0 has version 4 which is different from the version suggested by the DWARF unit header: 5 +# ERR-NOT: {{.}} + +# CHECK: .debug_addr contents +# CHECK-NEXT: length = 0x0000000c, version = 0x0005, addr_size = 0x04, seg_size = 0x00 +# CHECK-NEXT: Addrs: [ +# CHECK-NEXT: 0x00000000 +# CHECK-NEXT: 0x00000001 +# CHECK-NEXT: ] +# CHECK-NOT: {{.}} + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .section .debug_info,"",@progbits +.Lcu_begin0: + .long 8 # Length of Unit + .short 5 # DWARF version number + .byte 1 # DWARF unit type + .byte 4 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + + .section .debug_addr,"",@progbits +.Ldebug_addr0: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 4 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001 + + .section .debug_addr,"",@progbits +.Ldebug_addr1: + .long 12 # unit_length = .short + .byte + .byte + .long + .long + .short 5 # version + .byte 4 # address_size + .byte 0 # segment_selector_size + .long 0x00000000 + .long 0x00000001