From 48672afb662f4b23e1934debdb84ad9a20dd9ced Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Tue, 24 Jun 2014 22:22:43 +0000 Subject: [PATCH] Patch from Keno Fischer to enable JITLoaderGDB with mach-o file support. The patch is as is with the functionality left disabled for apple vendors because of performance regressions. If this is enabled it ends up searching for symbols in all shared libraries that are loadeded. llvm-svn: 211638 --- lldb/include/lldb/Core/Section.h | 14 ++++ lldb/lib/Makefile | 4 +- lldb/source/Core/Section.cpp | 6 +- lldb/source/Expression/IRExecutionUnit.cpp | 1 + lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 84 +++++++++++++++++++--- lldb/source/Plugins/Makefile | 2 + .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 1 + .../Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 5 +- .../Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 1 + 9 files changed, 107 insertions(+), 11 deletions(-) diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h index 437eaf5..32dac5f 100644 --- a/lldb/include/lldb/Core/Section.h +++ b/lldb/include/lldb/Core/Section.h @@ -119,6 +119,7 @@ public: lldb::addr_t vm_size, lldb::offset_t file_offset, lldb::offset_t file_size, + uint32_t log2align, uint32_t flags); // Create a section that is a child of parent_section_sp @@ -132,6 +133,7 @@ public: lldb::addr_t vm_size, lldb::offset_t file_offset, lldb::offset_t file_size, + uint32_t log2align, uint32_t flags); ~Section (); @@ -284,6 +286,17 @@ public: return m_obj_file; } + uint32_t GetLog2Align() + { + return m_log2align; + } + + void + SetLog2Align(uint32_t align) + { + m_log2align = align; + } + protected: @@ -296,6 +309,7 @@ protected: lldb::addr_t m_byte_size; // Size in bytes that this section will occupy in memory at runtime lldb::offset_t m_file_offset; // Object file offset (if any) lldb::offset_t m_file_size; // Object file size (can be smaller than m_byte_size for zero filled sections...) + uint32_t m_log2align; // log_2(align) of the section (i.e. section has to be aligned to 2^m_log2align) SectionList m_children; // Child sections bool m_fake:1, // If true, then this section only can contain the address if one of its // children contains an address. This allows for gaps between the children diff --git a/lldb/lib/Makefile b/lldb/lib/Makefile index fe0e11b..6913d01 100644 --- a/lldb/lib/Makefile +++ b/lldb/lib/Makefile @@ -101,7 +101,9 @@ ifeq ($(HOST_OS),Darwin) lldbPluginSymbolVendorMacOSX.a \ lldbPluginProcessDarwin.a \ lldbPluginProcessMachCore.a \ - lldbPluginSystemRuntimeMacOSX.a + lldbPluginSystemRuntimeMacOSX.a \ + lldbPluginProcessElfCore.a \ + lldbPluginJITLoaderGDB.a endif ifeq ($(HOST_OS),Linux) diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index deaebb4..3267c18 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -27,6 +27,7 @@ Section::Section (const ModuleSP &module_sp, addr_t byte_size, lldb::offset_t file_offset, lldb::offset_t file_size, + uint32_t log2align, uint32_t flags) : ModuleChild (module_sp), UserID (sect_id), @@ -39,6 +40,7 @@ Section::Section (const ModuleSP &module_sp, m_byte_size (byte_size), m_file_offset (file_offset), m_file_size (file_size), + m_log2align (log2align), m_children (), m_fake (false), m_encrypted (false), @@ -58,6 +60,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp, addr_t byte_size, lldb::offset_t file_offset, lldb::offset_t file_size, + uint32_t log2align, uint32_t flags) : ModuleChild (module_sp), UserID (sect_id), @@ -70,6 +73,7 @@ Section::Section (const lldb::SectionSP &parent_section_sp, m_byte_size (byte_size), m_file_offset (file_offset), m_file_size (file_size), + m_log2align (log2align), m_children (), m_fake (false), m_encrypted (false), @@ -142,7 +146,7 @@ Section::GetLoadBaseAddress (Target *target) const if (load_base_addr != LLDB_INVALID_ADDRESS) load_base_addr += GetOffset(); } - else + if (load_base_addr == LLDB_INVALID_ADDRESS) { load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast
(this)->shared_from_this()); } diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 9934a3b..90d8d76 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -917,6 +917,7 @@ IRExecutionUnit::PopulateSectionList (lldb_private::ObjectFile *obj_file, record.m_size, record.m_host_address, // file_offset (which is the host address for the data) record.m_size, // file_size + 0, record.m_permissions)); // flags section_list.AddSection (section_sp); } diff --git a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index d95271e..905984d 100644 --- a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -102,13 +102,15 @@ JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) log->Printf("JITLoaderGDB::%s looking for JIT register hook", __FUNCTION__); - addr_t jit_addr = GetSymbolAddress( - module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny); + addr_t jit_addr = GetSymbolAddress(module_list, + ConstString("__jit_debug_register_code"), + eSymbolTypeAny); if (jit_addr == LLDB_INVALID_ADDRESS) return; - m_jit_descriptor_addr = GetSymbolAddress( - module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData); + m_jit_descriptor_addr = GetSymbolAddress(module_list, + ConstString("__jit_debug_descriptor"), + eSymbolTypeData); if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) { if (log) @@ -144,6 +146,55 @@ JITLoaderGDB::JITDebugBreakpointHit(void *baton, return instance->ReadJITDescriptor(false); } +static void updateSectionLoadAddress(const SectionList §ion_list, + Target &target, + uint64_t symbolfile_addr, + uint64_t symbolfile_size, + uint64_t &vmaddrheuristic, + uint64_t &min_addr, + uint64_t &max_addr) +{ + const uint32_t num_sections = section_list.GetSize(); + for (uint32_t i = 0; iIsFake()) { + uint64_t lower = (uint64_t)-1; + uint64_t upper = 0; + updateSectionLoadAddress(section_sp->GetChildren(), target, symbolfile_addr, symbolfile_size, vmaddrheuristic, + lower, upper); + if (lower < min_addr) + min_addr = lower; + if (upper > max_addr) + max_addr = upper; + const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress(); + section_sp->Slide(slide_amount, false); + section_sp->GetChildren().Slide(-slide_amount, false); + section_sp->SetByteSize (upper - lower); + } else { + vmaddrheuristic += 2<GetLog2Align(); + uint64_t lower; + if (section_sp->GetFileAddress() > vmaddrheuristic) + lower = section_sp->GetFileAddress(); + else { + lower = symbolfile_addr+section_sp->GetFileOffset(); + section_sp->SetFileAddress(symbolfile_addr+section_sp->GetFileOffset()); + } + target.SetSectionLoadAddress(section_sp, lower, true); + uint64_t upper = lower + section_sp->GetByteSize(); + if (lower < min_addr) + min_addr = lower; + if (upper > max_addr) + max_addr = upper; + // This is an upper bound, but a good enough heuristic + vmaddrheuristic += section_sp->GetByteSize(); + } + } + } +} + bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) { @@ -209,10 +260,27 @@ JITLoaderGDB::ReadJITDescriptor(bool all_entries) if (module_sp && module_sp->GetObjectFile()) { bool changed; - m_jit_objects.insert( - std::pair( - symbolfile_addr, module_sp)); - module_sp->SetLoadAddress(target, 0, true, changed); + m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp)); + if (module_sp->GetObjectFile()->GetPluginName() == ConstString("mach-o")) + { + ObjectFile *image_object_file = module_sp->GetObjectFile(); + if (image_object_file) + { + const SectionList *section_list = image_object_file->GetSectionList (); + if (section_list) + { + uint64_t vmaddrheuristic = 0; + uint64_t lower = (uint64_t)-1; + uint64_t upper = 0; + updateSectionLoadAddress(*section_list, target, symbolfile_addr, symbolfile_size, + vmaddrheuristic, lower, upper); + } + } + } + else + { + module_sp->SetLoadAddress(target, 0, true, changed); + } // load the symbol table right away module_sp->GetObjectFile()->GetSymtab(); diff --git a/lldb/source/Plugins/Makefile b/lldb/source/Plugins/Makefile index eb15cf9..ed8c3b7 100644 --- a/lldb/source/Plugins/Makefile +++ b/lldb/source/Plugins/Makefile @@ -33,6 +33,8 @@ DIRS += SymbolVendor/MacOSX #DIRS += Process/MacOSX-User DIRS += Process/mach-core DIRS += SystemRuntime/MacOSX +DIRS += Process/elf-core +DIRS += JITLoader/GDB endif ifeq ($(HOST_OS),Linux) diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index e4de46e..688b64c 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1236,6 +1236,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) vm_size, // VM size in bytes of this section. header.sh_offset, // Offset of this section in the file. file_size, // Size of the section as found in the file. + __builtin_ffs(header.sh_addralign), // Alignment of the section header.sh_flags)); // Flags for this section. if (is_thread_specific) diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 9eab3a1..9341e27 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1346,6 +1346,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) load_cmd.vmsize, // VM size in bytes of this section load_cmd.fileoff, // Offset to the data for this section in the file load_cmd.filesize, // Size in bytes of this section as found in the the file + 0, // Segments have no alignment information load_cmd.flags)); // Flags for this section segment_sp->SetIsEncrypted (segment_is_encrypted); @@ -1474,6 +1475,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) sect64.size, // VM size in bytes of this section sect64.offset, // Offset to the data for this section in the file sect64.offset ? sect64.size : 0, // Size in bytes of this section as found in the the file + sect64.align, load_cmd.flags)); // Flags for this section segment_sp->SetIsFake(true); @@ -1612,6 +1614,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) sect64.size, sect64.offset, sect64.offset == 0 ? 0 : sect64.size, + sect64.align, sect64.flags)); // Set the section to be encrypted to match the segment @@ -2022,7 +2025,7 @@ ObjectFileMachO::ParseSymtab () uint32_t memory_module_load_level = eMemoryModuleLoadLevelComplete; - if (process) + if (process && m_header.filetype != llvm::MachO::MH_OBJECT) { Target &target = process->GetTarget(); diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index ca70b96..7b85342 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -753,6 +753,7 @@ ObjectFilePECOFF::CreateSections (SectionList &unified_section_list) m_sect_headers[idx].vmsize, // VM size in bytes of this section m_sect_headers[idx].offset, // Offset to the data for this section in the file m_sect_headers[idx].size, // Size in bytes of this section as found in the the file + m_coff_header_opt.sect_alignment, // Section alignment m_sect_headers[idx].flags)); // Flags for this section //section_sp->SetIsEncrypted (segment_is_encrypted); -- 2.7.4