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 <tbergham...@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 <ai...@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@cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits >> > >
_______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits