23#include "llvm/ADT/StringExtras.h"
93 : m_obj(&obj), m_section_type(
toString(section_type)),
94 m_next_section_idx(bookmark.section), m_current_line(bookmark.offset) {
109 const SectionList &list = *m_obj->GetSectionList();
111 while (m_next_line != llvm::StringRef::npos ||
112 m_next_section_idx < num_sections) {
113 if (m_next_line != llvm::StringRef::npos) {
114 m_current_line = m_next_line;
120 if (sect.
GetName() != m_section_type)
123 m_obj->ReadSectionData(§, data);
124 m_section_text = toStringRef(data.
GetData());
128 m_current_line = m_next_line;
132llvm::iterator_range<SymbolFileBreakpad::LineIterator>
141class SupportFileMap {
145 size_t operator[](
size_t file) {
146 return m_map.try_emplace(file, m_map.size() + 1).first->second;
152 llvm::ArrayRef<FileSpec> all_files);
155 llvm::DenseMap<size_t, size_t> m_map;
160 llvm::ArrayRef<FileSpec> all_files) {
161 std::vector<FileSpec> result;
162 result.resize(m_map.size() + 1);
164 for (
const auto &KV : m_map) {
165 if (KV.first < all_files.size())
166 result[KV.second] = all_files[KV.first];
215 if (record && record->FileNum <
m_files->size())
216 spec = (*m_files)[record->FileNum];
219 auto cu_sp = std::make_shared<CompileUnit>(
221 nullptr, std::make_shared<SupportFile>(spec), index,
238 LLDB_LOG(log,
"Unable to fetch the base address of object file. Skipping "
239 "symtab population.");
251 addr_t address = record->Address + base;
255 section_sp, address - section_sp->GetFileAddress(), record->Size);
257 func_sp = std::make_shared<Function>(&comp_unit,
id, 0, func_name,
258 nullptr, func_range);
301 std::vector<Block *> blocks;
304 blocks.push_back(&block);
306 size_t blocks_added = 0;
312 size_t last_added_nest_level = 0;
315 if (record->InlineNestLevel == 0 ||
316 record->InlineNestLevel <= last_added_nest_level + 1) {
317 last_added_nest_level = record->InlineNestLevel;
318 BlockSP block_sp = std::make_shared<Block>(It.GetBookmark().offset);
320 if (record->CallSiteFileNum <
m_files->size())
321 callsite_file = (*m_files)[record->CallSiteFileNum];
322 llvm::StringRef name;
324 name = (*m_inline_origins)[record->OriginNum];
326 Declaration callsite(callsite_file, record->CallSiteLineNum);
327 block_sp->SetInlinedFunctionInfo(name.str().c_str(),
330 for (
const auto &range : record->Ranges) {
334 block_sp->FinalizeRanges();
336 blocks[record->InlineNestLevel]->AddChild(block_sp);
337 if (record->InlineNestLevel + 1 >= blocks.size()) {
338 blocks.resize(blocks.size() + 1);
340 blocks[record->InlineNestLevel + 1] = block_sp.get();
358 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", line);
364 (*m_inline_origins)[record->Number] = record->Name;
370 SymbolContextItem resolve_scope,
373 if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry |
374 eSymbolContextFunction | eSymbolContextBlock)))
384 SymbolContextItem result = eSymbolContextCompUnit;
385 if (resolve_scope & eSymbolContextLineEntry) {
388 result |= eSymbolContextLineEntry;
392 if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
396 result |= eSymbolContextFunction;
397 if (resolve_scope & eSymbolContextBlock) {
398 Block &block = func_sp->GetBlock(
true);
403 result |= eSymbolContextBlock;
415 if (!(resolve_scope & eSymbolContextCompUnit))
418 uint32_t old_size = sc_list.
GetSize();
423 return sc_list.
GetSize() - old_size;
437 if (func_sp && name == func_sp->GetNameNoArguments()) {
441 sc.
module_sp = func_sp->CalculateSymbolContextModule();
448 bool include_inlines,
458 LLDB_LOG(log,
"Unable to fetch the base address of object file. Skipping "
459 "symtab population.");
464 llvm::DenseSet<addr_t> found_symbol_addresses;
465 std::vector<Symbol> symbols;
466 auto add_symbol = [&](
addr_t address, std::optional<addr_t> size,
467 llvm::StringRef name) {
472 "Ignoring symbol {0}, whose address ({1}) is outside of the "
473 "object file. Mismatched symbol file?",
479 if (!found_symbol_addresses.insert(address).second)
481 symbols.emplace_back(
485 AddressRange(section_sp, address - section_sp->GetFileAddress(),
487 size.has_value(),
false, 0);
492 add_symbol(record->Address, std::nullopt, record->Name);
494 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", line);
497 for (
Symbol &symbol : symbols)
502llvm::Expected<lldb::addr_t>
510 return record->ParameterSize;
512 return llvm::createStringError(llvm::inconvertibleErrorCode(),
513 "Parameter size unknown.");
516static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
522 llvm::StringRef lhs, rest;
523 std::tie(lhs, rest) = getToken(unwind_rules);
524 if (!lhs.consume_back(
":"))
528 llvm::StringRef::size_type pos = rest.find(
": ");
529 if (pos == llvm::StringRef::npos) {
531 unwind_rules = llvm::StringRef();
532 return std::make_pair(lhs, rest);
536 pos = rest.rfind(
' ', pos);
537 if (pos == llvm::StringRef::npos)
540 llvm::StringRef rhs = rest.take_front(pos);
541 unwind_rules = rest.drop_front(pos);
542 return std::make_pair(lhs, rhs);
548 llvm::StringRef name) {
549 if (triple.isX86() || triple.isMIPS()) {
552 if (!name.consume_front(
"$"))
561 llvm::StringRef name) {
571 ToDWARF(node,
dwarf);
573 std::memcpy(saved,
dwarf.GetData(),
dwarf.GetSize());
574 return {saved,
dwarf.GetSize()};
582 llvm::BumpPtrAllocator node_alloc;
583 llvm::Triple triple =
m_objfile_sp->GetArchitecture().GetTriple();
584 while (
auto rule =
GetRule(unwind_rules)) {
586 llvm::StringRef lhs = rule->first;
589 LLDB_LOG(log,
"Could not parse `{0}` as unwind rhs.", rule->second);
595 llvm::StringRef name = symbol.
GetName();
596 if (name ==
".cfa" && lhs !=
".cfa")
597 return postfix::MakeNode<postfix::InitialValueNode>(node_alloc);
601 return postfix::MakeNode<postfix::RegisterNode>(
608 LLDB_LOG(log,
"Resolving symbols in `{0}` failed.", rule->second);
621 LLDB_LOG(log,
"Invalid register `{0}` in unwind rule.", lhs);
623 if (unwind_rules.empty())
626 LLDB_LOG(log,
"Could not parse `{0}` as an unwind rule.", unwind_rules);
653 assert(init_record && init_record->Size &&
654 "Record already parsed successfully in ParseUnwindData!");
657 plan_sp->SetSourceName(
"breakpad STACK CFI");
658 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
661 plan_sp->SetPlanValidAddressRange(
662 AddressRange(base + init_record->Address, *init_record->Size,
665 auto row_sp = std::make_shared<UnwindPlan::Row>();
666 row_sp->SetOffset(0);
669 plan_sp->AppendRow(row_sp);
670 for (++It; It != End; ++It) {
677 row_sp = std::make_shared<UnwindPlan::Row>(*row_sp);
678 row_sp->SetOffset(record->Address - init_record->Address);
681 plan_sp->AppendRow(row_sp);
696 assert(record &&
"Record already parsed successfully in ParseUnwindData!");
699 plan_sp->SetSourceName(
"breakpad STACK WIN");
700 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
703 plan_sp->SetPlanValidAddressRange(
707 auto row_sp = std::make_shared<UnwindPlan::Row>();
708 row_sp->SetOffset(0);
710 llvm::BumpPtrAllocator node_alloc;
711 std::vector<std::pair<llvm::StringRef, postfix::Node *>> program =
714 if (program.empty()) {
715 LLDB_LOG(log,
"Invalid unwind rule: {0}.", record->ProgramString);
718 auto it = program.begin();
719 llvm::Triple triple =
m_objfile_sp->GetArchitecture().GetTriple();
720 const auto &symbol_resolver =
722 llvm::StringRef name = symbol.GetName();
723 for (
const auto &rule : llvm::make_range(program.begin(), it)) {
724 if (rule.first == name)
728 return postfix::MakeNode<postfix::RegisterNode>(
735 auto *symbol = llvm::dyn_cast<postfix::SymbolNode>(it->second);
736 if (symbol && symbol->GetName() ==
".raSearch") {
737 row_sp->GetCFAValue().SetRaSearch(record->LocalSize +
738 record->SavedRegisterSize);
741 LLDB_LOG(log,
"Resolving symbols in `{0}` failed.",
742 record->ProgramString);
745 llvm::ArrayRef<uint8_t> saved =
SaveAsDWARF(*it->second);
746 row_sp->GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size());
752 it->second = postfix::MakeNode<postfix::InitialValueNode>(node_alloc);
756 for (++it; it != program.end(); ++it) {
763 LLDB_LOG(log,
"Resolving symbols in `{0}` failed.",
764 record->ProgramString);
768 llvm::ArrayRef<uint8_t> saved =
SaveAsDWARF(*it->second);
774 plan_sp->AppendRow(row_sp);
796 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", line);
800 if (record->Number >=
m_files->size())
801 m_files->resize(record->Number + 1);
803 .value_or(FileSpec::Style::native);
804 (*m_files)[record->Number] =
FileSpec(record->Name, style);
816 LLDB_LOG(log,
"SymbolFile parsing failed: Unable to fetch the base address "
828 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", *It);
839 "How did we create compile units without a base address?");
842 std::vector<std::unique_ptr<LineSequence>> sequences;
843 std::unique_ptr<LineSequence> line_seq_up =
845 std::optional<addr_t> next_addr;
846 auto finish_sequence = [&]() {
848 line_seq_up.get(), *next_addr, 0, 0,
852 sequences.push_back(std::move(line_seq_up));
859 for (++It; It != End; ++It) {
868 record->Address += base;
870 if (next_addr && *next_addr != record->Address) {
875 line_seq_up.get(), record->Address, record->LineNum, 0,
876 map[record->FileNum],
true,
879 next_addr = record->Address + record->Size;
883 data.
line_table_up = std::make_unique<LineTable>(&cu, std::move(sequences));
895 LLDB_LOG(log,
"SymbolFile parsing failed: Unable to fetch the base address "
904 base + record->Address, *record->Size, It.GetBookmark()));
906 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", *It);
914 base + record->RVA, record->CodeSize, It.GetBookmark()));
916 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", *It);
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_PLUGIN_DEFINE(PluginName)
static std::optional< std::pair< llvm::StringRef, llvm::StringRef > > GetRule(llvm::StringRef &unwind_rules)
static const RegisterInfo * ResolveRegister(const llvm::Triple &triple, const SymbolFile::RegisterInfoResolver &resolver, llvm::StringRef name)
static const RegisterInfo * ResolveRegisterOrRA(const llvm::Triple &triple, const SymbolFile::RegisterInfoResolver &resolver, llvm::StringRef name)
llvm::StringRef m_section_text
Bookmark GetBookmark() const
llvm::StringRef operator*() const
const LineIterator & operator++()
ConstString m_section_type
friend bool operator!=(const LineIterator &lhs, const LineIterator &rhs)
LineIterator(ObjectFile &obj)
LineIterator(ObjectFile &obj, Record::Kind section_type)
uint32_t m_next_section_idx
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
lldb::addr_t GetByteSize() const
Get accessor for the byte size of this range.
A section + offset based address class.
lldb::addr_t GetFileAddress() const
Get the file address.
lldb::addr_t GetOffset() const
Get the section relative offset value.
An architecture specification class.
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
A class that describes a single lexical block.
Block * FindInnermostBlockByOffset(const lldb::addr_t offset)
void AddRange(const Range &range)
Add a new offset range to this block.
A class that describes a compilation unit.
const FileSpec & GetPrimaryFile() const
Return the primary source spec associated with this compile unit.
void ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list, RealpathPrefixes *realpath_prefixes=nullptr)
Resolve symbol contexts by file and line.
void SetLineTable(LineTable *line_table)
Set the line table for the compile unit.
void AddFunction(lldb::FunctionSP &function_sp)
Add a function to this compile unit.
lldb::FunctionSP FindFunctionByUID(lldb::user_id_t uid)
Finds a function by user ID.
LineTable * GetLineTable()
Get the line table for the compile unit.
Represents a generic declaration context in a program.
A uniqued constant string class.
A class that describes the declaration location of a lldb object.
static std::optional< Style > GuessPathStyle(llvm::StringRef absolute_path)
Attempt to guess path style for a given path string.
llvm::sys::path::Style Style
A class that describes a function.
const AddressRange & GetAddressRange()
CompileUnit * GetCompileUnit()
Get accessor for the compile unit that owns this function.
Block & GetBlock(bool can_create)
Get accessor for the block list.
static std::unique_ptr< LineSequence > CreateLineSequenceContainer()
bool FindLineEntryByAddress(const Address &so_addr, LineEntry &line_entry, uint32_t *index_ptr=nullptr)
Find a line entry that contains the section offset address so_addr.
static void AppendLineEntryToSequence(LineSequence *sequence, lldb::addr_t file_addr, uint32_t line, uint16_t column, uint16_t file_idx, bool is_start_of_statement, bool is_start_of_basic_block, bool is_prologue_end, bool is_epilogue_begin, bool is_terminal_entry)
A class that handles mangled names.
void SetValue(ConstString name)
Set the string value in this object.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
A class that encapsulates name lookup information.
ConstString GetLookupName() const
A class that describes an executable image and its associated object and symbol files.
virtual SectionList * GetSectionList()
Get the unified section list for the module.
A plug-in interface definition class for object file parsers.
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
virtual size_t ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
size_t GetNumSections(uint32_t depth) const
lldb::SectionSP FindSectionContainingFileAddress(lldb::addr_t addr, uint32_t depth=UINT32_MAX) const
lldb::SectionSP GetSectionAtIndex(size_t idx) const
ConstString GetName() const
"lldb/Core/SourceLocationSpec.h" A source location specifier class.
@ eBinary
Get and put data as binary instead of as the default string mode.
A list of support files for a CompileUnit.
void Append(const FileSpec &file)
Defines a list of symbol context objects.
uint32_t GetSize() const
Get accessor for a symbol context list size.
void Append(const SymbolContext &sc)
Append a new symbol context to the list.
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
Block * block
The Block for a given query.
lldb::ModuleSP module_sp
The Module for a given query.
CompileUnit * comp_unit
The CompileUnit for a given query.
LineEntry line_entry
The LineEntry for a given query.
lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) override
lldb::ObjectFileSP m_objfile_sp
void SetCompileUnitAtIndex(uint32_t idx, const lldb::CompUnitSP &cu_sp)
uint32_t GetNumCompileUnits() override
virtual std::recursive_mutex & GetModuleMutex() const
Symbols file subclasses should override this to return the Module that owns the TypeSystem that this ...
Address GetAddress() const
uint32_t AddSymbol(const Symbol &symbol)
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len)
void SetRegisterInfo(uint32_t reg_num, const RegisterLocation register_location)
static std::optional< FileRecord > parse(llvm::StringRef Line)
static std::optional< FuncRecord > parse(llvm::StringRef Line)
static std::optional< InlineOriginRecord > parse(llvm::StringRef Line)
static std::optional< InlineRecord > parse(llvm::StringRef Line)
static std::optional< LineRecord > parse(llvm::StringRef Line)
static std::optional< PublicRecord > parse(llvm::StringRef Line)
static std::optional< Kind > classify(llvm::StringRef Line)
Attempt to guess the kind of the record present in the argument without doing a full parse.
static std::optional< StackCFIRecord > parse(llvm::StringRef Line)
static std::optional< StackWinRecord > parse(llvm::StringRef Line)
std::unique_ptr< LineTable > line_table_up
std::optional< FileSpecList > support_files
size_t ParseBlocksRecursive(Function &func) override
uint64_t GetDebugInfoSize(bool load_all_debug_info=false) override
Metrics gathering functions.
size_t ParseFunctions(CompileUnit &comp_unit) override
uint32_t CalculateAbilities() override
static void DebuggerInitialize(Debugger &debugger)
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override
lldb::UnwindPlanSP ParseCFIUnwindPlan(const Bookmark &bookmark, const RegisterInfoResolver &resolver)
uint32_t CalculateNumCompileUnits() override
static llvm::StringRef GetPluginNameStatic()
lldb::UnwindPlanSP ParseWinUnwindPlan(const Bookmark &bookmark, const RegisterInfoResolver &resolver)
llvm::ArrayRef< uint8_t > SaveAsDWARF(postfix::Node &node)
lldb::addr_t GetBaseFileAddress()
bool ParseCFIUnwindRow(llvm::StringRef unwind_rules, const RegisterInfoResolver &resolver, UnwindPlan::Row &row)
lldb::UnwindPlanSP GetUnwindPlan(const Address &address, const RegisterInfoResolver &resolver) override
llvm::Expected< lldb::addr_t > GetParameterStackSize(Symbol &symbol) override
Return the number of stack bytes taken up by the parameters to this function.
std::optional< std::vector< llvm::StringRef > > m_inline_origins
static llvm::StringRef GetPluginDescriptionStatic()
std::optional< std::vector< FileSpec > > m_files
bool ParseLineTable(CompileUnit &comp_unit) override
uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) override
static SymbolFile * CreateInstance(lldb::ObjectFileSP objfile_sp)
void FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) override
static char ID
LLVM RTTI support.
void AddSymbols(Symtab &symtab) override
bool ParseSupportFiles(CompileUnit &comp_unit, SupportFileList &support_files) override
std::optional< CompUnitMap > m_cu_data
std::optional< UnwindData > m_unwind_data
llvm::BumpPtrAllocator m_allocator
void ParseLineTableAndSupportFiles(CompileUnit &cu, CompUnitData &data)
void ParseInlineOriginRecords()
lldb::FunctionSP GetOrCreateFunction(CompileUnit &comp_unit)
llvm::iterator_range< LineIterator > lines(Record::Kind section_type)
The base class for all nodes in the parsed postfix tree.
A node representing a symbolic reference to a named entity.
llvm::StringRef GetName() const
#define LLDB_INVALID_ADDRESS
#define LLDB_REGNUM_GENERIC_PC
llvm::StringRef toString(Record::Kind K)
Node * ParseOneExpression(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc)
Parse the given postfix expression.
bool ResolveSymbols(Node *&node, llvm::function_ref< Node *(SymbolNode &symbol)> replacer)
A utility function for "resolving" SymbolNodes.
std::vector< std::pair< llvm::StringRef, Node * > > ParseFPOProgram(llvm::StringRef prog, llvm::BumpPtrAllocator &alloc)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
const char * toString(AppleArm64ExceptionClass EC)
std::shared_ptr< lldb_private::Function > FunctionSP
std::shared_ptr< lldb_private::Block > BlockSP
@ eLanguageTypeUnknown
Unknown or invalid language value.
std::shared_ptr< lldb_private::UnwindPlan > UnwindPlanSP
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::CompileUnit > CompUnitSP
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
virtual const RegisterInfo * ResolveNumber(lldb::RegisterKind kind, uint32_t number) const =0
virtual const RegisterInfo * ResolveName(llvm::StringRef name) const =0
lldb::user_id_t GetID() const
Get accessor for the user ID.