From fc6a93854b3c9520259926891c3a5c559d3545d1 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Mon, 22 Nov 2021 09:14:15 +0100 Subject: [PATCH] [gdb/testsuite] Speed up MACRO_AT_* calls Currently, for each MACRO_AT_range or MACRO_AT_func in dwarf assembly the following is done: - $srcdir/$subdir/$srcfile is compiled to an executable using flags "debug" - a new gdb instance is started - the new executable is loaded. This is inefficient, because the executable is identical within the same Dwarf::assemble call. Share the gdb instance in the same Dwarf::assemble invocation, which speeds up a make check with RUNTESTFLAGS like this to catch all dwarf assembly test-cases: ... rtf=$(echo $(cd src/gdb/testsuite; find gdb.* -type f -name "*.exp" \ | xargs grep -l Dwarf::assemble)) ... from: ... real 1m39.916s user 1m25.668s sys 0m21.377s ... to: ... real 1m29.512s user 1m17.316s sys 0m19.100s ... Tested on x86_64-linux. --- gdb/testsuite/lib/dwarf.exp | 160 +++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 12 deletions(-) diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 7dd82b8a381..22124f6a080 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -196,6 +196,145 @@ proc build_executable_and_dwo_files { testname executable options args } { return 0 } +# Utility function for procs shared_gdb_*. + +proc init_shared_gdb {} { + global shared_gdb_enabled + global shared_gdb_started + + if { ! [info exists shared_gdb_enabled] } { + set shared_gdb_enabled 0 + set shared_gdb_started 0 + } +} + +# Cluster of four procs: +# - shared_gdb_enable +# - shared_gdb_disable +# - shared_gdb_start_use SRC OPTIONS +# - shared_gdb_end_use +# +# Can be used like so: +# +# { +# if { $share } shared_gdb_enable +# ... +# shared_gdb_start_use $src $options +# ... +# shared_gdb_end_use +# ... +# shared_gdb_start_use $src $options +# ... +# shared_gdb_end_use +# ... +# if { $share } shared_gdb_disable +# } +# +# to write functionalty that could share ($share == 1) or could not +# share ($share == 0) a gdb session between two uses. + +proc shared_gdb_enable {} { + set me shared_gdb_enable + + init_shared_gdb + global shared_gdb_enabled + global shared_gdb_started + + if { $shared_gdb_enabled } { + error "$me: gdb sharing already enabled" + } + set shared_gdb_enabled 1 + + if { $shared_gdb_started } { + error "$me: gdb sharing not stopped" + } +} + +# See above. + +proc shared_gdb_disable {} { + init_shared_gdb + global shared_gdb_enabled + global shared_gdb_started + + if { ! $shared_gdb_enabled } { + error "$me: gdb sharing not enabled" + } + set shared_gdb_enabled 0 + + if { $shared_gdb_started } { + gdb_exit + set shared_gdb_started 0 + } +} + +# See above. + +proc shared_gdb_start_use { src options } { + set me shared_gdb_start_use + + init_shared_gdb + global shared_gdb_enabled + global shared_gdb_started + global shared_gdb_src + global shared_gdb_options + + set do_start 1 + if { $shared_gdb_enabled && $shared_gdb_started } { + if { $shared_gdb_src != $src + || $shared_gdb_options != $options } { + error "$me: gdb sharing inconsistent" + } + + set do_start 0 + } + + if { $do_start } { + set exe [standard_temp_file func_addr[pid].x] + + gdb_compile $src $exe executable $options + + gdb_exit + gdb_start + gdb_load "$exe" + + if { $shared_gdb_enabled } { + set shared_gdb_started 1 + set shared_gdb_src $src + set shared_gdb_options $options + } + } +} + +# See above. + +proc shared_gdb_end_use {} { + init_shared_gdb + global shared_gdb_enabled + + if { ! $shared_gdb_enabled } { + gdb_exit + } +} + +# Enable gdb session sharing within BODY. + +proc with_shared_gdb { body } { + shared_gdb_enable + set code [catch { uplevel 1 $body } result] + shared_gdb_disable + + # Return as appropriate. + if { $code == 1 } { + global errorInfo errorCode + return -code error -errorinfo $errorInfo -errorcode $errorCode $result + } elseif { $code > 1 } { + return -code $code $result + } + + return $result +} + # 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. @@ -227,13 +366,7 @@ proc build_executable_and_dwo_files { testname executable options args } { proc function_range { func src {options {debug}} } { global decimal gdb_prompt - set exe [standard_temp_file func_addr[pid].x] - - gdb_compile $src $exe executable $options - - gdb_exit - gdb_start - gdb_load "$exe" + shared_gdb_start_use $src $options # Compute the label offset, and we can get the function start address # by "${func}_label - $func_label_offset". @@ -271,7 +404,8 @@ proc function_range { func src {options {debug}} } { } } - gdb_exit + shared_gdb_end_use + return [list "${func}_label - $func_label_offset" $func_length] } @@ -2624,10 +2758,12 @@ namespace eval Dwarf { # the first in .debug_info. dummy_cu - # Not "uplevel" here, because we want to evaluate in this - # namespace. This is somewhat bad because it means we can't - # readily refer to outer variables. - eval $body + with_shared_gdb { + # Not "uplevel" here, because we want to evaluate in this + # namespace. This is somewhat bad because it means we can't + # readily refer to outer variables. + eval $body + } # Dummy CU at the end to ensure that the last CU in $body is not # the last in .debug_info. -- 2.30.2