diff --git a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h index bd0b9941d192..d5d5e071169b 100644 --- a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -54,6 +54,25 @@ public: bool GetUnwindPlan (Address addr, UnwindPlan& unwind_plan); + typedef RangeVector FunctionAddressAndSizeVector; + + //------------------------------------------------------------------ + // Build a vector of file address and size for all functions in this Module + // based on the eh_frame FDE entries. + // + // The eh_frame information can be a useful source of file address and size of + // the functions in a Module. Often a binary's non-exported symbols are stripped + // before shipping so lldb won't know the start addr / size of many functions + // in the Module. But the eh_frame can help to give the addresses of these + // stripped symbols, at least. + // + // @param[out] function_info + // A vector provided by the caller is filled out. May be empty if no FDEs/no eh_frame + // is present in this Module. + + void + GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info); + private: enum { @@ -81,13 +100,13 @@ private: typedef STD_SHARED_PTR(CIE) CIESP; - // Start address, size, offset of FDE location + typedef std::map cie_map_t; + + // Start address (file address), size, offset of FDE location // used for finding an FDE for a given File address; the start address field is // an offset into an individual Module. typedef RangeDataVector FDEEntryMap; - typedef std::map cie_map_t; - bool IsEHFrame() const; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index e2b75ad8e16f..6f3093236897 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -28,6 +28,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" @@ -1449,6 +1450,17 @@ ObjectFileMachO::ParseSymtab (bool minimize) eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame); const bool is_arm = (m_header.cputype == llvm::MachO::CPUTypeARM); + + // lldb works best if it knows the start addresss of all functions in a module. + // Linker symbols or debug info are normally the best source of information for start addr / size but + // they may be stripped in a released binary. + // Two additional sources of information exist in Mach-O binaries: + // LC_FUNCTION_STARTS - a list of ULEB128 encoded offsets of each function's start address in the + // binary, relative to the text section. + // eh_frame - the eh_frame FDEs have the start addr & size of each function + // LC_FUNCTION_STARTS is the fastest source to read in, and is present on all modern binaries. + // Binaries built to run on older releases may need to use eh_frame information. + if (text_section_sp && function_starts_data.GetByteSize()) { FunctionStarts::Entry function_start_entry; @@ -1462,6 +1474,27 @@ ObjectFileMachO::ParseSymtab (bool minimize) function_start_entry.addr += delta; function_starts.Append(function_start_entry); } + } + else + { + if (text_section_sp.get() && eh_frame_section_sp.get()) + { + DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp, eRegisterKindGCC, true); + DWARFCallFrameInfo::FunctionAddressAndSizeVector functions; + eh_frame.GetFunctionAddressAndSizeVector (functions); + addr_t text_base_addr = text_section_sp->GetFileAddress(); + size_t count = functions.GetSize(); + for (size_t i = 0; i < count; ++i) + { + const DWARFCallFrameInfo::FunctionAddressAndSizeVector::Entry *func = functions.GetEntryAtIndex (i); + if (func) + { + FunctionStarts::Entry function_start_entry; + function_start_entry.addr = func->base - text_base_addr; + function_starts.Append(function_start_entry); + } + } + } } const size_t function_starts_count = function_starts.GetSize(); diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp index 3bc0e7e07fdf..c8bc08bbd991 100644 --- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -104,6 +104,22 @@ DWARFCallFrameInfo::GetFDEEntryByFileAddress (addr_t file_addr, FDEEntryMap::Ent return true; } +void +DWARFCallFrameInfo::GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info) +{ + GetFDEIndex(); + const size_t count = m_fde_index.GetSize(); + for (size_t i = 0; i < count; ++i) + { + const FDEEntryMap::Entry *func_offset_data_entry = m_fde_index.GetEntryAtIndex (i); + if (func_offset_data_entry) + { + FunctionAddressAndSizeVector::Entry function_offset_entry (func_offset_data_entry->base, func_offset_data_entry->size); + function_info.Append (function_offset_entry); + } + } +} + const DWARFCallFrameInfo::CIE* DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) {