inspecting value of formal parameter in gdb for x86

Hi all,

I’m generating code using CLANG + LLVM 2.9 and would like to inspect formal parameter value for x86 32-bit when -O2 -g is used.
It seems that when code is optimized by the compiler DWARF information generated doesn’t allow to inspect value of parameter.
Trying to inspect parameter value in GDB, parameter is marked as optimized by the compiler and thus I can’t track its value.
A simple example to reproduce the problem is compile following code as follows:

clang -m32 -O2 -g -c argpass.c

extern void bar(int ) ;
extern void zzz() ;

void foo(int c)
{
bar(c) ;
if (c == 0)
zzz() ;
}

Looking at LLVM code generated, I’ve got:

; ModuleID = ‘argpass.c’
target datalayout = “e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32”
target triple = “i386-unknown-linux-gnu”

define void @foo(i32 %c) nounwind {
tail call void @llvm.dbg.value(metadata !{i32 %c}, i64 0, metadata !5), !dbg !7
tail call void @bar(i32 %c) nounwind, !dbg !8
%1 = icmp eq i32 %c, 0, !dbg !10
br i1 %1, label %2, label %3, !dbg !10

; :2 ; preds = %0
tail call void (…)* @zzz() nounwind, !dbg !11
br label %3, !dbg !11

; :3 ; preds = %2, %0
ret void, !dbg !12
}

declare void @bar(i32)

declare void @zzz(…)

declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone

!llvm.dbg.sp = !{!0}
!llvm.dbg.lv.foo = !{!5}

!0 = metadata !{i32 589870, i32 0, metadata !1, metadata !“foo”, metadata !“foo”, metadata !"", metadata !1, i32 6, metadata !3, i1 false, i1 true, i32 0, i32 0, i32 0, i32 256, i1 true, void (i32)* @foo} ; [ DW_TAG_subprogram ]
!1 = metadata !{i32 589865, metadata !“argpass.c”, metadata !"/home/deldon/Work/OpenCL/DEBUG", metadata !2} ; [ DW_TAG_file_type ]
!2 = metadata !{i32 589841, i32 0, i32 12, metadata !“argpass.c”, metadata !"/home/deldon/Work/OpenCL/DEBUG", metadata !“clang version 2.9 (tags/RELEASE_29/final)”, i1 true, i1 true, metadata !"", i32 0} ; [ DW_TAG_compile_unit ]
!3 = metadata !{i32 589845, metadata !1, metadata !"", metadata !1, i32 0, i64 0, i64 0, i32 0, i32 0, i32 0, metadata !4, i32 0, i32 0} ; [ DW_TAG_subroutine_type ]
!4 = metadata !{null}
!5 = metadata !{i32 590081, metadata !0, metadata !“c”, metadata !1, i32 16777221, metadata !6, i32 0} ; [ DW_TAG_arg_variable ]
!6 = metadata !{i32 589860, metadata !2, metadata !“int”, null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ]
!7 = metadata !{i32 5, i32 14, metadata !0, null}
!8 = metadata !{i32 7, i32 5, metadata !9, null}
!9 = metadata !{i32 589835, metadata !0, i32 6, i32 1, metadata !1, i32 0} ; [ DW_TAG_lexical_block ]
!10 = metadata !{i32 8, i32 5, metadata !9, null}
!11 = metadata !{i32 9, i32 9, metadata !9, null}
!12 = metadata !{i32 10, i32 1, metadata !9, null}

As we can see ‘c’ parameter has been optimized and llvm.dbg.value is used to track its DWARF location.
Now when I look at DWARF informations for object file using readelf --debug-dump, I’ve got for ‘c’ param:


<2><81>: Abbrev Number: 3 (DW_TAG_formal_parameter)
<82> DW_AT_name : c
<84> DW_AT_decl_file : 1
<85> DW_AT_decl_line : 5
<86> DW_AT_type : <0x8d>
<8a> DW_AT_location : 1 byte block: 54 (DW_OP_reg4)

Looking at assembly code I’ve got:


foo: # @foo
.Lfunc_begin0:
.loc 1 6 0
.Ltmp3:

BB#0:

pushl %ebp
.Ltmp0:
movl %esp, %ebp
.Ltmp1:
pushl %esi
pushl %eax
.Ltmp2:
#DEBUG_VALUE: foo:c ← ESP+4294967295 # argpass.c:5:14
movl 8(%ebp), %esi
.loc 1 7 5
.Ltmp4:
movl %esi, (%esp) # argpass.c:7:5
calll bar # argpass.c:7:5
testl %esi, %esi
je .LBB0_2

BB#1:

.loc 1 10 1
.Ltmp5:
addl $4, %esp # argpass.c:10:1
.Ltmp6:
#DEBUG_VALUE: foo:c ← ESP+4294967295
popl %esi # argpass.c:10:1
popl %ebp # argpass.c:10:1
ret # argpass.c:10:1

‘c’ parameter is indeed stored in location 8(%ebp).
If I use a different compiler (PGI C compiler):
pgcc -tp=k8-32 -O2 -g -c argpass.c

I’ve got following DWARF information for ‘c’ parameter:


<2><68>: Abbrev Number: 3 (DW_TAG_formal_parameter)
<69> DW_AT_name : c
<6b> DW_AT_start_scope : 0x3
<6f> DW_AT_type : <0x77>
<73> DW_AT_location : 2 byte block: 91 8 (DW_OP_fbreg: 8)

and value of ‘c’ can be inspected in GDB. So my questions are:

Is there a way to enforce clang to generate DWARF information similar to pgcc ?

For the x86 target, a C argument is passed by value on the stack.
In the generated code, we can refer to the stack location of the
argument as created the caller. Ideally, for the dwarf DIE of the
argument, we would like see a DWARF location expression for the
argument which represents its location on the (caller’s) stack.

Is there a method in the metadata to effect this type of location expression?
In other words, is there a way in LLVM to write metadata so that DWARF location would be stack related for x86 ?

Thanks for your answer
Best Regards
Seb