[lldb-dev] Fixing cross platform mac to linux remote expression evaluation

Robert Flack flackr at gmail.com
Tue May 5 12:09:48 PDT 2015


Sorry I keep mistakenly writing malloc instead of mmap. The problem is
still that the lldb-server only instantiates a NativeProcessLinux, which
doesn't extend Process - i.e. it doesn't have an ABI object or Target
object, so we can't use it to create and execute a thread plan to run the
call to mmap and get the return value. In fact, we don't even initialize
any of the ABI plugins on lldb-server. We do have to run mmap from the
inferior process right?

Assuming we must generate the instructions from the host, how about adding
a constants map to the qHostInfo response? Alternately, how about just
hand-copying the few constants we need to some function in
InferiorCallPOSIX and switching based on the Target triple?

On Tue, May 5, 2015 at 2:44 PM, Greg Clayton <gclayton at apple.com> wrote:

> You need to use mmap() because that is the only way to change the type of
> the memory to be executable. If you use malloc, you get read+write memory
> and can't change it to restrict the type. Allocate memory can request read,
> write and execute (any combo of the three).
>
> > On May 4, 2015, at 2:54 PM, Robert Flack <flackr at gmail.com> wrote:
> >
> > Please let me know if I'm missing something, as far as I can see
> lldb-server does not have a Process object, only a NativeProcessLinux
> (which is a NativeProcessProtocol). This doesn't seem to have the context
> to run the thread plan to call malloc and allocate memory from lldb-server
> - see the comment in NativeProcessLinux::AllocateMemory and
> lldb_private::InferiorCallMmap / Process::RunThreadPlan for the full
> details of what it needs to do. I'm not completely familiar with how the
> interaction between lldb and lldb-server works, and I can try to implement
> a function call with a NativeProcessLinux (preserving the previous state)
> but it seems like this will be reimplementing a lot of functionality to do
> so naively. Any thoughts? Is there a simple way to call malloc in the
> context of the NativeProcessLinux and get the return that I'm missing?
> >
> > On Fri, May 1, 2015 at 2:27 PM, Greg Clayton <gclayton at apple.com> wrote:
> >
> > > On May 1, 2015, at 7:00 AM, Robert Flack <flackr at gmail.com> wrote:
> > >
> > > Thanks Greg for the suggestions, I'll start working on that and put up
> a patch when I have something working.
> > >
> > > Even doing it this way though, I imagine we'll still want to be able
> to load debug info for standard libraries if we can find it. I'm guessing
> we can only call functions from the symbol table if we have the function
> spec provided elsewhere (i.e. from a header file) or we know exactly what
> the function arguments are (as was the case in
> lldb_private::InferiorCallMmap).
> >
> > mmap is a symbol every app needs to be able to link to. We don't need
> debug info to call it. We just need to be able to find the symbol for it so
> we know where the code for mmap is.
> >
> > > On Fri, May 1, 2015 at 3:47 AM, Pavel Labath <labath at google.com>
> wrote:
> > > Hi,
> > >
> > > this may not be so important if we choose the approach Greg suggests
> > > (which sounds like a good idea), but in any case, I wanted to say that
> > > I don't think that we should be depending on the debug symbols in libc
> > > for a basic functionality like this. I think it's not safe to assume
> > > that debug symbols will be available on every machine. And in any
> > > case, mmap is a public symbol in libc, so it should be possible to
> > > find it without debug symbols:
> > > $ objdump -T /lib/libc-2.20.so  | grep mmap
> > > 00000000000e3670  w   DF .text    0000000000000024  GLIBC_2.2.5 mmap64
> > > 00000000000e3670  w   DF .text    0000000000000024  GLIBC_2.2.5 mmap
> > >
> > > What does objdump produce on your machine? If mmap is there, and lldb
> > > is not finding it then I think we should find out why...
> > >
> > > I'd like to not depend on the debug symbols, but we should definitely
> load them if we can find them (as we do when running locally).
> >
> > Agreed. We don't require them, but it will be nice to have them.
> >
> > > The symbol table is in the stripped .so (readelf -s or objdump -T show
> the symbol entries for mmap), but we're calling
> SymbolFileSymtab::FindFunctions which returns 0 because we don't have the
> full method info. When called from lldb_private::InferiorCallMmap, it seems
> like all we need is the base address which we could get that from the
> symbol table. To support general function calls into those functions
> though, as far as I can tell we can't tell from the symbol table what
> arguments are required, only the base address. I haven't tested this yet
> but I'm hoping that if the system header file for that function is included
> we'll find the function spec in the target's debug info.
> >
> > Again, if "mmap" can be looked up via:
> >
> > void *mmap_address = dlsym(..., "mmap");
> >
> > Then there must be a public symbol available in the libc.so. If LLDB
> doesn't see this, we need to fix that, even without debug symbols.
> >
> >
> >
> > >
> > > cheers,
> > > pl
> > >
> > >
> > > On 30 April 2015 at 23:53, Greg Clayton <gclayton at apple.com> wrote:
> > > >
> > > >> On Apr 30, 2015, at 3:36 PM, Robert Flack <flackr at gmail.com> wrote:
> > > >>
> > > >> Hi,
> > > >>
> > > >> I've been looking into why expression evaluation is failing when
> targeting a remote Linux machine from Mac lldb host and it seems there are
> only 2 distinct problems remaining - both around memory allocation:
> > > >>
> > > >> 1. Can't find symbol for mmap.
> > > >> 2. Once found, lldb is calling mmap with incorrect constant values
> for MAP_ANON.
> > > >>
> > > >> For problem 1, the library being linked against (e.g.
> /lib/x86_64-linux-gnu/libc-2.19.so) is copied into a local module cache,
> but we don't copy the unstripped library in
> /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so (I'm assuming we can't
> call mmap from the symtab file given SymbolFileSymtab::FindFunctions
> returns 0). To avoid having to duplicate the symbol discovery (in
> Symbols::LocateExecutableSymbolFile) we should probably ask lldb-platform
> on the target to find the symbol files for the current target (I'm thinking
> Platform::ResolveSymbolFile looks like the right place).
> > > >>
> > > >> For problem 2, we're building the argument list to mmap and the
> constant for MAP_ANON on macosx is 0x1000 whereas for linux it's 0x20. I'm
> not sure what the right way to fix this is, I could imagine asking Platform
> to allocate memory, but this would likely be an involved change, or perhaps
> being able to ask platform for various OS specific const values which would
> be hard-coded into it when built for the target.
> > > >>
> > > > So we need to implement the allocate and deallocate memory packets
> in lldb-server. It seems we have it implemented in the client, but not in
> the server:
> > > >
> > > > addr_t
> > > > GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t
> permissions)
> > > > {
> > > >     if (m_supports_alloc_dealloc_memory != eLazyBoolNo)
> > > >     {
> > > >         m_supports_alloc_dealloc_memory = eLazyBoolYes;
> > > >         char packet[64];
> > > >         const int packet_len = ::snprintf (packet, sizeof(packet),
> "_M%" PRIx64 ",%s%s%s",
> > > >                                            (uint64_t)size,
> > > >                                            permissions &
> lldb::ePermissionsReadable ? "r" : "",
> > > >                                            permissions &
> lldb::ePermissionsWritable ? "w" : "",
> > > >                                            permissions &
> lldb::ePermissionsExecutable ? "x" : "");
> > > >         assert (packet_len < (int)sizeof(packet));
> > > >         StringExtractorGDBRemote response;
> > > >         if (SendPacketAndWaitForResponse (packet, packet_len,
> response, false) == PacketResult::Success)
> > > >         {
> > > >             if (response.IsUnsupportedResponse())
> > > >                 m_supports_alloc_dealloc_memory = eLazyBoolNo;
> > > >             else if (!response.IsErrorResponse())
> > > >                 return response.GetHexMaxU64(false,
> LLDB_INVALID_ADDRESS);
> > > >         }
> > > >         else
> > > >         {
> > > >             m_supports_alloc_dealloc_memory = eLazyBoolNo;
> > > >         }
> > > >     }
> > > >     return LLDB_INVALID_ADDRESS;
> > > > }
> > > >
> > > > bool
> > > > GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
> > > > {
> > > >     if (m_supports_alloc_dealloc_memory != eLazyBoolNo)
> > > >     {
> > > >         m_supports_alloc_dealloc_memory = eLazyBoolYes;
> > > >         char packet[64];
> > > >         const int packet_len = ::snprintf(packet, sizeof(packet),
> "_m%" PRIx64, (uint64_t)addr);
> > > >         assert (packet_len < (int)sizeof(packet));
> > > >         StringExtractorGDBRemote response;
> > > >         if (SendPacketAndWaitForResponse (packet, packet_len,
> response, false) == PacketResult::Success)
> > > >         {
> > > >             if (response.IsUnsupportedResponse())
> > > >                 m_supports_alloc_dealloc_memory = eLazyBoolNo;
> > > >             else if (response.IsOKResponse())
> > > >                 return true;
> > > >         }
> > > >         else
> > > >         {
> > > >             m_supports_alloc_dealloc_memory = eLazyBoolNo;
> > > >         }
> > > >     }
> > > >     return false;
> > > > }
> > > >
> > > > Then you call mmap yourself on the native machine in lldb-server
> instead of trying to know what enums will work.
> > > >
> > > > We actually need to ask the PlatformLinux to run an
> allocate/deallocate memory and hand it a process. So we can add the
> following to lldb_private::Platform:
> > > >
> > > >     virtual bool
> > > >     SupportsMemoryAllocation();
> > > >
> > > >     virtual lldb::addr_t
> > > >     AllocateMemory (lldb_private::Process *process, size_t size,
> uint32_t permissions, Error &error);
> > > >
> > > >
> > > >     virtual Error
> > > >     DeallocateMemory (lldb_private::Process *process, lldb::addr_t
> ptr);
> > > >
> > > > Then the lldb_private::Process can get the current platform and ask
> it if it supports allocating memory, and if so call the
> Platform::AllocateMemory()/Platform:: DeallocateMemory().
> > > >
> > > > Then the PlatformLinux can "do the right thing" and use the right
> defines.
> > > >
> > > >> Anyways, I wanted to send this out to see if anyone had any
> thoughts on either of these issues or was already working on them. I have
> verified (by hacking in the correct const values for linux and placing
> debug libs in a path where they will be found) that this fixes expression
> evaluation (and 14 tests start passing) for mac->linux debugging.
> > > >>
> > > >> Thanks in advance for any suggestions,
> > > >> Rob
> > > >
> > > > So my suggestion is to implement the memory allocation/deallocation
> in lldb-server since it runs natively and will avoid the problems we run
> into by trying to evaluate functions by calling them remotely using #define
> values from the current system...
> > > >
> > > >
> > > >>
> > > >> P.S. the 14 tests passing mac->linux by fixing this (for other
> people looking at cross platform tests):
> > > >> Test11588.py
> > > >> TestAnonymous.py
> > > >> TestBreakpointConditions.py
> > > >> TestCPPStaticMethods.py
> > > >> TestCStrings.py
> > > >> TestCallStdStringFunction.py
> > > >> TestDataFormatterCpp.py
> > > >> TestDataFormatterStdList.py
> > > >> TestExprDoesntBlock.py
> > > >> TestExprHelpExamples.py
> > > >> TestFunctionTypes.py
> > > >> TestPrintfAfterUp.py
> > > >> TestSBValuePersist.py
> > > >> TestSetValues.py
> > > >>
> > > >> _______________________________________________
> > > >> lldb-dev mailing list
> > > >> lldb-dev at cs.uiuc.edu
> > > >> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> > > >
> > > >
> > > > _______________________________________________
> > > > lldb-dev mailing list
> > > > lldb-dev at cs.uiuc.edu
> > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> > >
> >
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150505/995ea0da/attachment.html>


More information about the lldb-dev mailing list