"image search-paths add" removes all breakpoints from remote server

Is “image search-paths add” supposed to remove all breakpoints from the remote server? I don’t think it should be doing this.

PathMappingList::Append calls Target::ImageSearchPathsChanged, which calls Target::SetExecutableModule, which calls Target::ClearModules, which removes the breakpoints. But SetExecutableModule doesn’t restore the breakpoints.

This test I use top-of-tree lldb, built on Ubuntu 12 with a native target. Packet log edited to remove chaff.

(lldb) log enable gdb-remote packets

(lldb) process launch –s

Process 18766 launched: ‘/usr2/tedwood/lldb_test/factlin’ (x86_64)

(lldb) process status

Process 18766 stopped

  • thread #1, name = ‘factlin’, stop reason = signal SIGSTOP

frame #0: 0x00007ffff7ddb6b0

→ 0x7ffff7ddb6b0: movq %rsp, %rdi

0x7ffff7ddb6b3: callq 0x7ffff7ddf010

0x7ffff7ddb6b8: movq %rax, %r12

0x7ffff7ddb6bb: movl 0x2215ff(%rip), %eax

(lldb) b main

< 15> send packet: $Z0,400586,1#4a

< 6> read packet: $OK#9a

Breakpoint 1: where = factlin`main + 22 at factorial.c:32, address = 0x0000000000400586

(lldb) br l

Current breakpoints:

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

1.1: where = factlin`main + 22 at factorial.c:32, address = 0x0000000000400586, resolved, hit count = 0

(lldb) image search-paths add /local /tmp

< 15> send packet: $z0,400586,1#6a

< 6> read packet: $OK#9a

< 15> send packet: $z0,400410,1#5c

< 6> read packet: $OK#9a

(lldb) br l

Current breakpoints:

1: name = ‘main’, locations = 1

1.1: where = factlin`main + 22 at factorial.c:32, address = factlin[0x0000000000400586], unresolved, hit count = 0

(lldb) c

< 5> send packet: $c#63

Process 18766 resuming

Factorial of 10 is 3628800

< 7> read packet: $W00#b7

Process 18766 exited with status = 0 (0x00000000)

As you can see, the breakpoint at main was removed on lldb-server, but shows as active in the breakpoint list. When I continue, the breakpoint isn’t hit, and the target runs to completion.

Is “image search-paths add” supposed to remove all breakpoints from the remote server? I don’t think it should be doing this.

PathMappingList::Append calls Target::ImageSearchPathsChanged, which calls Target::SetExecutableModule, which calls Target::ClearModules, which removes the breakpoints. But SetExecutableModule doesn’t restore the breakpoints.

This test I use top-of-tree lldb, built on Ubuntu 12 with a native target. Packet log edited to remove chaff.

(lldb) log enable gdb-remote packets
(lldb) process launch –s
Process 18766 launched: '/usr2/tedwood/lldb_test/factlin' (x86_64)
(lldb) process status
Process 18766 stopped
* thread #1, name = 'factlin', stop reason = signal SIGSTOP
    frame #0: 0x00007ffff7ddb6b0
-> 0x7ffff7ddb6b0: movq %rsp, %rdi
    0x7ffff7ddb6b3: callq 0x7ffff7ddf010
    0x7ffff7ddb6b8: movq %rax, %r12
    0x7ffff7ddb6bb: movl 0x2215ff(%rip), %eax
(lldb) b main
< 15> send packet: $Z0,400586,1#4a
< 6> read packet: $OK#9a
Breakpoint 1: where = factlin`main + 22 at factorial.c:32, address = 0x0000000000400586
(lldb) br l
Current breakpoints:
1: name = 'main', locations = 1, resolved = 1, hit count = 0
  1.1: where = factlin`main + 22 at factorial.c:32, address = 0x0000000000400586, resolved, hit count = 0
(lldb) image search-paths add /local /tmp
< 15> send packet: $z0,400586,1#6a
< 6> read packet: $OK#9a
< 15> send packet: $z0,400410,1#5c
< 6> read packet: $OK#9a
(lldb) br l
Current breakpoints:
1: name = 'main', locations = 1
  1.1: where = factlin`main + 22 at factorial.c:32, address = factlin[0x0000000000400586], unresolved, hit count = 0
(lldb) c
< 5> send packet: $c#63
Process 18766 resuming
Factorial of 10 is 3628800
< 7> read packet: $W00#b7
Process 18766 exited with status = 0 (0x00000000)

This is a distinction without much difference, but the break list output is actually telling you somebody forgot to re-install the breakpoints. Note the state went from resolved (i.e. there is a site in the targeted process for this breakpoint location) to unresolved. Still a bug, but the breakpoints aren't lying to you...

When you added search paths, all the breakpoints needed to be re-set, since the symbol world might have changed. But apparently only the removal part is getting done.

Jim

I tried having SetExecutableModule call ModuleDidLoad after appending the executable to m_images, but it didn't work. It eventually drills down to call GetSectionLoadList, which is empty. Probably because the module list got cleared. Any thoughts on how to clean up the new module list, and add the breakpoints back?

That leads me to think that other modules besides the executable would just be lost.

If you call SetExecutableModule while a process is running, we probably need to ask the dynamic loader plug-in to update the loaded shared libraries. We might actually need to clear the dynamic loader and let the process load a new one since some dynamic loaders might use the executable to figure out if the dynamic loader should be loaded. It might be better to add a new function to Process.cpp:

void
Process::ExecutableChanged()
{
  // Called when the executable is changed while a process is running.
  // Let the dynamic loader reload itself in case a different dynamic loader
  // might be selected with a different main executable.
  m_dyld_ap.reset();
  DynamicLoader *dyld = GetDynamicLoader();
  if (dyld)
    dyld->DidAttach();
}

This way even if breakpoints did get unresolved, the should get set again when the dynamic loader loads the shared libraries.

Thoughts Jim?

That seems like the cleanest way to do things. It doesn’t look like the Darwin & MacOS dynamic loaders don’t have any state that they wouldn’t correctly re-compute mid-flight. But for instance when the shared library list goes away, the runtime plugins might also need to get unset and reset, and they do have a bunch of state. Not that they can’t undo that, but it is untested whether they will or not at first go. So some caution would be warranted here.

Jim