[lldb-dev] Setting breakpoint on file and function name doesn't work as expected.

2019-11-04 Thread Konrad Kleine via lldb-dev
Hello,

I noticed this behavior for LLDB under Linux when setting a breakpoint on a
file and a function name:

When doing "breakpoint set --file  --name ", the
 is that of the compile unit (CU) and not necessarily where the
function is defined. This is not what an end-user expects.

Take this simple example program:

$ cat foo.h
int foo(){ return 42; }

$ cat main.c
#include "foo.h"
int main(){return foo();}

$ clang -g main.c

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?

$ lldb -x -b -o "breakpoint set --file foo.h --name foo" ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) breakpoint set --file foo.h --name foo
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.

Apparently, LLDB cannot find the symbol like this. Let's try the only other
file that we have in the project:

$ lldb -x -b -o "breakpoint set --file main.c --name foo" ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) breakpoint set --file main.c --name foo
Breakpoint 1: where = a.out`foo + 4 at foo.h:1:12, address =
0x00401114

Isn't that remarkable? LLDB uses main.c as the file to search in but then
finds it in foo.h.

Let's recall what the parameters --file and --name mean:

   -n  ( --name  )
Set the breakpoint by function name.  Can be repeated multiple
times to make one breakpoint for multiple names

   -f  ( --file  )
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
set breakpoints on .c/.cpp/.m/.mm files that are #included, set
target.inline-breakpoint-strategy to "always".

Let's check if setting the target.inline-breakpoint strategy to "always"
changes something:

$ lldb -x -b  -o "settings set target.inline-breakpoint-strategy always" -o
"breakpoint set --file foo.h --name foo" ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) settings set target.inline-breakpoint-strategy always
(lldb) breakpoint set --file foo.h --name foo
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.

No, it didn't change anything.

The only evidence for my assumption that LLDB uses the CU's name for --file
is the DWARF dump:

$ llvm-dwarfdump a.out
a.out: file format ELF64-x86-64

.debug_info contents:
0x: Compile Unit: length = 0x0060 version = 0x0004 abbr_offset
= 0x addr_size = 0x08 (next unit at 0x0064)

0x000b: DW_TAG_compile_unit
  DW_AT_producer ("clang version 8.0.0 (Fedora 8.0.0-3.fc30)")
  DW_AT_language (DW_LANG_C99)
  DW_AT_name ("main.c")
  DW_AT_stmt_list (0x)
  DW_AT_comp_dir ("/home/kkleine")
  DW_AT_low_pc (0x00401110)
  DW_AT_high_pc (0x0040113a)

0x002a:   DW_TAG_subprogram
DW_AT_low_pc (0x00401110)
DW_AT_high_pc (0x0040111b)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("foo")
DW_AT_decl_file ("/home/kkleine/./foo.h")
DW_AT_decl_line (1)
DW_AT_type (0x005c "int")
DW_AT_external (true)

0x0043:   DW_TAG_subprogram
DW_AT_low_pc (0x00401120)
DW_AT_high_pc (0x0040113a)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("main")
DW_AT_decl_file ("/home/kkleine/main.c")
DW_AT_decl_line (2)
DW_AT_type (0x005c "int")
DW_AT_external (true)

0x005c:   DW_TAG_base_type
DW_AT_name ("int")
DW_AT_encoding (DW_ATE_signed)
DW_AT_byte_size (0x04)

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.

The only reasonable implementation for --file to me seems to be when
combined with the line number:

$ lldb -x -b  -o "breakpoint set --file foo.h --line 1" ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) breakpoint set --file foo.h --line 1
Breakpoint 1: where = a.out`foo + 4 at foo.h:1:12, address =
0x00401114

This works as expected.

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 inform

Re: [lldb-dev] Setting breakpoint on file and function name doesn't work as expected.

2019-11-04 Thread Konrad Kleine via lldb-dev
I read the LLDB troubleshooting page [1] and found interesting quotes:

> When setting breakpoints in implementation source files (.c, cpp, cxx,
.m, .mm, etc), LLDB by
> default will only search for compile units whose filename matches.
> [...]
>   % echo "settings set target.inline-breakpoint-strategy always" >>
~/.lldbinit
> This tells LLDB to always look in all compile units and search for
breakpoint locations
> by file and line even if the implementation file doesn’t match. Setting
breakpoints in header
> files always searches all compile units because inline functions are
commonly defined in
> header files and often cause multiple breakpoints to have source line
information that matches
> many header file paths.

In my email before I did this

$ lldb -x -b -o "breakpoint set --file foo.h --name foo" ./a.out

I now added the breakpoint strategy and ran the above command without the
-x in order to pick up
the LLDB init code. Still no luck.

[1]: https://lldb.llvm.org/use/troubleshooting.html#troubleshooting

