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

Pavel Labath labath at google.com
Fri May 1 00:47:26 PDT 2015


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...

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




More information about the lldb-dev mailing list