Skip to content

Instantly share code, notes, and snippets.

@eonil
Last active August 29, 2015 14:13
Show Gist options
  • Save eonil/08a09245e3b5f4080a7d to your computer and use it in GitHub Desktop.
Save eonil/08a09245e3b5f4080a7d to your computer and use it in GitHub Desktop.

LLDB Note

A key conversation.

Well, it's three years ago, and now it works far better.

Remote Debugging Summary

  • debugserver is being deprecated. (lldb client's gdb-remote command) This is not a way to go.
  • Use lldb-platform as a server for remote debugging.

Then, how to use it? Here's brief procedure. From server side (target machine),

/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/lldb-platform --listen 9999

From client side (development machine),

lldb
platform select remote-macosx
platform connect connect://localhost:9999
target create /Users/Eonil/Workshop/Temp/SampleProgram1
target modules list
source list
b main
process launch
frame variable
q

Remote Debugging Explanation

First, run lldb-platform at anywhere. This is machine level server, and working directory doesn't matter.

/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/lldb-platform --listen 9999

It's done.

Now run lldb driver.

lldb

Set its running mode to remote debugging client.

platform select remote-macosx

Connect to the lldb-platform server.

platform connect connect://localhost:9999

Creates a target on the remote machine. Always use an absolute path becuase lldb-platform is machine scoped, and doesn't care working directory.

target create /Users/Eonil/Workshop/Temp/SampleProgram1

Check modules of target. You should be able to see some module list.

target modules list

Check sources of target. You should see some source code.

source list

Set a breakpoint at main symbol --- a function.

b main

Run target executable as a new process.

process launch

It should break at main function. Now you can inspect local variables.

frame variable

You should see something like this.

(int) argc = 1606422582
(const char **) argv = 0x00007fff5fbfff18

When you done, quit it gracefully unless you want some zombies.

q

This will also quit the lldb-platform server effectively and gracefully.

Problems

... that was the happy case scenario. But this randomly breaks with one of these errors.

error: memory read failed for 0x100000f3000
error: process launch failed: Malformed Mach-o file
...

I don't know why. Seems the protocol implementation is still immature.

Building LLDB.framwork without Code-Signing

If you're building LLDB from source, you will see various errors due to lack of code-signing. That related to script touching lldb-identity stuff. The lldb-identity is just an example certificate that explained by LLDB team.

If you're a registered OS X developer program license, the certificate also can be used for this singing.

Anyway, if you just want to run the lldb, there's a way to avoid this code-signing process. (currently 330.x version) This signing is applied to debugserver and lldb-platform, and those programs are not used for LLDB.framework itself. Search build script for lldb_identity related code-signing, and erase them all. And LLDB.framework will be built without code-signing.

Produced lldb binary will look working, but actually is not. It runs, but it fails when you order to launch a process. (with such error like lost connection -1) This is because the lldb uses debugserver as a backend, so it needs some proper privilege. You can give it a privilege by running the driver program with sudo.

sudo ./lldb

BEWARE! sudo gives full control on the OS, and use at your own risk.

And you will see it is magically running. If you're linking to this custom-built framework, I believe you need to run the linked application to run with sudo. I am not sure how can I do this with proper system GUIs.

Hacking to eliminate need for sudo

WARNING: THIS IS A DIRTY HACK

LLDB is mainly a library. LLDB.framework is a driver in C++ interface, and lldb is in command-line interface. All works are done by backend server --- debugserver. If the protocol implementation is stable enough, we can swap the backend-server.

We already have built LLDB.framework without code-signing. Bring it again. And replace LLDB.framework/A/Resources folder to Xcode provided one. (1) erase the folder, and (2) symlink to Xcode one.

Now run ./lldb <path-to-some-executable> WITHOUT sudo. Try process launch. I could make it work.

Anyway this is relying on a positive assumption on undefined behaviors, and very likely to be broken by any incompatibility between implementations. Do this at your own risk.

  • This trick doesn't work for GUI apps that links to LLDB.framework. Privileged code seems linked statically. You still need sudo.

Update

I made it to work with Xcode LLDB. Erase these files from LLDB.framework;

  • lldb-platform
  • debugserver
  • darwin-debug

and sylink corresonding files from Xcode's LLDB.framwork. Anyway currently this works with Debug build only. I don't know why. Seems I touched something wrong when I build Release build. I hope to review this eventually, and now I just use Debug version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment