Sorry for the delayed response Greg.
I have been working on a proof of concept which adds a new dynamic
loader for gdb-remote as you suggest, and perhaps when I get it working with
the behavior I'm expecting, I can post it for review and we can have a
look at how best to integrate something like this with upstream LLDB.
Perhaps
it can indeed by integrated cleanly with the posixDYLD.
There is one issue that has emerged while I have been working on this,
with regard to how LLDB regards the target executable as the first
module loaded.
Since the first and potentially only module that I can give to LLDB is a
shared library it doesn't seem to make sense to regard it as the
executable module.
My thoughts were to change the way the target handles this, so that LLDB
instead looks for the first executable module loaded, which would
exclude shared object.
I changed it to be something like this:
ModuleSP
Target::GetExecutableModule ()
{
for ( uint32_t i = 0; i < (uint32_t)m_images.GetSize( ); ++i )
{
ModuleSP modsp = m_images.GetModuleAtIndex( i );
lldb_private::ObjectFile * obj = modsp->GetObjectFile( );
if ( obj == nullptr )
continue;
ObjectFile::Type type = obj->GetType( );
if ( type == ObjectFile::Type::eTypeExecutable )
return modsp;
}
return ModuleSP();
}
Module*
Target::GetExecutableModulePointer ()
{
return GetExecutableModule().get();
}
This problem surfaced when I noticed the posixDYLD (which I was using at
the time) takes the executable (module index 0), and forcefully sets its
load address based
on the entry point of the program. In the case of my shared library
this is the incorrect address.
Does anyone have thoughts or opinions on this?
On 24/04/2015 18:31, Greg Clayton wrote:
A few things to check on:
lldb_private::Process already has:
//------------------------------------------------------------------
// Returns AUXV structure found in many ELF-based environments.
//
// The default action is to return an empty data buffer.
//
// @return
// A data buffer containing the contents of the AUXV data.
//------------------------------------------------------------------
virtual const lldb::DataBufferSP
GetAuxvData();
Would this help?
What dynamic loader is currently being selected when you debug?
PluginDynamicLoaderPosixDYLD? If so, maybe PluginDynamicLoaderPosixDYLD can
just use Process::GetAuxvData()? It would be nice to abstract this through
lldb_private::Process if PluginDynamicLoaderPosixDYLD just needs a bit of help
to get started as I would prefer to keep using PluginDynamicLoaderPosixDYLD or
its subclasses if possible so that we don't have to create
DynamicLoaderGDBRemote if we don't need to.
Greg
On Apr 24, 2015, at 10:21 AM, Aidan Dodds <ai...@codeplay.com> wrote:
Thanks for the quick response Greg.
Its an interesting point you raise when it comes to knowing how any
DynamicLoaderGDBRemote would detect newly loaded
modules. Since my target is Linux based the standard approach of hooking the
rendezvous address should still work.
Presumably since I will have the full list of loaded modules and their
locations, I would be able to find ld-linux.so,
and I additionally have access to the auxvector via the $qXfer:auxv packet.
Perhaps these will provide enough data for me
to locate the dyld rendezvous address.
Perhaps lldbPluginDynamicLoaderPosixDYLD would serve as a suitable base class
for DynamicLoaderGDBRemote.
I'll mull over your suggestions this weekend and get back to you with something
more concrete on Monday.
In the mean time, if anyone else also has ideas or suggestions I'm all ears.
Thanks again,
Aidan
On 24/04/2015 17:45, Greg Clayton wrote:
Actually scratch this last approach.
A better approach would be to make a new DynamicLoader subclass called
DynamicLoaderGDBRemote. This plug-in would only be created if the process' name is
"gdb-remote" and if the ProcessGDBRemote supports the qXfer:libraries:read
command. Then the DynamicLoaderGDBRemote can cast the abstract lldb_private::Process to a
ProcessGDBRemote and use any special functions in ProcessGDBRemote to get this info and
make the shared libraries get loaded correctly.
We try to make our GDB server binaries and simple as possible and we don't vend
shared library info from them. In this case we want to use the correct
DynamicLoader plug-ins for the current process. It also allows us to use the
DynamicLoader plug-ins with multiple processes. For example,
DynamicLoaderDarwinKernel can either be used with ProcessGDBRemote or
ProcessKDP. It just uses generic process calls on lldb_private::Process to do
its thing so these plug-ins can work with any lldb_private::Process. In this
case we have a case where the DynamicLoaderGDBRemote would only work with
ProcessGDBRemote. In the static class function you would need to check the
process plug-in name:
DynamicLoader *
DynamicLoaderGDBRemote::CreateInstance (Process* process, bool force)
{
if (process->GetPluginName() == ProcessGDBRemote::GetPluginNameStatic())
{
ProcessGDBRemote* gdb_process = (ProcessGDBRemote*)process;
if (gdb_process->Supports_qXfer_libraries())
{
// Create a new instance of DynamicLoaderGDBRemote and return it
}
}
return NULL;
}
Then the question becomes how do shared library loaded notifications come in
when a shared library is loaded dynamically?
Greg Clayton
On Apr 24, 2015, at 9:28 AM, Greg Clayton <gclay...@apple.com> wrote:
This if fine. We will want to make these changes as a virtual call in
lldb_private::Process where we ask the process if it can help discover loaded shared
libraries. The dynamic loader plug-ins will need to be modified to take advantage of this
as they get an abstract "lldb_private::Process*" when they are created. Then
the dynamic loader plug-ins can ask the process if they can supply the module loaded
info, and take advantage of this if needed.
Maybe something like:
namespace lldb_private {
class Process {
...
virtual Error GetLoadedSharedLibraries(std::vector<LoadedModuleInfo>
&loaded_modules)
{
Error error;
loaded_modules.clear();
error.SetErrorString("unimplemented");
return error;
}
I don't believe qModuleInfo if the correct call to be using. I believe this is
a platform packet only that allows you to ask about what a remote file
contains. It answers with the info on each contained file that is contained
within a file and returns the architecture, file offset, and file size for each
different slice. Most files only have one item inside them, so they would
return info on that single file. This isn't designed to be tied to a process
nor is it designed to pass along any module load info for a specific process.
I would just use the qXfer:libraries:read command and implement this as a new call in
"lldb_private::Process *" that returns an error in the default implementation,
and the ProcessGDBRemote will have a override version of this function that can give us
the info we need.
Let me know if you need any help in making this happen.
Greg
On Apr 24, 2015, at 7:06 AM, Aidan Dodds <ai...@codeplay.com> wrote:
Hi,
I would like to improve support for the case where LLDB is debugging a remote
target (via gdbserver)
yet doesn't have access to the target executable, and only has access to a
shared object already
loaded by the target.
This is supported from GDB, as I can connect to a remote GDBServer without
specifying any executable,
and after issuing 'set solib-search-paths' it will resolve all of the loaded
shared objects correctly, while
still being blind to the target executable.
I feel like LLDB should be able to connect to a remote target, and then after
issuing a 'target modules add'
command be able to resolve its load address automatically. I believe LLDB can
already do this to some extent
via the 'qModuleInfo' RSP packet.
The 'qXfer:libraries:read' packet is provided by GDBServer, and will return an
XML document containing
all of the shared objects loaded by the target and their load addresses. It is
possible to parse this now using the
recent libxml2 support in LLDB.
GDBRemoteCommunicationClient::GetModuleInfo() could be extended to try and gain
information about a
loaded module via the 'qXfer:libraries:read' packet if 'qModuleInfo' fails or
is not supported.
I would be interested to hear what others think, or get some feedback if I have
perhaps misunderstood something.
Thanks,
Aidan Dodds
_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev