[Lldb-commits] [lldb] r300138 - Use two LC_NOTE load commands for identifying the main binary that
Hal Finkel via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 12 17:22:35 PDT 2017
On 04/12/2017 06:33 PM, Jason Molenda via lldb-commits wrote:
> Author: jmolenda
> Date: Wed Apr 12 18:33:30 2017
> New Revision: 300138
>
> URL: http://llvm.org/viewvc/llvm-project?rev=300138&view=rev
> Log:
> Use two LC_NOTE load commands for identifying the main binary that
> lldb should use when given a corefile.
>
> This uses an LC_NOTE "main bin spec" or an LC_NOTE "kern ver str"
> if they are present in a Mach-O core file.
>
> Core files may have multiple different binaries -- different kernels,
> or a mix of user process and kernel binaries -- and it can be
> difficult for lldb to detect the correct one to use simply by looking
> at the pages of memory. These two new LC_NOTE load commands allow
> for the correct binary to be recorded unambiguously.
>
> <rdar://problem/20878266>
>
> Modified:
> lldb/trunk/include/lldb/Symbol/ObjectFile.h
> lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
> lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
> lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp
>
> Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=300138&r1=300137&r2=300138&view=diff
> ==============================================================================
> --- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original)
> +++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Wed Apr 12 18:33:30 2017
> @@ -18,6 +18,7 @@
> #include "lldb/Utility/DataExtractor.h"
> #include "lldb/Utility/Endian.h"
> #include "lldb/Utility/FileSpec.h"
> +#include "lldb/Utility/UUID.h"
> #include "lldb/lldb-private.h"
>
> namespace lldb_private {
> @@ -576,6 +577,32 @@ public:
> return std::string();
> }
>
> + //------------------------------------------------------------------
> + /// When the ObjectFile is a core file, lldb needs to locate the
> + /// "binary" in the core file. lldb can iterate over the pages looking
> + /// for a valid binary, but some core files may have metadata
> + /// describing where the main binary is exactly which removes ambiguity
> + /// when there are multiple binaries present in the captured memory pages.
> + ///
> + /// @param[out] address
> + /// If the address of the binary is specified, this will be set.
> + /// This is an address is the virtual address space of the core file
> + /// memory segments; it is not an offset into the object file.
> + /// If no address is available, will be set to LLDB_INVALID_ADDRESS.
> + ///
> + /// @param[out] uuid
> + /// If the uuid of the binary is specified, this will be set.
> + /// If no UUID is available, will be cleared.
> + ///
> + /// @return
> + /// Returns true if either address or uuid has been set.
> + //------------------------------------------------------------------
> + virtual bool GetCorefileMainBinaryInfo (lldb::addr_t &address, UUID &uuid) {
> + address = LLDB_INVALID_ADDRESS;
> + uuid.Clear();
> + return false;
> + }
> +
> virtual lldb::RegisterContextSP
> GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) {
> return lldb::RegisterContextSP();
>
> Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=300138&r1=300137&r2=300138&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
> +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Wed Apr 12 18:33:30 2017
> @@ -60,6 +60,8 @@
>
> #ifndef __APPLE__
> #include "Utility/UuidCompatibility.h"
> +#else
> +#include <uuid/uuid.h>
> #endif
This doesn't build for me on Linux:
/src/llvm/tools/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp:5471:39:
error: ‘uuid_clear’ was not declared in this scope
uuid_clear (raw_uuid);
^
There is a uuid_clear in my system uuid.h header, but on non-Apple
systems we seem to use ./source/Utility/UuidCompatibility.h, and there's
no uuid_clear in there.
-Hal
>
> #define THUMB_ADDRESS_BIT_MASK 0xfffffffffffffffeull
> @@ -5354,23 +5356,67 @@ uint32_t ObjectFileMachO::GetNumThreadCo
> return m_thread_context_offsets.GetSize();
> }
>
> -// The LC_IDENT load command has been obsoleted for a very
> -// long time and it should not occur in Mach-O files. But
> -// if it is there, it may contain a hint about where to find
> -// the main binary in a core file, so we'll use it.
> std::string ObjectFileMachO::GetIdentifierString() {
> std::string result;
> ModuleSP module_sp(GetModule());
> if (module_sp) {
> std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
> +
> + // First, look over the load commands for an LC_NOTE load command
> + // with data_owner string "kern ver str" & use that if found.
> lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
> for (uint32_t i = 0; i < m_header.ncmds; ++i) {
> const uint32_t cmd_offset = offset;
> + load_command lc;
> + if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
> + break;
> + if (lc.cmd == LC_NOTE)
> + {
> + char data_owner[17];
> + m_data.CopyData (offset, 16, data_owner);
> + data_owner[16] = '\0';
> + offset += 16;
> + uint64_t fileoff = m_data.GetU64_unchecked (&offset);
> + uint64_t size = m_data.GetU64_unchecked (&offset);
> +
> + // "kern ver str" has a uint32_t version and then a
> + // nul terminated c-string.
> + if (strcmp ("kern ver str", data_owner) == 0)
> + {
> + offset = fileoff;
> + uint32_t version;
> + if (m_data.GetU32 (&offset, &version, 1) != nullptr)
> + {
> + if (version == 1)
> + {
> + uint32_t strsize = size - sizeof (uint32_t);
> + char *buf = (char*) malloc (strsize);
> + if (buf)
> + {
> + m_data.CopyData (offset, strsize, buf);
> + buf[strsize - 1] = '\0';
> + result = buf;
> + if (buf)
> + free (buf);
> + return result;
> + }
> + }
> + }
> + }
> + }
> + offset = cmd_offset + lc.cmdsize;
> + }
> +
> + // Second, make a pass over the load commands looking for an
> + // obsolete LC_IDENT load command.
> + offset = MachHeaderSizeFromMagic(m_header.magic);
> + for (uint32_t i = 0; i < m_header.ncmds; ++i) {
> + const uint32_t cmd_offset = offset;
> struct ident_command ident_command;
> if (m_data.GetU32(&offset, &ident_command, 2) == NULL)
> break;
> if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) {
> - char *buf = (char *)malloc (ident_command.cmdsize);
> + char *buf = (char *) malloc (ident_command.cmdsize);
> if (buf != nullptr
> && m_data.CopyData (offset, ident_command.cmdsize, buf) == ident_command.cmdsize) {
> buf[ident_command.cmdsize - 1] = '\0';
> @@ -5381,10 +5427,65 @@ std::string ObjectFileMachO::GetIdentifi
> }
> offset = cmd_offset + ident_command.cmdsize;
> }
> +
> }
> return result;
> }
>
> +bool ObjectFileMachO::GetCorefileMainBinaryInfo (addr_t &address, UUID &uuid) {
> + address = LLDB_INVALID_ADDRESS;
> + uuid.Clear();
> + ModuleSP module_sp(GetModule());
> + if (module_sp) {
> + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
> + lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
> + for (uint32_t i = 0; i < m_header.ncmds; ++i) {
> + const uint32_t cmd_offset = offset;
> + load_command lc;
> + if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
> + break;
> + if (lc.cmd == LC_NOTE)
> + {
> + char data_owner[17];
> + memset (data_owner, 0, sizeof (data_owner));
> + m_data.CopyData (offset, 16, data_owner);
> + offset += 16;
> + uint64_t fileoff = m_data.GetU64_unchecked (&offset);
> + uint64_t size = m_data.GetU64_unchecked (&offset);
> +
> + // "main bin spec" (main binary specification) data payload is formatted:
> + // uint32_t version [currently 1]
> + // uint32_t type [0 == unspecified, 1 == kernel, 2 == user process]
> + // uint64_t address [ UINT64_MAX if address not specified ]
> + // uuid_t uuid [ all zero's if uuid not specified ]
> + // uint32_t log2_pagesize [ process page size in log base 2, e.g. 4k pages are 12. 0 for unspecified ]
> +
> + if (strcmp ("main bin spec", data_owner) == 0 && size >= 32)
> + {
> + offset = fileoff;
> + uint32_t version;
> + if (m_data.GetU32 (&offset, &version, 1) != nullptr && version == 1)
> + {
> + uint32_t type = 0;
> + uuid_t raw_uuid;
> + uuid_clear (raw_uuid);
> +
> + if (m_data.GetU32 (&offset, &type, 1)
> + && m_data.GetU64 (&offset, &address, 1)
> + && m_data.CopyData (offset, sizeof (uuid_t), raw_uuid) != 0
> + && uuid.SetBytes (raw_uuid, sizeof (uuid_t)))
> + {
> + return true;
> + }
> + }
> + }
> + }
> + offset = cmd_offset + lc.cmdsize;
> + }
> + }
> + return false;
> +}
> +
> lldb::RegisterContextSP
> ObjectFileMachO::GetThreadContextAtIndex(uint32_t idx,
> lldb_private::Thread &thread) {
>
> Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h?rev=300138&r1=300137&r2=300138&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (original)
> +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Wed Apr 12 18:33:30 2017
> @@ -20,6 +20,7 @@
> #include "lldb/Symbol/ObjectFile.h"
> #include "lldb/Utility/FileSpec.h"
> #include "lldb/Utility/SafeMachO.h"
> +#include "lldb/Utility/UUID.h"
>
> //----------------------------------------------------------------------
> // This class needs to be hidden as eventually belongs in a plugin that
> @@ -113,6 +114,8 @@ public:
>
> std::string GetIdentifierString() override;
>
> + bool GetCorefileMainBinaryInfo (lldb::addr_t &address, lldb_private::UUID &uuid) override;
> +
> lldb::RegisterContextSP
> GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override;
>
>
> Modified: lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp?rev=300138&r1=300137&r2=300138&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp (original)
> +++ lldb/trunk/source/Plugins/Process/mach-core/ProcessMachCore.cpp Wed Apr 12 18:33:30 2017
> @@ -294,11 +294,26 @@ Error ProcessMachCore::DoLoadCore() {
>
> bool found_main_binary_definitively = false;
>
> + addr_t objfile_binary_addr;
> + UUID objfile_binary_uuid;
> + if (core_objfile->GetCorefileMainBinaryInfo (objfile_binary_addr, objfile_binary_uuid))
> + {
> + if (objfile_binary_addr != LLDB_INVALID_ADDRESS)
> + {
> + m_mach_kernel_addr = objfile_binary_addr;
> + found_main_binary_definitively = true;
> + if (log)
> + log->Printf ("ProcessMachCore::DoLoadCore: using kernel address 0x%" PRIx64
> + " from LC_NOTE 'main bin spec' load command.", m_mach_kernel_addr);
> + }
> + }
> +
> // This checks for the presence of an LC_IDENT string in a core file;
> // LC_IDENT is very obsolete and should not be used in new code, but
> // if the load command is present, let's use the contents.
> std::string corefile_identifier = core_objfile->GetIdentifierString();
> - if (corefile_identifier.find("Darwin Kernel") != std::string::npos) {
> + if (found_main_binary_definitively == false
> + && corefile_identifier.find("Darwin Kernel") != std::string::npos) {
> UUID uuid;
> addr_t addr = LLDB_INVALID_ADDRESS;
> if (corefile_identifier.find("UUID=") != std::string::npos) {
> @@ -320,13 +335,13 @@ Error ProcessMachCore::DoLoadCore() {
> found_main_binary_definitively = true;
> if (log)
> log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64
> - "from LC_IDENT string '%s'", addr, corefile_identifier.c_str());
> + " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", addr, corefile_identifier.c_str());
> }
> }
>
> - if (found_main_binary_definitively == false &&
> - (m_dyld_addr == LLDB_INVALID_ADDRESS ||
> - m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
> + if (found_main_binary_definitively == false
> + && (m_dyld_addr == LLDB_INVALID_ADDRESS
> + || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
> // We need to locate the main executable in the memory ranges
> // we have in the core file. We need to search for both a user-process dyld
> // binary
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
--
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory
More information about the lldb-commits
mailing list