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

Pavel Labath via lldb-dev lldb-dev at lists.llvm.org
Mon Feb 13 05:46:38 PST 2017


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
>> >> >
>> >
>> >
>
>


More information about the lldb-dev mailing list