"target modules load" and breakpoints not working correctly

I’m seeing 2 issues with “target modules load”:

Issue #1: load address is forgotten after a connect:

(lldb) file u:\lldb_test\dlopen

Current executable set to ‘u:\lldb_test\dlopen’ (hexagon).

(lldb) target modules load -f dlopen -s 0x20000

(lldb) b main

Breakpoint 1: where = dlopen`main + 24 at dlopen.c:26, address = 0x00030018

(lldb) gdb-remote tedwood-ubuntu:5556

But it’s set the breakpoint at 0x10018 instead of 0x30018:

ProcessGDBRemote::EnableBreakpointSite (size_id = 14) address = 0x10018

< 14> send packet: $Z0,10018,4#10

< 4> read packet: $#00

Software breakpoints are unsupported

< 14> send packet: $Z1,10018,4#11

< 6> read packet: $OK#9a

(lldb) br l

Current breakpoints:

1: name = ‘main’, locations = 1, resolved = 1, hit count = 0

1.1: where = dlopen`main + 24 at dlopen.c:26, address = 0x00010018, resolved, hit count = 0

Issue #2: breakpoints on the remote server aren’t updated with a new load address, even though they’re updated in the breakpoint list:

(lldb) br l

Current breakpoints:

1: name = ‘main’, locations = 1, resolved = 1, hit count = 0

1.1: where = dlopen`main + 24 at dlopen.c:26, address = 0x00010018, resolved,

hit count = 0

(lldb) target modules load -f dlopen -s 0x20000

(lldb) br l

< 7> send packet: $p29#db

< 12> read packet: $00100000#81

< 7> send packet: $p1d#05

< 12> read packet: $00000000#80

Current breakpoints:

1: name = ‘main’, locations = 1, resolved = 1, hit count = 0

1.1: where = dlopen`main + 24 at dlopen.c:26, address = 0x00030018, resolved,

hit count = 0

(lldb) c

Process 1 stopped

  • thread #1: tid = 0x0001, 0x00030018 dlopen`main(argc=1, argv=0x00052348) + 24

at dlopen.c:26, stop reason = breakpoint 1.1

frame #0: 0x00030018 dlopen`main(argc=1, argv=0x00052348) + 24 at dlopen.c:26

(lldb) re r pc

pc = 0x00010018 dlopen`main + 24 at dlopen.c:26

Note that lldb says it’s stopped at 0x30018, but it’s really stopped at 0x10018. It never sent a z packet to remove the breakpoint at 0x10018 or a Z packet to add one at 0x30018.

Sounds like something is going wrong when resolving the address. I am guessing that your sections got unloaded when you attached to your GDB remote target. So try this:

(lldb) file u:\lldb_test\dlopen
Current executable set to 'u:\lldb_test\dlopen' (hexagon).
(lldb) target modules load -f dlopen -s 0x20000
(lldb) b main
Breakpoint 1: where = dlopen`main + 24 at dlopen.c:26, address = 0x00030018

Note we got the address correct. Now do a:

(lldb) image dump sections dlopen

Check to make sure all addresses for the sections look good.

Now do:

(lldb) gdb-remote tedwood-ubuntu:5556
(lldb) image dump sections dlopen

I am guessing that the sections have been moved...

Let me know what you find.

Your guess is right - the sections moved. Before attaching:

  0x00000008 code [0x0000000000030000-0x0000000000068d5c) 0x00011000 0x00038d5c 0x00000006 dlopen..text

After attaching:

  0x00000008 code [0x0000000000010000-0x0000000000048d5c) 0x00011000 0x00038d5c 0x00000006 dlopen..text

So you will need to find out who is sliding the shared library incorrectly. It might be a packet that is received through the GDB remote protocol, so there might be a bug in your GDB server.

Greg

I don't see anything in the packet log that would cause the change. Most of the interesting packets (like qShlibInfoAddr, qProcessInfo or qHostInfo) return an empty reply.

Where should I set a breakpoint to see the load addresses moving?

SectionLoadList::SetSectionLoadAddress() in SectionLoadList.cpp

I found why the load addresses are getting dropped. When I do "target modules load", it calls SectionLoadList::SetSectionLoadAddress(), setting the new load address for each section. Then when I attach, DynamicLoaderHexagonDYLD::DidAttach() calls DynamicLoaderHexagonDYLD::UpdateLoadedSections(), which calls Target::SetSectionLoadAddress() for each section, resetting the load address to the address in the relevant file.

If I remove the call to Target::SetSectionLoadAddress(), I can't hit breakpoints. So I need this, but I think I should only do this if the section isn't already loaded.

How do I tell if a section is already loaded?

I found why the load addresses are getting dropped. When I do "target modules load", it calls SectionLoadList::SetSectionLoadAddress(), setting the new load address for each section. Then when I attach, DynamicLoaderHexagonDYLD::DidAttach() calls DynamicLoaderHexagonDYLD::UpdateLoadedSections(), which calls Target::SetSectionLoadAddress() for each section, resetting the load address to the address in the relevant file.

If I remove the call to Target::SetSectionLoadAddress(), I can't hit breakpoints. So I need this, but I think I should only do this if the section isn't already loaded.

How do I tell if a section is already loaded?

Sounds like you need to fix you DynamicLoaderHexagonDYLD right? No? Is there nothing in your program that you can see where things are loaded?

You can ask the section to resolve itself:

    lldb::addr_t
    SBSection::GetLoadAddress (lldb::SBTarget &target);

If the return value is LLDB_INVALID_ADDRESS, then the section is not loaded in the target.

Greg

This is the code in DynamicLoaderHexagonDYLD.cpp that is loading sections, with my change to call GetLoadBaseAddress():

    for (unsigned i = 0; i < num_sections; ++i)
    {
        SectionSP section_sp (sections->GetSectionAtIndex(i));
        lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr;

        if (section_sp->GetLoadBaseAddress(&target) == LLDB_INVALID_ADDRESS)
            target.SetSectionLoadAddress(section_sp, new_load_addr);
    }

But section_sp->GetLoadBaseAddress() always returns LLDB_INVALID_ADDRESS, even when I set the slide with "target modules load -f dlopen -s 0x20000" and verify that it's there with " image dump sections dlopen", so I'm always calling SetSectionLoadAddress() with the section's file address.

Ted

Step through the code and let me know what isn't working.

"process launch" calls Target::Launch, which calls
PlatformHexagon::DebugProcess, which calls Target::CreateProcess, which
calls Target::DeleteCurrentProcess, which calls SectionLoadList::Clear,
which erases the section-to-addr mappings.

"gdb-remote" calls Platform::ConnectProcess, which calls
Target::CreateProcess, which calls Target::DeleteCurrentProcess, which calls
SectionLoadList::Clear, which erases the section-to-addr mappings.