<div dir="ltr"><div>I read the LLDB troubleshooting page [1] and found interesting quotes:</div><div><br></div><div>> When setting breakpoints in implementation source files (.c, cpp, cxx, .m, .mm,
etc), LLDB by</div><div>> default will only search for compile units whose filename
matches. <br></div><div>> [...]</div><div>> % echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit<br>> This tells LLDB to always look in all compile units and search for breakpoint locations</div><div>> by file and line even if the implementation file doesn’t match. Setting breakpoints in header</div><div>> files always searches all compile units because
inline functions are commonly defined in</div><div>> header files and often cause multiple
breakpoints to have source line information that matches</div><div>> many header file
paths.</div><div><br></div><div>In my email before I did this</div><div><br></div><div>$ lldb -x -b -o "breakpoint set --file foo.h --name foo" ./a.out</div><div><br></div><div>I now added the breakpoint strategy and ran the above command without the -x in order to pick up</div><div>the LLDB init code. Still no luck.</div><div><br></div><div>[1]: <a href="https://lldb.llvm.org/use/troubleshooting.html#troubleshooting">https://lldb.llvm.org/use/troubleshooting.html#troubleshooting</a></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am Mo., 4. Nov. 2019 um 13:56 Uhr schrieb Konrad Kleine <<a href="mailto:kkleine@redhat.com">kkleine@redhat.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hello,</div><div><br></div><div>I noticed this behavior for LLDB under Linux when setting a breakpoint on a file and a function name:</div><div><br></div><div>When doing "breakpoint set --file <filename> --name <function-name>", the <filename> is that of the compile unit (CU) and not necessarily where the function is defined. This is not what an end-user expects.<br></div><div><br></div><div>Take this simple example program:<br></div><div><br></div><div style="margin-left:40px">$ cat foo.h <br>int foo(){ return 42; }</div><div style="margin-left:40px"><br></div><div style="margin-left:40px">$ cat main.c<br>#include "foo.h"<br>int main(){return foo();}</div><div style="margin-left:40px"><br></div><div style="margin-left:40px">$ clang -g main.c</div><div style="margin-left:40px"><br></div>As you can see, the function foo is defined in foo.h so it seems natural to set a breakpoint on foo.h, doesn't it?<br><div><div><div><div style="margin-left:40px"><br></div><div style="margin-left:40px">$ lldb -x -b -o "breakpoint set --file foo.h --name foo" ./a.out <br></div><div style="margin-left:40px">(lldb) target create "./a.out"<br>Current executable set to './a.out' (x86_64).<br>(lldb) breakpoint set --file foo.h --name foo<br>Breakpoint 1: no locations (pending).<br>WARNING: Unable to resolve breakpoint to any actual locations.</div><div><br></div><div>Apparently, LLDB cannot find the symbol like this. Let's try the only other file that we have in the project:</div><div><br></div><div style="margin-left:40px">$ lldb -x -b -o "breakpoint set --file main.c --name foo" ./a.out<br>(lldb) target create "./a.out"<br>Current executable set to './a.out' (x86_64).<br>(lldb) breakpoint set --file main.c --name foo<br>Breakpoint 1: where = a.out`foo + 4 at foo.h:1:12, address = 0x0000000000401114</div><div><br></div><div>Isn't that remarkable? LLDB uses main.c as the file to search in but then finds it in foo.h.</div><div><div><br></div><div>Let's recall what the parameters --file and --name mean:</div><div><br></div><div style="margin-left:40px"> -n <function-name> ( --name <function-name> )<br> Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names</div><div style="margin-left:40px"><br></div><div style="margin-left:40px"> -f <filename> ( --file <filename> )<br> Specifies the source file in which to set this breakpoint. Note, by default lldb only looks for files that are #included if they use the standard include file extensions. To<br> set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy to "always".</div></div><div><br></div><div>Let's check if setting the target.inline-breakpoint strategy to "always" changes something:</div><div><br></div><div style="margin-left:40px">$ lldb -x -b -o "settings set target.inline-breakpoint-strategy always" -o "breakpoint set --file foo.h --name foo" ./a.out<br>(lldb) target create "./a.out"<br>Current executable set to './a.out' (x86_64).<br>(lldb) settings set target.inline-breakpoint-strategy always<br>(lldb) breakpoint set --file foo.h --name foo<br>Breakpoint 1: no locations (pending).<br>WARNING: Unable to resolve breakpoint to any actual locations.</div><div style="margin-left:40px"><br></div>No, it didn't change anything.<br></div><div><div><br></div><div>The only evidence for my assumption that LLDB uses the CU's name for --file is the DWARF dump:<br></div><div><br></div><div style="margin-left:40px">$ llvm-dwarfdump a.out <br>a.out: file format ELF64-x86-64<br><br>.debug_info contents:<br>0x00000000: Compile Unit: length = 0x00000060 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000064)<br><br>0x0000000b: DW_TAG_compile_unit<br> DW_AT_producer ("clang version 8.0.0 (Fedora 8.0.0-3.fc30)")<br> DW_AT_language (DW_LANG_C99)<br> DW_AT_name ("main.c")<br> DW_AT_stmt_list (0x00000000)<br> DW_AT_comp_dir ("/home/kkleine")<br> DW_AT_low_pc (0x0000000000401110)<br> DW_AT_high_pc (0x000000000040113a)<br><br>0x0000002a: DW_TAG_subprogram<br> DW_AT_low_pc (0x0000000000401110)<br> DW_AT_high_pc (0x000000000040111b)<br> DW_AT_frame_base (DW_OP_reg6 RBP)<br> DW_AT_name ("foo")<br> DW_AT_decl_file ("/home/kkleine/./foo.h")<br> DW_AT_decl_line (1)<br> DW_AT_type (0x0000005c "int")<br> DW_AT_external (true)<br><br>0x00000043: DW_TAG_subprogram<br> DW_AT_low_pc (0x0000000000401120)<br> DW_AT_high_pc (0x000000000040113a)<br> DW_AT_frame_base (DW_OP_reg6 RBP)<br> DW_AT_name ("main")<br> DW_AT_decl_file ("/home/kkleine/main.c")<br> DW_AT_decl_line (2)<br> DW_AT_type (0x0000005c "int")<br> DW_AT_external (true)<br><br>0x0000005c: DW_TAG_base_type<br> DW_AT_name ("int")<br> DW_AT_encoding (DW_ATE_signed)<br> DW_AT_byte_size (0x04)</div><div style="margin-left:40px"><br></div>As you can see, the DWARF is very small and simply. The function foo has a DW_AT_decl_file which is probably used to report the breakpoint location but for the actual filtering, it seems as if the CU is crucial for the --file argument.</div><div><br></div><div>The only reasonable implementation for --file to me seems to be when combined with the line number:</div><div style="margin-left:40px"><br></div><div style="margin-left:40px">$ lldb -x -b -o "breakpoint set --file foo.h --line 1" ./a.out<br>(lldb) target create "./a.out"<br>Current executable set to './a.out' (x86_64).<br>(lldb) breakpoint set --file foo.h --line 1<br>Breakpoint 1: where = a.out`foo + 4 at foo.h:1:12, address = 0x0000000000401114</div><div style="margin-left:40px"><br></div>This works as expected.</div><div><br></div><div>For myself I think that the --file --name combination works not like an end-user expects because in bigger projects you typically look at the definition of foo and want to pause, when execution reaches this. You don't care if a function is inlined or in which CU the function is located. Moreover I think the DWARF actually supports more than enough information with the DW_TAG_subprogram DIE's attributes for the file and line number. Enough to filter by file and line number.<br></div><div><br></div><div>IMHO we should come up with a very strong argument to justify that --file limits by a CU's DW_AT_name. To me the only reasonable argument is speed. But speed doesn't justify such a drastic limitation. Shouldn't we rather change what --file currently does and keep the old behavior when using --cu instead of --file?<br></div><div><br></div><div>- Konrad<br></div><div> <br></div><div><div><br></div><div><div><br></div></div></div></div></div>
</blockquote></div>