CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
275 lines
8.6 KiB
Plaintext
275 lines
8.6 KiB
Plaintext
# Copyright 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 <http://www.gnu.org/licenses/>.
|
|
|
|
# There was a bug in GCC, which appears to be fixed in version 9 and
|
|
# later, where GCC would, in some case, create an invalid
|
|
# DW_AT_abstract_origin value.
|
|
#
|
|
# The bug was that there existed a function which could be inlined,
|
|
# and so the DWARF contained a DW_TAG_subprogram describing the
|
|
# abstract instance of the function.
|
|
#
|
|
# For whatever reason, the compiler generated a non-inline instance of
|
|
# the function, and so we had a DW_TAG_subprogram with a
|
|
# DW_AT_abstract_origin that referenced the abstract instance.
|
|
#
|
|
# Additionally there was an inlined instance of the function, and so
|
|
# we had a DW_TAG_inlined_subroutine with a DW_AT_abstract_origin that
|
|
# referenced the abstract instance.
|
|
#
|
|
# Within the function there was a DW_TAG_lexical_block, which also
|
|
# appeared in the abstract instance, and both concrete instances. The
|
|
# lexical block also has DW_AT_abstract_origin that should link back
|
|
# to the lexical block within the abstract instance.
|
|
#
|
|
# The bug was that the DW_AT_abstract_origin for the lexical block
|
|
# within the inlined instance instead referenced the lexical block
|
|
# within the non-inline instance, not within the abstract instance.
|
|
#
|
|
# The problem this caused is that the non-inline instance defined the
|
|
# extents of the lexical block using DW_AT_ranges, while the inline
|
|
# instance defined the extend using DW_AT_low_pc and DW_AT_high_pc.
|
|
#
|
|
# When GDB tried to parse the block ranges for the lexical block for
|
|
# the inline function GDB would then find both the DW_AT_ranges and
|
|
# the DW_AT_low_pc/DW_AT_high_pc values. This alone is unexpected.
|
|
#
|
|
# What is worse though, is that the DW_AT_ranges were not within the
|
|
# low-pc/high-pc bounds, and this really confused GDB.
|
|
#
|
|
# The solution is that, when GDB finds blocks with both ranges AND
|
|
# low-pc/high-pc information, GDB should only accept the
|
|
# low-pc/high-pc information.
|
|
#
|
|
# Of course, there's no guarantee which of the information is correct,
|
|
# but if GDB tries to hold both piece of information, then we end up
|
|
# in a non-consistent state, and this triggers assertions.
|
|
|
|
load_lib dwarf.exp
|
|
|
|
require dwarf2_support
|
|
|
|
standard_testfile
|
|
|
|
# This compiles the source file and starts and stops GDB, so run it
|
|
# before calling prepare_for_testing otherwise GDB will have exited.
|
|
get_func_info func_a
|
|
get_func_info func_b
|
|
|
|
# Some line numbers needed in the generated DWARF.
|
|
set func_a_decl_line [gdb_get_line_number "func_a decl line"]
|
|
set func_b_decl_line [gdb_get_line_number "func_b decl line"]
|
|
set call_line [gdb_get_line_number "inline func_a call line"]
|
|
|
|
# See the problem description at the head of this file.
|
|
#
|
|
# Create the test program, use DWARF_VERSION to decide which format of
|
|
# ranges table to generate.
|
|
#
|
|
# Then run the test program and check that GDB doesn't crash, and
|
|
# check that the block structure is as we expect.
|
|
proc run_test { dwarf_version } {
|
|
set dw_testname "${::testfile}-${dwarf_version}"
|
|
|
|
set asm_file [standard_output_file "${dw_testname}.S"]
|
|
Dwarf::assemble $asm_file {
|
|
upvar dwarf_version dwarf_version
|
|
upvar entry_label entry_label
|
|
|
|
declare_labels lines_table foo_func foo_block block_ranges bad_block \
|
|
value_label int_label
|
|
|
|
cu { version $dwarf_version } {
|
|
compile_unit {
|
|
{producer "GNU C 14.1.0"}
|
|
{language @DW_LANG_C}
|
|
{name $::srcfile}
|
|
{comp_dir /tmp}
|
|
{stmt_list $lines_table DW_FORM_sec_offset}
|
|
{low_pc 0 addr}
|
|
} {
|
|
int_label: base_type {
|
|
{name "int"}
|
|
{byte_size 4 sdata}
|
|
{encoding @DW_ATE_signed}
|
|
}
|
|
foo_func: subprogram {
|
|
{name foo}
|
|
{inline @DW_INL_declared_inlined}
|
|
{decl_file 1 data1}
|
|
{decl_line $::func_a_decl_line data1}
|
|
} {
|
|
foo_block: lexical_block {
|
|
} {
|
|
value_label: DW_TAG_variable {
|
|
{name value}
|
|
{type :$int_label}
|
|
}
|
|
}
|
|
}
|
|
subprogram {
|
|
{abstract_origin %$foo_func}
|
|
{low_pc func_a_0 addr}
|
|
{high_pc func_a_6 addr}
|
|
{external 1 flag}
|
|
} {
|
|
bad_block: lexical_block {
|
|
{abstract_origin %$foo_block}
|
|
{ranges $block_ranges DW_FORM_sec_offset}
|
|
} {
|
|
DW_TAG_variable {
|
|
{abstract_origin %$value_label}
|
|
{DW_AT_location {
|
|
DW_OP_const1u 23
|
|
DW_OP_stack_value
|
|
} SPECIAL_expr}
|
|
}
|
|
}
|
|
}
|
|
subprogram {
|
|
{name baz}
|
|
{low_pc func_b_0 addr}
|
|
{high_pc func_b_5 addr}
|
|
{external 1 flag}
|
|
} {
|
|
inlined_subroutine {
|
|
{abstract_origin %$foo_func}
|
|
{call_file 1 data1}
|
|
{call_line $::call_line data1}
|
|
{low_pc func_b_1 addr}
|
|
{high_pc func_b_4 addr}
|
|
} {
|
|
lexical_block {
|
|
{abstract_origin %$bad_block}
|
|
{low_pc func_b_2 addr}
|
|
{high_pc func_b_3 addr}
|
|
} {
|
|
DW_TAG_variable {
|
|
{abstract_origin %$value_label}
|
|
{DW_AT_location {
|
|
DW_OP_const1u 99
|
|
DW_OP_stack_value
|
|
} SPECIAL_expr}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lines {version 2} lines_table {
|
|
include_dir "$::srcdir/$::subdir"
|
|
file_name "$::srcfile" 1
|
|
}
|
|
|
|
if { $dwarf_version == 5 } {
|
|
rnglists {} {
|
|
table {} {
|
|
block_ranges: list_ {
|
|
start_end func_a_1 func_a_2
|
|
start_end func_a_4 func_a_5
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
ranges { } {
|
|
block_ranges: sequence {
|
|
range func_a_1 func_a_2
|
|
range func_a_4 func_a_5
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if {[prepare_for_testing "failed to prepare" "${dw_testname}" \
|
|
[list $::srcfile $asm_file] {nodebug}]} {
|
|
return false
|
|
}
|
|
|
|
if {![runto_main]} {
|
|
return false
|
|
}
|
|
|
|
# Breakpoint on the inline function `foo'.
|
|
gdb_breakpoint foo
|
|
|
|
# Breakpoint within the lexical block inside of `foo'.
|
|
gdb_breakpoint func_a_1
|
|
gdb_breakpoint func_b_2
|
|
|
|
gdb_continue_to_breakpoint "continue to first foo breakpoint"
|
|
gdb_continue_to_breakpoint "continue to func_b_2 breakpoint"
|
|
|
|
gdb_test "print value" " = 99" "print value at func_b_2"
|
|
|
|
# Some addresses we need to look for in the 'maint info blocks'
|
|
# output.
|
|
set func_b_0 [get_hexadecimal_valueof "&func_b_0" "*UNKNOWN*"]
|
|
set func_b_1 [get_hexadecimal_valueof "&func_b_1" "*UNKNOWN*"]
|
|
set func_b_2 [get_hexadecimal_valueof "&func_b_2" "*UNKNOWN*"]
|
|
set func_b_3 [get_hexadecimal_valueof "&func_b_3" "*UNKNOWN*"]
|
|
set func_b_4 [get_hexadecimal_valueof "&func_b_4" "*UNKNOWN*"]
|
|
set func_b_5 [get_hexadecimal_valueof "&func_b_5" "*UNKNOWN*"]
|
|
|
|
gdb_test "maint info blocks" \
|
|
[multi_line \
|
|
"\\\[\\(block \\*\\) $::hex\\\] $func_b_0\\.\\.$func_b_5" \
|
|
" entry pc: $func_b_0" \
|
|
" function: baz" \
|
|
" is contiguous" \
|
|
"\\\[\\(block \\*\\) $::hex\\\] $func_b_1\\.\\.$func_b_4" \
|
|
" entry pc: $func_b_1" \
|
|
" inline function: foo" \
|
|
" symbol count: $::decimal" \
|
|
" is contiguous" \
|
|
"\\\[\\(block \\*\\) $::hex\\\] $func_b_2\\.\\.$func_b_3" \
|
|
" entry pc: $func_b_2" \
|
|
" symbol count: $::decimal" \
|
|
" is contiguous"] \
|
|
"check block structure at func_b_2"
|
|
|
|
gdb_continue_to_breakpoint "continue to second foo breakpoint"
|
|
gdb_continue_to_breakpoint "continue to func_a_1 breakpoint"
|
|
|
|
gdb_test "print value" " = 23" "print value at func_a_1"
|
|
|
|
# Some addresses we need to look for in the 'maint info blocks'
|
|
# output.
|
|
set func_a_0 [get_hexadecimal_valueof "&func_a_0" "*UNKNOWN*"]
|
|
set func_a_1 [get_hexadecimal_valueof "&func_a_1" "*UNKNOWN*"]
|
|
set func_a_2 [get_hexadecimal_valueof "&func_a_2" "*UNKNOWN*"]
|
|
set func_a_4 [get_hexadecimal_valueof "&func_a_4" "*UNKNOWN*"]
|
|
set func_a_5 [get_hexadecimal_valueof "&func_a_5" "*UNKNOWN*"]
|
|
set func_a_6 [get_hexadecimal_valueof "&func_a_6" "*UNKNOWN*"]
|
|
|
|
gdb_test "maint info blocks" \
|
|
[multi_line \
|
|
"\\\[\\(block \\*\\) $::hex\\\] $func_a_0\\.\\.$func_a_6" \
|
|
" entry pc: $func_a_0" \
|
|
" function: foo" \
|
|
" is contiguous" \
|
|
"\\\[\\(block \\*\\) $::hex\\\] $func_a_1\\.\\.$func_a_5" \
|
|
" entry pc: $func_a_1" \
|
|
" symbol count: $::decimal" \
|
|
" address ranges:" \
|
|
" $func_a_1\\.\\.$func_a_2" \
|
|
" $func_a_4\\.\\.$func_a_5"] \
|
|
"check block structure at func_a_1"
|
|
}
|
|
|
|
foreach_with_prefix dwarf_version { 4 5 } {
|
|
run_test $dwarf_version
|
|
}
|