Index: lib/DebugInfo/DWARFContext.h =================================================================== --- lib/DebugInfo/DWARFContext.h +++ lib/DebugInfo/DWARFContext.h @@ -27,6 +27,22 @@ /// This data structure is the top level entity that deals with dwarf debug /// information parsing. The actual data is supplied through pure virtual /// methods that a concrete implementation provides. +/// +/// 7.4 32-Bit and 64-Bit DWARF Formats +/// DWARF Version 3 specifies the 64-Bit format, which uses 0xffffffff in +/// the 32-bit initial length field to signal that the actual length and +/// later offsets are 64-Bit. Partial support is implemented to handle +/// 64-Bit DWARF emitted by some toolchains, even though it is not +/// actually necessary (the debug data is not > 4GB). +/// +/// Class 64-bit support Notes +/// DataExtractor No Prevents handling debug data >4GB +/// DWARFDebugAbbrev No +/// DWARFDebugLoc No +/// DWARFDebugAranges No +/// DWARFDebugLine Yes +/// DWARFDebugFrame Yes +/// class DWARFContext : public DIContext { SmallVector CUs; SmallVector TUs; Index: lib/DebugInfo/DWARFDebugLine.h =================================================================== --- lib/DebugInfo/DWARFDebugLine.h +++ lib/DebugInfo/DWARFDebugLine.h @@ -35,16 +35,17 @@ struct Prologue { Prologue() : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0), - DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0) {} + DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0), + IsDWARF64(false) {} // The size in bytes of the statement information for this compilation unit // (not including the total_length field itself). - uint32_t TotalLength; + uint64_t TotalLength; // Version identifier for the statement information format. uint16_t Version; // The number of bytes following the prologue_length field to the beginning // of the first byte of the statement program itself. - uint32_t PrologueLength; + uint64_t PrologueLength; // The size in bytes of the smallest target machine instruction. Statement // program opcodes that alter the address register first multiply their // operands by this value. @@ -61,14 +62,22 @@ std::vector IncludeDirectories; std::vector FileNames; + bool IsDWARF64; + uint32_t sizeofTotalLength() const { + return IsDWARF64 ? 12 : 4; + } + uint32_t sizeofPrologueLength() const { + return IsDWARF64 ? 8 : 4; + } + // Length of the prologue in bytes. uint32_t getLength() const { - return PrologueLength + sizeof(TotalLength) + sizeof(Version) + - sizeof(PrologueLength); + return PrologueLength + sizeofTotalLength() + sizeof(Version) + + sizeofPrologueLength(); } // Length of the line table data in bytes (not including the prologue). uint32_t getStatementTableLength() const { - return TotalLength + sizeof(TotalLength) - getLength(); + return TotalLength + sizeofTotalLength() - getLength(); } int32_t getMaxLineIncrementForSpecialOpcode() const { return LineBase + (int8_t)LineRange - 1; @@ -80,6 +89,7 @@ StandardOpcodeLengths.clear(); IncludeDirectories.clear(); FileNames.clear(); + IsDWARF64 = false; } }; Index: lib/DebugInfo/DWARFDebugLine.cpp =================================================================== --- lib/DebugInfo/DWARFDebugLine.cpp +++ lib/DebugInfo/DWARFDebugLine.cpp @@ -18,9 +18,9 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { OS << "Line table prologue:\n" - << format(" total_length: 0x%8.8x\n", TotalLength) + << format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength) << format(" version: %u\n", Version) - << format("prologue_length: 0x%8.8x\n", PrologueLength) + << format("prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength) << format("min_inst_length: %u\n", MinInstLength) << format("default_is_stmt: %u\n", DefaultIsStmt) << format(" line_base: %i\n", LineBase) @@ -165,16 +165,23 @@ bool DWARFDebugLine::parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr, Prologue *prologue) { - const uint32_t prologue_offset = *offset_ptr; + const uint64_t prologue_offset = *offset_ptr; prologue->clear(); prologue->TotalLength = debug_line_data.getU32(offset_ptr); + if (prologue->TotalLength == UINT32_MAX) { + prologue->IsDWARF64 = true; + prologue->TotalLength = debug_line_data.getU64(offset_ptr); + } else if (prologue->TotalLength >= 0xffffff00) { + return false; + } prologue->Version = debug_line_data.getU16(offset_ptr); if (prologue->Version != 2) return false; - prologue->PrologueLength = debug_line_data.getU32(offset_ptr); - const uint32_t end_prologue_offset = prologue->PrologueLength + *offset_ptr; + prologue->PrologueLength = debug_line_data.getUnsigned(offset_ptr, + prologue->sizeofPrologueLength()); + const uint64_t end_prologue_offset = prologue->PrologueLength + *offset_ptr; prologue->MinInstLength = debug_line_data.getU8(offset_ptr); prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr); prologue->LineBase = debug_line_data.getU8(offset_ptr); @@ -209,10 +216,15 @@ } } - if (*offset_ptr != end_prologue_offset) { - fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should" - " have ended at 0x%8.8x but it ended at 0x%8.8x\n", - prologue_offset, end_prologue_offset, *offset_ptr); + if (prologue->IsDWARF64 && end_prologue_offset - *offset_ptr == 12) { + fprintf(stderr, "warning: apparent 64-bit DWARF GNU as prologue length bug" + " detected (prologue length 12 bytes too long)\n"); + // Could correct the field: prologue->PrologueLength -= 12; + } else if (*offset_ptr != end_prologue_offset) { + fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 + " should have ended at 0x%8.8" PRIx64 + " but it ended at 0x%8.8" PRIx64 "\n", + prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr); return false; } return true; @@ -233,7 +245,7 @@ } const uint32_t end_offset = debug_line_offset + prologue->TotalLength + - sizeof(prologue->TotalLength); + prologue->sizeofTotalLength(); state.reset(); Index: test/DebugInfo/dwarfdump-64-bit-dwarf.test =================================================================== --- /dev/null +++ test/DebugInfo/dwarfdump-64-bit-dwarf.test @@ -0,0 +1,12 @@ +RUN: llvm-dwarfdump %p/Inputs/dwarfdump-inl-test.elf-mips64-64-bit-dwarf \ +RUN: --debug-dump=line | FileCheck %s + +CHECK: total_length: 0x00000212 +CHECK: version: 2 +CHECK:prologue_length: 0x000001ab +CHECK:min_inst_length: 1 +CHECK:default_is_stmt: 1 +CHECK: line_base: -5 +CHECK: line_range: 14 +CHECK: opcode_base: 13 +CHECK: is_stmt end_sequence