aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c
diff options
context:
space:
mode:
authorKevin Buettner <kevinb@redhat.com>2019-06-02 18:31:22 -0700
committerKevin Buettner <kevinb@redhat.com>2019-07-27 13:38:44 -0700
commit5c076da45ce9a24d47046ddb0bac02e158e6bf58 (patch)
tree694665f17b760f6dc12c52b89f30ba223c3eb343 /gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c
parent1aff7173105c9540bbbef75727aa200f5c288b2e (diff)
downloadgdb-5c076da45ce9a24d47046ddb0bac02e158e6bf58.zip
gdb-5c076da45ce9a24d47046ddb0bac02e158e6bf58.tar.gz
gdb-5c076da45ce9a24d47046ddb0bac02e158e6bf58.tar.bz2
Improve test gdb.dwarf2/dw2-ranges-func.exp
The original dw2-ranges-func.exp test caused a function named foo to be created with two non-contiguous address ranges. In the C source file, a function named foo_low was incorporated into the function foo which was also defined in that file. The DWARF assembler is used to do this manipulation. The source file had been laid out so that foo_low would likely be placed (by the compiler and linker) at a lower address than foo(). The case where a range at a higher set of addresses (than foo) was not being tested. In a recent discussion on gdb-patches, it became clear that performing such tests are desirable because bugs were discovered which only became evident when the other range was located at high(er) addresses than the range containing the entry point for the function. This other (non entry pc) address range is typically used for "cold" code which executes less frequently. Thus, I renamed foo_low to foo_cold and renamed the C source file from dw-ranges-func.c to dw-ranges-func-lo.c. I then made a copy of this file, naming it dw-ranges-func-hi.c. (That was my intent anyway. According to git, I renamed dw-ranges-func.c to dw-ranges-func-hi.c and then modified it. dw-ranges-func-lo.c shows up as an entirely new file.) Within dw-ranges-func-hi.c, I changed the placement of foo_cold() along with some of the other functions so that foo_cold() would be at a higher address than foo() while also remaining non-contiguous. The two files, dw-ranges-func-lo.c and dw-ranges-func-hi.c, are essentially the same except for the placement of some of the functions therein. The tests in dw2-ranges-func.exp where then wrapped in a new proc named do_test which was then called in a loop from the outermost level. The loop causes each of the source files to have the same tests run upon them. I also added a few new tests which test functionality fixed by the other commits to this patch series. Due to the reorganization of the file, it's hard to identify these changes in the patch. So, here are the tests which were added: with_test_prefix "no-cold-names" { # Due to the calling sequence, this backtrace would normally # show function foo_cold for frame #1. However, we don't want # this to be the case due to placing it in the same block # (albeit at a different range) as foo. Thus it is correct to # see foo for frames #1 and #2. It is incorrect to see # foo_cold at frame #1. gdb_test_sequence "bt" "backtrace from baz" { "\[\r\n\]#0 .*? baz \\(\\) " "\[\r\n\]#1 .*? foo \\(\\) " "\[\r\n\]#2 .*? foo \\(\\) " "\[\r\n\]#3 .*? main \\(\\) " } # Doing x/2i foo_cold should show foo_cold as the first symbolic # address and an offset from foo for the second. We also check to # make sure that the offset is not too large - we don't GDB to # display really large offsets that would (try to) wrap around the # address space. set foo_cold_offset 0 set test "x/2i foo_cold" gdb_test_multiple $test $test { -re " (?:$hex) <foo_cold>.*?\n (?:$hex) <foo\[+-\](\[0-9\]+)>.*${gdb_prompt}" { set foo_cold_offset $expect_out(1,string) pass $test } } gdb_assert {$foo_cold_offset <= 10000} "offset to foo_cold is not too large" # Likewise, verify that second address shown by "info line" is at # and offset from foo instead of foo_cold. gdb_test "info line *foo_cold" "starts at address $hex <foo_cold> and ends at $hex <foo\[+-\].*?>.*" } When run against a GDB without the requisite bug fixes (from this patch series), these 6 failures should be seen: FAIL: gdb.dwarf2/dw2-ranges-func.exp: lo-cold: no-cold-names: backtrace from baz (pattern 4) FAIL: gdb.dwarf2/dw2-ranges-func.exp: lo-cold: no-cold-names: x/2i foo_cold FAIL: gdb.dwarf2/dw2-ranges-func.exp: lo-cold: no-cold-names: info line *foo_cold FAIL: gdb.dwarf2/dw2-ranges-func.exp: hi-cold: no-cold-names: backtrace from baz (pattern 3) FAIL: gdb.dwarf2/dw2-ranges-func.exp: hi-cold: no-cold-names: x/2i foo_cold FAIL: gdb.dwarf2/dw2-ranges-func.exp: hi-cold: no-cold-names: info line *foo_cold gdb/testsuite/ChangeLog: * gdb.dwarf2/dw2-ranges-func.c: Rename to... * gdb.dwarf2/dw2-ranges-func-lo-cold.c: ...this. * gdb.dwarf2/dw2-ranges-func-lo-cold.c (foo_low): Change name to foo_cold. Revise comments to match. * gdb.dwarf2/dw2-ranges-func-hi-cold.c: New file. * gdb.dwarf2/dw2-ranges-func.exp (do_test): New proc. Existing tests were wrapped into this proc; Call do_test in loop from outermost level. (foo_low): Rename all occurrences to "foo_cold". (backtrace from baz): New test. (x2/i foo_cold): New test. (info line *foo_cold): New test.
Diffstat (limited to 'gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c')
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c b/gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c
new file mode 100644
index 0000000..40966ce
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ranges-func-lo-cold.c
@@ -0,0 +1,82 @@
+/* Copyright 2018-2019 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/>. */
+
+/* The idea here is to, via use of the dwarf assembler, create a function
+ which occupies two non-contiguous address ranges.
+
+ foo_cold and foo will be combined into a single function foo with a
+ function bar in between these two ranges.
+
+ This test case was motivated by a bug in which a function which
+ occupied two non-contiguous address ranges was calling another
+ function which resides in between these ranges. So we end up with
+ a situation in which the low/start address of our constructed foo
+ (in this case) will be less than any of the addresses in bar, but
+ the high/end address of foo will be greater than any of bar's
+ addresses.
+
+ This situation was causing a problem in the caching code of
+ find_pc_partial_function: When the low and high addresses of foo
+ are placed in the cache, the simple check that was used to see if
+ the cache was applicable would (incorrectly) succeed when presented
+ with an address in bar. I.e. an address in bar presented as an
+ input to find_pc_partial_function could produce the answer "this
+ address belongs to foo". */
+
+volatile int e = 0;
+
+void bar (void);
+void foo_cold (void);
+void baz (void);
+
+void
+baz (void)
+{
+ asm ("baz_label: .globl baz_label");
+} /* baz end */
+
+void
+foo_cold (void)
+{ /* foo_cold prologue */
+ asm ("foo_cold_label: .globl foo_cold_label");
+ baz (); /* foo_cold baz call */
+ asm ("foo_cold_label2: .globl foo_cold_label2");
+} /* foo_cold end */
+
+void
+bar (void)
+{
+ asm ("bar_label: .globl bar_label");
+} /* bar end */
+
+void
+foo (void)
+{ /* foo prologue */
+ asm ("foo_label: .globl foo_label");
+ bar (); /* foo bar call */
+ asm ("foo_label2: .globl foo_label2");
+ if (e) foo_cold (); /* foo foo_cold call */
+ asm ("foo_label3: .globl foo_label3");
+} /* foo end */
+
+int
+main (void)
+{ /* main prologue */
+ asm ("main_label: .globl main_label");
+ foo (); /* main foo call */
+ asm ("main_label2: .globl main_label2");
+ return 0; /* main return */
+} /* main end */
+