X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FDebugInfo%2FDWARFDebugLine.cpp;h=ce87635507e169237752f217c73382ba22866f6c;hb=45d53fd4c4d04b6feb2bc898f0a10ca98643edef;hp=83490b1d3ff9edbdeab56b92ddf5230701eadbd0;hpb=2a213a45325e803202246f0ccdc4510e4b37abda;p=oota-llvm.git diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp index 83490b1d3ff..ce87635507e 100644 --- a/lib/DebugInfo/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARFDebugLine.cpp @@ -15,6 +15,20 @@ #include using namespace llvm; using namespace dwarf; +typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; + +DWARFDebugLine::Prologue::Prologue() { + clear(); +} + +void DWARFDebugLine::Prologue::clear() { + TotalLength = Version = PrologueLength = 0; + MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; + OpcodeBase = 0; + StandardOpcodeLengths.clear(); + IncludeDirectories.clear(); + FileNames.clear(); +} void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { OS << "Line table prologue:\n" @@ -51,6 +65,67 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { } } +bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data, + uint32_t *offset_ptr) { + const uint32_t prologue_offset = *offset_ptr; + + clear(); + TotalLength = debug_line_data.getU32(offset_ptr); + Version = debug_line_data.getU16(offset_ptr); + if (Version < 2) + return false; + + PrologueLength = debug_line_data.getU32(offset_ptr); + const uint32_t end_prologue_offset = PrologueLength + *offset_ptr; + MinInstLength = debug_line_data.getU8(offset_ptr); + if (Version >= 4) + MaxOpsPerInst = debug_line_data.getU8(offset_ptr); + DefaultIsStmt = debug_line_data.getU8(offset_ptr); + LineBase = debug_line_data.getU8(offset_ptr); + LineRange = debug_line_data.getU8(offset_ptr); + OpcodeBase = debug_line_data.getU8(offset_ptr); + + StandardOpcodeLengths.reserve(OpcodeBase - 1); + for (uint32_t i = 1; i < OpcodeBase; ++i) { + uint8_t op_len = debug_line_data.getU8(offset_ptr); + StandardOpcodeLengths.push_back(op_len); + } + + while (*offset_ptr < end_prologue_offset) { + const char *s = debug_line_data.getCStr(offset_ptr); + if (s && s[0]) + IncludeDirectories.push_back(s); + else + break; + } + + while (*offset_ptr < end_prologue_offset) { + const char *name = debug_line_data.getCStr(offset_ptr); + if (name && name[0]) { + FileNameEntry fileEntry; + fileEntry.Name = name; + fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); + fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); + fileEntry.Length = debug_line_data.getULEB128(offset_ptr); + FileNames.push_back(fileEntry); + } else { + break; + } + } + + 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); + return false; + } + return true; +} + +DWARFDebugLine::Row::Row(bool default_is_stmt) { + reset(default_is_stmt); +} + void DWARFDebugLine::Row::postAppend() { BasicBlock = false; PrologueEnd = false; @@ -82,6 +157,22 @@ void DWARFDebugLine::Row::dump(raw_ostream &OS) const { << '\n'; } +DWARFDebugLine::Sequence::Sequence() { + reset(); +} + +void DWARFDebugLine::Sequence::reset() { + LowPC = 0; + HighPC = 0; + FirstRowIndex = 0; + LastRowIndex = 0; + Empty = true; +} + +DWARFDebugLine::LineTable::LineTable() { + clear(); +} + void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { Prologue.dump(OS); OS << '\n'; @@ -90,56 +181,46 @@ void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { OS << "Address Line Column File ISA Discriminator Flags\n" << "------------------ ------ ------ ------ --- ------------- " "-------------\n"; - for (std::vector::const_iterator pos = Rows.begin(), - end = Rows.end(); pos != end; ++pos) - pos->dump(OS); + for (const Row &R : Rows) { + R.dump(OS); + } } } -DWARFDebugLine::State::~State() {} - -void DWARFDebugLine::State::appendRowToMatrix(uint32_t offset) { - if (Sequence::Empty) { - // Record the beginning of instruction sequence. - Sequence::Empty = false; - Sequence::LowPC = Address; - Sequence::FirstRowIndex = row; - } - ++row; // Increase the row number. - LineTable::appendRow(*this); - if (EndSequence) { - // Record the end of instruction sequence. - Sequence::HighPC = Address; - Sequence::LastRowIndex = row; - if (Sequence::isValid()) - LineTable::appendSequence(*this); - Sequence::reset(); - } - Row::postAppend(); +void DWARFDebugLine::LineTable::clear() { + Prologue.clear(); + Rows.clear(); + Sequences.clear(); } -void DWARFDebugLine::State::finalize() { - row = DoneParsingLineTable; - if (!Sequence::Empty) { - fprintf(stderr, "warning: last sequence in debug line table is not" - "terminated!\n"); - } - // Sort all sequences so that address lookup will work faster. - if (!Sequences.empty()) { - std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); - // Note: actually, instruction address ranges of sequences should not - // overlap (in shared objects and executables). If they do, the address - // lookup would still work, though, but result would be ambiguous. - // We don't report warning in this case. For example, - // sometimes .so compiled from multiple object files contains a few - // rudimentary sequences for address ranges [0x0, 0xsomething). - } +DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT) + : LineTable(LT), RowNumber(0) { + resetRowAndSequence(); } -DWARFDebugLine::DumpingState::~DumpingState() {} +void DWARFDebugLine::ParsingState::resetRowAndSequence() { + Row.reset(LineTable->Prologue.DefaultIsStmt); + Sequence.reset(); +} -void DWARFDebugLine::DumpingState::finalize() { - LineTable::dump(OS); +void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) { + if (Sequence.Empty) { + // Record the beginning of instruction sequence. + Sequence.Empty = false; + Sequence.LowPC = Row.Address; + Sequence.FirstRowIndex = RowNumber; + } + ++RowNumber; + LineTable->appendRow(Row); + if (Row.EndSequence) { + // Record the end of instruction sequence. + Sequence.HighPC = Row.Address; + Sequence.LastRowIndex = RowNumber; + if (Sequence.isValid()) + LineTable->appendSequence(Sequence); + Sequence.reset(); + } + Row.postAppend(); } const DWARFDebugLine::LineTable * @@ -147,7 +228,7 @@ DWARFDebugLine::getLineTable(uint32_t offset) const { LineTableConstIter pos = LineTableMap.find(offset); if (pos != LineTableMap.end()) return &pos->second; - return 0; + return nullptr; } const DWARFDebugLine::LineTable * @@ -155,91 +236,31 @@ DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset) { std::pair pos = LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable())); + LineTable *LT = &pos.first->second; if (pos.second) { - // Parse and cache the line table for at this offset. - State state; - if (!parseStatementTable(debug_line_data, RelocMap, &offset, state)) - return 0; - pos.first->second = state; - } - return &pos.first->second; -} - -bool -DWARFDebugLine::parsePrologue(DataExtractor debug_line_data, - uint32_t *offset_ptr, Prologue *prologue) { - const uint32_t prologue_offset = *offset_ptr; - - prologue->clear(); - prologue->TotalLength = debug_line_data.getU32(offset_ptr); - 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->MinInstLength = debug_line_data.getU8(offset_ptr); - if (prologue->Version >= 4) - prologue->MaxOpsPerInst = debug_line_data.getU8(offset_ptr); - prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr); - prologue->LineBase = debug_line_data.getU8(offset_ptr); - prologue->LineRange = debug_line_data.getU8(offset_ptr); - prologue->OpcodeBase = debug_line_data.getU8(offset_ptr); - - prologue->StandardOpcodeLengths.reserve(prologue->OpcodeBase-1); - for (uint32_t i = 1; i < prologue->OpcodeBase; ++i) { - uint8_t op_len = debug_line_data.getU8(offset_ptr); - prologue->StandardOpcodeLengths.push_back(op_len); - } - - while (*offset_ptr < end_prologue_offset) { - const char *s = debug_line_data.getCStr(offset_ptr); - if (s && s[0]) - prologue->IncludeDirectories.push_back(s); - else - break; - } - - while (*offset_ptr < end_prologue_offset) { - const char *name = debug_line_data.getCStr(offset_ptr); - if (name && name[0]) { - FileNameEntry fileEntry; - fileEntry.Name = name; - fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); - fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); - fileEntry.Length = debug_line_data.getULEB128(offset_ptr); - prologue->FileNames.push_back(fileEntry); - } else { - break; - } + if (!LT->parse(debug_line_data, RelocMap, &offset)) + return nullptr; } - - 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); - return false; - } - return true; + return LT; } -bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, - const RelocAddrMap *RMap, - uint32_t *offset_ptr, State &state) { +bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data, + const RelocAddrMap *RMap, + uint32_t *offset_ptr) { const uint32_t debug_line_offset = *offset_ptr; - Prologue *prologue = &state.Prologue; + clear(); - if (!parsePrologue(debug_line_data, offset_ptr, prologue)) { + if (!Prologue.parse(debug_line_data, offset_ptr)) { // Restore our offset and return false to indicate failure! *offset_ptr = debug_line_offset; return false; } - const uint32_t end_offset = debug_line_offset + prologue->TotalLength + - sizeof(prologue->TotalLength); + const uint32_t end_offset = debug_line_offset + Prologue.TotalLength + + sizeof(Prologue.TotalLength); - state.reset(); + ParsingState State(this); while (*offset_ptr < end_offset) { uint8_t opcode = debug_line_data.getU8(offset_ptr); @@ -261,9 +282,9 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // with a DW_LNE_end_sequence instruction which creates a row whose // address is that of the byte after the last target machine instruction // of the sequence. - state.EndSequence = true; - state.appendRowToMatrix(*offset_ptr); - state.reset(); + State.Row.EndSequence = true; + State.appendRowToMatrix(*offset_ptr); + State.resetRowAndSequence(); break; case DW_LNE_set_address: @@ -278,9 +299,10 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr); if (AI != RMap->end()) { const std::pair &R = AI->second; - state.Address = debug_line_data.getAddress(offset_ptr) + R.second; + State.Row.Address = + debug_line_data.getAddress(offset_ptr) + R.second; } else - state.Address = debug_line_data.getAddress(offset_ptr); + State.Row.Address = debug_line_data.getAddress(offset_ptr); } break; @@ -311,12 +333,12 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); fileEntry.Length = debug_line_data.getULEB128(offset_ptr); - prologue->FileNames.push_back(fileEntry); + Prologue.FileNames.push_back(fileEntry); } break; case DW_LNE_set_discriminator: - state.Discriminator = debug_line_data.getULEB128(offset_ptr); + State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr); break; default: @@ -325,52 +347,52 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, (*offset_ptr) += arg_size; break; } - } else if (opcode < prologue->OpcodeBase) { + } else if (opcode < Prologue.OpcodeBase) { switch (opcode) { // Standard Opcodes case DW_LNS_copy: // Takes no arguments. Append a row to the matrix using the // current values of the state-machine registers. Then set // the basic_block register to false. - state.appendRowToMatrix(*offset_ptr); + State.appendRowToMatrix(*offset_ptr); 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.Address += debug_line_data.getULEB128(offset_ptr) * - prologue->MinInstLength; + State.Row.Address += + debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength; 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.Line += debug_line_data.getSLEB128(offset_ptr); + State.Row.Line += debug_line_data.getSLEB128(offset_ptr); break; case DW_LNS_set_file: // Takes a single unsigned LEB128 operand and stores it in the file // register of the state machine. - state.File = debug_line_data.getULEB128(offset_ptr); + State.Row.File = debug_line_data.getULEB128(offset_ptr); break; case DW_LNS_set_column: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. - state.Column = debug_line_data.getULEB128(offset_ptr); + State.Row.Column = debug_line_data.getULEB128(offset_ptr); break; case DW_LNS_negate_stmt: // Takes no arguments. Set the is_stmt register of the state // machine to the logical negation of its current value. - state.IsStmt = !state.IsStmt; + State.Row.IsStmt = !State.Row.IsStmt; break; case DW_LNS_set_basic_block: // Takes no arguments. Set the basic_block register of the // state machine to true - state.BasicBlock = true; + State.Row.BasicBlock = true; break; case DW_LNS_const_add_pc: @@ -386,10 +408,10 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // than twice that range will it need to use both DW_LNS_advance_pc // and a special opcode, requiring three or more bytes. { - uint8_t adjust_opcode = 255 - prologue->OpcodeBase; - uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * - prologue->MinInstLength; - state.Address += addr_offset; + uint8_t adjust_opcode = 255 - Prologue.OpcodeBase; + uint64_t addr_offset = + (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; + State.Row.Address += addr_offset; } break; @@ -403,25 +425,25 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // 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.Address += debug_line_data.getU16(offset_ptr); + State.Row.Address += debug_line_data.getU16(offset_ptr); break; case DW_LNS_set_prologue_end: // Takes no arguments. Set the prologue_end register of the // state machine to true - state.PrologueEnd = true; + State.Row.PrologueEnd = true; break; case DW_LNS_set_epilogue_begin: // Takes no arguments. Set the basic_block register of the // state machine to true - state.EpilogueBegin = true; + State.Row.EpilogueBegin = true; break; case DW_LNS_set_isa: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. - state.Isa = debug_line_data.getULEB128(offset_ptr); + State.Row.Isa = debug_line_data.getULEB128(offset_ptr); break; default: @@ -429,9 +451,9 @@ bool DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // of such opcodes because they are specified in the prologue // as a multiple of LEB128 operands for each opcode. { - assert(opcode - 1U < prologue->StandardOpcodeLengths.size()); - uint8_t opcode_length = prologue->StandardOpcodeLengths[opcode - 1]; - for (uint8_t i=0; iOpcodeBase; - uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * - prologue->MinInstLength; - int32_t line_offset = prologue->LineBase + - (adjust_opcode % prologue->LineRange); - state.Line += line_offset; - state.Address += addr_offset; - state.appendRowToMatrix(*offset_ptr); + uint8_t adjust_opcode = opcode - Prologue.OpcodeBase; + uint64_t addr_offset = + (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; + int32_t line_offset = + Prologue.LineBase + (adjust_opcode % Prologue.LineRange); + State.Row.Line += line_offset; + State.Row.Address += addr_offset; + State.appendRowToMatrix(*offset_ptr); } } - state.finalize(); + if (!State.Sequence.Empty) { + fprintf(stderr, "warning: last sequence in debug line table is not" + "terminated!\n"); + } + + // Sort all sequences so that address lookup will work faster. + if (!Sequences.empty()) { + std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); + // Note: actually, instruction address ranges of sequences should not + // overlap (in shared objects and executables). If they do, the address + // lookup would still work, though, but result would be ambiguous. + // We don't report warning in this case. For example, + // sometimes .so compiled from multiple object files contains a few + // rudimentary sequences for address ranges [0x0, 0xsomething). + } return end_offset; } -uint32_t -DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { +uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { uint32_t unknown_index = UINT32_MAX; if (Sequences.empty()) return unknown_index; @@ -532,10 +567,8 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { return index; } -bool -DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address, - uint64_t size, - std::vector& result) const { +bool DWARFDebugLine::LineTable::lookupAddressRange( + uint64_t address, uint64_t size, std::vector &result) const { if (Sequences.empty()) return false; uint64_t end_addr = address + size; @@ -611,13 +644,14 @@ DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address, bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + FileLineInfoKind Kind, std::string &Result) const { - if (FileIndex == 0 || FileIndex > Prologue.FileNames.size()) + if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() || + Kind == FileLineInfoKind::None) return false; const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; const char *FileName = Entry.Name; - if (!NeedsAbsoluteFilePath || + if (Kind != FileLineInfoKind::AbsoluteFilePath || sys::path::is_absolute(FileName)) { Result = FileName; return true;