[PATCH 2/6] DW attribute macro MACRO_AT_func and MACRO_AT_range
Doug Evans
dje@google.com
Tue Nov 4 22:50:00 GMT 2014
Yao Qi writes:
> This patch addes DW macro attributes MACRO_AT_func and MACRO_AT_range
> in dwarf assembler, which emits "DW_AT_low_pc func_start addr" and
> "DW_AT_high_pc func_end addr". func_start and func_end are computed
> automatically by proc function_range.
>
> These two attributes are pseudo attribute or macro attribute, which
> means they are not standard dwarf attribute in dwarf spec. Then can
> be substituted or expanded to standard attributes or macro attributes.
> See details in the comments to them. Dwarf assembler is extended to
> handle them.
>
> Now the attributes name/low_pc/high_pc can be replaced with
> MACRO_AT_func like this:
>
> subprogram {
> {name main}
> {low_pc main_start addr}
> {high_pc main_end addr}
> }
>
> becomes:
>
> subprogram {
> {MACRO_AT_func { main ${srcdir}/${subdir}/${srcfile} }}
> }
>
> users don't have to worry about the start and end of function main, and
> they only need to add a label main_label in main.
>
> gdb/testsuite:
>
> 2014-10-24 Yao Qi <yao@codesourcery.com>
>
> * lib/dwarf.exp (function_range): New procedure.
> (Dwarf::_handle_macro_attribute): New procedure.
> (Dwarf): Handle MACRO_AT_func and MACRO_AT_range.
> ---
> gdb/testsuite/lib/dwarf.exp | 128 +++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 122 insertions(+), 6 deletions(-)
>
> diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
> index 4986f83..401e791 100644
> --- a/gdb/testsuite/lib/dwarf.exp
> +++ b/gdb/testsuite/lib/dwarf.exp
> @@ -86,6 +86,81 @@ proc build_executable_from_fission_assembler { testname executable sources optio
> return 0
> }
>
> +# Return a list of expressions about function FUNC's address and length.
> +# The first expression is the address of function FUNC, and the second
> +# one is FUNC's length. SRC is the source file having function FUNC.
> +# An internal label ${func}_label must be defined inside FUNC:
> +#
> +# int main (void)
> +# {
> +# asm ("main_label: .globl main_label");
> +# return 0;
> +# }
> +#
> +# This label is needed to compute the start address of function FUNC.
> +# If the compiler is gcc, we can do the following to get function start
> +# and end address too:
> +#
> +# asm ("func_start: .globl func_start");
> +# static void func (void) {}
> +# asm ("func_end: .globl func_end");
> +#
> +# however, this isn't portable, because other compilers, such as clang,
> +# may not guarantee the order of global asms and function. The code
> +# becomes:
> +#
> +# asm ("func_start: .globl func_start");
> +# asm ("func_end: .globl func_end");
> +# static void func (void) {}
> +#
> +
> +proc function_range { func src } {
> + global decimal gdb_prompt
> +
> + set exe [standard_temp_file func_addr[pid].x]
> +
> + gdb_compile $src $exe executable {debug}
> +
> + gdb_exit
> + gdb_start
> + gdb_load "$exe"
> +
> + # Compute the label offset, and we can get the function start address
> + # by "${func}_label - $func_label_offset".
> + set func_label_offset ""
> + set test "p ${func}_label - ${func}"
> + gdb_test_multiple $test $test {
> + -re ".* = ($decimal)\r\n$gdb_prompt $" {
> + set func_label_offset $expect_out(1,string)
> + }
> + }
> +
> + # Compute the function length.
> + global hex
> + set func_length ""
> + set test "disassemble $func"
> + gdb_test_multiple $test $test {
> + -re ".*$hex <\\+($decimal)>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" {
> + set func_length $expect_out(1,string)
> + }
> + }
> +
> + # Compute the size of the last instruction.
> + set test "x/2i $func+$func_length"
> + gdb_test_multiple $test $test {
> + -re ".*($hex) <$func\\+$func_length>:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" {
> + set start $expect_out(1,string)
> + set end $expect_out(2,string)
> +
> + set func_length [expr $func_length + $end - $start]
> + }
> + }
> +
> + file delete $exe
> +
> + return [list "${func}_label - $func_label_offset" $func_length]
> +}
> +
> # A DWARF assembler.
> #
> # All the variables in this namespace are private to the
> @@ -121,6 +196,17 @@ proc build_executable_from_fission_assembler { testname executable sources optio
> # This can either be the full name, like 'DW_AT_name', or a shortened
> # name, like 'name'. These are fully equivalent.
> #
> +# Besides DWARF standard attributes, assembler supports 'macro' attribute
> +# which will be substituted by one or more standard or macro attributes.
> +# supported macro attributes are:
> +#
> +# - MACRO_AT_range { FUNC FILE }
> +# It is substituted by DW_AT_low_pc and DW_AT_high_pc with the start and
> +# end address of function FUNC in file FILE.
> +#
> +# - MACRO_AT_func { FUNC FILE }
> +# It is substituted by DW_AT_name with FUNC and MACRO_AT_range.
> +#
> # If FORM is given, it should name a DW_FORM_ constant.
> # This can either be the short form, like 'DW_FORM_addr', or a
> # shortened version, like 'addr'. If the form is given, VALUE
> @@ -473,6 +559,31 @@ namespace eval Dwarf {
> }
> }
>
> + proc _handle_macro_attribute { attr_name attr_value } {
> + switch -exact -- $attr_name {
> + MACRO_AT_func {
> + _handle_attribute DW_AT_name [lindex $attr_value 0] \
> + DW_FORM_string
> +
> + _handle_macro_attribute MACRO_AT_range $attr_value
> + }
> + MACRO_AT_range {
> + if {[llength $attr_value] != 2} {
> + error "usage: $attr_name { func file }"
> + }
> + set func [lindex $attr_value 0]
> + set src [lindex $attr_value 1]
> +
> + set result [function_range $func $src]
> + _handle_attribute DW_AT_low_pc [lindex $result 0] \
> + DW_FORM_addr
> + _handle_attribute DW_AT_high_pc \
> + "[lindex $result 0] + [lindex $result 1]" DW_FORM_addr
> + }
> + default { error "unknown macro attribute $attr_name" }
> + }
> + }
> +
> proc _handle_DW_TAG {tag_name {attrs {}} {children {}}} {
> variable _abbrev_section
> variable _abbrev_num
> @@ -494,14 +605,19 @@ namespace eval Dwarf {
> foreach attr $attrs {
> set attr_name [_map_name [lindex $attr 0] _AT]
> set attr_value [uplevel 2 [list subst [lindex $attr 1]]]
> - if {[llength $attr] > 2} {
> - set attr_form [lindex $attr 2]
> +
> + if { [string match "MACRO_AT_*" $attr_name] } {
> + _handle_macro_attribute $attr_name $attr_value
> } else {
> - set attr_form [_guess_form $attr_value attr_value]
> - }
> - set attr_form [_map_name $attr_form _FORM]
> + if {[llength $attr] > 2} {
> + set attr_form [lindex $attr 2]
> + } else {
> + set attr_form [_guess_form $attr_value attr_value]
> + }
> + set attr_form [_map_name $attr_form _FORM]
>
> - _handle_attribute $attr_name $attr_value $attr_form
> + _handle_attribute $attr_name $attr_value $attr_form
> + }
> }
>
> _defer_output $_abbrev_section {
Hi.
IWBN if one could add new macros simply by writing a new function.
Can _handle_macro_attribute be rewritten such that
MACRO_AT_{func,range} are themselves functions?
More information about the Gdb-patches
mailing list