dbgx/lldb.nvim

Breakpoint issues when a shared library is using in macOS Sierra

Closed this issue · 8 comments

A session created by the plugin is default.
I run it as

:LLsession load
:LLmode debug
:LL r

Default breakpoint (breakpoint set -n main) with no shared libraries. Cursor changes from 'B>' to '->'.

thread #1: tid = 0x22a109, 0x0000000100000f6d test`main(argc=1, argv=0x00007fff5fbff7a0) + 29 at main.c:5, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f6d test`main(argc=1, argv=0x00007fff5fbff7a0) + 29 at main.c:5
frame #1: 0x0000000100134255 libdyld.dylib`start + 1

Same breakpoint with a shared library. Cursos remains 'B>' and if I use a step-over then it goes to a next line after breakpoint and changes to '->'

thread #1: tid = 0x22b2b9, 0x000000010001185e dyld`gdb_image_notifier(dyld_image_mode, unsigned int, dyld_image_info const*) + 1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010001185e dyld`gdb_image_notifier(dyld_image_mode, unsigned int, dyld_image_info const*) + 1
frame #1: 0x000000010001158b dyld`notifyGDB(dyld_image_states, unsigned int, dyld_image_info const*) + 40
frame #2: 0x0000000100007e37 dyld`dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) + 943
frame #3: 0x0000000100012a95 dyld`ImageLoader::link(ImageLoader::LinkContext const&, bool, bool, bool, ImageLoader::RPathChain const&, char const*) + 101

Besides if I use a step-over and cursor is set on a line with a function which is located in a shared library then execution continues to the end without stopping on a next line after breakpoint as it should be. If i use step-into instead it works as it should.

I tried both scenarios in a terminal lldb and in a python shell (as described here http://lldb.llvm.org/python-reference.html) and they works just fine.

I'm not sure if I get the problem. Is it that when you have a shared library, the main breakpoint does not actually break at main?

I tried both scenarios [..] in a python shell (as described here http://lldb.llvm.org/python-reference.html) and they works just fine.

Did you load a script from lldb shell, or did you write a script which creates the debugger instance using lldb.SBDebugger.Create()? (as described in the last section of that page) If that's how you did it, can you provide that script file?

Here is my Makefile

BIN=test
SRCDIR=src
OBJDIR=obj
BINDIR=bin
SRCS:=$(shell ls $(SRCDIR))
OBJS:=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))

CFLAGS=-c -O0 -Wall -g3 -fPIC
LDFLAGS=
LIBS=
#LDFLAGS=$(shell pkg-config --libs-only-L glib-2.0)
#LIBS=-lm $(shell pkg-config --libs-only-l glib-2.0)
INCLUDE=-Iinclude

.PHONY: all clean distclean

all: $(BINDIR)/$(BIN)

$(BINDIR)/$(BIN): $(OBJS)
	@mkdir -p `dirname $@`
	$(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $@

$(OBJDIR)/%.o: $(SRCDIR)/%.c
	@mkdir -p `dirname $@`
	$(CC) $(CFLAGS) $(INCLUDE) $< -o $@

clean:
	@rm -rf $(OBJDIR)

distclean: clean
	@rm -rf $(BINDIR)

If I swap LDFLAGS and LIBS to non-empty ones I get an unexpected behaviour of a debugger only inside vim. I tried with my own shared libraries and the result is the same.

I tried to manually run from lldb shell. Here is the result.

(lldb) target create bin/test
Current executable set to 'bin/test' (x86_64).
(lldb) breakpoint set -n main
Breakpoint 1: 14 locations.
(lldb) r
Process 53193 launched: '/Users/beaver/test/bin/test' (x86_64)
4 locations added to breakpoint 1
Process 53193 stopped
* thread #1: tid = 0x2468e6, 0x0000000100000f6d test`main(argc=1, argv=0x00007fff5fbff978) + 29 at main.c:5, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000f6d test`main(argc=1, argv=0x00007fff5fbff978) + 29 at main.c:5
   2
   3   	int main(int argc, const char * argv[])
   4   	{
-> 5   	    int i = 0;
   6   	    printf("ololo %d", i);
   7   	    return 0;
   8   	}
(lldb) bt
* thread #1: tid = 0x246d08, 0x0000000100000f6d test`main(argc=1, argv=0x00007fff5fbff978) + 29 at main.c:5, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000100000f6d test`main(argc=1, argv=0x00007fff5fbff978) + 29 at main.c:5
    frame #1: 0x000000010022f255 libdyld.dylib`start + 1
    frame #2: 0x000000010022f255 libdyld.dylib`start + 1

As you can see backtrace is ok.
Python script is literally the same as described in the last section of LLDB Python Reference and debug stops where it should stop.

But when I try to debug through your plugin, execution stops in a strange place inside system library. Backtrace is shown in my first message.

Also debug doesn't work properly in a situation shown below if I don't step into call_some_shared_library_function and just use step-over.

1       int param = 0;
2 -> int code call_some_shared_library_function();
3      return code   

Debug doesn't jump to a third line but just continues to the end of an executable without stops.

I suppose there is an issue somewhere in system libraries but I don't know how to catch it. I will be grateful if you show me the way of doing it.

Python script is literally the same as described in the last section of LLDB Python Reference and debug stops where it should stop.

I see... Then, can you replace the lines given below:

main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename());
print main_bp

with these:

ci = dbg.GetCommandInterpreter()
res = lldb.SBCommandReturnObject()
ci.HandleCommand("breakpoint set -n main", res)
print res

and check if the behavior changes?

I replaced the lines you gave me. It works the same way and stops at first line of main.

I noticed one more thing. When I start debugging inside vim backtrace flashes for a moment and replaces with one shown above. It happens so fast so I can't see what is in that backtrace.
I found this in mailing list http://lists.llvm.org/pipermail/lldb-dev/2016-January/009453.html. Maybe it can help.

Hmm.. That's strange! Is it possible to give me a link to the source repository?

Also, can you post whatever that gets printed in the [lldb]logs buffer.

When I start debugging inside vim backtrace flashes for a moment and replaces with one shown above.

Can you add these two lines to the end of update_buffer function in lldb.nvim/rplugin/python/lldb_nvim/vim_buffers.py:

        if buf == 'backtrace':
            self.logger.info('Backtrace: \n%s', output)

and run Neovim with python logging as:

export NVIM_PYTHON_LOG_FILE=/tmp/nvlog
nvim

and post the contents of /tmp/nvlog_* ?

(Please post gist or pastebin links if text is too long.)

It is very specific to MacOS architecture. It runs fine in my Arch Linux. Anyway, it is not a bug in the plugin, and probably not a bug in LLDB either, since it is only a bit off. May be this gives more insight?

(LLDB's python API behaves very weirdly sometimes... Especially in Mac!)

Thanks for the report! I'm closing this, since this is beyond scope!