--- /dev/null
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022 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/>.
+
+# Compile a source file using different ways of passing the path to the
+# compiler. Then, verify that we can print a macro defined in that file.
+
+standard_testfile
+
+# If the host is remote, source files are uploaded to the host and compiled
+# there, but without the directory structure we expect, making the test
+# pointless. Skip the test in that case.
+if { [is_remote host] } {
+ return
+}
+
+# Copy the source file at these locations in the output directory ($out):
+#
+# $out/cwd/macro-source-path.c
+# $out/other/macro-source-path.c
+#
+# Set the current working directory to $out/cwd, so that we can test compiling
+# using relative paths.
+
+set out_dir [standard_output_file ""]
+file mkdir $out_dir/cwd
+file mkdir $out_dir/other
+file copy -force $srcdir/$subdir/$srcfile $out_dir/cwd
+file copy -force $srcdir/$subdir/$srcfile $out_dir/other
+
+# Run one test.
+#
+# SRC is the path to the source file, to be passed to the compiler as-is.
+# NAME is the name of the test.
+
+proc test { src name } {
+ with_test_prefix $name {
+ set binfile $::out_dir/$name
+
+ if { [gdb_compile $src $binfile executable {debug macros additional_flags=-DONE=1}] != "" } {
+ fail "could not compile"
+ return
+ }
+
+ clean_restart $binfile
+
+ if { ![runto_main] } {
+ return
+ }
+
+ # Print the macro that is defined on the command-line.
+ if { [test_compiler_info "clang-*"] } {
+ # This is really a clang bug, it puts the macros defined on the command
+ # line after the main source file, in the macro table.
+ setup_kfail "gdb/29034" "*-*-*"
+ }
+ gdb_test "print ONE" " = 1"
+
+ # Print the macro that is defined in the main file.
+ gdb_test "print TWO" " = 2"
+ }
+}
+
+# When adding a test here, please consider adding an equivalent case to the test
+# of the same name in gdb.dwarf2.
+
+with_cwd "$out_dir/cwd" {
+ test $testfile.c filename
+ test ./$testfile.c dot-filename
+ test ../cwd/$testfile.c dot-dot-filename
+ test [file normalize $testfile.c] absolute-cwd
+ test ../other/$testfile.c dot-dot-other
+ test [file normalize ../other/$testfile.c] absolute-other
+}
--- /dev/null
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2022 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/>.
+
+# Generate binaries imitating different ways source file paths can be passed to
+# compilers. Test printing macros from those binaries.
+
+load_lib dwarf.exp
+
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile .c
+
+lassign [function_range main $srcdir/$subdir/$srcfile] \
+ main_start main_len
+
+# Run one test.
+#
+# - TEST_NAME is the name of the test, used to differentiate the binaries.
+# - LINES_VERSION is the version of the version of the .debug_line section to
+# generate.
+# - DW_AT_NAME is the string to put in the compilation unit's DW_AT_name
+# attribute.
+# - MAIN_FILE_IDX is the file index the .debug_line and .debug_macro sections
+# will use to refer to the main file.
+# - DIRECTORIES is a list of directories to put in the .debug_line section
+# header
+# - FILE_NAMES is a list of {name, directory index} pairs describing the files
+# names to put in the .debug_line section header.
+
+proc do_test { test_name lines_version DW_AT_name main_file_idx directories
+ file_names } {
+ with_test_prefix "test_name=$test_name" {
+ foreach_with_prefix is_64 {true false} {
+ # So we can access them in Dwarf::assemble...
+ set ::lines_version $lines_version
+ set ::DW_AT_name $DW_AT_name
+ set ::main_file_idx $main_file_idx
+ set ::directories $directories
+ set ::file_names $file_names
+ set ::is_64 $is_64
+ set 32_or_64 [expr $is_64 ? 64 : 32]
+
+ set asm_file [standard_output_file ${::testfile}-${test_name}-${32_or_64}.S]
+ Dwarf::assemble $asm_file {
+ declare_labels Llines cu_macros
+
+ # DW_AT_comp_dir is always the current working directory
+ # from which the compiler was invoked. We pretend the compiler was
+ # always launched from /tmp/cwd.
+ set comp_dir "/tmp/cwd"
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_producer "My C Compiler"}
+ {DW_AT_language @DW_LANG_C11}
+ {DW_AT_name $::DW_AT_name}
+ {DW_AT_comp_dir $comp_dir}
+ {DW_AT_stmt_list $Llines DW_FORM_sec_offset}
+ {DW_AT_macros $cu_macros DW_FORM_sec_offset}
+ } {
+ declare_labels int_type
+
+ int_type: DW_TAG_base_type {
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_name int}
+ }
+
+ DW_TAG_subprogram {
+ {MACRO_AT_func {main}}
+ {type :$int_type}
+ }
+ }
+ }
+
+ # Define the .debug_line section.
+ lines [list version $::lines_version] "Llines" {
+ foreach directory $::directories {
+ include_dir $directory
+ }
+
+ foreach file_name $::file_names {
+ lassign $file_name name dir_index
+ file_name $name $dir_index
+ }
+
+ # A line number program just good enough so that GDB can
+ # figure out we are stopped in main.
+ program {
+ DW_LNS_set_file $::main_file_idx
+ DW_LNE_set_address $::main_start
+ line 10
+ DW_LNS_copy
+
+ DW_LNE_set_address "$::main_start + $::main_len"
+ DW_LNE_end_sequence
+ }
+ }
+
+ # Define the .debug_macro section.
+ macro {
+ cu_macros: unit {
+ "debug-line-offset-label" $Llines
+ "is-64" $::is_64
+ } {
+ # A macro defined outside the main file, as if it was defined
+ # on the command line with -D.
+ #
+ # Clang has this bug where it puts the macros defined on
+ # the command-line after the main file portion (see
+ # PR 29034). We're not trying to replicate that here,
+ # this is not in the scope of this test.
+ define 0 "ONE 1"
+ start_file 0 $::main_file_idx
+ # A macro defined at line 1 of the main file.
+ define 1 "TWO 2"
+ end_file
+ }
+ }
+ }
+
+ if { [prepare_for_testing "failed to prepare" ${::testfile}-${test_name}-${32_or_64} \
+ [list $::srcfile $asm_file] {nodebug}] } {
+ return
+ }
+
+ if ![runto_main] {
+ return
+ }
+
+ gdb_test "print ONE" " = 1"
+ gdb_test "print TWO" " = 2"
+ }
+ }
+}
+
+# When adding a test here, please consider adding an equivalent case to the test
+# of the same name in gdb.base.
+
+# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`,
+# gcc 11 paired with gas from binutils 2.38.
+
+## test.c
+do_test gcc11-ld238-dw5-filename 5 "test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"test.c" 0}
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test gcc11-ld238-dw5-dot-filename 5 "./test.c" 1 {
+ "/tmp/cwd"
+ "."
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test gcc11-ld238-dw5-dot-dot-cwd 5 "../cwd/test.c" 1 {
+ "/tmp/cwd"
+ "../cwd"
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test gcc11-ld238-dw5-absolute-cwd 5 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+ "/tmp/cwd"
+} {
+ {"test.c" 1}
+ {"test.c" 0}
+}
+
+## ../other/test.c
+do_test gcc11-ld238-dw5-dot-dot-other 5 "../other/test.c" 1 {
+ "/tmp/cwd"
+ "../other"
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test gcc11-ld238-dw5-absolute-other 5 "/tmp/other/test.c" 1 {
+ "/tmp/cwd"
+ "/tmp/other"
+} {
+ {"test.c" 1}
+ {"test.c" 1}
+}
+
+# The following tests are based on the output of `gcc -gdwarf-4 -g3 <file>`,
+# gcc 11 paired with gas from binutils 2.38. With -gdwarf-4, gcc generates a
+# v4 (pre-standard) .debug_macro section.
+
+## test.c
+do_test gcc11-ld238-dw4-filename 4 "test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test gcc11-ld238-dw4-dot-filename 4 "./test.c" 1 {
+ "."
+} {
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test gcc11-ld238-dw4-dot-dot-cwd 4 "../cwd/test.c" 1 {
+ "../cwd"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test gcc11-ld238-dw4-absolute-cwd 4 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"test.c" 1}
+}
+
+## ../other/test.c
+do_test gcc11-ld238-dw4-dot-dot-other 4 "../other/test.c" 1 {
+ "../other"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test gcc11-ld238-dw4-absolute-other 4 "/tmp/other/test.c" 1 {
+ "/tmp/other"
+} {
+ {"test.c" 1}
+}
+
+# The following tests are based on the output of `clang-14 -gdwarf-5
+# -fdebug-macro -g3 <file>` (using its built-in assembler)
+
+## test.c
+do_test clang14-dw5-filename 5 "test.c" 0 {
+ "/tmp/cwd"
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test clang14-dw5-dot-filename 5 "test.c" 1 {
+ "/tmp/cwd"
+ "."
+} {
+ {"test.c" 0}
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test clang14-dw5-dot-dot-cwd 5 "../cwd/test.c" 0 {
+ "/tmp/cwd"
+} {
+ {"../cwd/test.c" 0}
+}
+
+## /tmp/cwd/test.c
+do_test clang14-dw5-absolute-cwd 5 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"/tmp/cwd/test.c" 0}
+ {"test.c" 0}
+}
+
+## ../other/test.c
+do_test clang14-dw5-dot-dot-other 5 "../other/test.c" 0 {
+ "/tmp/cwd"
+} {
+ {"../other/test.c" 0}
+}
+
+## /tmp/other/test.c
+do_test clang14-dw5-absolute-other 5 "/tmp/other/test.c" 1 {
+ "/tmp/cwd"
+ "/tmp"
+} {
+ {"/tmp/other/test.c" 0}
+ {"other/test.c" 1}
+}
+
+# The following tests are based on the output of `clang-14 -gdwarf-4
+# -fdebug-macro -g3 <file>` (using its built-in assembler). With -gdwarf-4,
+# clang produces a .debug_macinfo section, not a .debug_macro section. But
+# this test still creates a .debug_macro section, that's good enough for what
+# we want to test.
+
+## test.c
+do_test clang14-dw4-filename 4 "test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test clang14-dw4-dot-filename 4 "test.c" 1 {
+ "."
+} {
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test clang14-dw4-dot-dot-cwd 4 "../cwd/test.c" 1 {
+ "../cwd"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test clang14-dw4-absolute-cwd 4 "/tmp/cwd/test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ../other/test.c
+do_test clang14-dw4-dot-dot-other 4 "../other/test.c" 1 {
+ "../other"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test clang14-dw4-absolute-other 4 "/tmp/other/test.c" 1 {
+ "/tmp"
+} {
+ {"other/test.c" 1}
+}
+
+# The following tests are based on the output of `gcc -gdwarf-5 -g3 <file>`,
+# gcc 11 paired with gas from binutils 2.34 (Ubuntu 20.04). It generates a v5
+# .debug_macro section, but a v3 .debug_line section.
+
+## test.c
+do_test gcc11-ld234-dw5-filename 3 "test.c" 1 {
+} {
+ {"test.c" 0}
+}
+
+## ./test.c
+do_test gcc11-ld234-dw5-dot-filename 3 "./test.c" 1 {
+ "."
+} {
+ {"test.c" 1}
+}
+
+## ../cwd/test.c
+do_test gcc11-ld234-dw5-dot-dot-cwd 3 "../cwd/test.c" 1 {
+ "../cwd"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/cwd/test.c
+do_test gcc11-ld234-dw5-absolute-cwd 3 "/tmp/cwd/test.c" 1 {
+ "/tmp/cwd"
+} {
+ {"test.c" 1}
+}
+
+## ../other/test.c
+do_test gcc11-ld234-dw5-dot-dot-other 3 "../other/test.c" 1 {
+ "../other"
+} {
+ {"test.c" 1}
+}
+
+## /tmp/other/test.c
+do_test gcc11-ld234-dw5-absolute-other 3 "/tmp/other/test.c" 1 {
+ "/tmp/other"
+} {
+ {"test.c" 1}
+}
incr _debug_loclists_locdesc_count
}
+ # Emit a DWARF .debug_macro section.
+ #
+ # BODY must be Tcl code that emits the content of the section. It is
+ # evaluated in the caller's context. The body can use the `unit` proc
+ # (see `_macro_unit`) to generate macro units.
+
+ proc macro { body } {
+ _section ".debug_macro"
+
+ with_override Dwarf::unit Dwarf::_macro_unit {
+ uplevel $body
+ }
+ }
+
+ # Generate one macro unit.
+ #
+ # This proc is meant to be used within proc macro's body. It is made
+ # available as `unit` while inside proc macro's body.
+ #
+ # BODY must be Tcl code that emits the content of the unit. It may call
+ # procedures defined below, prefixed with `_macro_unit_`, to generate the
+ # unit's content. It is evaluated in the caller's context.
+ #
+ # The `is-64 true|false` options tells whether to use 64-bit DWARF instead
+ # of 32-bit DWARF. The default is 32-bit.
+ #
+ # If specified, the `debug-line-offset-label` option is the name of a label
+ # to use for the unit header's `debug_line_offset` field value. If
+ # omitted, the unit header will not contain the `debug_line_offset` field.
+
+ proc _macro_unit { options body } {
+ parse_options {
+ {"is-64" "false"}
+ {"debug-line-offset-label" ""}
+ }
+
+ _op .2byte 5 "version"
+
+ # Flags:
+ #
+ # offset_size_flag = set if is-64 is true
+ # debug_line_offset_flag = set if debug-line-offset-label is set
+ # opcode_operands_table_flag = 0
+ set flags 0
+
+ if { ${is-64} } {
+ set flags [expr $flags | 0x1]
+ }
+
+ if { ${debug-line-offset-label} != "" } {
+ set flags [expr $flags | 0x2]
+ }
+
+ _op .byte $flags "flags"
+
+ if { ${debug-line-offset-label} != "" } {
+ if { ${is-64} } {
+ _op .8byte ${debug-line-offset-label} "debug_line offset"
+ } else {
+ _op .4byte ${debug-line-offset-label} "debug_line offset"
+ }
+ }
+
+ with_override Dwarf::define Dwarf::_macro_unit_define {
+ with_override Dwarf::start_file Dwarf::_macro_unit_start_file {
+ with_override Dwarf::end_file Dwarf::_macro_unit_end_file {
+ uplevel $body
+ }}}
+ }
+
+ # Emit a DW_MACRO_define entry.
+
+ proc _macro_unit_define { lineno text } {
+ _op .byte 0x1 "DW_MACRO_define"
+ _op .uleb128 $lineno "Line number"
+ _op .asciz "\"$text\"" "Macro definition"
+ }
+
+ # Emit a DW_MACRO_start_file entry.
+
+ proc _macro_unit_start_file { lineno file_idx } {
+ _op .byte 0x3 "DW_MACRO_start_file"
+ _op .uleb128 $lineno
+ _op .uleb128 $file_idx
+ }
+
+ # Emit a DW_MACRO_end_file entry.
+
+ proc _macro_unit_end_file {} {
+ _op .byte 0x4 "DW_MACRO_end_file"
+ }
+
# Emit a DWARF .debug_line unit.
# OPTIONS is a list with an even number of elements containing
# option-name and option-value pairs.