# Copyright 2012-2024 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 . load_lib dwarf.exp # This test can only be run on targets which support DWARF-2 and use gas. require dwarf2_support # This test has hard-wired assumptions that host and build filenames are # the same, and assumes POSIX pathname syntax. require {!is_remote host} require {!ishost *-*-mingw*} # Find length of addresses in bytes. if {[is_64_target]} { set addr_len 8 } else { set addr_len 4 } standard_testfile set func_info_names { compdir_missing__ldir_missing__file_basename compdir_missing__ldir_missing__file_relative compdir_missing__ldir_missing__file_absolute compdir_missing__ldir_relative_file_basename compdir_missing__ldir_relative_file_relative compdir_missing__ldir_relative_file_absolute compdir_missing__ldir_absolute_file_basename compdir_missing__ldir_absolute_file_relative compdir_missing__ldir_absolute_file_absolute_same compdir_missing__ldir_absolute_file_absolute_different compdir_relative_ldir_missing__file_basename compdir_relative_ldir_missing__file_relative compdir_relative_ldir_missing__file_absolute compdir_relative_ldir_relative_file_basename compdir_relative_ldir_relative_file_relative compdir_relative_ldir_relative_file_absolute compdir_relative_ldir_absolute_file_basename compdir_relative_ldir_absolute_file_relative compdir_relative_ldir_absolute_file_absolute_same compdir_relative_ldir_absolute_file_absolute_different compdir_absolute_ldir_missing__file_basename compdir_absolute_ldir_missing__file_relative compdir_absolute_ldir_missing__file_absolute_same compdir_absolute_ldir_missing__file_absolute_different compdir_absolute_ldir_relative_file_basename compdir_absolute_ldir_relative_file_relative compdir_absolute_ldir_relative_file_absolute_same compdir_absolute_ldir_relative_file_absolute_different compdir_absolute_ldir_absolute_file_basename_same compdir_absolute_ldir_absolute_file_basename_different compdir_absolute_ldir_absolute_file_relative_same compdir_absolute_ldir_absolute_file_relative_different compdir_absolute_ldir_absolute_file_absolute_same compdir_absolute_ldir_absolute_file_absolute_different } with_shared_gdb { foreach func_info_name $func_info_names { get_func_info $func_info_name } } set asmsrcfile [standard_output_file ${testfile}asm.S] set asmobjfile [standard_output_file ${testfile}asm.o] set srcabsdir [standard_output_file ${testfile}.d] set srctmpfile tmp-${testfile}.c # $srcdir may be relative. if {[file pathtype $srcabsdir] != "absolute"} { untested "objdir pathtype is not absolute" return -1 } set f [open $asmsrcfile "w"] puts $f "/* DO NOT EDIT! GENERATED AUTOMATICALLY! */" proc out_cu { name cu_dir cu_name line_dir line_name } { global f global addr_len global ${name}_start global ${name}_end set name_start [set ${name}_start] set name_end [set ${name}_end] puts -nonewline $f "\ .L${name}_begin: .4byte .L${name}_end - .L${name}_start /* Length of Compilation Unit */ .L${name}_start: .2byte 2 /* DWARF Version */ .4byte .Labbrev1_begin /* Offset into abbrev section */ .byte ${addr_len} /* Pointer size */ " if { $cu_dir != "" } { puts $f " .uleb128 ABBREV_COMP_DIR_NAME /* Abbrev: DW_TAG_compile_unit */" } else { puts $f " .uleb128 ABBREV_NAME /* Abbrev: DW_TAG_compile_unit */" } puts -nonewline $f "\ .ascii \"GNU C\\0\" /* DW_AT_producer */ .byte 2 /* DW_AT_language (DW_LANG_C) */ .4byte .Lline_${name}_begin /* DW_AT_stmt_list */ .${addr_len}byte $name_start /* DW_AT_low_pc */ .${addr_len}byte $name_end /* DW_AT_high_pc */ " if { $cu_dir != "" } { puts $f " .ascii $cu_dir /* DW_AT_comp_dir */" } puts -nonewline $f "\ .ascii $cu_name /* DW_AT_name */ .uleb128 3 /* Abbrev: DW_TAG_subprogram */ .asciz \"${name}\" /* DW_AT_name */ .${addr_len}byte $name_start /* DW_AT_low_pc */ .${addr_len}byte $name_end /* DW_AT_high_pc */ .byte 0 /* End of children of CU */ .L${name}_end: " } proc out_line { name cu_dir cu_name line_dir line_name } { global f global addr_len global ${name}_start global ${name}_end set name_start [set ${name}_start] set name_end [set ${name}_end] puts -nonewline $f "\ .Lline_${name}_begin: .4byte .Lline_${name}_end - .Lline_${name}_start /* Initial length */ .Lline_${name}_start: .2byte 2 /* Version */ .4byte .Lline_${name}_lines - .Lline_${name}_hdr /* header_length */ .Lline_${name}_hdr: .byte 1 /* Minimum insn length */ .byte 1 /* default_is_stmt */ .byte 1 /* line_base */ .byte 1 /* line_range */ .byte 4 /* opcode_base */ /* Standard lengths */ .byte 0 .byte 1 .byte 1 /* Include directories */ " if { $line_dir != "" } { puts $f " .ascii $line_dir" } puts -nonewline $f "\ .byte 0 /* File names */ .ascii $line_name " if { $line_dir != "" } { puts $f " .uleb128 1" } else { puts $f " .uleb128 0" } puts -nonewline $f "\ .uleb128 0 .uleb128 0 .byte 0 .Lline_${name}_lines: .byte 3 /* DW_LNS_advance_line */ .sleb128 997 /* ... to 998 */ .byte 0 /* DW_LNE_set_address */ .uleb128 ${addr_len}+1 .byte 2 .${addr_len}byte $name_start .byte 1 /* DW_LNS_copy */ .byte 3 /* DW_LNS_advance_line */ .sleb128 1 /* ... to 999 */ .byte 0 /* DW_LNE_set_address */ .uleb128 ${addr_len}+1 .byte 2 .${addr_len}byte ${name}_label .byte 1 /* DW_LNS_copy */ .byte 3 /* DW_LNS_advance_line */ .sleb128 1 /* ... to 1000 */ .byte 0 /* DW_LNE_set_address */ .uleb128 ${addr_len}+1 .byte 2 .${addr_len}byte $name_end .byte 1 /* DW_LNS_copy */ .byte 0 /* DW_LNE_end_of_sequence */ .uleb128 1 .byte 1 .Lline_${name}_end: " } # IFSOME can be optionally _same or _different if >= 2 absolute directories are # provided. Then in the _different case the overriden directories have invalid # XDIR value. proc out_unit { func compdir ldir file ifsame } { set name "compdir_${compdir}_ldir_${ldir}_file_${file}${ifsame}" if { $compdir == "missing_" } { set cu_dir {} } elseif { $compdir == "relative" } { set cu_dir {COMPDIR "\0"} } elseif { $compdir == "absolute" } { set cu_dir {BDIR "/" COMPDIR "\0"} } else { error "compdir $compdir" } if { $ldir == "missing_" } { set line_dir {} } elseif { $ldir == "relative" } { set line_dir {LDIR "\0"} } elseif { $ldir == "absolute" } { set line_dir {BDIR "/" LDIR "\0"} } else { error "ldir $ldir" } if { $file == "basename" } { set cu_name {FILE "\0"} } elseif { $file == "relative" } { set cu_name {FDIR "/" FILE "\0"} } elseif { $file == "absolute" } { set cu_name {BDIR "/" FILE "\0"} } else { error "file $file" } set line_name $cu_name if { "$ifsame" == "_different" } { if { $file == "absolute" } { if { $ldir == "absolute" } { set line_dir {XDIR "\0"} } if { $compdir == "absolute" } { set cu_dir {XDIR "\0"} } } elseif { $ldir == "absolute" } { if { $compdir == "absolute" } { set cu_dir {XDIR "\0"} } } else { error "not enough absolutes" } } $func $name $cu_dir $cu_name $line_dir $line_name } proc out_diff { func compdir ldir file } { set abscount 0 if { $compdir == "absolute" } { incr abscount } if { $ldir == "absolute" } { incr abscount } if { $file == "absolute" } { incr abscount } if { $abscount <= 1 } { out_unit $func $compdir $ldir $file "" } else { out_unit $func $compdir $ldir $file "_same" out_unit $func $compdir $ldir $file "_different" } } proc out_file { func compdir ldir } { out_diff $func $compdir $ldir "basename" out_diff $func $compdir $ldir "relative" out_diff $func $compdir $ldir "absolute" } proc out_ldir { func compdir } { out_file $func $compdir "missing_" out_file $func $compdir "relative" out_file $func $compdir "absolute" } proc out_compdir { func } { out_ldir $func "missing_" out_ldir $func "relative" out_ldir $func "absolute" } puts -nonewline $f "\ #define ABBREV_NAME 1 #define ABBREV_COMP_DIR_NAME 2 .section .debug_info " out_compdir out_cu Dwarf::assemble { add_dummy_cus 0 file_id $f } { global func_info_names foreach name $func_info_names { global ${name}_start global ${name}_end set name_start [set ${name}_start] set name_end [set ${name}_end] set cu_label .L${name}_begin aranges {} cu_label { arange {} $name_start "$name_end - $name_start" } } } puts $f " .section .debug_line" out_compdir out_line puts -nonewline $f "\ .section .debug_abbrev .Labbrev1_begin: .uleb128 ABBREV_NAME /* Abbrev code */ .uleb128 0x11 /* DW_TAG_compile_unit */ .byte 1 /* has_children */ .uleb128 0x25 /* DW_AT_producer */ .uleb128 0x8 /* DW_FORM_string */ .uleb128 0x13 /* DW_AT_language */ .uleb128 0xb /* DW_FORM_data1 */ .uleb128 0x10 /* DW_AT_stmt_list */ .uleb128 0x6 /* DW_FORM_data4 */ .uleb128 0x11 /* DW_AT_low_pc */ .uleb128 0x1 /* DW_FORM_addr */ .uleb128 0x12 /* DW_AT_high_pc */ .uleb128 0x1 /* DW_FORM_addr */ .uleb128 0x3 /* DW_AT_name */ .uleb128 0x8 /* DW_FORM_string */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ .uleb128 ABBREV_COMP_DIR_NAME /* Abbrev code */ .uleb128 0x11 /* DW_TAG_compile_unit */ .byte 1 /* has_children */ .uleb128 0x25 /* DW_AT_producer */ .uleb128 0x8 /* DW_FORM_string */ .uleb128 0x13 /* DW_AT_language */ .uleb128 0xb /* DW_FORM_data1 */ .uleb128 0x10 /* DW_AT_stmt_list */ .uleb128 0x6 /* DW_FORM_data4 */ .uleb128 0x11 /* DW_AT_low_pc */ .uleb128 0x1 /* DW_FORM_addr */ .uleb128 0x12 /* DW_AT_high_pc */ .uleb128 0x1 /* DW_FORM_addr */ .uleb128 0x1b /* DW_AT_comp_dir */ .uleb128 0x8 /* DW_FORM_string */ .uleb128 0x3 /* DW_AT_name */ .uleb128 0x8 /* DW_FORM_string */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ .uleb128 3 /* Abbrev code */ .uleb128 0x2e /* DW_TAG_subprogram */ .byte 0 /* has_children */ .uleb128 0x3 /* DW_AT_name */ .uleb128 0x8 /* DW_FORM_string */ .uleb128 0x11 /* DW_AT_low_pc */ .uleb128 0x1 /* DW_FORM_addr */ .uleb128 0x12 /* DW_AT_high_pc */ .uleb128 0x1 /* DW_FORM_addr */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ " close $f set opts {} # Base directory. lappend opts "additional_flags=-DBDIR=\"${srcabsdir}\"" # Incorrect directory which should never be visible from GDB. lappend opts "additional_flags=-DXDIR=\"${srcabsdir}/xdir\"" # CU's DW_AT_comp_dir. lappend opts "additional_flags=-DCOMPDIR=\"compdir\"" # .debug_line's directory. lappend opts "additional_flags=-DLDIR=\"ldir\"" # CU's DW_AT_name and .debug_line's filename relative directory, if needed. lappend opts "additional_flags=-DFDIR=\"fdir\"" # CU's DW_AT_name and .debug_line's filename. lappend opts "additional_flags=-DFILE=\"${srctmpfile}\"" # Clang's integrated assembler doesn't support .ascii directives # with multiple string literals. if { [test_compiler_info clang*] } { lappend opts "additional_flags=-fno-integrated-as" } if { [gdb_compile "${asmsrcfile} ${srcdir}/${subdir}/$srcfile" "${binfile}" executable $opts] != "" } { untested "failed to compile" return -1 } set dirs {} foreach r {"" /rdir} { foreach x {"" /xdir} { foreach comp {"" /compdir} { foreach l {"" /ldir} { foreach f {"" /fdir} { lappend dirs $r$x$comp$l$f } } } } } proc pathexpand {prefix dirlst suffix} { set retlst {} foreach dir $dirlst { lappend retlst "$prefix$dir$suffix" } return $retlst } set filelist [pathexpand $srcabsdir $dirs "/$srctmpfile"] set dircreatelist [pathexpand $srcabsdir $dirs ""] set dirremovelist [pathexpand $srcabsdir [lreverse $dirs] ""] remote_exec host "sh -c \"rm -f $filelist\"" remote_exec host "sh -c \"rmdir $dirremovelist\"" remote_exec host "sh -c \"mkdir $dircreatelist\"" remote_exec host "sh -c \"for d in $dircreatelist; do cp ${srcdir}/${subdir}/${srcfile} \\\$d/${srctmpfile}; done\"" clean_restart ${testfile} if ![runto_main] { return -1 } gdb_test "cd ${srcabsdir}/rdir" "Working directory [string_to_regexp ${srcabsdir}]/rdir\\." "cd .../rdir" proc test { func compdir filename } { with_test_prefix "$func" { # Clear the GDB cache. gdb_test_no_output "set directories" "" if {$compdir == ""} { set absolute "$filename" } else { set absolute "$compdir/$filename" } if {[string index $absolute 0] != "/"} { error "not absolute" } gdb_breakpoint ${func}_label gdb_test "continue" "$func \\(\\) at .*" "continue to $func" gdb_test_no_output "set filename-display absolute" verbose -log "expect: ${absolute}" gdb_test "frame" "$func \\(\\) at [string_to_regexp ${absolute}]:999" "absolute" gdb_test_no_output "set filename-display basename" verbose -log "expect: [file tail $filename]" gdb_test "frame" "$func \\(\\) at [string_to_regexp [file tail $filename]]:999" "basename" gdb_test_no_output "set filename-display relative" verbose -log "expect: $filename" gdb_test "frame" "$func \\(\\) at [string_to_regexp $filename]:999" "relative" } } set bdir "${srcabsdir}" set file "${srctmpfile}" test "compdir_missing__ldir_missing__file_basename" "$bdir/rdir" "$file" test "compdir_missing__ldir_missing__file_relative" "$bdir/rdir" "fdir/$file" test "compdir_missing__ldir_missing__file_absolute" "" "$bdir/$file" test "compdir_missing__ldir_relative_file_basename" "$bdir/rdir" "ldir/$file" test "compdir_missing__ldir_relative_file_relative" "$bdir/rdir" "ldir/fdir/$file" test "compdir_missing__ldir_relative_file_absolute" "" "$bdir/$file" test "compdir_missing__ldir_absolute_file_basename" "" "$bdir/ldir/$file" test "compdir_missing__ldir_absolute_file_relative" "" "$bdir/ldir/fdir/$file" test "compdir_missing__ldir_absolute_file_absolute_same" "" "$bdir/$file" test "compdir_missing__ldir_absolute_file_absolute_different" "" "$bdir/$file" test "compdir_relative_ldir_missing__file_basename" "$bdir/rdir/compdir" "$file" test "compdir_relative_ldir_missing__file_relative" "$bdir/rdir/compdir" "fdir/$file" test "compdir_relative_ldir_missing__file_absolute" "" "$bdir/$file" test "compdir_relative_ldir_relative_file_basename" "$bdir/rdir/compdir" "ldir/$file" test "compdir_relative_ldir_relative_file_relative" "$bdir/rdir/compdir" "ldir/fdir/$file" test "compdir_relative_ldir_relative_file_absolute" "" "$bdir/$file" test "compdir_relative_ldir_absolute_file_basename" "" "$bdir/ldir/$file" test "compdir_relative_ldir_absolute_file_relative" "" "$bdir/ldir/fdir/$file" test "compdir_relative_ldir_absolute_file_absolute_same" "" "$bdir/$file" test "compdir_relative_ldir_absolute_file_absolute_different" "" "$bdir/$file" test "compdir_absolute_ldir_missing__file_basename" "$bdir/compdir" "$file" test "compdir_absolute_ldir_missing__file_relative" "$bdir/compdir" "fdir/$file" test "compdir_absolute_ldir_missing__file_absolute_same" "" "$bdir/$file" test "compdir_absolute_ldir_missing__file_absolute_different" "" "$bdir/$file" test "compdir_absolute_ldir_relative_file_basename" "$bdir/compdir" "ldir/$file" test "compdir_absolute_ldir_relative_file_relative" "$bdir/compdir" "ldir/fdir/$file" test "compdir_absolute_ldir_relative_file_absolute_same" "" "$bdir/$file" test "compdir_absolute_ldir_relative_file_absolute_different" "" "$bdir/$file" test "compdir_absolute_ldir_absolute_file_basename_same" "" "$bdir/ldir/$file" test "compdir_absolute_ldir_absolute_file_relative_different" "" "$bdir/ldir/fdir/$file" test "compdir_absolute_ldir_absolute_file_absolute_same" "" "$bdir/$file" test "compdir_absolute_ldir_absolute_file_absolute_different" "" "$bdir/$file"