Author: labath Date: Tue Jun 20 03:11:47 2017 New Revision: 305780 URL: http://llvm.org/viewvc/llvm-project?rev=305780&view=rev Log: [linux] Change the way we load vdso pseudo-module
Summary: This is basically a revert of D16107 and parts of D10800, which were trying to get vdso loading working. They did this by implementing a generic load-an-elf-file from memory approach, which is not correct, since we cannot assume that an elf file is loaded in memory in full (it usually isn't, as there's no need to load section headers for example). This meant that we would read garbage instead of section sizes, and if that garbage happened to be a large number, we would crash while trying to allocate a buffer to accomodate the hypothetical section. Instead of this, I add a bit of custom code to load the vdso to DynamicLoaderPOSIXDYLD (which already needed to handle the vdso specially). I determine the size of the memory to read using Process::GetMemoryRegionInfo, which is information coming from the OS, and cannot be forged by a malicious/misbehaving application. Reviewers: eugene, clayborg Subscribers: lldb-commits, ravitheja, tberghammer, emaste Differential Revision: https://reviews.llvm.org/D34352 Modified: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Modified: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=305780&r1=305779&r2=305780&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp Tue Jun 20 03:11:47 2017 @@ -21,6 +21,7 @@ #include "lldb/Core/Section.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -484,6 +485,27 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTr return thread_plan_sp; } +void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) { + if (m_vdso_base == LLDB_INVALID_ADDRESS) + return; + + FileSpec file("[vdso]", false); + + MemoryRegionInfo info; + Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info); + if (status.Fail()) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + LLDB_LOG(log, "Failed to get vdso region info: {0}", status); + return; + } + + if (ModuleSP module_sp = m_process->ReadModuleFromMemory( + file, m_vdso_base, info.GetRange().GetByteSize())) { + UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_vdso_base, false); + m_process->GetTarget().GetImages().AppendIfNeeded(module_sp); + } +} + void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { DYLDRendezvous::iterator I; DYLDRendezvous::iterator E; @@ -502,14 +524,7 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurr // that ourselves here. ModuleSP executable = GetTargetExecutable(); m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); - if (m_vdso_base != LLDB_INVALID_ADDRESS) { - FileSpec file_spec("[vdso]", false); - ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, - m_vdso_base, false); - if (module_sp.get()) { - module_list.Append(module_sp); - } - } + LoadVDSO(module_list); std::vector<FileSpec> module_names; for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) Modified: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h?rev=305780&r1=305779&r2=305780&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h Tue Jun 20 03:11:47 2017 @@ -17,11 +17,11 @@ // Other libraries and framework includes // Project includes +#include "DYLDRendezvous.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/ModuleList.h" #include "lldb/Target/DynamicLoader.h" -#include "DYLDRendezvous.h" - class AuxVector; class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { @@ -138,6 +138,8 @@ protected: /// of all dependent modules. virtual void LoadAllCurrentModules(); + void LoadVDSO(lldb_private::ModuleList &modules); + /// Computes a value for m_load_offset returning the computed address on /// success and LLDB_INVALID_ADDRESS on failure. lldb::addr_t ComputeLoadOffset(); Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=305780&r1=305779&r2=305780&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Tue Jun 20 03:11:47 2017 @@ -707,10 +707,7 @@ size_t ObjectFileELF::GetModuleSpecifica SectionHeaderColl section_headers; lldb_private::UUID &uuid = spec.GetUUID(); - using namespace std::placeholders; - const SetDataFunction set_data = - std::bind(&ObjectFileELF::SetData, std::cref(data), _1, _2, _3); - GetSectionHeaderInfo(section_headers, set_data, header, uuid, + GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture()); @@ -748,7 +745,7 @@ size_t ObjectFileELF::GetModuleSpecifica data.SetData(data_sp); } ProgramHeaderColl program_headers; - GetProgramHeaderInfo(program_headers, set_data, header); + GetProgramHeaderInfo(program_headers, data, header); size_t segment_data_end = 0; for (ProgramHeaderCollConstIter I = program_headers.begin(); @@ -950,29 +947,7 @@ size_t ObjectFileELF::SectionIndex(const bool ObjectFileELF::ParseHeader() { lldb::offset_t offset = 0; - if (!m_header.Parse(m_data, &offset)) - return false; - - if (!IsInMemory()) - return true; - - // For in memory object files m_data might not contain the full object file. - // Try to load it - // until the end of the "Section header table" what is at the end of the ELF - // file. - addr_t file_size = m_header.e_shoff + m_header.e_shnum * m_header.e_shentsize; - if (m_data.GetByteSize() < file_size) { - ProcessSP process_sp(m_process_wp.lock()); - if (!process_sp) - return false; - - DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size); - if (!data_sp) - return false; - m_data.SetData(data_sp, 0, file_size); - } - - return true; + return m_header.Parse(m_data, &offset); } bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) { @@ -1188,7 +1163,7 @@ size_t ObjectFileELF::ParseDependentModu // GetProgramHeaderInfo //---------------------------------------------------------------------- size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers, - const SetDataFunction &set_data, + DataExtractor &object_data, const ELFHeader &header) { // We have already parsed the program headers if (!program_headers.empty()) @@ -1205,7 +1180,7 @@ size_t ObjectFileELF::GetProgramHeaderIn const size_t ph_size = header.e_phnum * header.e_phentsize; const elf_off ph_offset = header.e_phoff; DataExtractor data; - if (set_data(data, ph_offset, ph_size) != ph_size) + if (data.SetData(object_data, ph_offset, ph_size) != ph_size) return 0; uint32_t idx; @@ -1225,12 +1200,7 @@ size_t ObjectFileELF::GetProgramHeaderIn // ParseProgramHeaders //---------------------------------------------------------------------- size_t ObjectFileELF::ParseProgramHeaders() { - using namespace std::placeholders; - return GetProgramHeaderInfo( - m_program_headers, - std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, - _3), - m_header); + return GetProgramHeaderInfo(m_program_headers, m_data, m_header); } lldb_private::Status @@ -1562,7 +1532,7 @@ void ObjectFileELF::ParseARMAttributes(D // GetSectionHeaderInfo //---------------------------------------------------------------------- size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, - const SetDataFunction &set_data, + DataExtractor &object_data, const elf::ELFHeader &header, lldb_private::UUID &uuid, std::string &gnu_debuglink_file, @@ -1634,7 +1604,7 @@ size_t ObjectFileELF::GetSectionHeaderIn const size_t sh_size = header.e_shnum * header.e_shentsize; const elf_off sh_offset = header.e_shoff; DataExtractor sh_data; - if (set_data(sh_data, sh_offset, sh_size) != sh_size) + if (sh_data.SetData(object_data, sh_offset, sh_size) != sh_size) return 0; uint32_t idx; @@ -1653,7 +1623,7 @@ size_t ObjectFileELF::GetSectionHeaderIn const Elf64_Off offset = sheader.sh_offset; lldb_private::DataExtractor shstr_data; - if (set_data(shstr_data, offset, byte_size) == byte_size) { + if (shstr_data.SetData(object_data, offset, byte_size) == byte_size) { for (SectionHeaderCollIter I = section_headers.begin(); I != section_headers.end(); ++I) { static ConstString g_sect_name_gnu_debuglink(".gnu_debuglink"); @@ -1669,8 +1639,8 @@ size_t ObjectFileELF::GetSectionHeaderIn DataExtractor data; if (sheader.sh_type == SHT_MIPS_ABIFLAGS) { - if (section_size && (set_data(data, sheader.sh_offset, - section_size) == section_size)) { + if (section_size && (data.SetData(object_data, sheader.sh_offset, + section_size) == section_size)) { // MIPS ASE Mask is at offset 12 in MIPS.abiflags section lldb::offset_t offset = 12; // MIPS ABI Flags Version: 0 arch_flags |= data.GetU32(&offset); @@ -1735,14 +1705,14 @@ size_t ObjectFileELF::GetSectionHeaderIn DataExtractor data; if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 && - set_data(data, sheader.sh_offset, section_size) == section_size) + data.SetData(object_data, sheader.sh_offset, section_size) == section_size) ParseARMAttributes(data, section_size, arch_spec); } if (name == g_sect_name_gnu_debuglink) { DataExtractor data; - if (section_size && (set_data(data, sheader.sh_offset, - section_size) == section_size)) { + if (section_size && (data.SetData(object_data, sheader.sh_offset, + section_size) == section_size)) { lldb::offset_t gnu_debuglink_offset = 0; gnu_debuglink_file = data.GetCStr(&gnu_debuglink_offset); gnu_debuglink_offset = llvm::alignTo(gnu_debuglink_offset, 4); @@ -1762,8 +1732,8 @@ size_t ObjectFileELF::GetSectionHeaderIn if (is_note_header) { // Allow notes to refine module info. DataExtractor data; - if (section_size && (set_data(data, sheader.sh_offset, - section_size) == section_size)) { + if (section_size && (data.SetData(object_data, sheader.sh_offset, + section_size) == section_size)) { Status error = RefineModuleDetailsFromNote(data, arch_spec, uuid); if (error.Fail()) { if (log) @@ -1819,40 +1789,9 @@ ObjectFileELF::StripLinkerSymbolAnnotati // ParseSectionHeaders //---------------------------------------------------------------------- size_t ObjectFileELF::ParseSectionHeaders() { - 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); -} - -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) { - 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) { - addr_t file_size = offset + length; - - DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size); - if (!data_sp) - return false; - m_data.SetData(data_sp, 0, file_size); - } - - return dst.SetData(m_data, offset, length); + return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, + m_gnu_debuglink_file, m_gnu_debuglink_crc, + m_arch_spec); } const ObjectFileELF::ELFSectionHeaderInfo * Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=305780&r1=305779&r2=305780&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Tue Jun 20 03:11:47 2017 @@ -14,7 +14,6 @@ #include <stdint.h> // C++ Includes -#include <functional> #include <vector> // Other libraries and framework includes @@ -182,9 +181,6 @@ private: typedef std::map<lldb::addr_t, lldb::AddressClass> FileAddressToAddressClassMap; - typedef std::function<lldb::offset_t(lldb_private::DataExtractor &, - lldb::offset_t, lldb::offset_t)> - SetDataFunction; /// Version of this reader common to all plugins based on this class. static const uint32_t m_plugin_version = 1; @@ -230,7 +226,7 @@ private: // Parses the ELF program headers. static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers, - const SetDataFunction &set_data, + lldb_private::DataExtractor &object_data, const elf::ELFHeader &header); // Finds PT_NOTE segments and calculates their crc sum. @@ -255,7 +251,7 @@ private: /// Parses the elf section headers and returns the uuid, debug link name, crc, /// archspec. static size_t GetSectionHeaderInfo(SectionHeaderColl §ion_headers, - const SetDataFunction &set_data, + lldb_private::DataExtractor &object_data, const elf::ELFHeader &header, lldb_private::UUID &uuid, std::string &gnu_debuglink_file, @@ -379,14 +375,6 @@ private: 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 // liblldb_ObjectFileELF_h_ _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits