[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