Author: Jason Molenda Date: 2022-08-02T13:53:34-07:00 New Revision: 803386da2ff80f0a5e75d2baee6dfa79d9d8d26f
URL: https://github.com/llvm/llvm-project/commit/803386da2ff80f0a5e75d2baee6dfa79d9d8d26f DIFF: https://github.com/llvm/llvm-project/commit/803386da2ff80f0a5e75d2baee6dfa79d9d8d26f.diff LOG: Revert "Allow firmware binaries to be specified only by load address" This reverts commit d8879fba8825b9799166ba0ea552d4027bfb8ad1. Debian bot failure; I included <uuid/uuid.h> to get uuid_is_null() but don't get it there. Will memcmp or whatever & recommit. Added: Modified: lldb/docs/lldb-gdb-remote.txt lldb/include/lldb/Target/DynamicLoader.h lldb/source/Core/DynamicLoader.cpp lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp Removed: lldb/test/API/macosx/lc-note/multiple-binary-corefile/Makefile lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py lldb/test/API/macosx/lc-note/multiple-binary-corefile/create-multibin-corefile.cpp lldb/test/API/macosx/lc-note/multiple-binary-corefile/main.c lldb/test/API/macosx/lc-note/multiple-binary-corefile/one.c lldb/test/API/macosx/lc-note/multiple-binary-corefile/two.c ################################################################################ diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index 497980ed1229..820f3bd7bbc2 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -1073,12 +1073,6 @@ main-binary-uuid: is the UUID of a firmware type binary that the gdb stub knows main-binary-address: is the load address of the firmware type binary main-binary-slide: is the slide of the firmware type binary, if address isn't known -binary-addresses: A comma-separated list of binary load addresses base16. - lldb will parse the binaries in memory to get UUIDs, then - try to find the binaries & debug info by UUID. Intended for - use with a small number of firmware type binaries where the - search for binary/debug info may be expensive. - //---------------------------------------------------------------------- // "qShlibInfoAddr" // diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h index 7e7a4218810b..397b4aa30344 100644 --- a/lldb/include/lldb/Target/DynamicLoader.h +++ b/lldb/include/lldb/Target/DynamicLoader.h @@ -210,52 +210,6 @@ class DynamicLoader : public PluginInterface { lldb::addr_t base_addr, bool base_addr_is_offset); - /// Find/load a binary into lldb given a UUID and the address where it is - /// loaded in memory, or a slide to be applied to the file address. - /// May force an expensive search on the computer to find the binary by - /// UUID, should not be used for a large number of binaries - intended for - /// an environment where there may be one, or a few, binaries resident in - /// memory. - /// - /// Given a UUID, search for a binary and load it at the address provided, - /// or with the slide applied, or at the file address unslid. - /// - /// Given an address, try to read the binary out of memory, get the UUID, - /// find the file if possible and load it unslid, or add the memory module. - /// - /// \param[in] process - /// The process to add this binary to. - /// - /// \param[in] uuid - /// UUID of the binary to be loaded. UUID may be empty, and if a - /// load address is supplied, will read the binary from memory, get - /// a UUID and try to find a local binary. There is a performance - /// cost to doing this, it is not preferable. - /// - /// \param[in] value - /// Address where the binary should be loaded, or read out of memory. - /// Or a slide value, to be applied to the file addresses of the binary. - /// - /// \param[in] value_is_offset - /// A flag indicating that \p value is an address, or an offset to - /// be applied to the file addresses. - /// - /// \param[in] force_symbol_search - /// Allow the search to do a possibly expensive external search for - /// the ObjectFile and/or SymbolFile. - /// - /// \param[in] notify - /// Whether ModulesDidLoad should be called when a binary has been added - /// to the Target. The caller may prefer to batch up these when loading - /// multiple binaries. - /// - /// \return - /// Returns a shared pointer for the Module that has been added. - static lldb::ModuleSP - LoadBinaryWithUUIDAndAddress(Process *process, UUID uuid, lldb::addr_t value, - bool value_is_offset, bool force_symbol_search, - bool notify); - /// Get information about the shared cache for a process, if possible. /// /// On some systems (e.g. Darwin based systems), a set of libraries that are diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index 1fe60e000c6d..96e0d4ec6555 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -13,15 +13,11 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" -#include "lldb/Symbol/LocateSymbolFile.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" #include "lldb/Utility/ConstString.h" -#include "lldb/Utility/LLDBLog.h" -#include "lldb/Utility/Log.h" #include "lldb/lldb-private-interfaces.h" #include "llvm/ADT/StringRef.h" @@ -175,100 +171,6 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, return nullptr; } -static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr) { - char namebuf[80]; - snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr); - return process->ReadModuleFromMemory(FileSpec(namebuf), addr); -} - -ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(Process *process, - UUID uuid, addr_t value, - bool value_is_offset, - bool force_symbol_search, - bool notify) { - ModuleSP memory_module_sp; - ModuleSP module_sp; - PlatformSP platform_sp = process->GetTarget().GetPlatform(); - Target &target = process->GetTarget(); - Status error; - ModuleSpec module_spec; - module_spec.GetUUID() = uuid; - - if (!uuid.IsValid() && !value_is_offset) { - memory_module_sp = ReadUnnamedMemoryModule(process, value); - - if (memory_module_sp) - uuid = memory_module_sp->GetUUID(); - } - - if (uuid.IsValid()) { - ModuleSpec module_spec; - module_spec.GetUUID() = uuid; - - if (!module_sp) - module_sp = target.GetOrCreateModule(module_spec, false, &error); - - // If we haven't found a binary, or we don't have a SymbolFile, see - // if there is an external search tool that can find it. - if (force_symbol_search && - (!module_sp || !module_sp->GetSymbolFileFileSpec())) { - Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); - if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { - module_sp = std::make_shared<Module>(module_spec); - } - } - } - - // If we couldn't find the binary anywhere else, as a last resort, - // read it out of memory. - if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) { - if (!memory_module_sp) - memory_module_sp = ReadUnnamedMemoryModule(process, value); - if (memory_module_sp) - module_sp = memory_module_sp; - } - - Log *log = GetLog(LLDBLog::DynamicLoader); - if (module_sp.get()) { - target.GetImages().AppendIfNeeded(module_sp, false); - - bool changed = false; - if (module_sp->GetObjectFile()) { - if (value != LLDB_INVALID_ADDRESS) { - LLDB_LOGF(log, "Loading binary UUID %s at %s 0x%" PRIx64, - uuid.GetAsString().c_str(), - value_is_offset ? "offset" : "address", value); - module_sp->SetLoadAddress(target, value, value_is_offset, changed); - } else { - // No address/offset/slide, load the binary at file address, - // offset 0. - LLDB_LOGF(log, "Loading binary UUID %s at file address", - uuid.GetAsString().c_str()); - module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, - changed); - } - } else { - // In-memory image, load at its true address, offset 0. - LLDB_LOGF(log, "Loading binary UUID %s from memory at address 0x%" PRIx64, - uuid.GetAsString().c_str(), value); - module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, changed); - } - - if (notify) { - ModuleList added_module; - added_module.Append(module_sp, false); - target.ModulesDidLoad(added_module); - } - } else { - LLDB_LOGF(log, "Unable to find binary with UUID %s and load it at " - "%s 0x%" PRIx64, - uuid.GetAsString().c_str(), - value_is_offset ? "offset" : "address", value); - } - - return module_sp; -} - int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, int size_in_bytes) { Status error; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 15b06dbbfaec..5dc71fca36c2 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5600,8 +5600,7 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, } if (m_data.CopyData(offset, sizeof(uuid_t), raw_uuid) != 0) { - if (!uuid_is_null(raw_uuid)) - uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t)); + uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t)); // convert the "main bin spec" type into our // ObjectFile::BinaryType enum switch (binspec_type) { @@ -6902,8 +6901,7 @@ ObjectFileMachO::GetCorefileAllImageInfos() { MachOCorefileImageEntry image_entry; image_entry.filename = (const char *)m_data.GetCStr(&filepath_offset); - if (!uuid_is_null(uuid)) - image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t)); + image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t)); image_entry.load_address = load_address; image_entry.currently_executing = currently_executing; @@ -6934,11 +6932,9 @@ ObjectFileMachO::GetCorefileAllImageInfos() { MachOCorefileImageEntry image_entry; image_entry.filename = filename; - if (!uuid_is_null(uuid)) - image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t)); + image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t)); image_entry.load_address = load_address; image_entry.slide = slide; - image_entry.currently_executing = true; image_infos.all_image_infos.push_back(image_entry); } } @@ -6955,41 +6951,42 @@ bool ObjectFileMachO::LoadCoreFileImages(lldb_private::Process &process) { ModuleList added_modules; for (const MachOCorefileImageEntry &image : image_infos.all_image_infos) { - ModuleSP module_sp; - - if (!image.filename.empty()) { - Status error; - ModuleSpec module_spec; - module_spec.GetUUID() = image.uuid; + ModuleSpec module_spec; + module_spec.GetUUID() = image.uuid; + if (image.filename.empty()) { + char namebuf[80]; + if (image.load_address != LLDB_INVALID_ADDRESS) + snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, + image.load_address); + else + snprintf(namebuf, sizeof(namebuf), "mem-image+0x%" PRIx64, image.slide); + module_spec.GetFileSpec() = FileSpec(namebuf); + } else { module_spec.GetFileSpec() = FileSpec(image.filename.c_str()); - if (image.currently_executing) { - Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); - if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { - process.GetTarget().GetOrCreateModule(module_spec, false); - } + } + if (image.currently_executing) { + Status error; + Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + process.GetTarget().GetOrCreateModule(module_spec, false); } - module_sp = - process.GetTarget().GetOrCreateModule(module_spec, false, &error); - process.GetTarget().GetImages().AppendIfNeeded(module_sp, - false /* notify */); - } else { + } + Status error; + ModuleSP module_sp = + process.GetTarget().GetOrCreateModule(module_spec, false, &error); + if (!module_sp.get() || !module_sp->GetObjectFile()) { if (image.load_address != LLDB_INVALID_ADDRESS) { - module_sp = DynamicLoader::LoadBinaryWithUUIDAndAddress( - &process, image.uuid, image.load_address, - false /* value_is_offset */, image.currently_executing, - false /* notify */); - } else if (image.slide != LLDB_INVALID_ADDRESS) { - module_sp = DynamicLoader::LoadBinaryWithUUIDAndAddress( - &process, image.uuid, image.slide, true /* value_is_offset */, - image.currently_executing, false /* notify */); + module_sp = process.ReadModuleFromMemory(module_spec.GetFileSpec(), + image.load_address); } } - if (module_sp.get()) { // Will call ModulesDidLoad with all modules once they've all // been added to the Target with load addresses. Don't notify // here, before the load address is set. - added_modules.Append(module_sp, false /* notify */); + const bool notify = false; + process.GetTarget().GetImages().AppendIfNeeded(module_sp, notify); + added_modules.Append(module_sp, notify); if (image.segment_load_addresses.size() > 0) { if (log) { std::string uuidstr = image.uuid.GetAsString(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 8687175ee36c..580cdde57d80 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1033,13 +1033,6 @@ bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary( return true; } -std::vector<addr_t> -GDBRemoteCommunicationClient::GetProcessStandaloneBinaries() { - if (m_qProcessInfo_is_valid == eLazyBoolCalculate) - GetCurrentProcessInfo(); - return m_binary_addresses; -} - bool GDBRemoteCommunicationClient::GetGDBServerVersion() { if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) { m_gdb_server_name.clear(); @@ -2199,14 +2192,6 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { m_process_standalone_value_is_offset = false; ++num_keys_decoded; } - } else if (name.equals("binary-addresses")) { - addr_t addr; - while (!value.empty()) { - llvm::StringRef addr_str; - std::tie(addr_str, value) = value.split(','); - if (!addr_str.getAsInteger(16, addr)) - m_binary_addresses.push_back(addr); - } } } if (num_keys_decoded > 0) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 3a62747603f6..3d838d6d8074 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -220,8 +220,6 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value, bool &value_is_offset); - std::vector<lldb::addr_t> GetProcessStandaloneBinaries(); - void GetRemoteQSupported(); bool GetVContSupported(char flavor); @@ -595,7 +593,6 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { UUID m_process_standalone_uuid; lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS; bool m_process_standalone_value_is_offset = false; - std::vector<lldb::addr_t> m_binary_addresses; llvm::VersionTuple m_os_version; llvm::VersionTuple m_maccatalyst_version; std::string m_os_build; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index e3dada1864da..b7de05d498aa 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -581,31 +581,80 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { ModuleSP module_sp; if (standalone_uuid.IsValid()) { - const bool force_symbol_search = true; - const bool notify = true; - DynamicLoader::LoadBinaryWithUUIDAndAddress( - this, standalone_uuid, standalone_value, - standalone_value_is_offset, force_symbol_search, notify); - } - } + ModuleSpec module_spec; + module_spec.GetUUID() = standalone_uuid; + + // Look up UUID in global module cache before attempting + // a more expensive search. + Status error = ModuleList::GetSharedModule(module_spec, module_sp, + nullptr, nullptr, nullptr); + + if (!module_sp) { + // Force a an external lookup, if that tool is available. + if (!module_spec.GetSymbolFileSpec()) { + Status error; + Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); + } + + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + module_sp = std::make_shared<Module>(module_spec); + } + } + + // If we couldn't find the binary anywhere else, as a last resort, + // read it out of memory. + if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS && + !standalone_value_is_offset) { + char namebuf[80]; + snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, + standalone_value); + module_sp = + ReadModuleFromMemory(FileSpec(namebuf), standalone_value); + } - // The remote stub may know about a list of binaries to - // force load into the process -- a firmware type situation - // where multiple binaries are present in virtual memory, - // and we are only given the addresses of the binaries. - // Not intended for use with userland debugging when we - // a DynamicLoader plugin that knows how to find the loaded - // binaries and will track updates as binaries are added. - - std::vector<addr_t> bin_addrs = m_gdb_comm.GetProcessStandaloneBinaries(); - if (bin_addrs.size()) { - UUID uuid; - const bool value_is_slide = false; - for (addr_t addr : bin_addrs) { - const bool force_symbol_search = true; - const bool notify = true; - DynamicLoader::LoadBinaryWithUUIDAndAddress( - this, uuid, addr, value_is_slide, force_symbol_search, notify); + Log *log = GetLog(LLDBLog::DynamicLoader); + if (module_sp.get()) { + target.GetImages().AppendIfNeeded(module_sp, false); + + bool changed = false; + if (module_sp->GetObjectFile()) { + if (standalone_value != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("Loading binary UUID %s at %s 0x%" PRIx64, + standalone_uuid.GetAsString().c_str(), + standalone_value_is_offset ? "offset" : "address", + standalone_value); + module_sp->SetLoadAddress(target, standalone_value, + standalone_value_is_offset, changed); + } else { + // No address/offset/slide, load the binary at file address, + // offset 0. + if (log) + log->Printf("Loading binary UUID %s at file address", + standalone_uuid.GetAsString().c_str()); + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + } else { + // In-memory image, load at its true address, offset 0. + if (log) + log->Printf("Loading binary UUID %s from memory", + standalone_uuid.GetAsString().c_str()); + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + + ModuleList added_module; + added_module.Append(module_sp, false); + target.ModulesDidLoad(added_module); + } else { + if (log) + log->Printf("Unable to find binary with UUID %s and load it at " + "%s 0x%" PRIx64, + standalone_uuid.GetAsString().c_str(), + standalone_value_is_offset ? "offset" : "address", + standalone_value); + } } } diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index 68786e8d80b0..7f943a5258c4 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -180,6 +180,88 @@ bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) { return false; } +// We have a hint about a binary -- a UUID, possibly a load address. +// Try to load a file with that UUID into lldb, and if we have a load +// address, set it correctly. Else assume that the binary was loaded +// with no slide. +static bool load_standalone_binary(UUID uuid, addr_t value, + bool value_is_offset, Target &target) { + if (uuid.IsValid()) { + ModuleSpec module_spec; + module_spec.GetUUID() = uuid; + + // Look up UUID in global module cache before attempting + // dsymForUUID-like action. + ModuleSP module_sp; + Status error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr, + nullptr, nullptr); + + if (!module_sp.get()) { + // Force a a dsymForUUID lookup, if that tool is available. + if (!module_spec.GetSymbolFileSpec()) { + Status error; + Symbols::DownloadObjectAndSymbolFile(module_spec, error, true); + } + + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + module_sp = std::make_shared<Module>(module_spec); + } + } + + // If we couldn't find the binary anywhere else, as a last resort, + // read it out of memory in the corefile. + if (!module_sp.get() && value != LLDB_INVALID_ADDRESS && !value_is_offset) { + char namebuf[80]; + snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, value); + module_sp = + target.GetProcessSP()->ReadModuleFromMemory(FileSpec(namebuf), value); + } + + if (module_sp.get()) { + target.SetArchitecture(module_sp->GetObjectFile()->GetArchitecture()); + target.GetImages().AppendIfNeeded(module_sp, false); + + // TODO: Instead of using the load address as a value, if we create a + // memory module from that address, we could get the correct segment + // offset values from the in-memory load commands and set them correctly. + // In case the load address we were given is not correct for all segments, + // e.g. something in the shared cache. DynamicLoaderDarwinKernel does + // something similar for kexts. In the context of a corefile, this would + // be an inexpensive operation. Not all binaries in a corefile will have + // a Mach-O header/load commands in memory, so this will not work in all + // cases. + + bool changed = false; + if (module_sp->GetObjectFile()) { + if (value != LLDB_INVALID_ADDRESS) { + module_sp->SetLoadAddress(target, value, value_is_offset, changed); + } else { + // No address/offset/slide, load the binary at file address, + // offset 0. + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + } else { + // In-memory image, load at its true address, offset 0. + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + + ModuleList added_module; + added_module.Append(module_sp, false); + target.ModulesDidLoad(added_module); + + // Flush info in the process (stack frames, etc). + ProcessSP process_sp(target.GetProcessSP()); + if (process_sp) + process_sp->Flush(); + + return true; + } + } + return false; +} + // Process Control Status ProcessMachCore::DoLoadCore() { Log *log(GetLog(LLDBLog::DynamicLoader | LLDBLog::Process)); @@ -277,21 +359,28 @@ Status ProcessMachCore::DoLoadCore() { objfile_binary_uuid.GetAsString().c_str(), objfile_binary_value, objfile_binary_value_is_offset, type); } - const bool force_symbol_search = true; - const bool notify = true; - if (DynamicLoader::LoadBinaryWithUUIDAndAddress( - this, objfile_binary_uuid, objfile_binary_value, - objfile_binary_value_is_offset, force_symbol_search, notify)) { - found_main_binary_definitively = true; - m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic(); - } - if (type == ObjectFile::eBinaryTypeUser) { - m_dyld_addr = objfile_binary_value; - m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + if (objfile_binary_value != LLDB_INVALID_ADDRESS && + !objfile_binary_value_is_offset) { + if (type == ObjectFile::eBinaryTypeUser) { + load_standalone_binary(objfile_binary_uuid, objfile_binary_value, + objfile_binary_value_is_offset, GetTarget()); + m_dyld_addr = objfile_binary_value; + m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); + found_main_binary_definitively = true; + } + if (type == ObjectFile::eBinaryTypeKernel) { + m_mach_kernel_addr = objfile_binary_value; + m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); + found_main_binary_definitively = true; + } } - if (type == ObjectFile::eBinaryTypeKernel) { - m_mach_kernel_addr = objfile_binary_value; - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); + if (!found_main_binary_definitively) { + // ObjectFile::eBinaryTypeStandalone, undeclared types + if (load_standalone_binary(objfile_binary_uuid, objfile_binary_value, + objfile_binary_value_is_offset, GetTarget())) { + found_main_binary_definitively = true; + m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic(); + } } } @@ -337,11 +426,8 @@ Status ProcessMachCore::DoLoadCore() { // We have no address specified, only a UUID. Load it at the file // address. const bool value_is_offset = false; - const bool force_symbol_search = true; - const bool notify = true; - if (DynamicLoader::LoadBinaryWithUUIDAndAddress( - this, ident_uuid, ident_binary_addr, value_is_offset, - force_symbol_search, notify)) { + if (load_standalone_binary(ident_uuid, ident_binary_addr, value_is_offset, + GetTarget())) { found_main_binary_definitively = true; m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic(); } diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/Makefile b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/Makefile deleted file mode 100644 index 8e561f17383f..000000000000 --- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -MAKE_DSYM := NO -C_SOURCES := main.c -LD_EXTRAS := -L. -lone -ltwo - -.PHONY: libone.dylib libtwo.dylib -all: libone.dylib libtwo.dylib a.out create-empty-corefile - -create-empty-corefile: - "$(MAKE)" -f "$(MAKEFILE_RULES)" EXE=create-multibin-corefile \ - CXX_SOURCES=create-multibin-corefile.cpp - -libone.dylib: one.c - $(MAKE) -f $(MAKEFILE_RULES) \ - DYLIB_ONLY=YES DYLIB_NAME=one DYLIB_C_SOURCES=one.c - -libtwo.dylib: two.c - $(MAKE) -f $(MAKEFILE_RULES) \ - DYLIB_ONLY=YES DYLIB_NAME=two DYLIB_C_SOURCES=two.c - -include Makefile.rules diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py deleted file mode 100644 index 5e74f0c3f8bf..000000000000 --- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/TestMultipleBinaryCorefile.py +++ /dev/null @@ -1,187 +0,0 @@ -"""Test corefiles with "main bin spec"/"load binary" with only addrs work.""" - - -import os -import re -import subprocess - -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestMultipleBinaryCorefile(TestBase): - - def initial_setup(self): - self.build() - self.aout_exe_basename = "a.out" - self.libone_exe_basename = "libone.dylib" - self.libtwo_exe_basename = "libtwo.dylib" - self.aout_exe = self.getBuildArtifact(self.aout_exe_basename) - self.aout_slide = 0x5000 - self.libone_exe = self.getBuildArtifact(self.libone_exe_basename) - self.libone_slide = 0x100840000 - self.libtwo_exe = self.getBuildArtifact(self.libtwo_exe_basename) - self.libtwo_slide = 0 - self.corefile = self.getBuildArtifact("multiple-binaries.core") - self.create_corefile = self.getBuildArtifact("create-multibin-corefile") - cmd="%s %s %s@%x %s@%x %s@%x" % (self.create_corefile, self.corefile, - self.aout_exe, self.aout_slide, - self.libone_exe, self.libone_slide, - self.libtwo_exe, self.libtwo_slide) - call(cmd, shell=True) - - - def load_corefile_and_test(self): - target = self.dbg.CreateTarget('') - err = lldb.SBError() - if self.TraceOn(): - self.runCmd("script print('loading corefile %s')" % self.corefile) - process = target.LoadCore(self.corefile) - self.assertEqual(process.IsValid(), True) - if self.TraceOn(): - self.runCmd("script print('image list after loading corefile:')") - self.runCmd("image list") - - self.assertEqual(target.GetNumModules(), 3) - fspec = target.GetModuleAtIndex(0).GetFileSpec() - self.assertEqual(fspec.GetFilename(), self.aout_exe_basename) - - # libone.dylib was never loaded into lldb, see that we added a memory module. - fspec = target.GetModuleAtIndex(1).GetFileSpec() - self.assertIn('memory-image', fspec.GetFilename()) - - dwarfdump_uuid_regex = re.compile( - 'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*') - dwarfdump_cmd_output = subprocess.check_output( - ('/usr/bin/dwarfdump --uuid "%s"' % self.libone_exe), shell=True).decode("utf-8") - libone_uuid = None - for line in dwarfdump_cmd_output.splitlines(): - match = dwarfdump_uuid_regex.search(line) - if match: - libone_uuid = match.group(1) - - memory_image_uuid = target.GetModuleAtIndex(1).GetUUIDString() - self.assertEqual(libone_uuid, memory_image_uuid) - - fspec = target.GetModuleAtIndex(2).GetFileSpec() - self.assertEqual(fspec.GetFilename(), self.libtwo_exe_basename) - - # Executables "always" have this base address - aout_load = target.GetModuleAtIndex(0).GetObjectFileHeaderAddress().GetLoadAddress(target) - self.assertEqual(aout_load, 0x100000000 + self.aout_slide) - - # Value from Makefile - libone_load = target.GetModuleAtIndex(1).GetObjectFileHeaderAddress().GetLoadAddress(target) - self.assertEqual(libone_load, self.libone_slide) - - # Value from Makefile - libtwo_load = target.GetModuleAtIndex(2).GetObjectFileHeaderAddress().GetLoadAddress(target) - self.assertEqual(libtwo_load, self.libtwo_slide) - - self.dbg.DeleteTarget(target) - self.dbg.Clear() - - NO_DEBUG_INFO_TESTCASE = True - - @skipIf(archs=no_match(['x86_64', 'arm64', 'arm64e', 'aarch64'])) - @skipIfRemote - @skipUnlessDarwin - def test_corefile_binaries_dsymforuuid(self): - self.initial_setup() - - if self.TraceOn(): - self.runCmd("log enable lldb dyld host") - self.addTearDownHook(lambda: self.runCmd("log disable lldb dyld host")) - - ## We can hook in our dsym-for-uuid shell script to lldb with this env - ## var instead of requiring a defaults write. - dsym_for_uuid = self.getBuildArtifact("dsym-for-uuid.sh") - os.environ['LLDB_APPLE_DSYMFORUUID_EXECUTABLE'] = dsym_for_uuid - if self.TraceOn(): - print("Setting env var LLDB_APPLE_DSYMFORUUID_EXECUTABLE=" + dsym_for_uuid) - self.addTearDownHook(lambda: os.environ.pop('LLDB_APPLE_DSYMFORUUID_EXECUTABLE', None)) - - self.runCmd("settings set target.load-script-from-symbol-file true") - self.addTearDownHook(lambda: self.runCmd("settings set target.load-script-from-symbol-file false")) - - dwarfdump_uuid_regex = re.compile( - 'UUID: ([-0-9a-fA-F]+) \(([^\(]+)\) .*') - dwarfdump_cmd_output = subprocess.check_output( - ('/usr/bin/dwarfdump --uuid "%s"' % self.libtwo_exe), shell=True).decode("utf-8") - libtwo_uuid = None - for line in dwarfdump_cmd_output.splitlines(): - match = dwarfdump_uuid_regex.search(line) - if match: - libtwo_uuid = match.group(1) - self.assertNotEqual(libtwo_uuid, None, "Could not get uuid of built libtwo.dylib") - - ### Create our dsym-for-uuid shell script which returns aout_exe - shell_cmds = [ - '#! /bin/sh', - '# the last argument is the uuid', - 'while [ $# -gt 1 ]', - 'do', - ' shift', - 'done', - 'ret=0', - 'echo "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>"', - 'echo "<!DOCTYPE plist PUBLIC \\"-//Apple//DTD PLIST 1.0//EN\\" \\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\\">"', - 'echo "<plist version=\\"1.0\\">"', - '', - 'if [ "$1" != "%s" ]' % (libtwo_uuid), - 'then', - ' echo "<key>DBGError</key><string>not found</string>"', - ' echo "</plist>"', - ' exit 1', - 'fi', - ' uuid=%s' % libtwo_uuid, - ' bin=%s' % self.libtwo_exe, - ' dsym=%s.dSYM/Contents/Resources/DWARF/%s' % (self.libtwo_exe, os.path.basename(self.libtwo_exe)), - 'echo "<dict><key>$uuid</key><dict>"', - '', - 'echo "<key>DBGDSYMPath</key><string>$dsym</string>"', - 'echo "<key>DBGSymbolRichExecutable</key><string>$bin</string>"', - 'echo "</dict></dict></plist>"', - 'exit $ret' - ] - - with open(dsym_for_uuid, "w") as writer: - for l in shell_cmds: - writer.write(l + '\n') - - os.chmod(dsym_for_uuid, 0o755) - - # Register TWO of our binaries, but require dsymForUUID to find the third. - target = self.dbg.CreateTarget(self.aout_exe, '', '', False, lldb.SBError()) - self.dbg.DeleteTarget(target) - - if self.TraceOn(): - self.runCmd("script print('Global image list, before loading corefile:')") - self.runCmd("image list -g") - - self.load_corefile_and_test() - - @skipIf(archs=no_match(['x86_64', 'arm64', 'arm64e', 'aarch64'])) - @skipIfRemote - @skipUnlessDarwin - def test_corefile_binaries_preloaded(self): - self.initial_setup() - - if self.TraceOn(): - self.runCmd("log enable lldb dyld host") - self.addTearDownHook(lambda: self.runCmd("log disable lldb dyld host")) - - # Register all three binaries in lldb's global module - # cache, then throw the Targets away. - target = self.dbg.CreateTarget(self.aout_exe, '', '', False, lldb.SBError()) - self.dbg.DeleteTarget(target) - target = self.dbg.CreateTarget(self.libtwo_exe, '', '', False, lldb.SBError()) - self.dbg.DeleteTarget(target) - - if self.TraceOn(): - self.runCmd("script print('Global image list, before loading corefile:')") - self.runCmd("image list -g") - - self.load_corefile_and_test() diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/create-multibin-corefile.cpp b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/create-multibin-corefile.cpp deleted file mode 100644 index ebe71606806d..000000000000 --- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/create-multibin-corefile.cpp +++ /dev/null @@ -1,484 +0,0 @@ -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <mach-o/loader.h> -#include <mach/thread_status.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <string> -#include <sys/errno.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <unistd.h> -#include <uuid/uuid.h> -#include <vector> - -// Given a list of binaries, and optional slides to be applied, -// create a corefile whose memory is those binaries laid at at -// their slid addresses. -// -// Add a 'main bin spec' LC_NOTE for the first binary, and -// 'load binary' LC_NOTEs for any additional binaries, and -// these LC_NOTEs will ONLY have the vmaddr of the binary - no -// UUID, no slide, no filename. -// -// Test that lldb can use the load addresses, find the UUIDs, -// and load the binaries/dSYMs and put them at the correct load -// address. - -struct main_bin_spec_payload { - uint32_t version; - uint32_t type; - uint64_t address; - uint64_t slide; - uuid_t uuid; - uint32_t log2_pagesize; - uint32_t platform; -}; - -struct load_binary_payload { - uint32_t version; - uuid_t uuid; - uint64_t address; - uint64_t slide; - const char name[4]; -}; - -union uint32_buf { - uint8_t bytebuf[4]; - uint32_t val; -}; - -union uint64_buf { - uint8_t bytebuf[8]; - uint64_t val; -}; - -void add_uint64(std::vector<uint8_t> &buf, uint64_t val) { - uint64_buf conv; - conv.val = val; - for (int i = 0; i < 8; i++) - buf.push_back(conv.bytebuf[i]); -} - -void add_uint32(std::vector<uint8_t> &buf, uint32_t val) { - uint32_buf conv; - conv.val = val; - for (int i = 0; i < 4; i++) - buf.push_back(conv.bytebuf[i]); -} - -std::vector<uint8_t> lc_thread_load_command(cpu_type_t cputype) { - std::vector<uint8_t> data; - // Emit an LC_THREAD register context appropriate for the cputype - // of the binary we're embedded. The tests in this case do not - // use the register values, so 0's are fine, lldb needs to see at - // least one LC_THREAD in the corefile. -#if defined(__x86_64__) - if (cputype == CPU_TYPE_X86_64) { - add_uint32(data, LC_THREAD); // thread_command.cmd - add_uint32(data, - 16 + (x86_THREAD_STATE64_COUNT * 4)); // thread_command.cmdsize - add_uint32(data, x86_THREAD_STATE64); // thread_command.flavor - add_uint32(data, x86_THREAD_STATE64_COUNT); // thread_command.count - for (int i = 0; i < x86_THREAD_STATE64_COUNT; i++) { - add_uint32(data, 0); // whatever, just some empty register values - } - } -#endif -#if defined(__arm64__) || defined(__aarch64__) - if (cputype == CPU_TYPE_ARM64) { - add_uint32(data, LC_THREAD); // thread_command.cmd - add_uint32(data, - 16 + (ARM_THREAD_STATE64_COUNT * 4)); // thread_command.cmdsize - add_uint32(data, ARM_THREAD_STATE64); // thread_command.flavor - add_uint32(data, ARM_THREAD_STATE64_COUNT); // thread_command.count - for (int i = 0; i < ARM_THREAD_STATE64_COUNT; i++) { - add_uint32(data, 0); // whatever, just some empty register values - } - } -#endif - return data; -} - -void add_lc_note_main_bin_spec_load_command( - std::vector<std::vector<uint8_t>> &loadcmds, std::vector<uint8_t> &payload, - int payload_file_offset, std::string uuidstr, uint64_t address, - uint64_t slide) { - std::vector<uint8_t> loadcmd_data; - - add_uint32(loadcmd_data, LC_NOTE); // note_command.cmd - add_uint32(loadcmd_data, 40); // note_command.cmdsize - char lc_note_name[16]; - memset(lc_note_name, 0, 16); - strcpy(lc_note_name, "main bin spec"); - - // lc_note.data_owner - for (int i = 0; i < 16; i++) - loadcmd_data.push_back(lc_note_name[i]); - - // we start writing the payload at payload_file_offset to leave - // room at the start for the header & the load commands. - uint64_t current_payload_offset = payload.size() + payload_file_offset; - - add_uint64(loadcmd_data, current_payload_offset); // note_command.offset - add_uint64(loadcmd_data, - sizeof(struct main_bin_spec_payload)); // note_command.size - - loadcmds.push_back(loadcmd_data); - - // Now write the "main bin spec" payload. - add_uint32(payload, 2); // version - add_uint32(payload, 3); // type == 3 [ firmware, standalone, etc ] - add_uint64(payload, address); // load address - add_uint64(payload, slide); // slide - uuid_t uuid; - uuid_parse(uuidstr.c_str(), uuid); - for (int i = 0; i < sizeof(uuid_t); i++) - payload.push_back(uuid[i]); - add_uint32(payload, 0); // log2_pagesize unspecified - add_uint32(payload, 0); // platform unspecified -} - -void add_lc_note_load_binary_load_command( - std::vector<std::vector<uint8_t>> &loadcmds, std::vector<uint8_t> &payload, - int payload_file_offset, std::string uuidstr, uint64_t address, - uint64_t slide) { - std::vector<uint8_t> loadcmd_data; - - add_uint32(loadcmd_data, LC_NOTE); // note_command.cmd - add_uint32(loadcmd_data, 40); // note_command.cmdsize - char lc_note_name[16]; - memset(lc_note_name, 0, 16); - strcpy(lc_note_name, "load binary"); - - // lc_note.data_owner - for (int i = 0; i < 16; i++) - loadcmd_data.push_back(lc_note_name[i]); - - // we start writing the payload at payload_file_offset to leave - // room at the start for the header & the load commands. - uint64_t current_payload_offset = payload.size() + payload_file_offset; - - add_uint64(loadcmd_data, current_payload_offset); // note_command.offset - add_uint64(loadcmd_data, - sizeof(struct load_binary_payload)); // note_command.size - - loadcmds.push_back(loadcmd_data); - - // Now write the "load binary" payload. - add_uint32(payload, 1); // version - uuid_t uuid; - uuid_parse(uuidstr.c_str(), uuid); - for (int i = 0; i < sizeof(uuid_t); i++) - payload.push_back(uuid[i]); - add_uint64(payload, address); // load address - add_uint64(payload, slide); // slide - add_uint32(payload, 0); // name -} - -void add_lc_segment(std::vector<std::vector<uint8_t>> &loadcmds, - std::vector<uint8_t> &payload, int payload_file_offset, - uint64_t vmaddr, uint64_t size) { - std::vector<uint8_t> loadcmd_data; - struct segment_command_64 seg; - seg.cmd = LC_SEGMENT_64; - seg.cmdsize = sizeof(struct segment_command_64); // no sections - memset(seg.segname, 0, 16); - seg.vmaddr = vmaddr; - seg.vmsize = size; - seg.fileoff = payload.size() + payload_file_offset; - seg.filesize = size; - seg.maxprot = 1; - seg.initprot = 1; - seg.nsects = 0; - seg.flags = 0; - - uint8_t *p = (uint8_t *)&seg; - for (int i = 0; i < sizeof(struct segment_command_64); i++) { - loadcmd_data.push_back(*(p + i)); - } - loadcmds.push_back(loadcmd_data); -} - -std::string scan_binary(const char *fn, uint64_t &vmaddr, cpu_type_t &cputype, - cpu_subtype_t &cpusubtype) { - FILE *f = fopen(fn, "r"); - if (f == nullptr) { - fprintf(stderr, "Unable to open binary '%s' to get uuid\n", fn); - exit(1); - } - uint32_t num_of_load_cmds = 0; - uint32_t size_of_load_cmds = 0; - std::string uuid; - off_t file_offset = 0; - vmaddr = UINT64_MAX; - - uint8_t magic[4]; - if (::fread(magic, 1, 4, f) != 4) { - fprintf(stderr, "Failed to read magic number from input file %s\n", fn); - exit(1); - } - uint8_t magic_32_be[] = {0xfe, 0xed, 0xfa, 0xce}; - uint8_t magic_32_le[] = {0xce, 0xfa, 0xed, 0xfe}; - uint8_t magic_64_be[] = {0xfe, 0xed, 0xfa, 0xcf}; - uint8_t magic_64_le[] = {0xcf, 0xfa, 0xed, 0xfe}; - - if (memcmp(magic, magic_32_be, 4) == 0 || - memcmp(magic, magic_64_be, 4) == 0) { - fprintf(stderr, "big endian corefiles not supported\n"); - exit(1); - } - - ::fseeko(f, 0, SEEK_SET); - if (memcmp(magic, magic_32_le, 4) == 0) { - struct mach_header mh; - if (::fread(&mh, 1, sizeof(mh), f) != sizeof(mh)) { - fprintf(stderr, "error reading mach header from input file\n"); - exit(1); - } - if (mh.cputype != CPU_TYPE_X86_64 && mh.cputype != CPU_TYPE_ARM64) { - fprintf(stderr, - "This tool creates an x86_64/arm64 corefile but " - "the supplied binary '%s' is cputype 0x%x\n", - fn, (uint32_t)mh.cputype); - exit(1); - } - num_of_load_cmds = mh.ncmds; - size_of_load_cmds = mh.sizeofcmds; - file_offset += sizeof(struct mach_header); - cputype = mh.cputype; - cpusubtype = mh.cpusubtype; - } else { - struct mach_header_64 mh; - if (::fread(&mh, 1, sizeof(mh), f) != sizeof(mh)) { - fprintf(stderr, "error reading mach header from input file\n"); - exit(1); - } - if (mh.cputype != CPU_TYPE_X86_64 && mh.cputype != CPU_TYPE_ARM64) { - fprintf(stderr, - "This tool creates an x86_64/arm64 corefile but " - "the supplied binary '%s' is cputype 0x%x\n", - fn, (uint32_t)mh.cputype); - exit(1); - } - num_of_load_cmds = mh.ncmds; - size_of_load_cmds = mh.sizeofcmds; - file_offset += sizeof(struct mach_header_64); - cputype = mh.cputype; - cpusubtype = mh.cpusubtype; - } - - off_t load_cmds_offset = file_offset; - - for (int i = 0; i < num_of_load_cmds && - (file_offset - load_cmds_offset) < size_of_load_cmds; - i++) { - ::fseeko(f, file_offset, SEEK_SET); - uint32_t cmd; - uint32_t cmdsize; - ::fread(&cmd, sizeof(uint32_t), 1, f); - ::fread(&cmdsize, sizeof(uint32_t), 1, f); - if (vmaddr == UINT64_MAX && cmd == LC_SEGMENT_64) { - struct segment_command_64 segcmd; - ::fseeko(f, file_offset, SEEK_SET); - if (::fread(&segcmd, 1, sizeof(segcmd), f) != sizeof(segcmd)) { - fprintf(stderr, "Unable to read LC_SEGMENT_64 load command.\n"); - exit(1); - } - if (strcmp("__TEXT", segcmd.segname) == 0) - vmaddr = segcmd.vmaddr; - } - if (cmd == LC_UUID) { - struct uuid_command uuidcmd; - ::fseeko(f, file_offset, SEEK_SET); - if (::fread(&uuidcmd, 1, sizeof(uuidcmd), f) != sizeof(uuidcmd)) { - fprintf(stderr, "Unable to read LC_UUID load command.\n"); - exit(1); - } - uuid_string_t uuidstr; - uuid_unparse(uuidcmd.uuid, uuidstr); - uuid = uuidstr; - } - file_offset += cmdsize; - } - return uuid; -} - -void slide_macho_binary(std::vector<uint8_t> &image, uint64_t slide) { - uint8_t *p = image.data(); - struct mach_header_64 *mh = (struct mach_header_64 *)p; - p += sizeof(struct mach_header_64); - for (int lc_idx = 0; lc_idx < mh->ncmds; lc_idx++) { - struct load_command *lc = (struct load_command *)p; - if (lc->cmd == LC_SEGMENT_64) { - struct segment_command_64 *seg = (struct segment_command_64 *)p; - if (seg->maxprot != 0 && seg->nsects > 0) { - seg->vmaddr += slide; - uint8_t *j = p + sizeof(segment_command_64); - for (int sect_idx = 0; sect_idx < seg->nsects; sect_idx++) { - struct section_64 *sect = (struct section_64 *)j; - sect->addr += slide; - j += sizeof(struct section_64); - } - } - } - p += lc->cmdsize; - } -} - -int main(int argc, char **argv) { - if (argc < 3) { - fprintf(stderr, - "usage: output-corefile binary1[@optional-slide] " - "[binary2[@optional-slide] [binary3[@optional-slide] ...]]\n"); - exit(1); - } - - // An array of load commands (in the form of byte arrays) - std::vector<std::vector<uint8_t>> load_commands; - - // An array of corefile contents (page data, lc_note data, etc) - std::vector<uint8_t> payload; - - std::vector<std::string> input_filenames; - std::vector<uint64_t> input_slides; - std::vector<uint64_t> input_filesizes; - std::vector<uint64_t> input_filevmaddrs; - uint64_t main_binary_cputype = CPU_TYPE_ARM64; - uint64_t vmaddr = UINT64_MAX; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - for (int i = 2; i < argc; i++) { - std::string filename; - std::string filename_and_opt_hex(argv[i]); - uint64_t slide = 0; - auto at_pos = filename_and_opt_hex.find_last_of('@'); - if (at_pos == std::string::npos) { - filename = filename_and_opt_hex; - } else { - filename = filename_and_opt_hex.substr(0, at_pos); - std::string hexstr = filename_and_opt_hex.substr(at_pos + 1); - errno = 0; - slide = (uint64_t)strtoull(hexstr.c_str(), nullptr, 16); - if (errno != 0) { - fprintf(stderr, "Unable to parse hex slide value in %s\n", argv[i]); - exit(1); - } - } - struct stat stbuf; - if (stat(filename.c_str(), &stbuf) == -1) { - fprintf(stderr, "Unable to stat '%s', exiting.\n", filename.c_str()); - exit(1); - } - input_filenames.push_back(filename); - input_slides.push_back(slide); - input_filesizes.push_back(stbuf.st_size); - scan_binary(filename.c_str(), vmaddr, cputype, cpusubtype); - input_filevmaddrs.push_back(vmaddr + slide); - if (i == 2) { - main_binary_cputype = cputype; - } - } - - const char *output_corefile_name = argv[1]; - std::string empty_uuidstr = "00000000-0000-0000-0000-000000000000"; - - // First add all the load commands / payload so we can figure out how large - // the load commands will actually be. - load_commands.push_back(lc_thread_load_command(cputype)); - - add_lc_note_main_bin_spec_load_command(load_commands, payload, 0, - empty_uuidstr, 0, UINT64_MAX); - for (int i = 1; i < input_filenames.size(); i++) { - add_lc_note_load_binary_load_command(load_commands, payload, 0, - empty_uuidstr, 0, UINT64_MAX); - } - - for (int i = 0; i < input_filenames.size(); i++) { - add_lc_segment(load_commands, payload, 0, 0, 0); - } - - int size_of_load_commands = 0; - for (const auto &lc : load_commands) - size_of_load_commands += lc.size(); - - int size_of_header_and_load_cmds = - sizeof(struct mach_header_64) + size_of_load_commands; - - // Erase the load commands / payload now that we know how much space is - // needed, redo it. - load_commands.clear(); - payload.clear(); - - // Push the LC_THREAD load command. - load_commands.push_back(lc_thread_load_command(main_binary_cputype)); - - const off_t payload_offset = size_of_header_and_load_cmds; - - add_lc_note_main_bin_spec_load_command(load_commands, payload, payload_offset, - empty_uuidstr, input_filevmaddrs[0], - UINT64_MAX); - - for (int i = 1; i < input_filenames.size(); i++) { - add_lc_note_load_binary_load_command(load_commands, payload, payload_offset, - empty_uuidstr, input_filevmaddrs[i], - UINT64_MAX); - } - - for (int i = 0; i < input_filenames.size(); i++) { - add_lc_segment(load_commands, payload, payload_offset, input_filevmaddrs[i], - input_filesizes[i]); - - // Copy the contents of the binary into payload. - int fd = open(input_filenames[i].c_str(), O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Unable to open %s for reading\n", - input_filenames[i].c_str()); - exit(1); - } - std::vector<uint8_t> binary_contents; - for (int j = 0; j < input_filesizes[i]; j++) { - uint8_t byte; - read(fd, &byte, 1); - binary_contents.push_back(byte); - } - close(fd); - - size_t cur_payload_size = payload.size(); - payload.resize(cur_payload_size + binary_contents.size()); - slide_macho_binary(binary_contents, input_slides[i]); - memcpy(payload.data() + cur_payload_size, binary_contents.data(), - binary_contents.size()); - } - - struct mach_header_64 mh; - mh.magic = MH_MAGIC_64; - mh.cputype = cputype; - - mh.cpusubtype = cpusubtype; - mh.filetype = MH_CORE; - mh.ncmds = load_commands.size(); - mh.sizeofcmds = size_of_load_commands; - mh.flags = 0; - mh.reserved = 0; - - FILE *f = fopen(output_corefile_name, "w"); - - if (f == nullptr) { - fprintf(stderr, "Unable to open file %s for writing\n", - output_corefile_name); - exit(1); - } - - fwrite(&mh, sizeof(mh), 1, f); - - for (const auto &lc : load_commands) - fwrite(lc.data(), lc.size(), 1, f); - - fwrite(payload.data(), payload.size(), 1, f); - - fclose(f); -} diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/main.c b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/main.c deleted file mode 100644 index eaab873b53e4..000000000000 --- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/main.c +++ /dev/null @@ -1,7 +0,0 @@ -#include <stdio.h> -int one(); -int two(); -int main() { - puts("this is the standalone binary test program"); - return one() + two(); -} diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/one.c b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/one.c deleted file mode 100644 index 6e8fe4ad5ff7..000000000000 --- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/one.c +++ /dev/null @@ -1 +0,0 @@ -int one() { return 5; } diff --git a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/two.c b/lldb/test/API/macosx/lc-note/multiple-binary-corefile/two.c deleted file mode 100644 index f44baa69c293..000000000000 --- a/lldb/test/API/macosx/lc-note/multiple-binary-corefile/two.c +++ /dev/null @@ -1 +0,0 @@ -int two() { return 10; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits