<div dir="ltr">Thank you very much Greg and Pavel for help!<div><br></div><div>I will probably need another months or so to work on my variable tracing stuff. I don't see any additional roadblocks yet.</div></div><div class="gmail_extra"><br><div class="gmail_quote">2017-02-13 22:11 GMT+03:00 Greg Clayton <span dir="ltr"><<a href="mailto:gclayton@apple.com" target="_blank">gclayton@apple.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Clang just doesn't currently know where to look for the standard headers. Not sure if this is a top level code only bug or not. I know the expression parser can include common C headers on Darwin. Not sure if any includes work on linux. Try importing <stdio.h> and see how that goes? <div><br></div><div>The better way to do what you want is to write a shared library, save it to "/tmp/liba.so" and then load it at runtime:<div><br></div><div>(lldb) process load /tmp/liba.so</div><div><br></div><div>This will load a shared library with all of the top level code you want into your current program, then you can call any functions in that shared library as well using expressions that you need.</div><div><br></div><div>If you feel you still need to use the expression parser, then a few tips on the expression parser when not in top level code mode:</div><div>- C++ lambda functions that don't capture anything can be cast to function pointer types and used as static callbacks.</div><div>- Any variable you define that is prefixed with a '$' will become a global variable and persist beyond your expression (assign a function callback from C++ lambda, and you have a callback you can now use.</div><div>- Any type you declare that is prefixed with a '$' will persist beyond that expression and be available for future expressions.</div><div>- Any type returned as the result type of an expression will have its type available</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>Greg</div></font></span><div><div class="h5"><div><br></div><div><div><blockquote type="cite"><div>On Feb 13, 2017, at 6:00 AM, Roman Popov via lldb-dev <<a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a>> wrote:</div><br class="m_-4861244670194674880Apple-interchange-newline"><div><div dir="ltr">Thats nice! But how to enable C++?:<div><br></div><div><div>(lldb) expr --top-level --</div><div>Enter expressions, then terminate with an empty line to evaluate:</div><div>1 #include <iostream></div><div>2 void HOOK() { std::cout << "in hook\n"; }</div><div>3 </div></div><div><br></div><div><div>error: 'iostream' file not found</div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2017-02-13 16:46 GMT+03:00 Pavel Labath <span dir="ltr"><<a href="mailto:labath@google.com" target="_blank">labath@google.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Try this for size:<br>
<br>
<br>
$ bin/lldb /tmp/a.out<br>
(lldb) target create "/tmp/a.out"<br>
Current executable set to '/tmp/a.out' (x86_64).<br>
(lldb) b main<br>
Breakpoint 1: where = a.out`main + 4 at <a href="http://a.cc" target="_blank">a.cc</a>:6, address = 0x0000000000400531<br>
(lldb) pr la<br>
Process 22550 launched: '/tmp/a.out' (x86_64)<br>
Process 22550 stopped<br>
* thread #1, name = 'a.out', stop reason = breakpoint 1.1<br>
frame #0: 0x0000000000400531 a.out`main at <a href="http://a.cc" target="_blank">a.cc</a>:6<br>
3 void (* volatile hook)();<br>
4<br>
5 int main() {<br>
-> 6 printf("before\n");<br>
7 if(hook) hook();<br>
8 printf("after\n");<br>
9 }<br>
(lldb) expr --top-level -- void HOOK() { (int)printf("in hook\n"); }<br>
(lldb) expr hook = &HOOK<br>
(void (*volatile)()) $0 = 0x00007ffff7ff5030<br>
(lldb) c<br>
Process 22550 resuming<br>
before<br>
in hook<br>
after<br>
Process 22550 exited with status = 0 (0x00000000)<br>
(lldb)<br>
<div class="m_-4861244670194674880HOEnZb"><div class="m_-4861244670194674880h5"><br>
<br>
On 13 February 2017 at 13:38, Roman Popov <<a href="mailto:ripopov@gmail.com" target="_blank">ripopov@gmail.com</a>> wrote:<br>
> Yes, it would fit. I can even insert hooks manually, like:<br>
><br>
> std::function<void()> instrumentation_hook = []{ /*dear lldb script, please<br>
> insert your code here*/ }<br>
><br>
> instrumentation_hook(); // run instrumentation, by default does nothing.<br>
><br>
><br>
> Is there an easy way to compile some code in lldb and assign to<br>
> instrumentation_hook ?<br>
><br>
><br>
> 2017-02-13 16:33 GMT+03:00 Pavel Labath <<a href="mailto:labath@google.com" target="_blank">labath@google.com</a>>:<br>
>><br>
>> Making the code persist is easy - that's sort of what expr --top-level<br>
>> does.<br>
>><br>
>> The tricky part is getting your code to execute. When you evaluate<br>
>> expressions interactively, we manually modify the registers (PC being<br>
>> the most important one) to point to the code you want to execute. If<br>
>> you want it to happen automatically at runtime, you would have to<br>
>> insert a jump instruction somewhere. The problem is, that can't<br>
>> usually be done without overwriting a couple of instructions of<br>
>> original code, which means you then have to somehow simulate the<br>
>> effects of the overwritten instructions. And there's always a danger<br>
>> that you will overwrite a jump target and things will blow up when<br>
>> someone tries to jump there. The way this is normally done is that you<br>
>> have the compiler insert hooks into your code during compilation, that<br>
>> you can then intercept if necessary. I am not sure if that would fit<br>
>> your use case.<br>
>><br>
>> pl<br>
>><br>
>><br>
>><br>
>> On 13 February 2017 at 13:13, Roman Popov <<a href="mailto:ripopov@gmail.com" target="_blank">ripopov@gmail.com</a>> wrote:<br>
>> > Thanks Pavel, you are correct. This was the direction I thought to<br>
>> > investigate, but I didnt done my homework yet.<br>
>> ><br>
>> > Yes, dynamic instrumentation is what I want. Looks like both lldb and<br>
>> > gdb do<br>
>> > not allow this directly.<br>
>> ><br>
>> > As GDB doc says "After execution, the compiled code is removed from gdb<br>
>> > and<br>
>> > any new types or variables you have defined will be deleted."<br>
>> ><br>
>> > Do you know why it is the case? Why cannot my generated code persist?<br>
>> ><br>
>> ><br>
>> > Looks like technically it is possible. For example you can allocate<br>
>> > memory<br>
>> > for generated code on heap.<br>
>> ><br>
>> > GDB does not even allow me to define a new function. But for data<br>
>> > dynamic<br>
>> > allocation works perfectly fine:<br>
>> ><br>
>> ><br>
>> > Example:<br>
>> ><br>
>> > #include <stdio.h><br>
>> ><br>
>> > char message[1000] = "test message\n";<br>
>> ><br>
>> > int main() {<br>
>> > char *msg = message;<br>
>> ><br>
>> > for (int i = 0; i < 5; i++)<br>
>> > printf("%s\n", msg);<br>
>> ><br>
>> > return 0;<br>
>> > }<br>
>> ><br>
>> ><br>
>> ><br>
>> > gdb session:<br>
>> ><br>
>> > (gdb) break main.c:8<br>
>> > Breakpoint 1 at 0x400536: file main.c, line 8.<br>
>> > (gdb) run<br>
>> > Starting program: /home/ripopov/work/test_c_inje<wbr>ct/a.out<br>
>> ><br>
>> > Breakpoint 1, main () at main.c:8<br>
>> > 8 for (int i = 0; i < 5; i++)<br>
>> > (gdb) compile code<br>
>> >>char *str;<br>
>> >>str = (char *) malloc(3);<br>
>> >>str[0] = 'T';<br>
>> >>str[1] = '\n';<br>
>> >>str[2] = 0;<br>
>> >>msg = str;<br>
>> >>end<br>
>> > (gdb) c<br>
>> > Continuing.<br>
>> > T<br>
>> ><br>
>> > T<br>
>> ><br>
>> > T<br>
>> ><br>
>> > T<br>
>> ><br>
>> > T<br>
>> ><br>
>> > [Inferior 1 (process 96445) exited normally]<br>
>> > (gdb)<br>
>> ><br>
>> ><br>
>> ><br>
>> ><br>
>> > 2017-02-13 13:56 GMT+03:00 Pavel Labath <<a href="mailto:labath@google.com" target="_blank">labath@google.com</a>>:<br>
>> >><br>
>> >> Every time you use the "expr" command, we compile a tiny c++ code<br>
>> >> snippet inject it into the target process and execute it. If you type<br>
>> >> "log enable lldb expr" you should be able to follow how exactly that<br>
>> >> works. You can use pretty much any c++ construct in the expression<br>
>> >> including declaring variables/types:<br>
>> >> (lldb) expr -- char s[]="qwerty"; for(int i=0; i < sizeof s; ++i)<br>
>> >> printf("%d: %c\n", i, s[i]);<br>
>> >> 0: q<br>
>> >> 1: w<br>
>> >> 2: e<br>
>> >> 3: r<br>
>> >> 4: t<br>
>> >> 5: y<br>
>> >> 6:<br>
>> >><br>
>> >><br>
>> >> So, if your question is "do we support compiling code and running it<br>
>> >> in the debugged process", then the answer is yes. If you want<br>
>> >> something that would automatically intercept some function to execute<br>
>> >> your code while the process is running (some kind of dynamic<br>
>> >> instrumentation), then the answer is no. (But I don't see any mention<br>
>> >> of that on the gdb page you quoted either).<br>
>> >><br>
>> >> cheers,<br>
>> >> pavel<br>
>> >><br>
>> >> On 12 February 2017 at 18:34, Roman Popov via lldb-dev<br>
>> >> <<a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a>> wrote:<br>
>> >> > Hello Benjamin , all<br>
>> >> ><br>
>> >> >>>I recently started using lldb to write a basic instrumentation tool<br>
>> >> >>> for<br>
>> >> >>>tracking the values of variables at various code-points in a<br>
>> >> >>> program.<br>
>> >> ><br>
>> >> > I have the same problem of tracing some variables and debugging<br>
>> >> > application<br>
>> >> > post-mortem. Without knowing about your experience I've started<br>
>> >> > walking<br>
>> >> > same<br>
>> >> > path and encountered same problem. In my case inserting an empty<br>
>> >> > callback<br>
>> >> > slows-down application by 100x. This is not acceptable for me,<br>
>> >> > because<br>
>> >> > instead of minutes I got hours of runtime.<br>
>> >> ><br>
>> >> > Did you found any faster solution?<br>
>> >> ><br>
>> >> > My current plan is to solve it with code injection: I plan to find<br>
>> >> > pointers<br>
>> >> > to interesting values using debugger scripting and then inject code<br>
>> >> > to<br>
>> >> > trace<br>
>> >> > them.<br>
>> >> ><br>
>> >> > Does LLDB supports code injection ? I've found information only about<br>
>> >> > gdb<br>
>> >> ><br>
>> >> ><br>
>> >> > <a href="https://sourceware.org/gdb/onlinedocs/gdb/Compiling-and-Injecting-Code.html" rel="noreferrer" target="_blank">https://sourceware.org/gdb/onl<wbr>inedocs/gdb/Compiling-and-Inje<wbr>cting-Code.html</a><br>
>> >> > but not about lldb<br>
>> >> ><br>
>> >> ><br>
>> >> > -Roman<br>
>> >> ><br>
>> >> ><br>
>> >> > ______________________________<wbr>_________________<br>
>> >> > lldb-dev mailing list<br>
>> >> > <a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a><br>
>> >> > <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/lldb-dev</a><br>
>> >> ><br>
>> ><br>
>> ><br>
><br>
><br>
</div></div></blockquote></div><br></div>
______________________________<wbr>_________________<br>lldb-dev mailing list<br><a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a><br><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/lldb-dev</a><br></div></blockquote></div><br></div></div></div></div></div></blockquote></div><br></div>