diff options
| author | 2018-04-06 14:26:03 +0000 | |
|---|---|---|
| committer | 2018-04-06 14:26:03 +0000 | |
| commit | bdabc2f19ffb9e20600dad6e8a300842a7bda50e (patch) | |
| tree | c50e7b2e5449b074651bb82a58517a8ebc4a8cf7 /gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | |
| parent | Print a 'p' flag for file descriptors that were opened after pledge(2). (diff) | |
| download | wireguard-openbsd-bdabc2f19ffb9e20600dad6e8a300842a7bda50e.tar.xz wireguard-openbsd-bdabc2f19ffb9e20600dad6e8a300842a7bda50e.zip | |
Import LLVM 6.0.1 release including clang, lld and lldb.
"where is the kaboom?" deraadt@
Diffstat (limited to 'gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp')
| -rw-r--r-- | gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 189 |
1 files changed, 154 insertions, 35 deletions
diff --git a/gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 7d180564e9f..e5ef4eaceeb 100644 --- a/gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/gnu/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -12,7 +12,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/Format.h" @@ -49,6 +48,7 @@ void DWARFDebugLine::Prologue::clear() { MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; OpcodeBase = 0; FormParams = DWARFFormParams({0, 0, DWARF32}); + HasMD5 = false; StandardOpcodeLengths.clear(); IncludeDirectories.clear(); FileNames.clear(); @@ -79,15 +79,23 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { << IncludeDirectories[I] << "'\n"; if (!FileNames.empty()) { - OS << " Dir Mod Time File Len File Name\n" - << " ---- ---------- ---------- -----------" - "----------------\n"; + if (HasMD5) + OS << " Dir MD5 Checksum File Name\n" + << " ---- -------------------------------- -----------" + "---------------\n"; + else + OS << " Dir Mod Time File Len File Name\n" + << " ---- ---------- ---------- -----------" + "----------------\n"; for (uint32_t I = 0; I != FileNames.size(); ++I) { const FileNameEntry &FileEntry = FileNames[I]; - OS << format("file_names[%3u] %4" PRIu64 " ", I + 1, FileEntry.DirIdx) - << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ", FileEntry.ModTime, - FileEntry.Length) - << FileEntry.Name << '\n'; + OS << format("file_names[%3u] %4" PRIu64 " ", I + 1, FileEntry.DirIdx); + if (HasMD5) + OS << FileEntry.Checksum.digest(); + else + OS << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64, FileEntry.ModTime, + FileEntry.Length); + OS << ' ' << FileEntry.Name << '\n'; } } } @@ -123,7 +131,7 @@ parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, // ran off the end of the prologue. static ContentDescriptors parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - uint64_t EndPrologueOffset) { + uint64_t EndPrologueOffset, bool *HasMD5) { ContentDescriptors Descriptors; int FormatCount = DebugLineData.getU8(OffsetPtr); bool HasPath = false; @@ -136,6 +144,8 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr)); if (Descriptor.Type == dwarf::DW_LNCT_path) HasPath = true; + else if (Descriptor.Type == dwarf::DW_LNCT_MD5 && HasMD5) + *HasMD5 = true; Descriptors.push_back(Descriptor); } return HasPath ? Descriptors : ContentDescriptors(); @@ -144,12 +154,12 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, static bool parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, uint64_t EndPrologueOffset, - const DWARFFormParams &FormParams, - std::vector<StringRef> &IncludeDirectories, + const DWARFFormParams &FormParams, const DWARFUnit *U, + bool &HasMD5, std::vector<StringRef> &IncludeDirectories, std::vector<DWARFDebugLine::FileNameEntry> &FileNames) { // Get the directory entry description. ContentDescriptors DirDescriptors = - parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset); + parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, nullptr); if (DirDescriptors.empty()) return false; @@ -162,7 +172,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, DWARFFormValue Value(Descriptor.Form); switch (Descriptor.Type) { case DW_LNCT_path: - if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U)) return false; IncludeDirectories.push_back(Value.getAsCString().getValue()); break; @@ -175,7 +185,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, // Get the file entry description. ContentDescriptors FileDescriptors = - parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset); + parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, &HasMD5); if (FileDescriptors.empty()) return false; @@ -187,7 +197,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, DWARFDebugLine::FileNameEntry FileEntry; for (auto Descriptor : FileDescriptors) { DWARFFormValue Value(Descriptor.Form); - if (!Value.extractValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, U)) return false; switch (Descriptor.Type) { case DW_LNCT_path: @@ -202,7 +212,11 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, case DW_LNCT_size: FileEntry.Length = Value.getAsUnsignedConstant().getValue(); break; - // FIXME: Add MD5 + case DW_LNCT_MD5: + assert(Value.getAsBlock().getValue().size() == 16); + std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16, + FileEntry.Checksum.Bytes.begin()); + break; default: break; } @@ -213,7 +227,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, } bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr) { + uint32_t *OffsetPtr, const DWARFUnit *U) { const uint64_t PrologueOffset = *OffsetPtr; clear(); @@ -230,7 +244,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, if (getVersion() >= 5) { FormParams.AddrSize = DebugLineData.getU8(OffsetPtr); - assert(getAddressSize() == DebugLineData.getAddressSize() && + assert((DebugLineData.getAddressSize() == 0 || + DebugLineData.getAddressSize() == getAddressSize()) && "Line table header and data extractor disagree"); SegSelectorSize = DebugLineData.getU8(OffsetPtr); } @@ -253,7 +268,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, if (getVersion() >= 5) { if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, - getFormParams(), IncludeDirectories, FileNames)) { + getFormParams(), U, HasMD5, IncludeDirectories, + FileNames)) { fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 " found an invalid directory or file table description at" @@ -381,46 +397,71 @@ DWARFDebugLine::getLineTable(uint32_t Offset) const { } const DWARFDebugLine::LineTable * -DWARFDebugLine::getOrParseLineTable(const DWARFDataExtractor &DebugLineData, - uint32_t Offset) { +DWARFDebugLine::getOrParseLineTable(DWARFDataExtractor &DebugLineData, + uint32_t Offset, const DWARFUnit *U) { std::pair<LineTableIter, bool> Pos = LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable())); LineTable *LT = &Pos.first->second; if (Pos.second) { - if (!LT->parse(DebugLineData, &Offset)) + if (!LT->parse(DebugLineData, &Offset, U)) return nullptr; } return LT; } -bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, - uint32_t *OffsetPtr) { +bool DWARFDebugLine::LineTable::parse(DWARFDataExtractor &DebugLineData, + uint32_t *OffsetPtr, const DWARFUnit *U, + raw_ostream *OS) { const uint32_t DebugLineOffset = *OffsetPtr; clear(); - if (!Prologue.parse(DebugLineData, OffsetPtr)) { + if (!Prologue.parse(DebugLineData, OffsetPtr, U)) { // Restore our offset and return false to indicate failure! *OffsetPtr = DebugLineOffset; return false; } + if (OS) + Prologue.dump(*OS); + const uint32_t EndOffset = DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength(); + // See if we should tell the data extractor the address size. + if (DebugLineData.getAddressSize() == 0) + DebugLineData.setAddressSize(Prologue.getAddressSize()); + else + assert(Prologue.getAddressSize() == 0 || + Prologue.getAddressSize() == DebugLineData.getAddressSize()); + ParsingState State(this); while (*OffsetPtr < EndOffset) { + if (OS) + *OS << format("0x%08.08" PRIx32 ": ", *OffsetPtr); + uint8_t Opcode = DebugLineData.getU8(OffsetPtr); + if (OS) + *OS << format("%02.02" PRIx8 " ", Opcode); + if (Opcode == 0) { // Extended Opcodes always start with a zero opcode followed by // a uleb128 length so you can skip ones you don't know about - uint32_t ExtOffset = *OffsetPtr; uint64_t Len = DebugLineData.getULEB128(OffsetPtr); - uint32_t ArgSize = Len - (*OffsetPtr - ExtOffset); + uint32_t ExtOffset = *OffsetPtr; + + // Tolerate zero-length; assume length is correct and soldier on. + if (Len == 0) { + if (OS) + *OS << "Badly formed extended line op (length 0)\n"; + continue; + } uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr); + if (OS) + *OS << LNExtendedString(SubOpcode); switch (SubOpcode) { case DW_LNE_end_sequence: // Set the end_sequence register of the state machine to true and @@ -432,6 +473,11 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, // of the sequence. State.Row.EndSequence = true; State.appendRowToMatrix(*OffsetPtr); + if (OS) { + *OS << "\n"; + OS->indent(12); + State.Row.dump(*OS); + } State.resetRowAndSequence(); break; @@ -442,7 +488,16 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, // relocatable address. All of the other statement program opcodes // that affect the address register add a delta to it. This instruction // stores a relocatable value into it instead. + // + // Make sure the extractor knows the address size. If not, infer it + // from the size of the operand. + if (DebugLineData.getAddressSize() == 0) + DebugLineData.setAddressSize(Len - 1); + else + assert(DebugLineData.getAddressSize() == Len - 1); State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr); + if (OS) + *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address); break; case DW_LNE_define_file: @@ -473,20 +528,42 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr); FileEntry.Length = DebugLineData.getULEB128(OffsetPtr); Prologue.FileNames.push_back(FileEntry); + if (OS) + *OS << " (" << FileEntry.Name.str() + << ", dir=" << FileEntry.DirIdx << ", mod_time=" + << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime) + << ", length=" << FileEntry.Length << ")"; } break; case DW_LNE_set_discriminator: State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr); + if (OS) + *OS << " (" << State.Row.Discriminator << ")"; break; default: - // Length doesn't include the zero opcode byte or the length itself, but - // it does include the sub_opcode, so we have to adjust for that below - (*OffsetPtr) += ArgSize; + if (OS) + *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode) + << format(" length %" PRIx64, Len); + // Len doesn't include the zero opcode byte or the length itself, but + // it does include the sub_opcode, so we have to adjust for that. + (*OffsetPtr) += Len - 1; break; } + // Make sure the stated and parsed lengths are the same. + // Otherwise we have an unparseable line-number program. + if (*OffsetPtr - ExtOffset != Len) { + fprintf(stderr, "Unexpected line op length at offset 0x%8.8" PRIx32 + " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32 "\n", + ExtOffset, Len, *OffsetPtr - ExtOffset); + // Skip the rest of the line-number program. + *OffsetPtr = EndOffset; + return false; + } } else if (Opcode < Prologue.OpcodeBase) { + if (OS) + *OS << LNStandardString(Opcode); switch (Opcode) { // Standard Opcodes case DW_LNS_copy: @@ -494,32 +571,49 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, // current values of the state-machine registers. Then set // the basic_block register to false. State.appendRowToMatrix(*OffsetPtr); + if (OS) { + *OS << "\n"; + OS->indent(12); + State.Row.dump(*OS); + *OS << "\n"; + } break; case DW_LNS_advance_pc: // Takes a single unsigned LEB128 operand, multiplies it by the // min_inst_length field of the prologue, and adds the // result to the address register of the state machine. - State.Row.Address += - DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength; + { + uint64_t AddrOffset = + DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength; + State.Row.Address += AddrOffset; + if (OS) + *OS << " (" << AddrOffset << ")"; + } break; case DW_LNS_advance_line: // Takes a single signed LEB128 operand and adds that value to // the line register of the state machine. State.Row.Line += DebugLineData.getSLEB128(OffsetPtr); + if (OS) + *OS << " (" << State.Row.Line << ")"; break; case DW_LNS_set_file: // Takes a single unsigned LEB128 operand and stores it in the file // register of the state machine. State.Row.File = DebugLineData.getULEB128(OffsetPtr); + if (OS) + *OS << " (" << State.Row.File << ")"; break; case DW_LNS_set_column: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. State.Row.Column = DebugLineData.getULEB128(OffsetPtr); + if (OS) + *OS << " (" << State.Row.Column << ")"; break; case DW_LNS_negate_stmt: @@ -551,6 +645,9 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, uint64_t AddrOffset = (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength; State.Row.Address += AddrOffset; + if (OS) + *OS + << format(" (0x%16.16" PRIx64 ")", AddrOffset); } break; @@ -564,7 +661,13 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, // judge when the computation of a special opcode overflows and // requires the use of DW_LNS_advance_pc. Such assemblers, however, // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. - State.Row.Address += DebugLineData.getU16(OffsetPtr); + { + uint16_t PCOffset = DebugLineData.getU16(OffsetPtr); + State.Row.Address += PCOffset; + if (OS) + *OS + << format(" (0x%16.16" PRIx64 ")", PCOffset); + } break; case DW_LNS_set_prologue_end: @@ -583,6 +686,8 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. State.Row.Isa = DebugLineData.getULEB128(OffsetPtr); + if (OS) + *OS << " (" << State.Row.Isa << ")"; break; default: @@ -592,8 +697,12 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, { assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size()); uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1]; - for (uint8_t I = 0; I < OpcodeLength; ++I) - DebugLineData.getULEB128(OffsetPtr); + for (uint8_t I = 0; I < OpcodeLength; ++I) { + uint64_t Value = DebugLineData.getULEB128(OffsetPtr); + if (OS) + *OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n", + Value); + } } break; } @@ -638,10 +747,20 @@ bool DWARFDebugLine::LineTable::parse(const DWARFDataExtractor &DebugLineData, Prologue.LineBase + (AdjustOpcode % Prologue.LineRange); State.Row.Line += LineOffset; State.Row.Address += AddrOffset; + + if (OS) { + *OS << "address += " << ((uint32_t)AdjustOpcode) + << ", line += " << LineOffset << "\n"; + OS->indent(12); + State.Row.dump(*OS); + } + State.appendRowToMatrix(*OffsetPtr); // Reset discriminator to 0. State.Row.Discriminator = 0; } + if(OS) + *OS << "\n"; } if (!State.Sequence.Empty) { |
