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>(
m_objfile_sp->GetModule(),
220 nullptr, spec, index,
237 LLDB_LOG(log,
"Unable to fetch the base address of object file. Skipping "
238 "symtab population.");
250 addr_t address = record->Address + base;
254 section_sp, address - section_sp->GetFileAddress(), record->Size);
256 func_sp = std::make_shared<Function>(&comp_unit,
id, 0, func_name,
257 nullptr, func_range);
299 std::vector<Block *> blocks;
302 blocks.push_back(&block);
304 size_t blocks_added = 0;
310 size_t last_added_nest_level = 0;
313 if (record->InlineNestLevel == 0 ||
314 record->InlineNestLevel <= last_added_nest_level + 1) {
315 last_added_nest_level = record->InlineNestLevel;
316 BlockSP block_sp = std::make_shared<Block>(It.GetBookmark().offset);
318 if (record->CallSiteFileNum <
m_files->size())
319 callsite_file = (*m_files)[record->CallSiteFileNum];
320 llvm::StringRef name;
322 name = (*m_inline_origins)[record->OriginNum];
324 Declaration callsite(callsite_file, record->CallSiteLineNum);
325 block_sp->SetInlinedFunctionInfo(name.str().c_str(),
328 for (
const auto &range : record->Ranges) {
332 block_sp->FinalizeRanges();
334 blocks[record->InlineNestLevel]->AddChild(block_sp);
335 if (record->InlineNestLevel + 1 >= blocks.size()) {
336 blocks.resize(blocks.size() + 1);
338 blocks[record->InlineNestLevel + 1] = block_sp.get();
356 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", line);
362 (*m_inline_origins)[record->Number] = record->Name;
368 SymbolContextItem resolve_scope,
371 if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry |
372 eSymbolContextFunction | eSymbolContextBlock)))
382 SymbolContextItem result = eSymbolContextCompUnit;
383 if (resolve_scope & eSymbolContextLineEntry) {
386 result |= eSymbolContextLineEntry;
390 if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
394 result |= eSymbolContextFunction;
395 if (resolve_scope & eSymbolContextBlock) {
396 Block &block = func_sp->GetBlock(
true);
401 result |= eSymbolContextBlock;
413 if (!(resolve_scope & eSymbolContextCompUnit))
416 uint32_t old_size = sc_list.
GetSize();
421 return sc_list.
GetSize() - old_size;
435 if (func_sp && name == func_sp->GetNameNoArguments()) {
439 sc.
module_sp = func_sp->CalculateSymbolContextModule();
446 bool include_inlines,
453 uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
457 llvm::ArrayRef<CompilerContext> pattern,
LanguageSet languages,
458 llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) {}
465 LLDB_LOG(log,
"Unable to fetch the base address of object file. Skipping "
466 "symtab population.");
471 llvm::DenseSet<addr_t> found_symbol_addresses;
472 std::vector<Symbol> symbols;
473 auto add_symbol = [&](
addr_t address, std::optional<addr_t> size,
474 llvm::StringRef name) {
479 "Ignoring symbol {0}, whose address ({1}) is outside of the "
480 "object file. Mismatched symbol file?",
486 if (!found_symbol_addresses.insert(address).second)
488 symbols.emplace_back(
492 AddressRange(section_sp, address - section_sp->GetFileAddress(),
494 size.has_value(),
false, 0);
499 add_symbol(record->Address, std::nullopt, record->Name);
501 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", line);
504 for (
Symbol &symbol : symbols)
509llvm::Expected<lldb::addr_t>
517 return record->ParameterSize;
519 return llvm::createStringError(llvm::inconvertibleErrorCode(),
520 "Parameter size unknown.");
523static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
529 llvm::StringRef lhs, rest;
530 std::tie(lhs, rest) = getToken(unwind_rules);
531 if (!lhs.consume_back(
":"))
535 llvm::StringRef::size_type pos = rest.find(
": ");
536 if (pos == llvm::StringRef::npos) {
538 unwind_rules = llvm::StringRef();
539 return std::make_pair(lhs, rest);
543 pos = rest.rfind(
' ', pos);
544 if (pos == llvm::StringRef::npos)
547 llvm::StringRef rhs = rest.take_front(pos);
548 unwind_rules = rest.drop_front(pos);
549 return std::make_pair(lhs, rhs);
555 llvm::StringRef name) {
556 if (triple.isX86() || triple.isMIPS()) {
559 if (!name.consume_front(
"$"))
568 llvm::StringRef name) {
578 ToDWARF(node,
dwarf);
580 std::memcpy(saved,
dwarf.GetData(),
dwarf.GetSize());
581 return {saved,
dwarf.GetSize()};
589 llvm::BumpPtrAllocator node_alloc;
590 llvm::Triple triple =
m_objfile_sp->GetArchitecture().GetTriple();
591 while (
auto rule =
GetRule(unwind_rules)) {
593 llvm::StringRef lhs = rule->first;
596 LLDB_LOG(log,
"Could not parse `{0}` as unwind rhs.", rule->second);
602 llvm::StringRef name = symbol.
GetName();
603 if (name ==
".cfa" && lhs !=
".cfa")
604 return postfix::MakeNode<postfix::InitialValueNode>(node_alloc);
608 return postfix::MakeNode<postfix::RegisterNode>(
615 LLDB_LOG(log,
"Resolving symbols in `{0}` failed.", rule->second);
628 LLDB_LOG(log,
"Invalid register `{0}` in unwind rule.", lhs);
630 if (unwind_rules.empty())
633 LLDB_LOG(log,
"Could not parse `{0}` as an unwind rule.", unwind_rules);
660 assert(init_record && init_record->Size &&
661 "Record already parsed successfully in ParseUnwindData!");
664 plan_sp->SetSourceName(
"breakpad STACK CFI");
665 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
668 plan_sp->SetPlanValidAddressRange(
669 AddressRange(base + init_record->Address, *init_record->Size,
672 auto row_sp = std::make_shared<UnwindPlan::Row>();
673 row_sp->SetOffset(0);
676 plan_sp->AppendRow(row_sp);
677 for (++It; It != End; ++It) {
684 row_sp = std::make_shared<UnwindPlan::Row>(*row_sp);
685 row_sp->SetOffset(record->Address - init_record->Address);
688 plan_sp->AppendRow(row_sp);
703 assert(record &&
"Record already parsed successfully in ParseUnwindData!");
706 plan_sp->SetSourceName(
"breakpad STACK WIN");
707 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
710 plan_sp->SetPlanValidAddressRange(
714 auto row_sp = std::make_shared<UnwindPlan::Row>();
715 row_sp->SetOffset(0);
717 llvm::BumpPtrAllocator node_alloc;
718 std::vector<std::pair<llvm::StringRef, postfix::Node *>> program =
721 if (program.empty()) {
722 LLDB_LOG(log,
"Invalid unwind rule: {0}.", record->ProgramString);
725 auto it = program.begin();
726 llvm::Triple triple =
m_objfile_sp->GetArchitecture().GetTriple();
727 const auto &symbol_resolver =
729 llvm::StringRef name = symbol.GetName();
730 for (
const auto &rule : llvm::make_range(program.begin(), it)) {
731 if (rule.first == name)
735 return postfix::MakeNode<postfix::RegisterNode>(
742 auto *symbol = llvm::dyn_cast<postfix::SymbolNode>(it->second);
743 if (symbol && symbol->GetName() ==
".raSearch") {
744 row_sp->GetCFAValue().SetRaSearch(record->LocalSize +
745 record->SavedRegisterSize);
748 LLDB_LOG(log,
"Resolving symbols in `{0}` failed.",
749 record->ProgramString);
752 llvm::ArrayRef<uint8_t> saved =
SaveAsDWARF(*it->second);
753 row_sp->GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size());
759 it->second = postfix::MakeNode<postfix::InitialValueNode>(node_alloc);
763 for (++it; it != program.end(); ++it) {
770 LLDB_LOG(log,
"Resolving symbols in `{0}` failed.",
771 record->ProgramString);
775 llvm::ArrayRef<uint8_t> saved =
SaveAsDWARF(*it->second);
781 plan_sp->AppendRow(row_sp);
803 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", line);
807 if (record->Number >=
m_files->size())
808 m_files->resize(record->Number + 1);
810 .value_or(FileSpec::Style::native);
811 (*m_files)[record->Number] =
FileSpec(record->Name, style);
823 LLDB_LOG(log,
"SymbolFile parsing failed: Unable to fetch the base address "
835 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", *It);
846 "How did we create compile units without a base address?");
849 std::vector<std::unique_ptr<LineSequence>> sequences;
850 std::unique_ptr<LineSequence> line_seq_up =
852 std::optional<addr_t> next_addr;
853 auto finish_sequence = [&]() {
855 line_seq_up.get(), *next_addr, 0, 0,
859 sequences.push_back(std::move(line_seq_up));
866 for (++It; It != End; ++It) {
875 record->Address += base;
877 if (next_addr && *next_addr != record->Address) {
882 line_seq_up.get(), record->Address, record->LineNum, 0,
883 map[record->FileNum],
true,
886 next_addr = record->Address + record->Size;
890 data.
line_table_up = std::make_unique<LineTable>(&cu, std::move(sequences));
902 LLDB_LOG(log,
"SymbolFile parsing failed: Unable to fetch the base address "
911 base + record->Address, *record->Size, It.GetBookmark()));
913 LLDB_LOG(log,
"Failed to parse: {0}. Skipping record.", *It);
921 base + record->RVA, record->CodeSize, It.GetBookmark()));
923 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 file associated with this compile unit.
void ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list)
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.
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
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
bool ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) 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
void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, llvm::DenseSet< SymbolFile * > &searched_symbol_files, TypeMap &types) override
uint64_t GetDebugInfoSize() override
Metrics gathering functions.
static char ID
LLVM RTTI support.
void AddSymbols(Symtab &symtab) 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
A SmallBitVector that represents a set of source languages (lldb::LanguageType).
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.