From: Caroline Tice <cmtice@google.com>
To: Andrew Burgess <andrew.burgess@embecosm.com>
Cc: Caroline Tice via Gdb-patches <gdb-patches@sourceware.org>
Subject: Re: [PATCH, v2] Add directory containing executable to relative search paths for .dwo files.
Date: Thu, 25 Mar 2021 08:09:21 -0700 [thread overview]
Message-ID: <CABtf2+RnNHkZ9NYcx1mYbUYHcViHnnY6P2syUKcqGZrtkkyc_w@mail.gmail.com> (raw)
In-Reply-To: <20210318002602.GB5520@embecosm.com>
Hi Andrew,
As I said previously, your suggested patch works well and fixes the
problem. I thought you were going to submit it, but I have not seen it go
out for review or be committed. Is there something else you need me to
do? I would be happy to send your version for review if you would like?
-- Caroline
cmtice@google.com
On Wed, Mar 17, 2021 at 5:26 PM Andrew Burgess <andrew.burgess@embecosm.com>
wrote:
> * Caroline Tice <cmtice@google.com> [2021-03-04 07:48:37 -0800]:
>
> > Hi Andrew,
> >
> > I updated my change to gdb/dwarf2/read.c as you suggested (spaces
> > before '(' and use nullptr).
> >
> > I spent a long time looking into using Dwarf::assemble in my testcase,
> > to make it hardware agnostic (although I'd like to point out
> > that most of the rest of the fission tests specifically only work for
> > x86_64),
>
> Most of these were written before the Dwarf assembler was available.
> If they were being written today then we'd be using the Dwarf
> assembler.
>
> > but in the end found that it would not work for me. The
> > problems that I was unable to make this work for was that I needed to
> > generate not only the binary but the .dwo file; I needed reasonably
> > valid DWARF in both of them; and the path name for the .dwo file had
> > to be relative not absolute -- the way gdb compiles the test suites it
> > always uses complete absolute paths for all of its files.
>
> I don't understand what problem you ran into here. The path to the
> DWO file is encoded into the DWARF of the executable in a
> DW_AT_GNU_dwo_name attribute, which would be entirely generated within
> the .exp file, and so could contain whatever you like. Likewise for
> the DW_AT_comp_dir.
>
> I made an attempt at writing a test using the dwarf assembler. You
> will need to start by applying this patch to a clean GDB tree:
>
> https://sourceware.org/pipermail/gdb-patches/2021-March/177049.html
>
> Then grab the patch below and give it a try. It includes your fix,
> and a brand new test case. Let me know if you don't think this is
> covering your change correctly, I'm sure we can get it working as
> needed.
>
> Thanks,
> Andrew
>
> ---
>
> commit 47bf19a7ed4c96a86d67329efb7e5ce983debddd
> Author: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Wed Mar 17 22:54:22 2021 +0000
>
> gdb: handle relative paths to DWO files
>
> **** NOTE ****
>
> The fix in dwarf2/read.c includes a hack to allow the fix to be
> toggled on/off using environment variable GDB_NO_FIX. This must be
> removed before pushing upstream.
>
> **** END NOTE ****
>
> DWARF allows .dwo file paths to be relative rather than absolute.
>
> When they are relative, DWARF uses DW_AT_comp_dir to find the .dwo
> file. DW_AT_comp_dir can also be relative, making the entire search
> patch for the .dwo file relative.
>
> In this case, GDB currently searches relative to its current working
> directory, i.e. the directory from which the debugger was launched,
> but not relative to the directory containing the built binary. This
> cannot be right, as the compiler, when generating the relative paths,
> knows where it's building the binary but can have no idea where the
> debugger will be launched.
>
> The correct thing is to add the directory containing the binary to the
> search paths used for resolving relative locations of dwo files. That
> is what this patch does.
>
> gdb/ChangeLog:
>
> * dwarf2/read.c (try_open_dwop_file): Add path for the binary
> to
> the search paths used resolve relative location of .dwo file.
>
> gdb/testsuite/ChangeLog:
>
> * gdb.dwarf2/fission-relative-dwo.c: New file.
> * gdb.dwarf2/fission-relative-dwo.exp: New file.
> * lib/dwarf.exp (extract_dwo_information): New proc.
> (strip_dwo_information): New proc.
> (build_executable_from_fission_assembler): Use
> extract_dwo_information and strip_dwo_information.
> (Dwarf::_debug_addr_index): New variable.
> (Dwarf::_cu_is_fission): New variable.
> (Dwarf::_handle_DW_FORM): Handle DW_OP_GNU_addr_index.
> (Dwarf::_default_form): Supply a default for
> DW_AT_GNU_addr_base.
> (Dwarf::_handle_macro_at_range): Use form
> DW_FORM_GNU_addr_index
> if this is a fission CU.
> (Dwarf::_location): Handle DW_OP_GNU_addr_index.
> (Dwarf::debug_addr_index): New proc.
> (Dwarf::cu): Initialise _cu_is_fission.
> (Dwarf::tu): Likewise.
> (Dwarf::assemble): Initialise _debug_addr_index.
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index d6881300fa6..522ccc2506e 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -12581,6 +12581,15 @@ try_open_dwop_file (dwarf2_per_objfile
> *per_objfile,
> else
> search_path = debug_file_directory;
>
> + if (getenv ("GDB_NO_FIX") == nullptr)
> + {
> + /* Add the path for the executable binary to the list of search
> paths. */
> + search_path_holder.reset
> + (concat (ldirname (per_objfile->objfile->original_name).c_str (),
> + dirname_separator_string, search_path, nullptr));
> + search_path = search_path_holder.get ();
> + }
> +
> openp_flags flags = OPF_RETURN_REALPATH;
> if (is_dwp)
> flags |= OPF_SEARCH_IN_PATH;
> diff --git a/gdb/testsuite/gdb.dwarf2/fission-relative-dwo.c
> b/gdb/testsuite/gdb.dwarf2/fission-relative-dwo.c
> new file mode 100644
> index 00000000000..27f7f0dfb4b
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/fission-relative-dwo.c
> @@ -0,0 +1,28 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright 2021 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see
> + <http://www.gnu.org/licenses/>. */
> +
> +/* Our fake object. */
> +int global_var[100];
> +
> +int
> +main (int argc, char **argv)
> +{
> + asm ("main_label: .globl main_label");
> +
> + return 0;
> +}
> diff --git a/gdb/testsuite/gdb.dwarf2/fission-relative-dwo.exp
> b/gdb/testsuite/gdb.dwarf2/fission-relative-dwo.exp
> new file mode 100644
> index 00000000000..f9ab3b8c6a4
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/fission-relative-dwo.exp
> @@ -0,0 +1,145 @@
> +# Copyright 2021 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +load_lib dwarf.exp
> +
> +# This test can only be run on targets which support DWARF-2 and use gas.
> +if {![dwarf2_support]} {
> + return 0
> +}
> +
> +standard_testfile .c -dw.S
> +
> +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
> + return -1
> +}
> +
> +set asm_file [standard_output_file $srcfile2]
> +Dwarf::assemble $asm_file {
> + global srcfile gdb_test_file_name
> +
> + set debug_addr_base -1
> +
> + # The information that will be split out into the .dwo file.
> + cu {fission 1} {
> +
> + # Capture the current index into .debug_addr so we can fill in
> + # DW_AT_GNU_addr_base later.
> + set debug_addr_base [debug_addr_index]
> +
> + compile_unit {
> + {language @DW_LANG_C}
> + {name ${srcfile}}
> + {DW_AT_comp_dir .}
> + {DW_AT_GNU_dwo_id 0x1234 DW_FORM_data8}
> + } {
> + declare_labels int4_type struct_type
> +
> + int4_type: DW_TAG_base_type {
> + {DW_AT_byte_size 4 DW_FORM_sdata}
> + {DW_AT_encoding @DW_ATE_signed}
> + {DW_AT_name integer}
> + }
> +
> + struct_type: DW_TAG_structure_type {
> + {DW_AT_name "foo_t"}
> + {DW_AT_byte_size 12 DW_FORM_sdata}
> + } {
> + member {
> + {name "aa"}
> + {type :$int4_type}
> + {data_member_location 0 data1}
> + }
> + member {
> + {name "bb"}
> + {type :$int4_type}
> + {data_member_location 4 data1}
> + }
> + member {
> + {name "cc"}
> + {type :$int4_type}
> + {data_member_location 8 data1}
> + }
> + }
> +
> + DW_TAG_variable {
> + {DW_AT_name global_var}
> + {DW_AT_type :$struct_type}
> + {DW_AT_location {
> + DW_OP_GNU_addr_index [gdb_target_symbol global_var]
> + } SPECIAL_expr}
> + {external 1 flag}
> + }
> +
> + subprogram {
> + {external 1 flag}
> + {DW_AT_name main DW_FORM_string}
> + {MACRO_AT_func {main}}
> + }
> + }
> + }
> +
> + # The information that will remain in the .o file.
> + cu {} {
> + compile_unit {
> + {DW_AT_GNU_dwo_name ${gdb_test_file_name}.dwo DW_FORM_strp}
> + {DW_AT_comp_dir .}
> + {DW_AT_GNU_dwo_id 0x1234 DW_FORM_data8}
> + {DW_AT_GNU_addr_base $debug_addr_base}
> + } {
> + # Nothing.
> + }
> + }
> +}
> +
> +# Assemble the file containing the .dwo information, we can then split
> +# this out into a separate .dwo file. Once we've extracted the DWO
> +# information from this object file we're done with it, we recompile
> +# this again in the BUILD_EXECUTABLE call below.
> +set object_file [standard_output_file ${binfile}-dwo.o]
> +if { [gdb_compile $asm_file $object_file object {nodebug}] != "" } {
> + return -1
> +}
> +
> +# Split out the dwo sections into a dwo file.
> +if { [extract_dwo_information $object_file ${binfile}.dwo] == -1 } {
> + perror "failed to extract dwo information"
> + return -1
> +}
> +
> +# Build the executable, but don't use prepare_for_testing as we don't
> +# want to start GDB just yet.
> +if { [build_executable "failed to prepare" "${testfile}" \
> + [list $srcfile $asm_file] {nodebug}] } {
> + return -1
> +}
> +
> +# Just so we can't be found cheating, strip all the dwo information
> +# from the executable.
> +if { [strip_dwo_information ${binfile}] == -1 } {
> + perror "failed to strip dwo information"
> + return -1
> +}
> +
> +# Now we can start GDB.
> +clean_restart ${testfile}
> +
> +if ![runto_main] {
> + return -1
> +}
> +
> +# Print the type of global_var. This type information is entirely
> +# fictional, it only exists in the DWARF. If we don't have the DWARF
> +# information then there's no way we can print this.
> +gdb_test "p global_var" " = \\{aa = 0, bb = 0, cc = 0\\}"
> diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
> index 4cd5e16c604..a41366f1747 100644
> --- a/gdb/testsuite/lib/dwarf.exp
> +++ b/gdb/testsuite/lib/dwarf.exp
> @@ -28,6 +28,38 @@ proc dwarf2_support {} {
> return 0
> }
>
> +# Use 'objcopy --extract-dwo to extract DWO information from
> +# OBJECT_FILE and place it into DWO_FILE.
> +#
> +# Return 0 on success, otherwise, return -1.
> +proc extract_dwo_information { object_file dwo_file } {
> + set objcopy [gdb_find_objcopy]
> + set command "$objcopy --extract-dwo $object_file $dwo_file"
> + verbose -log "Executing $command"
> + set result [catch "exec $command" output]
> + verbose -log "objcopy --extract-dwo output: $output"
> + if { $result == 1 } {
> + return -1
> + }
> + return 0
> +}
> +
> +# Use 'objcopy --strip-dwo to remove DWO information from
> +# FILENAME.
> +#
> +# Return 0 on success, otherwise, return -1.
> +proc strip_dwo_information { filename } {
> + set objcopy [gdb_find_objcopy]
> + set command "$objcopy --strip-dwo $filename"
> + verbose -log "Executing $command"
> + set result [catch "exec $command" output]
> + verbose -log "objcopy --strip-dwo output: $output"
> + if { $result == 1 } {
> + return -1
> + }
> + return 0
> +}
> +
> # Build an executable from a fission-based .S file.
> # This handles the extra work of splitting the .o into non-dwo and dwo
> # pieces, making sure the .dwo is available if we're using
> cc-with-tweaks.sh
> @@ -54,26 +86,17 @@ proc build_executable_from_fission_assembler {
> testname executable sources optio
> set object_file ${output_base}.o
> set dwo_file ${output_base}.dwo
> set object_options "object $options"
> - set objcopy [gdb_find_objcopy]
>
> set result [gdb_compile $source_file $object_file object $options]
> if { "$result" != "" } {
> return -1
> }
>
> - set command "$objcopy --extract-dwo $object_file $dwo_file"
> - verbose -log "Executing $command"
> - set result [catch "exec $command" output]
> - verbose -log "objcopy --extract-dwo output: $output"
> - if { $result == 1 } {
> + if { [extract_dwo_information $object_file $dwo_file] == -1 } {
> return -1
> }
>
> - set command "$objcopy --strip-dwo $object_file"
> - verbose -log "Executing $command"
> - set result [catch "exec $command" output]
> - verbose -log "objcopy --strip-dwo output: $output"
> - if { $result == 1 } {
> + if { [strip_dwo_information $object_file] == -1 } {
> return -1
> }
>
> @@ -329,6 +352,14 @@ namespace eval Dwarf {
> # The address size for debug ranges section.
> variable _debug_ranges_64_bit
>
> + # The index into the .debug_addr section (used for fission
> + # generation).
> + variable _debug_addr_index
> +
> + # Flag, true if the current CU is contains fission information,
> + # otherwise false.
> + variable _cu_is_fission
> +
> proc _process_one_constant {name value} {
> variable _constants
> variable _AT
> @@ -486,6 +517,18 @@ namespace eval Dwarf {
> _op .${_cu_addr_size}byte $value
> }
>
> + DW_FORM_GNU_addr_index {
> + variable _debug_addr_index
> + variable _cu_addr_size
> +
> + _op .uleb128 ${_debug_addr_index}
> + incr _debug_addr_index
> +
> + _defer_output .debug_addr {
> + _op .${_cu_addr_size}byte $value
> + }
> + }
> +
> DW_FORM_data2 -
> DW_FORM_ref2 {
> _op .2byte $value
> @@ -553,7 +596,6 @@ namespace eval Dwarf {
> DW_FORM_strx3 -
> DW_FORM_strx4 -
>
> - DW_FORM_GNU_addr_index -
> DW_FORM_GNU_str_index -
>
> default {
> @@ -609,6 +651,9 @@ namespace eval Dwarf {
> DW_AT_name {
> return DW_FORM_string
> }
> + DW_AT_GNU_addr_base {
> + return DW_FORM_sec_offset
> + }
> }
> return ""
> }
> @@ -649,6 +694,8 @@ namespace eval Dwarf {
> # Handle macro attribute MACRO_AT_range.
>
> proc _handle_macro_at_range { attr_value } {
> + variable _cu_is_fission
> +
> if {[llength $attr_value] != 1} {
> error "usage: MACRO_AT_range { func }"
> }
> @@ -658,10 +705,14 @@ namespace eval Dwarf {
> set src ${srcdir}/${subdir}/${srcfile}
> set result [function_range $func $src]
>
> - _handle_attribute DW_AT_low_pc [lindex $result 0] \
> - DW_FORM_addr
> + set form DW_FORM_addr
> + if { $_cu_is_fission } {
> + set form DW_FORM_GNU_addr_index
> + }
> +
> + _handle_attribute DW_AT_low_pc [lindex $result 0] $form
> _handle_attribute DW_AT_high_pc \
> - "[lindex $result 0] + [lindex $result 1]" DW_FORM_addr
> + "[lindex $result 0] + [lindex $result 1]" $form
> }
>
> # Handle macro attribute MACRO_AT_func.
> @@ -929,6 +980,18 @@ namespace eval Dwarf {
> _op .${addr_size}byte [lindex $line 1]
> }
>
> + DW_OP_GNU_addr_index {
> + variable _debug_addr_index
> + variable _cu_addr_size
> +
> + _op .uleb128 ${_debug_addr_index}
> + incr _debug_addr_index
> +
> + _defer_output .debug_addr {
> + _op .${_cu_addr_size}byte [lindex $line 1]
> + }
> + }
> +
> DW_OP_regx {
> _op .uleb128 [lindex $line 1]
> }
> @@ -1050,6 +1113,14 @@ namespace eval Dwarf {
> }
> }
>
> + # Return the current value of _DEBUG_ADDR_INDEX. The return value
> + # of this function can be used for the value of
> + # DW_AT_GNU_addr_base.
> + proc debug_addr_index {} {
> + variable _debug_addr_index
> + return ${_debug_addr_index}
> + }
> +
> # Emit a DWARF CU.
> # OPTIONS is a list with an even number of elements containing
> # option-name and option-value pairs.
> @@ -1073,12 +1144,13 @@ namespace eval Dwarf {
> variable _cu_version
> variable _cu_addr_size
> variable _cu_offset_size
> + variable _cu_is_fission
>
> # Establish the defaults.
> set is_64 0
> set _cu_version 4
> set _cu_addr_size default
> - set fission 0
> + set _cu_is_fission 0
> set section ".debug_info"
> set _abbrev_section ".debug_abbrev"
>
> @@ -1088,7 +1160,7 @@ namespace eval Dwarf {
> is_64 { set is_64 $value }
> version { set _cu_version $value }
> addr_size { set _cu_addr_size $value }
> - fission { set fission $value }
> + fission { set _cu_is_fission $value }
> default { error "unknown option $name" }
> }
> }
> @@ -1100,7 +1172,7 @@ namespace eval Dwarf {
> }
> }
> set _cu_offset_size [expr { $is_64 ? 8 : 4 }]
> - if { $fission } {
> + if { $_cu_is_fission } {
> set section ".debug_info.dwo"
> set _abbrev_section ".debug_abbrev.dwo"
> }
> @@ -1180,12 +1252,13 @@ namespace eval Dwarf {
> variable _cu_version
> variable _cu_addr_size
> variable _cu_offset_size
> + variable _cu_is_fission
>
> # Establish the defaults.
> set is_64 0
> set _cu_version 4
> set _cu_addr_size default
> - set fission 0
> + set _cu_is_fission 0
> set section ".debug_types"
> set _abbrev_section ".debug_abbrev"
>
> @@ -1194,7 +1267,7 @@ namespace eval Dwarf {
> is_64 { set is_64 $value }
> version { set _cu_version $value }
> addr_size { set _cu_addr_size $value }
> - fission { set fission $value }
> + fission { set _cu_is_fission $value }
> default { error "unknown option $name" }
> }
> }
> @@ -1206,7 +1279,7 @@ namespace eval Dwarf {
> }
> }
> set _cu_offset_size [expr { $is_64 ? 8 : 4 }]
> - if { $fission } {
> + if { $_cu_is_fission } {
> set section ".debug_types.dwo"
> set _abbrev_section ".debug_abbrev.dwo"
> }
> @@ -2056,6 +2129,7 @@ namespace eval Dwarf {
> variable _line_saw_program
> variable _line_header_end_label
> variable _debug_ranges_64_bit
> + variable _debug_addr_index
>
> if {!$_initialized} {
> _read_constants
> @@ -2074,6 +2148,8 @@ namespace eval Dwarf {
> set _line_saw_program 0
> set _debug_ranges_64_bit [is_64_target]
>
> + set _debug_addr_index 0
> +
> # 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.
>
next prev parent reply other threads:[~2021-03-25 15:09 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-03 0:42 [PATCH] " Caroline Tice
2021-03-03 9:53 ` Andrew Burgess
2021-03-04 15:48 ` [PATCH, v2] " Caroline Tice
2021-03-11 15:33 ` Caroline Tice
2021-03-18 0:26 ` Andrew Burgess
[not found] ` <CABtf2+RmUPwpmsx+1i+a-QynhZKEpAib=EcFR4jDbr6PgH9t3g@mail.gmail.com>
2021-03-21 2:33 ` Caroline Tice
2021-03-25 15:09 ` Caroline Tice [this message]
2021-03-25 17:46 ` Andrew Burgess
2021-03-26 17:54 ` [PATCHv3 0/2] " Andrew Burgess
2021-03-26 17:54 ` [PATCHv3 1/2] gdb/testsuite: fix fission support in the Dwarf assembler Andrew Burgess
2021-03-29 16:30 ` Simon Marchi
2021-03-30 11:07 ` Andrew Burgess
2021-04-01 16:41 ` Tom Tromey
2021-03-26 17:54 ` [PATCHv3 2/2] gdb: handle relative paths to DWO files Andrew Burgess
2021-04-01 16:42 ` Tom Tromey
2021-03-31 15:57 ` [PATCHv3 0/2] Add directory containing executable to relative search paths for .dwo files Caroline Tice
2021-03-31 20:04 ` Andrew Burgess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CABtf2+RnNHkZ9NYcx1mYbUYHcViHnnY6P2syUKcqGZrtkkyc_w@mail.gmail.com \
--to=cmtice@google.com \
--cc=andrew.burgess@embecosm.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).