Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -10,6 +10,7 @@ #ifndef liblldb_ObjectFileELF_h_ #define liblldb_ObjectFileELF_h_ +#include #include #include @@ -216,6 +217,8 @@ typedef DynamicSymbolColl::iterator DynamicSymbolCollIter; typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter; + typedef std::function SetDataFunction; + /// Version of this reader common to all plugins based on this class. static const uint32_t m_plugin_version = 1; static const uint32_t g_core_uuid_magic; @@ -249,6 +252,8 @@ /// The architecture detected from parsing elf file contents. lldb_private::ArchSpec m_arch_spec; + const lldb::addr_t m_header_addr; + /// Returns a 1 based index of the given section header. size_t SectionIndex(const SectionHeaderCollIter &I); @@ -260,7 +265,7 @@ // Parses the ELF program headers. static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers, - lldb_private::DataExtractor &data, + const SetDataFunction set_data, const elf::ELFHeader &header); // Finds PT_NOTE segments and calculates their crc sum. @@ -283,7 +288,7 @@ /// Parses the elf section headers and returns the uuid, debug link name, crc, archspec. static size_t GetSectionHeaderInfo(SectionHeaderColl §ion_headers, - lldb_private::DataExtractor &data, + const SetDataFunction set_data, const elf::ELFHeader &header, lldb_private::UUID &uuid, std::string &gnu_debuglink_file, @@ -418,6 +423,12 @@ static lldb_private::Error RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid); + + static lldb::offset_t + SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length); + + lldb::offset_t + SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length); }; #endif // #ifndef liblldb_ObjectFileELF_h_ Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -591,7 +591,11 @@ lldb::offset_t length, lldb_private::ModuleSpecList &specs) { + using namespace std::placeholders; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES)); + if (log) + log->Printf("ObjectFileELF::%s", __FUNCTION__); const size_t initial_count = specs.GetSize(); @@ -645,7 +649,8 @@ SectionHeaderColl section_headers; lldb_private::UUID &uuid = spec.GetUUID(); - GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ()); + const SetDataFunction set_data = std::bind(&ObjectFileELF::SetData, std::cref(data), _1, _2, _3); + GetSectionHeaderInfo(section_headers, set_data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ()); // If the module vendor is not set and the module OS matches this host OS, set the module vendor to the host vendor. llvm::Triple &spec_triple = spec.GetArchitecture ().GetTriple (); @@ -682,7 +687,7 @@ data.SetData(data_sp); } ProgramHeaderColl program_headers; - GetProgramHeaderInfo(program_headers, data, header); + GetProgramHeaderInfo(program_headers, set_data, header); size_t segment_data_end = 0; for (ProgramHeaderCollConstIter I = program_headers.begin(); @@ -765,7 +770,8 @@ m_dynamic_symbols(), m_filespec_ap(), m_entry_point_address(), - m_arch_spec() + m_arch_spec(), + m_header_addr(LLDB_INVALID_ADDRESS) { if (file) m_file = *file; @@ -786,7 +792,8 @@ m_dynamic_symbols(), m_filespec_ap(), m_entry_point_address(), - m_arch_spec() + m_arch_spec(), + m_header_addr(header_addr) { ::memset(&m_header, 0, sizeof(m_header)); } @@ -806,9 +813,13 @@ lldb::addr_t value, bool value_is_offset) { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES)); + ModuleSP module_sp = GetModule(); if (module_sp) { + if (log) + log->Printf("S1"); size_t num_loaded_sections = 0; SectionList *section_list = GetSectionList (); if (section_list) @@ -817,17 +828,28 @@ { const size_t num_sections = section_list->GetSize(); size_t sect_idx = 0; + if (log) + log->Printf("S2 %d", num_sections); for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { // Iterate through the object file sections to find all // of the sections that have SHF_ALLOC in their flag bits. SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); + if (section_sp && log) + log->Printf("S30 %s, %d, flags %d", section_sp->GetName().GetCString(), sect_idx, section_sp->Get()); // if (section_sp && !section_sp->IsThreadSpecific()) if (section_sp && section_sp->Test(SHF_ALLOC)) { + if (log) + log->Printf("S3 %d", sect_idx); + if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value)) + { + if (log) + log->Printf("S4 %d", sect_idx); ++num_loaded_sections; + } } } return num_loaded_sections > 0; @@ -905,8 +927,18 @@ bool ObjectFileELF::ParseHeader() { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES)); + lldb::offset_t offset = 0; - return m_header.Parse(m_data, &offset); + bool res = m_header.Parse(m_data, &offset); + if (res && log) + { + log->Printf("ELF header: header size=%d, programs headers(%x, %d, %d), section headers(%x, %d, %d)", + m_header.e_ehsize, + m_header.e_phoff, (m_header.e_phentsize * m_header.e_phnum), m_header.e_phnum, + m_header.e_shoff, (m_header.e_shentsize * m_header.e_shnum), m_header.e_shnum); + } + return res; } bool @@ -1121,7 +1153,7 @@ //---------------------------------------------------------------------- size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers, - DataExtractor &object_data, + const SetDataFunction set_data, const ELFHeader &header) { // We have already parsed the program headers @@ -1139,7 +1171,7 @@ const size_t ph_size = header.e_phnum * header.e_phentsize; const elf_off ph_offset = header.e_phoff; DataExtractor data; - if (data.SetData(object_data, ph_offset, ph_size) != ph_size) + if (set_data(data, ph_offset, ph_size) != ph_size) return 0; uint32_t idx; @@ -1163,7 +1195,11 @@ size_t ObjectFileELF::ParseProgramHeaders() { - return GetProgramHeaderInfo(m_program_headers, m_data, m_header); + using namespace std::placeholders; + + return GetProgramHeaderInfo(m_program_headers, + std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3), + m_header); } lldb_private::Error @@ -1351,7 +1387,7 @@ //---------------------------------------------------------------------- size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, - lldb_private::DataExtractor &object_data, + const SetDataFunction set_data, const elf::ELFHeader &header, lldb_private::UUID &uuid, std::string &gnu_debuglink_file, @@ -1407,7 +1443,7 @@ const size_t sh_size = header.e_shnum * header.e_shentsize; const elf_off sh_offset = header.e_shoff; DataExtractor sh_data; - if (sh_data.SetData (object_data, sh_offset, sh_size) != sh_size) + if (set_data(sh_data, sh_offset, sh_size) != sh_size) return 0; uint32_t idx; @@ -1428,7 +1464,7 @@ const Elf64_Off offset = sheader.sh_offset; lldb_private::DataExtractor shstr_data; - if (shstr_data.SetData (object_data, offset, byte_size) == byte_size) + if (set_data(shstr_data, offset, byte_size) == byte_size) { for (SectionHeaderCollIter I = section_headers.begin(); I != section_headers.end(); ++I) @@ -1443,7 +1479,7 @@ if (name == g_sect_name_gnu_debuglink) { DataExtractor data; - if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + if (section_size && (set_data(data, header.sh_offset, section_size) == section_size)) { lldb::offset_t gnu_debuglink_offset = 0; gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset); @@ -1457,7 +1493,7 @@ { // Allow notes to refine module info. DataExtractor data; - if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + if (section_size && (set_data(data, header.sh_offset, section_size) == section_size)) { Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid); if (error.Fail ()) @@ -1498,10 +1534,12 @@ DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) { + DataExtractor data; const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id); - if (segment_header == NULL) - return DataExtractor(); - return DataExtractor(m_data, segment_header->p_offset, segment_header->p_filesz); + if (segment_header != nullptr) + SetDataWithReadMemoryFallback(data, segment_header->p_offset, segment_header->p_filesz); + + return data; } //---------------------------------------------------------------------- @@ -1510,7 +1548,15 @@ size_t ObjectFileELF::ParseSectionHeaders() { - return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc, m_arch_spec); + using namespace std::placeholders; + + return GetSectionHeaderInfo(m_section_headers, + std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3), + m_header, + m_uuid, + m_gnu_debuglink_file, + m_gnu_debuglink_crc, + m_arch_spec); } const ObjectFileELF::ELFSectionHeaderInfo * @@ -1966,6 +2012,10 @@ size_t ObjectFileELF::ParseDynamicSymbols() { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES)); + if (log) + log->Printf("ObjectFileELF::%s", __FUNCTION__); + if (m_dynamic_symbols.size()) return m_dynamic_symbols.size(); @@ -1995,6 +2045,8 @@ } } + if (log) + log->Printf("ObjectFileELF::%s, size %d", __FUNCTION__, m_dynamic_symbols.size()); return m_dynamic_symbols.size(); } @@ -2766,15 +2818,26 @@ bool ObjectFileELF::GetArchitecture (ArchSpec &arch) { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES)); + if (log) + log->Printf("ObjectFileELF::%s 0", __FUNCTION__); + if (!ParseHeader()) return false; + if (log) + log->Printf("ObjectFileELF::%s 1", __FUNCTION__); + if (m_section_headers.empty()) { // Allow elf notes to be parsed which may affect the detected architecture. + if (log) + log->Printf("ObjectFileELF::%s 2", __FUNCTION__); ParseSectionHeaders(); } + if (log) + log->Printf("ObjectFileELF::%s 3 %s", __FUNCTION__, m_arch_spec.GetArchitectureName()); arch = m_arch_spec; return true; } @@ -2850,3 +2913,31 @@ return eStrataUnknown; } +lldb::offset_t +ObjectFileELF::SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length) +{ + return dst.SetData(src, offset, length); +} + +lldb::offset_t +ObjectFileELF::SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES)); + + if (offset + length <= m_data.GetByteSize()) + return dst.SetData(m_data, offset, length); + + const auto process_sp = m_process_wp.lock(); + if (process_sp != nullptr) + { + const auto proc_addr = m_header_addr + offset; + const auto data_sp = ReadMemory(process_sp, proc_addr, length); + if (data_sp != nullptr) + return dst.SetData(data_sp); + + if (log) + log->Printf("ObjectFileELF::%s failed to read process memory: address 0x%" PRIx64 ", length 0x%" PRIx64, __FUNCTION__, proc_addr, length); + } + + return dst.SetData(m_data, offset, length); +}