[lldb-dev] Breakpoint + callback performance ... Can it be faster?

Roman Popov via lldb-dev lldb-dev at lists.llvm.org
Mon Feb 13 06:00:34 PST 2017


Thats nice! But how to enable C++?:

(lldb) expr --top-level --
Enter expressions, then terminate with an empty line to evaluate:
1 #include <iostream>
2 void HOOK() { std::cout << "in hook\n"; }
3

error: 'iostream' file not found


2017-02-13 16:46 GMT+03:00 Pavel Labath <labath at google.com>:

> Try this for size:
>
>
> $ bin/lldb /tmp/a.out
> (lldb) target create "/tmp/a.out"
> Current executable set to '/tmp/a.out' (x86_64).
> (lldb) b main
> Breakpoint 1: where = a.out`main + 4 at a.cc:6, address =
> 0x0000000000400531
> (lldb) pr la
> Process 22550 launched: '/tmp/a.out' (x86_64)
> Process 22550 stopped
> * thread #1, name = 'a.out', stop reason = breakpoint 1.1
>     frame #0: 0x0000000000400531 a.out`main at a.cc:6
>    3   void (* volatile hook)();
>    4
>    5   int main() {
> -> 6    printf("before\n");
>    7    if(hook) hook();
>    8    printf("after\n");
>    9   }
> (lldb) expr --top-level -- void HOOK() { (int)printf("in hook\n"); }
> (lldb) expr hook = &HOOK
> (void (*volatile)()) $0 = 0x00007ffff7ff5030
> (lldb) c
> Process 22550 resuming
> before
> in hook
> after
> Process 22550 exited with status = 0 (0x00000000)
> (lldb)
>
>
> On 13 February 2017 at 13:38, Roman Popov <ripopov at gmail.com> wrote:
> > Yes, it would fit. I can even insert hooks manually, like:
> >
> >  std::function<void()> instrumentation_hook = []{ /*dear lldb script,
> please
> > insert your code here*/ }
> >
> > instrumentation_hook(); // run instrumentation, by default does nothing.
> >
> >
> > Is there an easy way to compile some code in lldb and assign to
> > instrumentation_hook ?
> >
> >
> > 2017-02-13 16:33 GMT+03:00 Pavel Labath <labath at google.com>:
> >>
> >> Making the code persist is easy - that's sort of what expr --top-level
> >> does.
> >>
> >> The tricky part is getting your code to execute. When you evaluate
> >> expressions interactively, we manually modify the registers (PC being
> >> the most important one) to point to the code you want to execute. If
> >> you want it to happen automatically at runtime, you would have to
> >> insert a jump instruction somewhere. The problem is, that can't
> >> usually be done without overwriting a couple of instructions of
> >> original code, which means you then have to somehow simulate the
> >> effects of the overwritten instructions. And there's always a danger
> >> that you will overwrite a jump target and things will blow up when
> >> someone tries to jump there. The way this is normally done is that you
> >> have the compiler insert hooks into your code during compilation, that
> >> you can then intercept if necessary. I am not sure if that would fit
> >> your use case.
> >>
> >> pl
> >>
> >>
> >>
> >> On 13 February 2017 at 13:13, Roman Popov <ripopov at gmail.com> wrote:
> >> > Thanks Pavel, you are correct. This was the direction I thought to
> >> > investigate, but I didnt done my homework yet.
> >> >
> >> > Yes, dynamic instrumentation is what I want. Looks like both lldb and
> >> > gdb do
> >> > not allow this directly.
> >> >
> >> > As GDB doc says "After execution, the compiled code is removed from
> gdb
> >> > and
> >> > any new types or variables you have defined will be deleted."
> >> >
> >> > Do you know why it is the case? Why cannot my generated code persist?
> >> >
> >> >
> >> > Looks like technically it is possible. For example you can allocate
> >> > memory
> >> > for generated code on heap.
> >> >
> >> > GDB does not even allow me to define a new function. But for data
> >> > dynamic
> >> > allocation works perfectly fine:
> >> >
> >> >
> >> > Example:
> >> >
> >> > #include <stdio.h>
> >> >
> >> > char message[1000] = "test message\n";
> >> >
> >> > int main() {
> >> >     char *msg = message;
> >> >
> >> >     for (int i = 0; i < 5; i++)
> >> >         printf("%s\n", msg);
> >> >
> >> >     return 0;
> >> > }
> >> >
> >> >
> >> >
> >> > gdb session:
> >> >
> >> > (gdb) break main.c:8
> >> > Breakpoint 1 at 0x400536: file main.c, line 8.
> >> > (gdb) run
> >> > Starting program: /home/ripopov/work/test_c_inject/a.out
> >> >
> >> > Breakpoint 1, main () at main.c:8
> >> > 8           for (int i = 0; i < 5; i++)
> >> > (gdb) compile code
> >> >>char *str;
> >> >>str = (char *) malloc(3);
> >> >>str[0] = 'T';
> >> >>str[1] = '\n';
> >> >>str[2] = 0;
> >> >>msg = str;
> >> >>end
> >> > (gdb) c
> >> > Continuing.
> >> > T
> >> >
> >> > T
> >> >
> >> > T
> >> >
> >> > T
> >> >
> >> > T
> >> >
> >> > [Inferior 1 (process 96445) exited normally]
> >> > (gdb)
> >> >
> >> >
> >> >
> >> >
> >> > 2017-02-13 13:56 GMT+03:00 Pavel Labath <labath at google.com>:
> >> >>
> >> >> Every time you use the "expr" command, we compile a tiny c++ code
> >> >> snippet inject it into the target process and execute it. If you type
> >> >> "log enable lldb expr" you should be able to follow how exactly that
> >> >> works. You can use pretty much any c++ construct in the expression
> >> >> including declaring variables/types:
> >> >> (lldb) expr -- char s[]="qwerty"; for(int i=0; i < sizeof s; ++i)
> >> >> printf("%d: %c\n", i, s[i]);
> >> >> 0: q
> >> >> 1: w
> >> >> 2: e
> >> >> 3: r
> >> >> 4: t
> >> >> 5: y
> >> >> 6:
> >> >>
> >> >>
> >> >> So, if your question is "do we support compiling code and running it
> >> >> in the debugged process", then the answer is yes. If you want
> >> >> something that would automatically intercept some function to execute
> >> >> your code while the process is running (some kind of dynamic
> >> >> instrumentation), then the answer is no. (But I don't see any mention
> >> >> of that on the gdb page you quoted either).
> >> >>
> >> >> cheers,
> >> >> pavel
> >> >>
> >> >> On 12 February 2017 at 18:34, Roman Popov via lldb-dev
> >> >> <lldb-dev at lists.llvm.org> wrote:
> >> >> > Hello Benjamin , all
> >> >> >
> >> >> >>>I recently started using lldb to write a basic instrumentation
> tool
> >> >> >>> for
> >> >> >>>tracking the values of variables at various code-points in a
> >> >> >>> program.
> >> >> >
> >> >> > I have the same problem of tracing some variables and debugging
> >> >> > application
> >> >> > post-mortem. Without knowing about your experience I've started
> >> >> > walking
> >> >> > same
> >> >> > path and encountered same problem. In my case inserting an empty
> >> >> > callback
> >> >> > slows-down application by 100x. This is not acceptable for me,
> >> >> > because
> >> >> > instead of minutes I got hours of runtime.
> >> >> >
> >> >> > Did you found any faster solution?
> >> >> >
> >> >> > My current plan is to solve it with code injection: I plan to find
> >> >> > pointers
> >> >> > to interesting values using debugger scripting and then inject code
> >> >> > to
> >> >> > trace
> >> >> > them.
> >> >> >
> >> >> > Does LLDB supports code injection ? I've found information only
> about
> >> >> > gdb
> >> >> >
> >> >> >
> >> >> > https://sourceware.org/gdb/onlinedocs/gdb/Compiling-and-
> Injecting-Code.html
> >> >> > but not about lldb
> >> >> >
> >> >> >
> >> >> > -Roman
> >> >> >
> >> >> >
> >> >> > _______________________________________________
> >> >> > lldb-dev mailing list
> >> >> > lldb-dev at lists.llvm.org
> >> >> > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> >> >> >
> >> >
> >> >
> >
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20170213/efd14880/attachment-0001.html>


More information about the lldb-dev mailing list