On 07/17/2015 08:31 PM, Michael Eager wrote:
On 07/17/2015 03:43 AM, Nikolai Bozhenov wrote:
Consider the following example:
1 extern void bar(int *i1, int *i2, int *i3);
2
3 int __attribute__((noinline)) foo(int i1, int i2) {
4 int a, b, c;
5 a = i1 << i2;
6 b = (i1 + i2) * i1;
7 c = (b + i1);
8 bar(&a, &b, &c);
9 }
10
11 int main() {
12 foo(42, 12);
13 }
Let's compile it:
$ gcc-trunk tst.c -g -fvar-tracking-uninit -O2
After hitting a breakpoint at line 8 (the last line of the function
foo) I have some random (and very confusing) values displayed in gdb
for all three variables a, b and c. This is because GCC allocates
these three variables on the stack (their addresses are taken) and
creates for them DWARF entries like this:
<2><a8>: Abbrev Number: 8 (DW_TAG_variable)
<a9> DW_AT_name : a
<ab> DW_AT_decl_file : 1
<ac> DW_AT_decl_line : 4
<ad> DW_AT_type : <0x64>
<b1> DW_AT_location : 2 byte block: 91 64 (DW_OP_fbreg: -28)
This (incorrectly) says that the variable is at the specified location
for the entire scope of the function. This should be a location list,
which specifies the live range for the variable. At the breakpoint,
this location list would/should have no location for the variable.
A related issue is where the breakpoint is taken. GCC sets breakpoints
at the first instruction generated for a statement, which in this case,
appears to be before any of the arguments to bar are evaluated. A
possibly better location would be after arguments are evaluated, before
the call is executed.
Not sure that this is a GCC issue. I annotated instructions with line
numbers taken from debug info that GCC generated for the function and
these numbers look perfectly correct:
0000000000000000 <foo>:
0: 89 f1 mov %esi,%ecx // 5
2: 01 fe add %edi,%esi // 6
4: 48 83 ec 18 sub $0x18,%rsp // 3
8: 0f af f7 imul %edi,%esi // 6
b: 89 f8 mov %edi,%eax // 5
d: 48 8d 54 24 0c lea 0xc(%rsp),%rdx // 8
12: d3 e0 shl %cl,%eax // 5
14: 89 44 24 04 mov %eax,0x4(%rsp) // 5
18: 89 74 24 08 mov %esi,0x8(%rsp) // 6
1c: 01 fe add %edi,%esi // 7
1e: 48 8d 7c 24 04 lea 0x4(%rsp),%rdi // 8
23: 89 74 24 0c mov %esi,0xc(%rsp) // 7
27: 48 8d 74 24 08 lea 0x8(%rsp),%rsi // 8
2c: e8 00 00 00 00 callq 31 <foo+0x31> // 8
31: 48 83 c4 18 add $0x18,%rsp // 9
35: c3 retq // 9
In this case GDB set the breakpoint at the instruction at 0x0d where
evaluation of the first argument for the call is performed. I'm not
sure that there is a less confusing way to choose an address to set a
breakpoint. For example I don't think it is a good idea to ignore
evaluation of function arguments and set a breakpoint right at the
call instruction. But even if there is a better way, such new feature
is likely to be implemented in GDB rather than in GCC.
Nikolai