Am Mo., 4. Nov. 2019 um 13:56 Uhr schrieb Konrad Kleine :

> Hello,
>
> I noticed this behavior for LLDB under Linux when setting a breakpoint on
> a file and a function name:
>
> When doing "breakpoint set --file  --name ", the
>  is that of the compile unit (CU) and not necessarily where the
> function is defined. This is not what an end-user expects.
>
> Take this simple example program:
>
> $ cat foo.h
> int foo(){ return 42; }
>
> $ cat main.c
> #include "foo.h"
> int main(){return foo();}
>
> $ clang -g main.c
>
> 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?
>
> $ lldb -x -b -o "breakpoint set --file foo.h --name foo" ./a.out
> (lldb) target create "./a.out"
> Current executable set to './a.out' (x86_64).
> (lldb) breakpoint set --file foo.h --name foo
> Breakpoint 1: no locations (pending).
> WARNING:  Unable to resolve breakpoint to any actual locations.
>
> Apparently, LLDB cannot find the symbol like this. Let's try the only
> other file that we have in the project:
>
> $ lldb -x -b -o "breakpoint set --file main.c --name foo" ./a.out
> (lldb) target create "./a.out"
> Current executable set to './a.out' (x86_64).
> (lldb) breakpoint set --file main.c --name foo
> Breakpoint 1: where = a.out`foo + 4 at foo.h:1:12, address =
> 0x00401114
>
> Isn't that remarkable? LLDB uses main.c as the file to search in but then
> finds it in foo.h.
>
> Let's recall what the parameters --file and --name mean:
>
>-n  ( --name  )
> Set the breakpoint by function name.  Can be repeated multiple
> times to make one breakpoint for multiple names
>
>-f  ( --file  )
> 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
> set breakpoints on .c/.cpp/.m/.mm files that are #included,
> set target.inline-breakpoint-strategy to "always".
>
> Let's check if setting the target.inline-breakpoint strategy to "always"
> changes something:
>
> $ lldb -x -b  -o "settings set target.inline-breakpoint-strategy always"
> -o "breakpoint set --file foo.h --name foo" ./a.out
> (lldb) target create "./a.out"
> Current executable set to './a.out' (x86_64).
> (lldb) settings set target.inline-breakpoint-strategy always
> (lldb) breakpoint set --file foo.h --name foo
> Breakpoint 1: no locations (pending).
> WARNING:  Unable to resolve breakpoint to any actual locations.
>
> No, it didn't change anything.
>
> The only evidence for my assumption that LLDB uses the CU's name for
> --file is the DWARF dump:
>
> $ llvm-dwarfdump a.out
> a.out: file format ELF64-x86-64
>
> .debug_info contents:
> 0x: Compile Unit: length = 0x0060 version = 0x0004 abbr_offset
> = 0x addr_size = 0x08 (next unit at 0x0064)
>
> 0x000b: DW_TAG_compile_unit
>   DW_AT_producer ("clang version 8.0.0 (Fedora 8.0.0-3.fc30)")
>   DW_AT_language (DW_LANG_C99)
>   DW_AT_name ("main.c")
>   DW_AT_stmt_list (0x)
>   DW_AT_comp_dir ("/home/kkleine")
>   DW_AT_low_pc (0x00401110)
>   DW_AT_high_pc (0x0040113a)
>
> 0x002a:   DW_TAG_subprogram
> DW_AT_low_pc (0x00401110)
> DW_AT_high_pc (0x0040111b)
> DW_AT_frame_base (DW_OP_reg6 RBP)
> DW_AT_name ("foo")
> DW_AT_decl_file ("/home/kkleine/./foo.h")
> DW_AT_decl_line (1)
> DW_AT_type (0x005c "int")
> DW_AT_external (true)
>
> 0x0043:   DW_TAG_subprogram
> DW_AT_low_pc (0x00401120)
> DW_AT_high_pc (0x0040113a)
> DW_AT_frame_base (DW_OP_reg6 RBP)
> DW_AT_name ("main")
> DW_AT_decl_file ("/home/kkl

Re: [lldb-dev] https://reviews.llvm.org/D69273

2019-11-04 Thread Pavel Labath via lldb-dev

On 31/10/2019 20:51, Jim Ingham via lldb-dev wrote:

It looks like this change is causing problems with swift.  I was talking a 
little bit with Davide about this and it seems like it wasn't obvious how this 
was designed to work.  So here's what this was intended to do (apologies if 
this is at too basic a level and the issue was something deeper I missed, but 
anyway this might get us started...)

The lldb ValueObject system supports two fairly different kinds of values, live 
and frozen.

The classic example of a live ValueObject is ValueObjectVariable.  That ValueObject is backed by an 
entity in the target, and knows when that entity is valid and not.  So it can always try to do 
"UpdateValueIfNeeded" and that will always return good values.  However, there's on 
complication with this, which is that we also want ValueObjectVariable to be able to answer 
"IsChanged".  That's so in a UI you can mark values that change over a step in red, which 
is very helpful for following along in a debugging session.  So you have to copy the values into 
host memory, in order to have something to compare against when you stop again.  That's why there's 
this slightly complex dance between host and target memory for the live ValueObjects.

The example of a frozen object is the ValueObjectConstResult that is returned 
from expression evaluation.  That value is fixed to a StopID, so the backing 
entity is only known to be good at that stop id.  This is implemented by 
copying the value into Host memory and fetching it from there when requested.

The use case for this is for people like me who have a bad memory.  So I can 
stop somewhere and do:

(lldb) expr foo
struct baz $1 = {
   bar = 20
}

Then later on when I forget what foo.bar was at that time, I can do:

(lldb) expr $1.bar
bar = 20

At a first approximation, this leads to the statement that ConstValues should 
fetch what they fetch when made, and then not offer any information that wasn't 
gathered when the variable was fetched, and you certainly don't ever want these 
values to be updated.

A little complication arises because I might do:

(lldb) expr foo_which_has_a_pointer
$1 = ...
(lldb) expr *$1->the_pointer

If the StopID is the same between the first and second evaluation, then you 
should follow the pointer into target memory and fetch the value.  But if the 
StopID has changed, then trying to dereference a pointer should be an error.  
After all, you are now accessing an incoherent object, and if you try to do 
anything fancier with it than just print some memory (like asking the Swift 
Language Runtime what this value happens to be) you are very likely to get into 
trouble.

So it's clear we need two different behaviors w.r.t. how we treat live or 
frozen values.  Pavel's change was addressing a failure in ValueObjectChild, 
and the solution was to move the ValueObjectVariable behavior up to the 
ValueObject level.  But then that means that ValueObjectConstResults are no 
longer obeying the ConstResult rules.

But it seems like the problem really is that we have only one ValueObjectChild 
class, but child value objects can either be live or frozen, depending on the 
nature of their Root ValueObject.  And this is made a little more complicated 
by the fact that frozen values only freeze when the stop ID changes.



Thanks for the writeup Jim. I haven't managed to dive into the source 
code yet, but the thing that's not clear to me from this otherwise 
detailed an understandable explanation is what is the interaction 
between this ConstResult stuff and the above patch.


Superficially, it doesn't sound like that patch should do anything bad 
here. As the ValueObjectConstResult's data is located in host memory, 
the patch will compute that its pointer children will be of "load 
address" type, which sounds like precisely what's needed here.


Of course, under the surface, there are plenty of ways this can go 
wrong, but precisely because of that, it's hard to say what's the right 
thing to do. Is it that ValueObjectConstResult uses the "address type" 
field to implement the "are the children valid at this stop ID" logic, 
and so this patch interferes with that? What's exactly the nature of the 
crash/misbehavior you were witnessing?


pl
___
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] Setting breakpoint on file and function name doesn't work as expected.

2019-11-04 Thread Jan Kratochvil via lldb-dev
On Mon, 04 Nov 2019 16:16:30 +0100, Konrad Kleine via lldb-dev wrote:
> I read the LLDB troubleshooting page [1] and found interesting quotes:
> 
> > When setting breakpoints in implementation source files (.c, cpp, cxx,
> .m, .mm, etc), LLDB by
> > default will only search for compile units whose filename matches.
> > [...]
> >   % echo "settings set target.inline-breakpoint-strategy always" >>
> ~/.lldbinit
...
> I now added the breakpoint strategy and ran the above command without the
> -x in order to pick up
> the LLDB init code. Still no luck.

That doc is obsolete, LLDB has this setting by default:

(lldb) settings show target.inline-breakpoint-strategy
target.inline-breakpoint-strategy (enum) = always

It has been changed:
https://github.com/llvm/llvm-project/commit/ad6eee639952090684aa84c35218ec327a017ca1

This setting does work but only for the --line option:

==> inc.C <==
#include "inc2.C"
int main() {
  func();
}

==> inc2.C <==
static volatile int i;
static void func() {
  i++;
}
$ clang++ -o inc inc.C -Wall -g;lldb ./inc
(lldb) target create "./inc"
Current executable set to './inc' (x86_64).
(lldb) settings set target.inline-breakpoint-strategy headers
(lldb) breakpoint set --file inc2.C --line 3
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) settings set target.inline-breakpoint-strategy always
(lldb) breakpoint set --file inc2.C --line 3
Breakpoint 2: where = inc`func() + 4 at inc2.C:3:4, address = 0x00401124
(lldb) _

