[Lldb-commits] [lldb] r236817 - This patch allows LLDB to use the $qXfer:Libraries: packet.
Tamas Berghammer
tberghammer at google.com
Fri May 8 03:42:07 PDT 2015
Hi Aidan,
This patch caused a regression on android-arm (remote debugging) with
breaking the code for setting a breakpoint. I haven't found out the exact
reason for the problem but it looks like as the location of the breakpoints
isn't deduced correctly because of a wrong load address for the executable
(android use position independent code what might effect this issue).
Please take a look into it.
Thanks,
Tamas
On Fri, May 8, 2015 at 10:36 AM, Aidan Dodds <aidan at codeplay.com> wrote:
> Author: aidandodds
> Date: Fri May 8 04:36:31 2015
> New Revision: 236817
>
> URL: http://llvm.org/viewvc/llvm-project?rev=236817&view=rev
> Log:
> This patch allows LLDB to use the $qXfer:Libraries: packet.
>
> Differential Revision: http://reviews.llvm.org/D9471
>
> Modified:
> lldb/trunk/include/lldb/Target/Process.h
>
> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
> lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
> lldb/trunk/source/Target/Target.cpp
>
> Modified: lldb/trunk/include/lldb/Target/Process.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=236817&r1=236816&r2=236817&view=diff
>
> ==============================================================================
> --- lldb/trunk/include/lldb/Target/Process.h (original)
> +++ lldb/trunk/include/lldb/Target/Process.h Fri May 8 04:36:31 2015
> @@ -1121,6 +1121,22 @@ public:
> virtual const lldb::DataBufferSP
> GetAuxvData();
>
> + //------------------------------------------------------------------
> + /// Sometimes processes know how to retrieve and load shared
> libraries.
> + /// This is normally done by DynamicLoader plug-ins, but sometimes the
> + /// connection to the process allows retrieving this information. The
> + /// dynamic loader plug-ins can use this function if they can't
> + /// determine the current shared library load state.
> + ///
> + /// @return
> + /// The number of shared libraries that were loaded
> + //------------------------------------------------------------------
> + virtual size_t
> + LoadModules ()
> + {
> + return 0;
> + }
> +
> protected:
> virtual JITLoaderList &
> GetJITLoaders ();
>
> 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=236817&r1=236816&r2=236817&view=diff
>
> ==============================================================================
> ---
> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
> (original)
> +++
> lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
> Fri May 8 04:36:31 2015
> @@ -120,15 +120,45 @@ DynamicLoaderPOSIXDYLD::DidAttach()
> if (log)
> log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded
> auxv data", __FUNCTION__, m_process ? m_process->GetID () :
> LLDB_INVALID_PROCESS_ID);
>
> - ModuleSP executable_sp = GetTargetExecutable();
> - ResolveExecutableModule(executable_sp);
> + // ask the process if it can load any of its own modules
> + m_process->LoadModules ();
>
> - addr_t load_offset = ComputeLoadOffset();
> + ModuleSP executable_sp = GetTargetExecutable ();
> + ResolveExecutableModule (executable_sp);
> +
> + // find the main process load offset
> + addr_t load_offset = ComputeLoadOffset ();
> if (log)
> log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 "
> executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ?
> m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ?
> executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>",
> load_offset);
>
> + // if we dont have a load address we cant re-base
> + bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false :
> true;
>
> - if (executable_sp && load_offset != LLDB_INVALID_ADDRESS)
> + // if we have a valid executable
> + if (executable_sp.get())
> + {
> + lldb_private::ObjectFile * obj = executable_sp->GetObjectFile();
> + if (obj)
> + {
> + // don't rebase if the module is not an executable
> + if (obj->GetType() != ObjectFile::Type::eTypeExecutable)
> + rebase_exec = false;
> +
> + // don't rebase if the module already has a load address
> + Target & target = m_process->GetTarget ();
> + Address addr = obj->GetImageInfoAddress (&target);
> + if (addr.GetLoadAddress (&target) != LLDB_INVALID_ADDRESS)
> + rebase_exec = false;
> + }
> + }
> + else
> + {
> + // no executable, nothing to re-base
> + rebase_exec = false;
> + }
> +
> + // if the target executable should be re-based
> + if (rebase_exec)
> {
> ModuleList module_list;
>
> @@ -537,6 +567,9 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffse
> if (!exe)
> return LLDB_INVALID_ADDRESS;
>
> + if (exe->GetType() != ObjectFile::Type::eTypeExecutable)
> + return LLDB_INVALID_ADDRESS;
> +
> Address file_entry = exe->GetEntryPointAddress();
>
> if (!file_entry.IsValid())
>
> Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=236817&r1=236816&r2=236817&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
> (original)
> +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Fri
> May 8 04:36:31 2015
> @@ -174,6 +174,107 @@ namespace {
>
> } // anonymous namespace end
>
> +class ProcessGDBRemote::GDBLoadedModuleInfoList
> +{
> +public:
> +
> + class LoadedModuleInfo
> + {
> + public:
> +
> + enum e_data_point
> + {
> + e_has_name = 0,
> + e_has_base ,
> + e_has_dynamic ,
> + e_has_link_map ,
> + e_num
> + };
> +
> + LoadedModuleInfo ()
> + {
> + for (uint32_t i = 0; i < e_num; ++i)
> + m_has[i] = false;
> + };
> +
> + void set_name (const std::string & name)
> + {
> + m_name = name;
> + m_has[e_has_name] = true;
> + }
> + bool get_name (std::string & out) const
> + {
> + out = m_name;
> + return m_has[e_has_name];
> + }
> +
> + void set_base (const lldb::addr_t base)
> + {
> + m_base = base;
> + m_has[e_has_base] = true;
> + }
> + bool get_base (lldb::addr_t & out) const
> + {
> + out = m_base;
> + return m_has[e_has_base];
> + }
> +
> + void set_link_map (const lldb::addr_t addr)
> + {
> + m_link_map = addr;
> + m_has[e_has_link_map] = true;
> + }
> + bool get_link_map (lldb::addr_t & out) const
> + {
> + out = m_link_map;
> + return m_has[e_has_link_map];
> + }
> +
> + void set_dynamic (const lldb::addr_t addr)
> + {
> + m_dynamic = addr;
> + m_has[e_has_dynamic] = true;
> + }
> + bool get_dynamic (lldb::addr_t & out) const
> + {
> + out = m_dynamic;
> + return m_has[e_has_dynamic];
> + }
> +
> + bool has_info (e_data_point datum)
> + {
> + assert (datum < e_num);
> + return m_has[datum];
> + }
> +
> + protected:
> +
> + bool m_has[e_num];
> + std::string m_name;
> + lldb::addr_t m_link_map;
> + lldb::addr_t m_base;
> + lldb::addr_t m_dynamic;
> + };
> +
> + GDBLoadedModuleInfoList ()
> + : m_list ()
> + , m_link_map (LLDB_INVALID_ADDRESS)
> + {}
> +
> + void add (const LoadedModuleInfo & mod)
> + {
> + m_list.push_back (mod);
> + }
> +
> + void clear ()
> + {
> + m_list.clear ();
> + }
> +
> + std::vector<LoadedModuleInfo> m_list;
> + lldb::addr_t m_link_map;
> +};
> +
> // TODO Randomly assigning a port is unsafe. We should get an unused
> // ephemeral port from the kernel and make sure we reserve it before
> passing
> // it to debugserver.
> @@ -575,7 +676,7 @@ ProcessGDBRemote::BuildDynamicRegisterIn
> if (reg_num == 0)
> {
> // try to extract information from servers target.xml
> - if ( GetGDBServerInfo( ) )
> + if (GetGDBServerRegisterInfo ())
> return;
>
> FileSpec target_definition_fspec =
> GetGlobalPluginProperties()->GetTargetDefinitionFile ();
> @@ -2281,7 +2382,18 @@ ProcessGDBRemote::IsAlive ()
> addr_t
> ProcessGDBRemote::GetImageInfoAddress()
> {
> - return m_gdb_comm.GetShlibInfoAddr();
> + // request the link map address via the $qShlibInfoAddr packet
> + lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();
> +
> + // the loaded module list can also provides a link map address
> + if (addr == LLDB_INVALID_ADDRESS)
> + {
> + GDBLoadedModuleInfoList list;
> + if (GetLoadedModuleList (list).Success())
> + addr = list.m_link_map;
> + }
> +
> + return addr;
> }
>
> //------------------------------------------------------------------
> @@ -3855,7 +3967,7 @@ libxml2NullErrorFunc (void *ctx, const c
> // return: 'true' on success
> // 'false' on failure
> bool
> -ProcessGDBRemote::GetGDBServerInfo ()
> +ProcessGDBRemote::GetGDBServerRegisterInfo ()
> {
>
> // redirect libxml2's error handler since the default prints to stdout
> @@ -3928,12 +4040,140 @@ ProcessGDBRemote::GetGDBServerInfo ()
> return true;
> }
>
> +Error
> +ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
> +{
> + Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS);
> + if (log)
> + log->Printf ("ProcessGDBRemote::%s", __FUNCTION__);
> +
> + // redirect libxml2's error handler since the default prints to stdout
> + xmlGenericErrorFunc func = libxml2NullErrorFunc;
> + initGenericErrorDefaultFunc (&func);
> +
> + GDBRemoteCommunicationClient & comm = m_gdb_comm;
> + GDBRemoteDynamicRegisterInfo & regInfo = m_register_info;
> +
> + // check that we have extended feature read support
> + if (!comm.GetQXferLibrariesSVR4ReadSupported ())
> + return Error (0, ErrorType::eErrorTypeGeneric);
> +
> + list.clear ();
> +
> + // request the loaded library list
> + std::string raw;
> + lldb_private::Error lldberr;
> + if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString
> (""), raw, lldberr))
> + return Error (0, ErrorType::eErrorTypeGeneric);
> +
> + // parse the xml file in memory
> + if (log)
> + log->Printf ("parsing: %s", raw.c_str());
> + xmlDocPtr doc = xmlReadMemory (raw.c_str(), raw.size(), "noname.xml",
> nullptr, 0);
> + if (doc == nullptr)
> + return Error (0, ErrorType::eErrorTypeGeneric);
> +
> + xmlNodePtr elm = xmlExFindElement (doc->children,
> {"library-list-svr4"});
> + if (!elm)
> + return Error();
> +
> + // main link map structure
> + xmlAttr * attr = xmlExFindAttribute (elm, "main-lm");
> + if (attr)
> + {
> + std::string val = xmlExGetTextContent (attr);
> + if (val.length() > 2)
> + {
> + uint32_t process_lm = std::stoul (val.c_str()+2, 0, 16);
> + list.m_link_map = process_lm;
> + }
> + }
> +
> + // parse individual library entries
> + for (xmlNode * child = elm->children; child; child=child->next)
> + {
> + if (!child->name)
> + continue;
> +
> + if (strcmp ((char*)child->name, "library") != 0)
> + continue;
> +
> + GDBLoadedModuleInfoList::LoadedModuleInfo module;
> +
> + for (xmlAttrPtr prop = child->properties; prop; prop=prop->next)
> + {
> + if (strcmp ((char*)prop->name, "name") == 0)
> + module.set_name (xmlExGetTextContent (prop));
> +
> + // the address of the link_map struct.
> + if (strcmp ((char*)prop->name, "lm") == 0)
> + {
> + std::string val = xmlExGetTextContent (prop);
> + if (val.length() > 2)
> + {
> + uint32_t module_lm = std::stoul (val.c_str()+2, 0,
> 16);
> + module.set_link_map (module_lm);
> + }
> + }
> +
> + // the displacement as read from the field 'l_addr' of the
> link_map struct.
> + if (strcmp ((char*)prop->name, "l_addr") == 0)
> + {
> + std::string val = xmlExGetTextContent (prop);
> + if (val.length() > 2)
> + {
> + uint32_t module_base = std::stoul (val.c_str()+2, 0,
> 16);
> + module.set_base (module_base);
> + }
> + }
> +
> + // the memory address of the libraries PT_DYAMIC section.
> + if (strcmp ((char*)prop->name, "l_ld") == 0)
> + {
> + std::string val = xmlExGetTextContent (prop);
> + if (val.length() > 2)
> + {
> + uint32_t module_dyn = std::stoul (val.c_str()+2, 0,
> 16);
> + module.set_dynamic (module_dyn);
> + }
> + }
> + }
> +
> + if (log)
> + {
> + std::string name ("");
> + lldb::addr_t lm=0, base=0, ld=0;
> +
> + module.get_name (name);
> + module.get_link_map (lm);
> + module.get_base (base);
> + module.get_dynamic (ld);
> +
> + log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%"
> PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str());
> + }
> +
> + list.add (module);
> + }
> +
> + if (log)
> + log->Printf ("found %" PRId32 " modules in total", (int)
> list.m_list.size());
> +
> + return Error();
> +}
> +
> #else // if defined( LIBXML2_DEFINED )
>
> -using namespace lldb_private::process_gdb_remote;
> +Error
> +ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList &)
> +{
> + // stub (libxml2 not present)
> + Error err;
> + err.SetError (0, ErrorType::eErrorTypeGeneric);
> + return err;
> +}
>
> bool
> -ProcessGDBRemote::GetGDBServerInfo ()
> +ProcessGDBRemote::GetGDBServerRegisterInfo ()
> {
> // stub (libxml2 not present)
> return false;
> @@ -3941,6 +4181,91 @@ ProcessGDBRemote::GetGDBServerInfo ()
>
> #endif // if defined( LIBXML2_DEFINED )
>
> +lldb::ModuleSP
> +ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t
> base_addr)
> +{
> + Target &target = m_process->GetTarget();
> + ModuleList &modules = target.GetImages();
> + ModuleSP module_sp;
> +
> + bool changed = false;
> +
> + ModuleSpec module_spec (file, target.GetArchitecture());
> + if ((module_sp = modules.FindFirstModule (module_spec)))
> + {
> + module_sp->SetLoadAddress (target, base_addr, true, changed);
> + }
> + else if ((module_sp = target.GetSharedModule (module_spec)))
> + {
> + module_sp->SetLoadAddress (target, base_addr, true, changed);
> + }
> +
> + return module_sp;
> +}
> +
> +size_t
> +ProcessGDBRemote::LoadModules ()
> +{
> + using lldb_private::process_gdb_remote::ProcessGDBRemote;
> +
> + // request a list of loaded libraries from GDBServer
> + GDBLoadedModuleInfoList module_list;
> + if (GetLoadedModuleList (module_list).Fail())
> + return 0;
> +
> + // get a list of all the modules
> + ModuleList new_modules;
> +
> + for (GDBLoadedModuleInfoList::LoadedModuleInfo & modInfo :
> module_list.m_list)
> + {
> + std::string mod_name;
> + lldb::addr_t mod_base;
> +
> + bool valid = true;
> + valid &= modInfo.get_name (mod_name);
> + valid &= modInfo.get_base (mod_base);
> + if (!valid)
> + continue;
> +
> + // hack (cleaner way to get file name only?) (win/unix compat?)
> + int marker = mod_name.rfind ('/');
> + if (marker == std::string::npos)
> + marker = 0;
> + else
> + marker += 1;
> +
> + FileSpec file (mod_name.c_str()+marker, true);
> + lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base);
> +
> + if (module_sp.get())
> + new_modules.Append (module_sp);
> + }
> +
> + if (new_modules.GetSize() > 0)
> + {
> + Target & target = m_target;
> +
> + new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) ->
> bool
> + {
> + lldb_private::ObjectFile * obj = module_sp->GetObjectFile ();
> + if (!obj)
> + return true;
> +
> + if (obj->GetType () != ObjectFile::Type::eTypeExecutable)
> + return true;
> +
> + lldb::ModuleSP module_copy_sp = module_sp;
> + target.SetExecutableModule (module_copy_sp, false);
> + return false;
> + });
> +
> + ModuleList &loaded_modules = m_process->GetTarget().GetImages();
> + loaded_modules.AppendIfNeeded (new_modules);
> + m_process->GetTarget().ModulesDidLoad (new_modules);
> + }
> +
> + return new_modules.GetSize();
> +}
>
> class CommandObjectProcessGDBRemotePacketHistory : public
> CommandObjectParsed
> {
>
> Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=236817&r1=236816&r2=236817&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
> (original)
> +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Fri
> May 8 04:36:31 2015
> @@ -241,15 +241,16 @@ public:
> const ArchSpec& arch,
> ModuleSpec &module_spec) override;
>
> - // query remote gdbserver for information
> - bool
> - GetGDBServerInfo ( );
> + virtual size_t
> + LoadModules () override;
>
> protected:
> friend class ThreadGDBRemote;
> friend class GDBRemoteCommunicationClient;
> friend class GDBRemoteRegisterContext;
>
> + class GDBLoadedModuleInfoList;
> +
>
> //----------------------------------------------------------------------
> // Accessors
>
> //----------------------------------------------------------------------
> @@ -396,6 +397,17 @@ protected:
> DynamicLoader *
> GetDynamicLoader () override;
>
> + // Query remote GDBServer for register information
> + bool
> + GetGDBServerRegisterInfo ();
> +
> + // Query remote GDBServer for a detailed loaded library list
> + Error
> + GetLoadedModuleList (GDBLoadedModuleInfoList &);
> +
> + lldb::ModuleSP
> + LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr);
> +
> private:
> //------------------------------------------------------------------
> // For ProcessGDBRemote only
>
> Modified: lldb/trunk/source/Target/Target.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=236817&r1=236816&r2=236817&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Target/Target.cpp (original)
> +++ lldb/trunk/source/Target/Target.cpp Fri May 8 04:36:31 2015
> @@ -1057,13 +1057,24 @@ Target::IgnoreWatchpointByID (lldb::watc
> ModuleSP
> Target::GetExecutableModule ()
> {
> - return m_images.GetModuleAtIndex(0);
> + // search for the first executable in the module list
> + for (size_t i = 0; i < m_images.GetSize(); ++i)
> + {
> + ModuleSP module_sp = m_images.GetModuleAtIndex (i);
> + lldb_private::ObjectFile * obj = module_sp->GetObjectFile();
> + if (obj == nullptr)
> + continue;
> + if (obj->GetType() == ObjectFile::Type::eTypeExecutable)
> + return module_sp;
> + }
> + // as fall back return the first module loaded
> + return m_images.GetModuleAtIndex (0);
> }
>
> Module*
> Target::GetExecutableModulePointer ()
> {
> - return m_images.GetModulePointerAtIndex(0);
> + return GetExecutableModule().get();
> }
>
> static void
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20150508/0fdcce77/attachment.html>
More information about the lldb-commits
mailing list