[Lldb-commits] [lldb] r236817 - This patch allows LLDB to use the $qXfer:Libraries: packet.
Tamas Berghammer
tberghammer at google.com
Fri May 8 04:12:45 PDT 2015
I committed in a fix for the issue as http://reviews.llvm.org/rL236826.
Please take a look and let me know if it causing some issue for you.
Tamas
On Fri, May 8, 2015 at 11:42 AM, Tamas Berghammer <tberghammer at google.com>
wrote:
> 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/dfff66a5/attachment.html>
More information about the lldb-commits
mailing list