To make it working also for the -n option will require some fix, maybe some
code around lldb/source/Commands/CommandObjectBreakpoint.cpp line 500, dunno.


Jan

___
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] https://reviews.llvm.org/D69273

2019-11-04 Thread Jim Ingham via lldb-dev
Sorry, my brain is not working this morning, I answered your question in the 
review comments…

Jim


> On Nov 4, 2019, at 7:28 AM, Pavel Labath  wrote:
> 
> On 31/10/2019 20:51, Jim Ingham via lldb-dev wrote:
>> It looks like this change is causing problems with swift.  I was talking a 
>> little bit with Davide about this and it seems like it wasn't obvious how 
>> this was designed to work.  So here's what this was intended to do 
>> (apologies if this is at too basic a level and the issue was something 
>> deeper I missed, but anyway this might get us started...)
>> The lldb ValueObject system supports two fairly different kinds of values, 
>> live and frozen.
>> The classic example of a live ValueObject is ValueObjectVariable.  That 
>> ValueObject is backed by an entity in the target, and knows when that entity 
>> is valid and not.  So it can always try to do "UpdateValueIfNeeded" and that 
>> will always return good values.  However, there's on complication with this, 
>> which is that we also want ValueObjectVariable to be able to answer 
>> "IsChanged".  That's so in a UI you can mark values that change over a step 
>> in red, which is very helpful for following along in a debugging session.  
>> So you have to copy the values into host memory, in order to have something 
>> to compare against when you stop again.  That's why there's this slightly 
>> complex dance between host and target memory for the live ValueObjects.
>> The example of a frozen object is the ValueObjectConstResult that is 
>> returned from expression evaluation.  That value is fixed to a StopID, so 
>> the backing entity is only known to be good at that stop id.  This is 
>> implemented by copying the value into Host memory and fetching it from there 
>> when requested.
>> The use case for this is for people like me who have a bad memory.  So I can 
>> stop somewhere and do:
>> (lldb) expr foo
>> struct baz $1 = {
>>   bar = 20
>> }
>> Then later on when I forget what foo.bar was at that time, I can do:
>> (lldb) expr $1.bar
>> bar = 20
>> At a first approximation, this leads to the statement that ConstValues 
>> should fetch what they fetch when made, and then not offer any information 
>> that wasn't gathered when the variable was fetched, and you certainly don't 
>> ever want these values to be updated.
>> A little complication arises because I might do:
>> (lldb) expr foo_which_has_a_pointer
>> $1 = ...
>> (lldb) expr *$1->the_pointer
>> If the StopID is the same between the first and second evaluation, then you 
>> should follow the pointer into target memory and fetch the value.  But if 
>> the StopID has changed, then trying to dereference a pointer should be an 
>> error.  After all, you are now accessing an incoherent object, and if you 
>> try to do anything fancier with it than just print some memory (like asking 
>> the Swift Language Runtime what this value happens to be) you are very 
>> likely to get into trouble.
>> So it's clear we need two different behaviors w.r.t. how we treat live or 
>> frozen values.  Pavel's change was addressing a failure in ValueObjectChild, 
>> and the solution was to move the ValueObjectVariable behavior up to the 
>> ValueObject level.  But then that means that ValueObjectConstResults are no 
>> longer obeying the ConstResult rules.
>> But it seems like the problem really is that we have only one 
>> ValueObjectChild class, but child value objects can either be live or 
>> frozen, depending on the nature of their Root ValueObject.  And this is made 
>> a little more complicated by the fact that frozen values only freeze when 
>> the stop ID changes.
> 
> Thanks for the writeup Jim. I haven't managed to dive into the source code 
> yet, but the thing that's not clear to me from this otherwise detailed an 
> understandable explanation is what is the interaction between this 
> ConstResult stuff and the above patch.
> 
> Superficially, it doesn't sound like that patch should do anything bad here. 
> As the ValueObjectConstResult's data is located in host memory, the patch 
> will compute that its pointer children will be of "load address" type, which 
> sounds like precisely what's needed here.
> 
> Of course, under the surface, there are plenty of ways this can go wrong, but 
> precisely because of that, it's hard to say what's the right thing to do. Is 
> it that ValueObjectConstResult uses the "address type" field to implement the 
> "are the children valid at this stop ID" logic, and so this patch interferes 
> with that? What's exactly the nature of the crash/misbehavior you were 
> witnessing?
> 
> pl

___
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev


Re: [lldb-dev] https://reviews.llvm.org/D69273

2019-11-04 Thread Pavel Labath via lldb-dev

On 04/11/2019 18:19, Jim Ingham wrote:

Sorry, my brain is not working this morning, I answered your question in the 
review comments…

Jim



NP, maybe let's continue the discussion there? I find it useful to have 
the actual code change around..

___
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev