aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2011-10-09 19:29:11 +0000
committerJan Kratochvil <jan.kratochvil@redhat.com>2011-10-09 19:29:11 +0000
commit2d6c5dc2c7f35f46bdbcee6ea442a97ae880db4b (patch)
treeb2564d2dc726b474ab05bf82be51fe330cf227f4
parent111c64899c7b1811c3a04c711f4a0dc95776eecc (diff)
downloadgdb-2d6c5dc2c7f35f46bdbcee6ea442a97ae880db4b.zip
gdb-2d6c5dc2c7f35f46bdbcee6ea442a97ae880db4b.tar.gz
gdb-2d6c5dc2c7f35f46bdbcee6ea442a97ae880db4b.tar.bz2
gdb/
Protect entry values against self tail calls. * dwarf2loc.c (VEC (CORE_ADDR), func_verify_no_selftailcall): New. (dwarf_expr_dwarf_reg_entry_value): Call func_verify_no_selftailcall. gdb/testsuite/ Protect entry values against self tail calls. * gdb.arch/amd64-entry-value.cc (self2, self): New. (main): Call self. * gdb.arch/amd64-entry-value.exp (self: breakhere, self: bt) (set debug entry-values 1, self: bt debug entry-values): New tests.
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/dwarf2loc.c85
-rw-r--r--gdb/testsuite/ChangeLog8
-rw-r--r--gdb/testsuite/gdb.arch/amd64-entry-value.cc24
-rw-r--r--gdb/testsuite/gdb.arch/amd64-entry-value.exp13
5 files changed, 136 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 76e62f2..3c11113 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2011-10-09 Jan Kratochvil <jan.kratochvil@redhat.com>
+ Protect entry values against self tail calls.
+ * dwarf2loc.c (VEC (CORE_ADDR), func_verify_no_selftailcall): New.
+ (dwarf_expr_dwarf_reg_entry_value): Call func_verify_no_selftailcall.
+
+2011-10-09 Jan Kratochvil <jan.kratochvil@redhat.com>
+
Recognize virtual tail call frames.
* Makefile.in (SFILES): Add dwarf2-frame-tailcall.c.
(HFILES_NO_SRCDIR): Add dwarf2-frame-tailcall.h.
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 1661d9f..fef0c6b 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -422,6 +422,87 @@ func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
return sym;
}
+/* Define VEC (CORE_ADDR) functions. */
+DEF_VEC_I (CORE_ADDR);
+
+/* Verify function with entry point exact address ADDR can never call itself
+ via its tail calls (incl. transitively). Throw NO_ENTRY_VALUE_ERROR if it
+ can call itself via tail calls.
+
+ If a funtion can tail call itself its entry value based parameters are
+ unreliable. There is no verification whether the value of some/all
+ parameters is unchanged through the self tail call, we expect if there is
+ a self tail call all the parameters can be modified. */
+
+static void
+func_verify_no_selftailcall (struct gdbarch *gdbarch, CORE_ADDR verify_addr)
+{
+ struct obstack addr_obstack;
+ struct cleanup *old_chain;
+ CORE_ADDR addr;
+
+ /* Track here CORE_ADDRs which were already visited. */
+ htab_t addr_hash;
+
+ /* The verification is completely unordered. Track here function addresses
+ which still need to be iterated. */
+ VEC (CORE_ADDR) *todo = NULL;
+
+ obstack_init (&addr_obstack);
+ old_chain = make_cleanup_obstack_free (&addr_obstack);
+ addr_hash = htab_create_alloc_ex (64, core_addr_hash, core_addr_eq, NULL,
+ &addr_obstack, hashtab_obstack_allocate,
+ NULL);
+ make_cleanup_htab_delete (addr_hash);
+
+ make_cleanup (VEC_cleanup (CORE_ADDR), &todo);
+
+ VEC_safe_push (CORE_ADDR, todo, verify_addr);
+ while (!VEC_empty (CORE_ADDR, todo))
+ {
+ struct symbol *func_sym;
+ struct call_site *call_site;
+
+ addr = VEC_pop (CORE_ADDR, todo);
+
+ func_sym = func_addr_to_tail_call_list (gdbarch, addr);
+
+ for (call_site = TYPE_TAIL_CALL_LIST (SYMBOL_TYPE (func_sym));
+ call_site; call_site = call_site->tail_call_next)
+ {
+ CORE_ADDR target_addr;
+ void **slot;
+
+ /* CALLER_FRAME with registers is not available for tail-call jumped
+ frames. */
+ target_addr = call_site_to_target_addr (gdbarch, call_site, NULL);
+
+ if (target_addr == verify_addr)
+ {
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol_by_pc (verify_addr);
+ throw_error (NO_ENTRY_VALUE_ERROR,
+ _("DW_OP_GNU_entry_value resolving has found "
+ "function \"%s\" at %s can call itself via tail "
+ "calls"),
+ msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym),
+ paddress (gdbarch, verify_addr));
+ }
+
+ slot = htab_find_slot (addr_hash, &target_addr, INSERT);
+ if (*slot == NULL)
+ {
+ *slot = obstack_copy (&addr_obstack, &target_addr,
+ sizeof (target_addr));
+ VEC_safe_push (CORE_ADDR, todo, target_addr);
+ }
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
/* Print user readable form of CALL_SITE->PC to gdb_stdlog. Used only for
ENTRY_VALUES_DEBUG. */
@@ -780,6 +861,10 @@ dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
paddress (gdbarch, func_addr));
}
+ /* No entry value based parameters would be reliable if this function can
+ call itself via tail calls. */
+ func_verify_no_selftailcall (gdbarch, func_addr);
+
for (iparams = 0; iparams < call_site->parameter_count; iparams++)
{
parameter = &call_site->parameter[iparams];
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ce9800c..86fe0e9 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,13 @@
2011-10-09 Jan Kratochvil <jan.kratochvil@redhat.com>
+ Protect entry values against self tail calls.
+ * gdb.arch/amd64-entry-value.cc (self2, self): New.
+ (main): Call self.
+ * gdb.arch/amd64-entry-value.exp (self: breakhere, self: bt)
+ (set debug entry-values 1, self: bt debug entry-values): New tests.
+
+2011-10-09 Jan Kratochvil <jan.kratochvil@redhat.com>
+
Recognize virtual tail call frames.
* gdb.arch/amd64-entry-value.cc (c, a, b, amb_z, amb_y, amb_x, amb)
(amb_b, amb_a): New.
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value.cc b/gdb/testsuite/gdb.arch/amd64-entry-value.cc
index 9e09c8a..44b7564 100644
--- a/gdb/testsuite/gdb.arch/amd64-entry-value.cc
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value.cc
@@ -91,6 +91,29 @@ amb_a (int i)
amb_b (i + 1);
}
+static void __attribute__((noinline, noclone)) self (int i);
+
+static void __attribute__((noinline, noclone))
+self2 (int i)
+{
+ self (i);
+}
+
+static void __attribute__((noinline, noclone))
+self (int i)
+{
+ if (i == 200)
+ {
+ /* GCC would inline `self' as `cmovne' without the `self2' indirect. */
+ self2 (i + 1);
+ }
+ else
+ {
+ e (v, v);
+ d (i + 2, i + 2.5);
+ }
+}
+
int
main ()
{
@@ -100,5 +123,6 @@ main ()
else
b (5, 5.25);
amb_a (100);
+ self (200);
return 0;
}
diff --git a/gdb/testsuite/gdb.arch/amd64-entry-value.exp b/gdb/testsuite/gdb.arch/amd64-entry-value.exp
index 6abc7ab..fdf8040 100644
--- a/gdb/testsuite/gdb.arch/amd64-entry-value.exp
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value.exp
@@ -73,3 +73,16 @@ gdb_continue_to_breakpoint "ambiguous: breakhere"
gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>, j=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in amb_z \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in amb_y \\(i=<optimized out>\\)\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in amb_x \\(i=<optimized out>\\)\[^\r\n\]*\r\n#4 +0x\[0-9a-f\]+ in amb_b \\(i=101\\)\[^\r\n\]*\r\n#5 +0x\[0-9a-f\]+ in amb_a \\(i=100\\)\[^\r\n\]*\r\n#6 +0x\[0-9a-f\]+ in main \\(\\)\[^\r\n\]*" \
"ambiguous: bt"
+
+
+# Test self tail calls verification.
+# GDB should not print the real value as it is ambiguous.
+
+gdb_continue_to_breakpoint "self: breakhere"
+
+gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>, j=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in self \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in main \\(\\)\[^\r\n\]*" \
+ "self: bt"
+
+gdb_test_no_output "set debug entry-values 1"
+gdb_test "bt" "DW_OP_GNU_entry_value resolving has found function \"self\\(int\\)\" at 0x\[0-9a-f\]+ can call itself via tail calls\r\n.*" \
+ "self: bt debug entry-values"