From 48cf710500f7b60bee2ee3d9962438462daaefd0 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 20 Mar 2011 21:44:20 +0100 Subject: [PATCH] Rebase to FSF GDB 7.2.50.20110320 (which is a 7.3 pre-release). Merge archer-sergiodj-stap, the SystemTap probes breakpoints feature. [stap] Fix -O2 warnings. Fix Ada support crash on uninitialized gdbarch. --- .gitignore | 2 +- gdb-6.3-bz202689-exec-from-pthread-test.patch | 2 +- gdb-6.3-inferior-notification-20050721.patch | 16 +- gdb-6.3-test-pie-20050107.patch | 60 +- gdb-6.6-buildid-locate-rpm.patch | 94 +- gdb-6.6-buildid-locate.patch | 106 +- gdb-6.6-bz235197-fork-detach-info.patch | 18 +- gdb-6.8-bz254229-gcore-prpsinfo.patch | 38 +- gdb-6.8-bz442765-threaded-exec-test.patch | 2 +- gdb-ada-gdbarch-crash.patch | 49 + gdb-archer-pie-addons-keep-disabled.patch | 30 +- gdb-archer.patch | 5003 +++++++++++++++-- gdb-physname-pr11734-1of2.patch | 619 -- gdb-physname-pr11734-2of2.patch | 18 - gdb-physname-pr12273.patch | 207 - gdb-python-newbacktrace.patch | 153 - gdb-stap-warnings.patch | 59 + gdb-upstream.patch | 66 - gdb.spec | 35 +- sources | 2 +- 20 files changed, 4769 insertions(+), 1810 deletions(-) create mode 100644 gdb-ada-gdbarch-crash.patch delete mode 100644 gdb-physname-pr11734-1of2.patch delete mode 100644 gdb-physname-pr11734-2of2.patch delete mode 100644 gdb-physname-pr12273.patch delete mode 100644 gdb-python-newbacktrace.patch create mode 100755 gdb-stap-warnings.patch delete mode 100644 gdb-upstream.patch diff --git a/.gitignore b/.gitignore index ae274c5..a5eda3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ /libstdc++-v3-python-r155978.tar.bz2 -/gdb-7.2.50.20110305.tar.bz2 +/gdb-7.2.50.20110320.tar.bz2 diff --git a/gdb-6.3-bz202689-exec-from-pthread-test.patch b/gdb-6.3-bz202689-exec-from-pthread-test.patch index 1d9c61b..91dc69a 100644 --- a/gdb-6.3-bz202689-exec-from-pthread-test.patch +++ b/gdb-6.3-bz202689-exec-from-pthread-test.patch @@ -92,7 +92,7 @@ +gdb_run_cmd + +gdb_test_multiple {} "Program exited" { -+ -re "\r\nProgram exited normally.\r\n$gdb_prompt $" { ++ -re "\r\n\\\[Inferior .* exited normally\\\]\r\n$gdb_prompt $" { + pass "Program exited" + } +} diff --git a/gdb-6.3-inferior-notification-20050721.patch b/gdb-6.3-inferior-notification-20050721.patch index a789b1b..0eb397c 100644 --- a/gdb-6.3-inferior-notification-20050721.patch +++ b/gdb-6.3-inferior-notification-20050721.patch @@ -9,10 +9,10 @@ * gdb.base/attach-32.exp: Fix forgotten $GDBFLAGS as set. -Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.base/attach-32.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.c 2008-12-07 10:06:03.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.base/attach-32.c 2011-03-20 20:15:57.000000000 +0100 @@ -0,0 +1,20 @@ +/* This program is intended to be started outside of gdb, and then + attached to by gdb. Thus, it simply spins in a loop. The loop @@ -34,10 +34,10 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.c + } + return 0; +} -Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.base/attach-32.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp 2008-12-07 10:08:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.base/attach-32.exp 2011-03-20 20:20:03.000000000 +0100 @@ -0,0 +1,245 @@ +# Copyright 2005 Free Software Foundation, Inc. + @@ -153,7 +153,7 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp + + # Allow the test process to exit, to cleanup after ourselves. + -+ gdb_test "continue" "Program exited normally." "after attach-32, exit" ++ gdb_test "continue" {\[Inferior .* exited normally\]} "after attach-32, exit" + + # Make sure we don't leave a process around to confuse + # the next test run (and prevent the compile by keeping @@ -234,7 +234,7 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp + # Get rid of the process + + gdb_test "p should_exit = 1" -+ gdb_test "c" "Program exited normally." ++ gdb_test "c" {\[Inferior .* exited normally\]} + + # Be paranoid + @@ -284,10 +284,10 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32.exp +do_call_attach_tests + +return 0 -Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32b.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.base/attach-32b.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.base/attach-32b.c 2008-12-07 10:06:03.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.base/attach-32b.c 2011-03-20 20:15:57.000000000 +0100 @@ -0,0 +1,24 @@ +/* This program is intended to be started outside of gdb, and then + attached to by gdb. Thus, it simply spins in a loop. The loop diff --git a/gdb-6.3-test-pie-20050107.patch b/gdb-6.3-test-pie-20050107.patch index 9828afa..0b4a2db 100644 --- a/gdb-6.3-test-pie-20050107.patch +++ b/gdb-6.3-test-pie-20050107.patch @@ -1,7 +1,7 @@ -Index: gdb-7.2.50.20110305/gdb/testsuite/configure.ac +Index: gdb-7.2.50.20110320/gdb/testsuite/configure.ac =================================================================== ---- gdb-7.2.50.20110305.orig/gdb/testsuite/configure.ac 2011-03-03 17:57:55.000000000 +0100 -+++ gdb-7.2.50.20110305/gdb/testsuite/configure.ac 2011-03-05 08:26:53.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/testsuite/configure.ac 2011-03-03 17:57:55.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/configure.ac 2011-03-20 20:21:43.000000000 +0100 @@ -97,6 +97,6 @@ AC_OUTPUT([Makefile \ gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile \ gdb.hp/gdb.defects/Makefile \ @@ -10,10 +10,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/configure.ac + gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.pie/Makefile \ gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile \ gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile]) -Index: gdb-7.2.50.20110305/gdb/testsuite/configure +Index: gdb-7.2.50.20110320/gdb/testsuite/configure =================================================================== ---- gdb-7.2.50.20110305.orig/gdb/testsuite/configure 2011-03-03 17:57:55.000000000 +0100 -+++ gdb-7.2.50.20110305/gdb/testsuite/configure 2011-03-05 08:26:58.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/testsuite/configure 2011-03-03 17:57:55.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/configure 2011-03-20 20:21:43.000000000 +0100 @@ -3448,7 +3448,7 @@ done @@ -31,10 +31,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/configure "gdb.python/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.python/Makefile" ;; "gdb.reverse/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.reverse/Makefile" ;; "gdb.stabs/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.stabs/Makefile" ;; -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/attach.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.c 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/attach.c 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,20 @@ +/* This program is intended to be started outside of gdb, and then + attached to by gdb. Thus, it simply spins in a loop. The loop @@ -56,10 +56,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.c + } + return 0; +} -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach2.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/attach2.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach2.c 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/attach2.c 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,24 @@ +/* This program is intended to be started outside of gdb, and then + attached to by gdb. Thus, it simply spins in a loop. The loop @@ -85,10 +85,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach2.c + } + return (0); +} -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/break.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break.c 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/break.c 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,146 @@ +/* This testcase is part of GDB, the GNU debugger. + @@ -236,10 +236,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break.c + } + return 0; +} -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break1.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/break1.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break1.c 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/break1.c 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,44 @@ +/* This testcase is part of GDB, the GNU debugger. + @@ -285,10 +285,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break1.c +void marker3 (a, b) char *a, *b; {} /* set breakpoint 18 here */ +void marker4 (d) long d; {} /* set breakpoint 13 here */ +#endif -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/coremaker.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/coremaker.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/coremaker.c 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/coremaker.c 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,142 @@ +/* Copyright 1992, 1993, 1994, 1995, 1996, 1999 + Free Software Foundation, Inc. @@ -432,11 +432,11 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/coremaker.c + return 0; +} + -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/attach.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.exp 2011-03-05 08:26:28.000000000 +0100 -@@ -0,0 +1,423 @@ ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/attach.exp 2011-03-20 20:25:53.000000000 +0100 +@@ -0,0 +1,417 @@ +# Copyright 1997, 1999, 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify @@ -699,13 +699,7 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.exp + + # Allow the test process to exit, to cleanup after ourselves. + # -+ send_gdb "continue\n" -+ gdb_expect { -+ -re "Program exited normally.*$gdb_prompt $"\ -+ {pass "after attach2, exit"} -+ -re "$gdb_prompt $" {fail "after attach2, exit"} -+ timeout {fail "(timeout) after attach2, exit"} -+ } ++ gdb_test "continue" {\[Inferior .* exited normally\]} "after attach2, exit" + + # Make sure we don't leave a process around to confuse + # the next test run (and prevent the compile by keeping @@ -831,7 +825,7 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.exp + # Get rid of the process + # + gdb_test "p should_exit = 1" ".*" -+ gdb_test "c" ".*Program exited normally.*" ++ gdb_test "c" {\[Inferior .* exited normally\]} + + # Be paranoid + # @@ -860,10 +854,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/attach.exp +do_call_attach_tests + +return 0 -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/break.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break.exp 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/break.exp 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,966 @@ +# Copyright 1988, 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2002, 2003, 2004 @@ -1831,10 +1825,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/break.exp + send_gdb "set args main\n" + gdb_expect -re ".*$gdb_prompt $" {} +} -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/corefile.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/corefile.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/corefile.exp 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/corefile.exp 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,233 @@ +# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. @@ -2069,10 +2063,10 @@ Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/corefile.exp +gdb_test "up" "#\[0-9\]* *\[0-9xa-fH'\]* in .* \\(.*\\).*" "up in corefile.exp (reinit)" + +gdb_test "core" "No core file now." -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/Makefile.in +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/Makefile.in =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.pie/Makefile.in 2011-03-05 08:26:28.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.pie/Makefile.in 2011-03-20 20:21:43.000000000 +0100 @@ -0,0 +1,19 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ diff --git a/gdb-6.6-buildid-locate-rpm.patch b/gdb-6.6-buildid-locate-rpm.patch index 038aa84..2ffade1 100644 --- a/gdb-6.6-buildid-locate-rpm.patch +++ b/gdb-6.6-buildid-locate-rpm.patch @@ -1,7 +1,7 @@ -Index: gdb-7.2.50.20110213/gdb/event-top.c +Index: gdb-7.2.50.20110320/gdb/event-top.c =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/event-top.c 2011-01-01 16:33:03.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/event-top.c 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/event-top.c 2011-03-16 16:18:58.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/event-top.c 2011-03-20 15:22:51.000000000 +0100 @@ -33,6 +33,7 @@ #include "cli/cli-script.h" /* for reset_command_nest_depth */ #include "main.h" @@ -28,11 +28,11 @@ Index: gdb-7.2.50.20110213/gdb/event-top.c /* Each interpreter has its own rules on displaying the command prompt. */ if (!current_interp_display_prompt_p ()) -Index: gdb-7.2.50.20110213/gdb/elfread.c +Index: gdb-7.2.50.20110320/gdb/elfread.c =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/elfread.c 2011-02-13 19:21:44.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/elfread.c 2011-02-13 19:21:49.000000000 +0100 -@@ -42,6 +42,7 @@ +--- gdb-7.2.50.20110320.orig/gdb/elfread.c 2011-03-20 15:22:34.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/elfread.c 2011-03-20 15:22:51.000000000 +0100 +@@ -49,6 +49,7 @@ #include "gdbcore.h" #include "gdbcmd.h" #include "observer.h" @@ -40,7 +40,7 @@ Index: gdb-7.2.50.20110213/gdb/elfread.c extern void _initialize_elfread (void); -@@ -1374,8 +1375,361 @@ build_id_to_filename (struct build_id *b +@@ -1623,8 +1624,361 @@ build_id_to_filename (struct build_id *b return retval; } @@ -403,7 +403,7 @@ Index: gdb-7.2.50.20110213/gdb/elfread.c avoidance. */ struct missing_filepair -@@ -1429,11 +1783,17 @@ missing_filepair_change (void) +@@ -1678,11 +2032,17 @@ missing_filepair_change (void) /* All their memory came just from missing_filepair_OBSTACK. */ missing_filepair_hash = NULL; } @@ -421,7 +421,7 @@ Index: gdb-7.2.50.20110213/gdb/elfread.c missing_filepair_change (); } -@@ -1500,14 +1860,35 @@ debug_print_missing (const char *binary, +@@ -1749,14 +2109,35 @@ debug_print_missing (const char *binary, *slot = missing_filepair; @@ -464,11 +464,11 @@ Index: gdb-7.2.50.20110213/gdb/elfread.c } static char * -Index: gdb-7.2.50.20110213/gdb/symfile.h +Index: gdb-7.2.50.20110320/gdb/symfile.h =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/symfile.h 2011-02-13 19:21:44.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/symfile.h 2011-02-13 19:21:49.000000000 +0100 -@@ -560,6 +560,8 @@ extern struct build_id *build_id_addr_ge +--- gdb-7.2.50.20110320.orig/gdb/symfile.h 2011-03-20 15:19:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/symfile.h 2011-03-20 15:22:51.000000000 +0100 +@@ -617,6 +617,8 @@ extern struct build_id *build_id_addr_ge extern char *build_id_to_filename (struct build_id *build_id, char **link_return, int add_debug_suffix); extern void debug_print_missing (const char *binary, const char *debug); @@ -477,11 +477,11 @@ Index: gdb-7.2.50.20110213/gdb/symfile.h /* From dwarf2read.c */ -Index: gdb-7.2.50.20110213/gdb/testsuite/lib/gdb.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/lib/gdb.exp =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/testsuite/lib/gdb.exp 2011-02-13 19:21:44.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/testsuite/lib/gdb.exp 2011-02-13 19:21:49.000000000 +0100 -@@ -1395,7 +1395,7 @@ proc default_gdb_start { } { +--- gdb-7.2.50.20110320.orig/gdb/testsuite/lib/gdb.exp 2011-03-20 15:19:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/lib/gdb.exp 2011-03-20 15:22:51.000000000 +0100 +@@ -1397,7 +1397,7 @@ proc default_gdb_start { } { warning "Couldn't set the width to 0." } } @@ -490,10 +490,10 @@ Index: gdb-7.2.50.20110213/gdb/testsuite/lib/gdb.exp send_gdb "set build-id-verbose 0\n" gdb_expect 10 { -re "$gdb_prompt $" { -Index: gdb-7.2.50.20110213/gdb/testsuite/lib/mi-support.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/lib/mi-support.exp =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/testsuite/lib/mi-support.exp 2011-02-13 19:21:44.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/testsuite/lib/mi-support.exp 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/testsuite/lib/mi-support.exp 2011-03-20 15:19:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/lib/mi-support.exp 2011-03-20 15:22:51.000000000 +0100 @@ -221,7 +221,7 @@ proc default_mi_gdb_start { args } { } } @@ -503,10 +503,10 @@ Index: gdb-7.2.50.20110213/gdb/testsuite/lib/mi-support.exp send_gdb "190-gdb-set build-id-verbose 0\n" gdb_expect 10 { -re ".*190-gdb-set build-id-verbose 0\r\n190\\\^done\r\n$mi_gdb_prompt$" { -Index: gdb-7.2.50.20110213/gdb/tui/tui-interp.c +Index: gdb-7.2.50.20110320/gdb/tui/tui-interp.c =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/tui/tui-interp.c 2011-01-01 16:33:52.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/tui/tui-interp.c 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/tui/tui-interp.c 2011-01-01 16:33:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/tui/tui-interp.c 2011-03-20 15:22:51.000000000 +0100 @@ -31,6 +31,7 @@ #include "tui/tui.h" #include "tui/tui-io.h" @@ -524,10 +524,10 @@ Index: gdb-7.2.50.20110213/gdb/tui/tui-interp.c /* Tell readline what the prompt to display is and what function it will need to call after a whole line is read. This also displays the first prompt. */ -Index: gdb-7.2.50.20110213/gdb/aclocal.m4 +Index: gdb-7.2.50.20110320/gdb/aclocal.m4 =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/aclocal.m4 2010-05-23 02:56:59.000000000 +0200 -+++ gdb-7.2.50.20110213/gdb/aclocal.m4 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/aclocal.m4 2011-02-15 22:05:53.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/aclocal.m4 2011-03-20 15:22:51.000000000 +0100 @@ -19,6 +19,162 @@ You have another version of autoconf. I If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) @@ -691,10 +691,10 @@ Index: gdb-7.2.50.20110213/gdb/aclocal.m4 # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation -Index: gdb-7.2.50.20110213/gdb/config.in +Index: gdb-7.2.50.20110320/gdb/config.in =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/config.in 2011-01-14 14:38:23.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/config.in 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/config.in 2011-03-17 14:19:09.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/config.in 2011-03-20 15:22:51.000000000 +0100 @@ -46,6 +46,9 @@ /* Define to BFD's default target vector. */ #undef DEFAULT_BFD_VEC @@ -705,7 +705,7 @@ Index: gdb-7.2.50.20110213/gdb/config.in /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS -@@ -229,6 +232,9 @@ +@@ -233,6 +236,9 @@ /* Define if Python 2.7 is being used. */ #undef HAVE_LIBPYTHON2_7 @@ -715,10 +715,10 @@ Index: gdb-7.2.50.20110213/gdb/config.in /* Define if libunwind library is being used. */ #undef HAVE_LIBUNWIND -Index: gdb-7.2.50.20110213/gdb/configure +Index: gdb-7.2.50.20110320/gdb/configure =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/configure 2011-02-11 10:57:24.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/configure 2011-02-13 19:22:37.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/configure 2011-03-17 14:19:09.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/configure 2011-03-20 15:23:29.000000000 +0100 @@ -682,6 +682,9 @@ REPORT_BUGS_TO PKGVERSION TARGET_OBS @@ -747,7 +747,7 @@ Index: gdb-7.2.50.20110213/gdb/configure YACC YFLAGS XMKMF' -@@ -1653,6 +1660,8 @@ Optional Packages: +@@ -1652,6 +1659,8 @@ Optional Packages: [DATADIR/gdb] --with-relocated-sources=PATH automatically relocate this path for source files @@ -756,7 +756,7 @@ Index: gdb-7.2.50.20110213/gdb/configure --with-libunwind use libunwind frame unwinding support --with-curses use the curses library instead of the termcap library -@@ -1688,6 +1697,9 @@ Some influential environment variables: +@@ -1687,6 +1696,9 @@ Some influential environment variables: CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor @@ -766,7 +766,7 @@ Index: gdb-7.2.50.20110213/gdb/configure YACC The `Yet Another C Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. -@@ -7885,6 +7897,486 @@ _ACEOF +@@ -7884,6 +7896,486 @@ _ACEOF fi @@ -1253,10 +1253,10 @@ Index: gdb-7.2.50.20110213/gdb/configure subdirs="$subdirs testsuite" -Index: gdb-7.2.50.20110213/gdb/configure.ac +Index: gdb-7.2.50.20110320/gdb/configure.ac =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/configure.ac 2011-02-11 10:57:25.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/configure.ac 2011-02-13 19:22:30.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/configure.ac 2011-03-17 14:19:10.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/configure.ac 2011-03-20 15:23:17.000000000 +0100 @@ -108,6 +108,199 @@ AS_HELP_STRING([--with-relocated-sources [Relocated directory for source files. ]) ]) @@ -1455,12 +1455,12 @@ Index: gdb-7.2.50.20110213/gdb/configure.ac +fi + AC_CONFIG_SUBDIRS(testsuite) - AC_CONFIG_SUBDIRS(common) -Index: gdb-7.2.50.20110213/gdb/acinclude.m4 + # Check whether to support alternative target configurations +Index: gdb-7.2.50.20110320/gdb/acinclude.m4 =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/acinclude.m4 2010-05-27 05:40:45.000000000 +0200 -+++ gdb-7.2.50.20110213/gdb/acinclude.m4 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/acinclude.m4 2010-05-27 05:40:45.000000000 +0200 ++++ gdb-7.2.50.20110320/gdb/acinclude.m4 2011-03-20 15:22:51.000000000 +0100 @@ -1,3 +1,5 @@ +# serial 1 + @@ -1476,10 +1476,10 @@ Index: gdb-7.2.50.20110213/gdb/acinclude.m4 # @defmac AC_PROG_CC_STDC # @maindex PROG_CC_STDC # @ovindex CC -Index: gdb-7.2.50.20110213/gdb/corelow.c +Index: gdb-7.2.50.20110320/gdb/corelow.c =================================================================== ---- gdb-7.2.50.20110213.orig/gdb/corelow.c 2011-02-13 19:21:44.000000000 +0100 -+++ gdb-7.2.50.20110213/gdb/corelow.c 2011-02-13 19:21:49.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/corelow.c 2011-03-20 15:19:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/corelow.c 2011-03-20 15:22:51.000000000 +0100 @@ -320,7 +320,7 @@ build_id_locate_exec (int from_tty) symfile_objfile->flags |= OBJF_BUILD_ID_CORE_LOADED; } diff --git a/gdb-6.6-buildid-locate.patch b/gdb-6.6-buildid-locate.patch index 3d8e5de..720bf21 100644 --- a/gdb-6.6-buildid-locate.patch +++ b/gdb-6.6-buildid-locate.patch @@ -1,7 +1,7 @@ -Index: gdb-7.2.50.20110117/gdb/corelow.c +Index: gdb-7.2.50.20110320/gdb/corelow.c =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/corelow.c 2011-01-05 23:22:47.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/corelow.c 2011-01-17 15:52:06.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/corelow.c 2011-02-26 03:07:07.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/corelow.c 2011-03-20 15:19:52.000000000 +0100 @@ -47,6 +47,9 @@ #include "filenames.h" #include "progspace.h" @@ -90,11 +90,11 @@ Index: gdb-7.2.50.20110117/gdb/corelow.c + NULL, NULL, NULL, + &setlist, &showlist); } -Index: gdb-7.2.50.20110117/gdb/doc/gdb.texinfo +Index: gdb-7.2.50.20110320/gdb/doc/gdb.texinfo =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/doc/gdb.texinfo 2011-01-17 15:50:41.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/doc/gdb.texinfo 2011-01-17 15:52:06.000000000 +0100 -@@ -15220,6 +15220,27 @@ information files. +--- gdb-7.2.50.20110320.orig/gdb/doc/gdb.texinfo 2011-03-20 15:17:44.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/doc/gdb.texinfo 2011-03-20 15:19:52.000000000 +0100 +@@ -15343,6 +15343,27 @@ information files. @end table @@ -122,10 +122,10 @@ Index: gdb-7.2.50.20110117/gdb/doc/gdb.texinfo @cindex @code{.gnu_debuglink} sections @cindex debug link sections A debug link is a special section of the executable file named -Index: gdb-7.2.50.20110117/gdb/solib-svr4.c +Index: gdb-7.2.50.20110320/gdb/solib-svr4.c =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/solib-svr4.c 2011-01-17 15:47:37.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/solib-svr4.c 2011-01-17 15:52:06.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/solib-svr4.c 2011-03-20 15:17:43.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/solib-svr4.c 2011-03-20 15:19:52.000000000 +0100 @@ -1179,9 +1179,49 @@ svr4_current_sos (void) safe_strerror (errcode)); else @@ -179,13 +179,13 @@ Index: gdb-7.2.50.20110117/gdb/solib-svr4.c } xfree (buffer); -Index: gdb-7.2.50.20110117/gdb/elfread.c +Index: gdb-7.2.50.20110320/gdb/elfread.c =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/elfread.c 2011-01-17 15:47:37.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/elfread.c 2011-01-17 15:52:06.000000000 +0100 -@@ -38,6 +38,10 @@ - #include "demangle.h" - #include "psympriv.h" +--- gdb-7.2.50.20110320.orig/gdb/elfread.c 2011-03-20 15:17:42.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/elfread.c 2011-03-20 15:22:34.000000000 +0100 +@@ -45,6 +45,10 @@ + #include "stap-probe.h" + #include "arch-utils.h" #include "gdbtypes.h" +#include "libbfd.h" +#include "gdbcore.h" @@ -194,8 +194,8 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c extern void _initialize_elfread (void); -@@ -823,16 +827,65 @@ resolve_gnu_ifunc (const char *function_ - return 0; +@@ -1072,16 +1076,65 @@ elf_gnu_ifunc_resolver_return_stop (stru + update_breakpoint_locations (b, sals); } +/* Locate NT_GNU_BUILD_ID and return its matching debug filename. @@ -262,7 +262,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c { struct build_id *retval; -@@ -848,6 +901,348 @@ build_id_bfd_get (bfd *abfd) +@@ -1097,6 +1150,348 @@ build_id_bfd_get (bfd *abfd) return retval; } @@ -611,7 +611,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c /* Return if FILENAME has NT_GNU_BUILD_ID matching the CHECK value. */ static int -@@ -862,7 +1257,7 @@ build_id_verify (const char *filename, s +@@ -1111,7 +1506,7 @@ build_id_verify (const char *filename, s if (abfd == NULL) return 0; @@ -620,7 +620,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c if (found == NULL) warning (_("File \"%s\" has no build-id, file skipped"), filename); -@@ -880,14 +1275,16 @@ build_id_verify (const char *filename, s +@@ -1129,14 +1524,16 @@ build_id_verify (const char *filename, s return retval; } @@ -641,7 +641,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will cause "/.build-id/..." lookups. */ -@@ -918,7 +1315,10 @@ build_id_to_debug_filename (struct build +@@ -1167,7 +1564,10 @@ build_id_to_debug_filename (struct build *s++ = '/'; while (size-- > 0) s += sprintf (s, "%02x", (unsigned) *data++); @@ -653,7 +653,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c /* lrealpath() is expensive even for the usually non-existent files. */ if (access (link, F_OK) == 0) -@@ -931,26 +1331,201 @@ build_id_to_debug_filename (struct build +@@ -1180,26 +1580,201 @@ build_id_to_debug_filename (struct build } if (retval != NULL) @@ -723,9 +723,9 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c + + retval = obstack_alloc (&missing_filepair_obstack, size); + memset (retval, 0, size); - return retval; - } - ++ return retval; ++} ++ +static hashval_t +missing_filepair_hash_func (const struct missing_filepair *elem) +{ @@ -735,9 +735,9 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c + if (elem->debug != NULL) + retval ^= htab_hash_string (elem->debug); + -+ return retval; -+} -+ + return retval; + } + +static int +missing_filepair_eq (const struct missing_filepair *elem1, + const struct missing_filepair *elem2) @@ -859,7 +859,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c xfree (build_id); /* Prevent looping on a stripped .debug file. */ if (build_id_name != NULL && strcmp (build_id_name, objfile->name) == 0) -@@ -960,7 +1535,7 @@ find_separate_debug_file_by_buildid (str +@@ -1209,7 +1784,7 @@ find_separate_debug_file_by_buildid (str xfree (build_id_name); } else if (build_id_name != NULL) @@ -868,9 +868,9 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c } return NULL; } -@@ -1148,9 +1723,10 @@ elf_symfile_read (struct objfile *objfil +@@ -1407,9 +1982,10 @@ elf_symfile_read (struct objfile *objfil `.note.gnu.build-id'. */ - if (!objfile_has_partial_symbols (objfile)) + else if (!objfile_has_partial_symbols (objfile)) { - char *debugfile; + char *debugfile, *build_id_filename; @@ -881,7 +881,7 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c if (debugfile == NULL) debugfile = find_separate_debug_file_by_debuglink (objfile); -@@ -1162,6 +1738,12 @@ elf_symfile_read (struct objfile *objfil +@@ -1421,6 +1997,12 @@ elf_symfile_read (struct objfile *objfil symbol_file_add_separate (abfd, symfile_flags, objfile); xfree (debugfile); } @@ -894,10 +894,10 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c } } -@@ -1337,4 +1919,16 @@ void - _initialize_elfread (void) - { - add_symtab_fns (&elf_sym_fns); +@@ -1879,4 +2461,16 @@ _initialize_elfread (void) + + elf_objfile_gnu_ifunc_cache_data = register_objfile_data (); + gnu_ifunc_fns_p = &elf_gnu_ifunc_fns; + + add_setshow_zinteger_cmd ("build-id-verbose", no_class, &build_id_verbose, + _("\ @@ -911,11 +911,11 @@ Index: gdb-7.2.50.20110117/gdb/elfread.c + + observer_attach_executable_changed (debug_print_executable_changed); } -Index: gdb-7.2.50.20110117/gdb/symfile.h +Index: gdb-7.2.50.20110320/gdb/symfile.h =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/symfile.h 2011-01-11 22:53:24.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/symfile.h 2011-01-17 15:52:06.000000000 +0100 -@@ -554,6 +554,13 @@ void free_symfile_segment_data (struct s +--- gdb-7.2.50.20110320.orig/gdb/symfile.h 2011-03-20 15:17:43.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/symfile.h 2011-03-20 15:19:52.000000000 +0100 +@@ -611,6 +611,13 @@ void free_symfile_segment_data (struct s extern struct cleanup *increment_reading_symtab (void); @@ -929,11 +929,11 @@ Index: gdb-7.2.50.20110117/gdb/symfile.h /* From dwarf2read.c */ extern int dwarf2_has_info (struct objfile *); -Index: gdb-7.2.50.20110117/gdb/testsuite/lib/gdb.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/lib/gdb.exp =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/testsuite/lib/gdb.exp 2011-01-17 15:47:37.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/testsuite/lib/gdb.exp 2011-01-17 15:52:06.000000000 +0100 -@@ -1395,6 +1395,16 @@ proc default_gdb_start { } { +--- gdb-7.2.50.20110320.orig/gdb/testsuite/lib/gdb.exp 2011-03-20 15:17:43.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/lib/gdb.exp 2011-03-20 15:19:52.000000000 +0100 +@@ -1397,6 +1397,16 @@ proc default_gdb_start { } { warning "Couldn't set the width to 0." } } @@ -950,10 +950,10 @@ Index: gdb-7.2.50.20110117/gdb/testsuite/lib/gdb.exp return 0; } -Index: gdb-7.2.50.20110117/gdb/testsuite/lib/mi-support.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/lib/mi-support.exp =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/testsuite/lib/mi-support.exp 2011-01-01 16:33:52.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/testsuite/lib/mi-support.exp 2011-01-17 15:52:06.000000000 +0100 +--- gdb-7.2.50.20110320.orig/gdb/testsuite/lib/mi-support.exp 2011-03-07 17:03:04.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/lib/mi-support.exp 2011-03-20 15:19:52.000000000 +0100 @@ -221,6 +221,16 @@ proc default_mi_gdb_start { args } { } } @@ -971,13 +971,13 @@ Index: gdb-7.2.50.20110117/gdb/testsuite/lib/mi-support.exp detect_async -Index: gdb-7.2.50.20110117/gdb/objfiles.h +Index: gdb-7.2.50.20110320/gdb/objfiles.h =================================================================== ---- gdb-7.2.50.20110117.orig/gdb/objfiles.h 2011-01-10 21:38:49.000000000 +0100 -+++ gdb-7.2.50.20110117/gdb/objfiles.h 2011-01-17 15:52:26.000000000 +0100 -@@ -434,6 +434,10 @@ struct objfile +--- gdb-7.2.50.20110320.orig/gdb/objfiles.h 2011-03-07 17:17:29.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/objfiles.h 2011-03-20 15:20:29.000000000 +0100 +@@ -441,6 +441,10 @@ struct objfile - #define OBJF_USERLOADED (1 << 3) /* User loaded */ + #define OBJF_PSYMTABS_READ (1 << 4) +/* This file was loaded according to the BUILD_ID_CORE_LOADS rules. */ + diff --git a/gdb-6.6-bz235197-fork-detach-info.patch b/gdb-6.6-bz235197-fork-detach-info.patch index 64bc686..d7263ff 100644 --- a/gdb-6.6-bz235197-fork-detach-info.patch +++ b/gdb-6.6-bz235197-fork-detach-info.patch @@ -3,11 +3,11 @@ Port to GDB-6.8pre. Remove the `[' character from the GDB-6.8 default message. -Index: gdb-7.0.50.20100115/gdb/linux-nat.c +Index: gdb-7.2.50.20110320/gdb/linux-nat.c =================================================================== ---- gdb-7.0.50.20100115.orig/gdb/linux-nat.c 2010-01-15 03:22:31.000000000 +0100 -+++ gdb-7.0.50.20100115/gdb/linux-nat.c 2010-01-15 03:23:28.000000000 +0100 -@@ -724,7 +724,7 @@ holding the child stopped. Try \"set de +--- gdb-7.2.50.20110320.orig/gdb/linux-nat.c 2011-03-20 16:59:51.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/linux-nat.c 2011-03-20 16:59:51.000000000 +0100 +@@ -716,7 +716,7 @@ holding the child stopped. Try \"set de remove_breakpoints_pid (GET_PID (inferior_ptid)); } @@ -16,10 +16,10 @@ Index: gdb-7.0.50.20100115/gdb/linux-nat.c { target_terminal_ours (); fprintf_filtered (gdb_stdlog, -Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.base/fork-detach.c +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.base/fork-detach.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.base/fork-detach.c 2010-01-15 03:22:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.base/fork-detach.c 2011-03-20 16:59:51.000000000 +0100 @@ -0,0 +1,57 @@ +/* This testcase is part of GDB, the GNU debugger. + @@ -78,10 +78,10 @@ Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.base/fork-detach.c + } + return 0; +} -Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.base/fork-detach.exp +Index: gdb-7.2.50.20110320/gdb/testsuite/gdb.base/fork-detach.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.base/fork-detach.exp 2010-01-15 03:22:52.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/testsuite/gdb.base/fork-detach.exp 2011-03-20 17:12:22.000000000 +0100 @@ -0,0 +1,36 @@ +# Copyright 2007 Free Software Foundation, Inc. + @@ -117,5 +117,5 @@ Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.base/fork-detach.exp +gdb_run_cmd +# `Starting program: .*' prefix is available since gdb-6.7. +gdb_test "" \ -+ "Detaching after fork from child process.*Program exited normally\\..*" \ ++ "Detaching after fork from child process.*\\\[Inferior .* exited normally\\\]" \ + "Info message caught" diff --git a/gdb-6.8-bz254229-gcore-prpsinfo.patch b/gdb-6.8-bz254229-gcore-prpsinfo.patch index 216a95d..b5eb514 100644 --- a/gdb-6.8-bz254229-gcore-prpsinfo.patch +++ b/gdb-6.8-bz254229-gcore-prpsinfo.patch @@ -1,8 +1,8 @@ -Index: gdb-7.1.90.20100711/bfd/elf-bfd.h +Index: gdb-7.2.50.20110320/bfd/elf-bfd.h =================================================================== ---- gdb-7.1.90.20100711.orig/bfd/elf-bfd.h 2010-06-27 06:07:51.000000000 +0200 -+++ gdb-7.1.90.20100711/bfd/elf-bfd.h 2010-07-12 23:00:04.000000000 +0200 -@@ -2171,8 +2171,10 @@ extern Elf_Internal_Phdr * _bfd_elf_find +--- gdb-7.2.50.20110320.orig/bfd/elf-bfd.h 2011-03-20 15:17:42.000000000 +0100 ++++ gdb-7.2.50.20110320/bfd/elf-bfd.h 2011-03-20 15:24:02.000000000 +0100 +@@ -2193,8 +2193,10 @@ extern Elf_Internal_Phdr * _bfd_elf_find /* Exported interface for writing elf corefile notes. */ extern char *elfcore_write_note (bfd *, char *, int *, const char *, int, const void *, int); @@ -14,11 +14,11 @@ Index: gdb-7.1.90.20100711/bfd/elf-bfd.h extern char *elfcore_write_prstatus (bfd *, char *, int *, long, int, const void *); extern char * elfcore_write_pstatus -Index: gdb-7.1.90.20100711/bfd/elf.c +Index: gdb-7.2.50.20110320/bfd/elf.c =================================================================== ---- gdb-7.1.90.20100711.orig/bfd/elf.c 2010-05-18 05:31:05.000000000 +0200 -+++ gdb-7.1.90.20100711/bfd/elf.c 2010-07-12 22:51:17.000000000 +0200 -@@ -8582,13 +8582,12 @@ elfcore_write_note (bfd *abfd, +--- gdb-7.2.50.20110320.orig/bfd/elf.c 2011-03-20 15:17:42.000000000 +0100 ++++ gdb-7.2.50.20110320/bfd/elf.c 2011-03-20 15:24:02.000000000 +0100 +@@ -8814,13 +8814,12 @@ elfcore_write_note (bfd *abfd, return buf; } @@ -34,7 +34,7 @@ Index: gdb-7.1.90.20100711/bfd/elf.c { const char *note_name = "CORE"; const struct elf_backend_data *bed = get_elf_backend_data (abfd); -@@ -8596,48 +8595,55 @@ elfcore_write_prpsinfo (bfd *abfd, +@@ -8828,48 +8827,55 @@ elfcore_write_prpsinfo (bfd *abfd, if (bed->elf_backend_write_core_note != NULL) { char *ret; @@ -109,11 +109,11 @@ Index: gdb-7.1.90.20100711/bfd/elf.c #if defined (HAVE_PRSTATUS_T) char * -Index: gdb-7.1.90.20100711/gdb/linux-nat.c +Index: gdb-7.2.50.20110320/gdb/linux-nat.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/linux-nat.c 2010-07-12 23:05:22.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/linux-nat.c 2010-07-12 22:57:34.000000000 +0200 -@@ -4466,6 +4466,131 @@ linux_spu_make_corefile_notes (bfd *obfd +--- gdb-7.2.50.20110320.orig/gdb/linux-nat.c 2011-03-20 15:17:46.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/linux-nat.c 2011-03-20 15:25:36.000000000 +0100 +@@ -4603,6 +4603,131 @@ linux_spu_make_corefile_notes (bfd *obfd return args.note_data; } @@ -245,11 +245,11 @@ Index: gdb-7.1.90.20100711/gdb/linux-nat.c /* Fills the "to_make_corefile_note" target vector. Builds the note section for a corefile, and returns it in a malloc buffer. */ -@@ -4484,26 +4609,11 @@ linux_nat_make_corefile_notes (bfd *obfd +@@ -4621,26 +4746,11 @@ linux_nat_make_corefile_notes (bfd *obfd if (get_exec_file (0)) { -- strncpy (fname, strrchr (get_exec_file (0), '/') + 1, sizeof (fname)); +- strncpy (fname, lbasename (get_exec_file (0)), sizeof (fname)); - strncpy (psargs, get_exec_file (0), sizeof (psargs)); - if (get_inferior_args ()) - { @@ -275,11 +275,11 @@ Index: gdb-7.1.90.20100711/gdb/linux-nat.c } /* Dump information for threads. */ -Index: gdb-7.1.90.20100711/gdb/procfs.c +Index: gdb-7.2.50.20110320/gdb/procfs.c =================================================================== ---- gdb-7.1.90.20100711.orig/gdb/procfs.c 2010-07-07 18:15:16.000000000 +0200 -+++ gdb-7.1.90.20100711/gdb/procfs.c 2010-07-12 23:05:23.000000000 +0200 -@@ -5770,6 +5770,7 @@ procfs_make_note_section (bfd *obfd, int +--- gdb-7.2.50.20110320.orig/gdb/procfs.c 2011-03-09 13:48:55.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/procfs.c 2011-03-20 15:24:02.000000000 +0100 +@@ -5752,6 +5752,7 @@ procfs_make_note_section (bfd *obfd, int note_data = (char *) elfcore_write_prpsinfo (obfd, note_data, note_size, diff --git a/gdb-6.8-bz442765-threaded-exec-test.patch b/gdb-6.8-bz442765-threaded-exec-test.patch index 986894d..1006588 100644 --- a/gdb-6.8-bz442765-threaded-exec-test.patch +++ b/gdb-6.8-bz442765-threaded-exec-test.patch @@ -170,4 +170,4 @@ diff -up -u -X /root/jkratoch/.diffi.list -rup gdb-6.8/gdb/testsuite/gdb.threads +gdb_run_cmd ${binfile_nothreads} ${binfile_threads} 0 gdb_test_multiple {} "Program exited" { - -re "\r\nProgram exited normally.\r\n$gdb_prompt $" { + -re "\r\n\\\[Inferior .* exited normally\\\]\r\n$gdb_prompt $" { diff --git a/gdb-ada-gdbarch-crash.patch b/gdb-ada-gdbarch-crash.patch new file mode 100644 index 0000000..561fce1 --- /dev/null +++ b/gdb-ada-gdbarch-crash.patch @@ -0,0 +1,49 @@ +http://sourceware.org/ml/gdb-patches/2011-03/msg00946.html +Subject: [patch] ada: Fix rashes on gdbarch garbage + +Hi Joel, + +for gdb.ada/str_ref_cmp.exp on x86_64-fedora15-linux-gnu it turns: + +(gdb) print String_Var (1 .. 3) = "Hel" +ERROR: Process no longer exists +UNRESOLVED: gdb.ada/str_ref_cmp.exp: print String_Var (1 .. 3) = "Hel" +-> +(gdb) print String_Var (1 .. 3) = "Hel" +$1 = false +(gdb) FAIL: gdb.ada/str_ref_cmp.exp: print String_Var (1 .. 3) = "Hel" + +GDB crashes the former way without this fix on: + gcc-gnat-4.6.0-0.14.fc15.x86_64 + gcc-gnat-4.5.1-4.fc14.x86_64 + +I cannot test FSF gcc <=4.5 myself as its Ada build errors out for me on: + uintp.adb:242:22: expect type "Hnum" defined at line 91 + +GDB PASSes on these GNATs even without this fix but that is not the point: + GNAT 4.7.0 20110320 (experimental) + GNAT 4.6.0 20110320 (prerelease) + +This is only a suggestion, I do not know much about the ada-* code. + + +Thanks, +Jan + + +gdb/ +2011-03-20 Jan Kratochvil + + * ada-lang.c (replace_operator_with_call): Copy also GDBARCH. + +--- a/gdb/ada-lang.c ++++ b/gdb/ada-lang.c +@@ -3661,6 +3661,7 @@ replace_operator_with_call (struct expression **expp, int pc, int nargs, + + newexp->nelts = exp->nelts + 7 - oplen; + newexp->language_defn = exp->language_defn; ++ newexp->gdbarch = exp->gdbarch; + memcpy (newexp->elts, exp->elts, EXP_ELEM_TO_BYTES (pc)); + memcpy (newexp->elts + pc + 7, exp->elts + pc + oplen, + EXP_ELEM_TO_BYTES (exp->nelts - pc - oplen)); + diff --git a/gdb-archer-pie-addons-keep-disabled.patch b/gdb-archer-pie-addons-keep-disabled.patch index 81661ca..8d16e6a 100644 --- a/gdb-archer-pie-addons-keep-disabled.patch +++ b/gdb-archer-pie-addons-keep-disabled.patch @@ -1,8 +1,8 @@ -Index: gdb-7.2.50.20110222/gdb/breakpoint.c +Index: gdb-7.2.50.20110320/gdb/breakpoint.c =================================================================== ---- gdb-7.2.50.20110222.orig/gdb/breakpoint.c 2011-02-23 00:12:59.000000000 +0100 -+++ gdb-7.2.50.20110222/gdb/breakpoint.c 2011-02-23 00:13:04.000000000 +0100 -@@ -10547,6 +10547,50 @@ update_breakpoint_locations (struct brea +--- gdb-7.2.50.20110320.orig/gdb/breakpoint.c 2011-03-20 15:17:42.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/breakpoint.c 2011-03-20 15:28:48.000000000 +0100 +@@ -10678,6 +10678,50 @@ update_breakpoint_locations (struct brea update_global_location_list (1); } @@ -53,25 +53,25 @@ Index: gdb-7.2.50.20110222/gdb/breakpoint.c /* Reset a breakpoint given it's struct breakpoint * BINT. The value we return ends up being the return value from catch_errors. Unused in this case. */ -Index: gdb-7.2.50.20110222/gdb/breakpoint.h +Index: gdb-7.2.50.20110320/gdb/breakpoint.h =================================================================== ---- gdb-7.2.50.20110222.orig/gdb/breakpoint.h 2011-02-23 00:12:59.000000000 +0100 -+++ gdb-7.2.50.20110222/gdb/breakpoint.h 2011-02-23 00:13:16.000000000 +0100 -@@ -1192,4 +1192,7 @@ extern int user_breakpoint_p (struct bre +--- gdb-7.2.50.20110320.orig/gdb/breakpoint.h 2011-03-20 15:17:42.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/breakpoint.h 2011-03-20 15:29:33.000000000 +0100 +@@ -1210,4 +1210,7 @@ extern struct breakpoint *iterate_over_b - extern int get_number_or_range (char **pp); + extern int user_breakpoint_p (struct breakpoint *); +extern void breakpoints_relocate (struct objfile *objfile, + struct section_offsets *delta); + #endif /* !defined (BREAKPOINT_H) */ -Index: gdb-7.2.50.20110222/gdb/objfiles.c +Index: gdb-7.2.50.20110320/gdb/objfiles.c =================================================================== ---- gdb-7.2.50.20110222.orig/gdb/objfiles.c 2011-01-10 21:38:49.000000000 +0100 -+++ gdb-7.2.50.20110222/gdb/objfiles.c 2011-02-23 00:13:04.000000000 +0100 -@@ -846,6 +846,11 @@ objfile_relocate1 (struct objfile *objfi - obj_section_addr (s)); - } +--- gdb-7.2.50.20110320.orig/gdb/objfiles.c 2011-03-20 15:17:42.000000000 +0100 ++++ gdb-7.2.50.20110320/gdb/objfiles.c 2011-03-20 15:29:05.000000000 +0100 +@@ -851,6 +851,11 @@ objfile_relocate1 (struct objfile *objfi + objfile->sf->sym_probe_fns->sym_relocate_probe (objfile, + new_offsets, delta); + /* Final call of breakpoint_re_set can keep breakpoint locations disabled if + their addresses match. */ diff --git a/gdb-archer.patch b/gdb-archer.patch index 690b025..4b4a6a6 100644 --- a/gdb-archer.patch +++ b/gdb-archer.patch @@ -2,22 +2,116 @@ http://sourceware.org/gdb/wiki/ProjectArcher http://sourceware.org/gdb/wiki/ArcherBranchManagement GIT snapshot: -commit e802e1fb23d455d675dca0f4d7d6c8df18467719 +commit 6b2a0bf758263d22bf2b3bd2e02665cf0c24b0be branch `archer' - the merge of branches: archer-jankratochvil-vla archer-jankratochvil-watchpoint3 archer-jankratochvil-ifunc archer-tromey-python +archer-sergiodj-stap #TODO?:archer-tromey-optional-psymtab (cherry-picked from post-7.2 master) #TODO?:archer-tromey-threaded-dwarf +diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h +index 21ec38f..50c1272 100644 +--- a/bfd/elf-bfd.h ++++ b/bfd/elf-bfd.h +@@ -1476,6 +1476,13 @@ enum + Tag_compatibility = 32 + }; + ++struct sdt_note ++{ ++ struct sdt_note *next; ++ bfd_size_type size; ++ bfd_byte data[1]; ++}; ++ + /* Some private data is stashed away for future use using the tdata pointer + in the bfd structure. */ + +@@ -1633,6 +1640,8 @@ struct elf_obj_tdata + bfd_size_type build_id_size; + bfd_byte *build_id; + ++ struct sdt_note *sdt_note_head; ++ + /* True if the bfd contains symbols that have the STT_GNU_IFUNC + symbol type. Used to set the osabi field in the ELF header + structure. */ +diff --git a/bfd/elf.c b/bfd/elf.c +index f69abf2..3c038eb 100644 +--- a/bfd/elf.c ++++ b/bfd/elf.c +@@ -8416,6 +8416,37 @@ elfobj_grok_gnu_note (bfd *abfd, Elf_Internal_Note *note) + } + } + ++#define SDT_NOTE_TYPE 3 ++ ++static bfd_boolean ++elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note) ++{ ++ struct sdt_note *cur = ++ (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note) ++ + note->descsz); ++ ++ cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head; ++ cur->size = (bfd_size_type) note->descsz; ++ memcpy (cur->data, note->descdata, note->descsz); ++ ++ elf_tdata (abfd)->sdt_note_head = cur; ++ ++ return TRUE; ++} ++ ++static bfd_boolean ++elfobj_grok_stapsdt_note (bfd *abfd, Elf_Internal_Note *note) ++{ ++ switch (note->type) ++ { ++ case SDT_NOTE_TYPE: ++ return elfobj_grok_stapsdt_note_1 (abfd, note); ++ ++ default: ++ return TRUE; ++ } ++} ++ + static bfd_boolean + elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp) + { +@@ -9189,6 +9220,12 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset) + if (! elfobj_grok_gnu_note (abfd, &in)) + return FALSE; + } ++ else if (in.namesz == sizeof "stapsdt" ++ && strcmp (in.namedata, "stapsdt") == 0) ++ { ++ if (! elfobj_grok_stapsdt_note (abfd, &in)) ++ return FALSE; ++ } + break; + } + diff --git a/gdb/Makefile.in b/gdb/Makefile.in -index 00d624f..635acd3 100644 +index 489b1e9..c332b1b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in -@@ -808,7 +808,8 @@ annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ +@@ -716,8 +716,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ + sentinel-frame.c \ + serial.c ser-base.c ser-unix.c \ + solib.c solib-target.c source.c \ +- stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ +- symtab.c \ ++ stabsread.c stack.c stap-probe.c std-regs.c \ ++ symfile.c symfile-mem.c symmisc.c symtab.c \ + target.c target-descriptions.c target-memory.c \ + thread.c top.c tracepoint.c \ + trad-frame.c \ +@@ -801,7 +801,8 @@ annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \ gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h \ @@ -27,7 +121,16 @@ index 00d624f..635acd3 100644 # Header files that already have srcdir in them, or which are in objdir. -@@ -1317,6 +1318,12 @@ stamp-h: $(srcdir)/config.in config.status +@@ -886,7 +887,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ + prologue-value.o memory-map.o memrange.o xml-support.o xml-syscall.o \ + target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ + inferior.o osdata.o gdb_usleep.o record.o gcore.o \ +- jit.o progspace.o ++ jit.o progspace.o stap-probe.o + + TSOBS = inflow.o + +@@ -1307,6 +1308,12 @@ stamp-h: $(srcdir)/config.in config.status CONFIG_LINKS= \ $(SHELL) config.status @@ -40,11 +143,26 @@ index 00d624f..635acd3 100644 config.status: $(srcdir)/configure configure.tgt configure.host $(SHELL) config.status --recheck +diff --git a/gdb/NEWS b/gdb/NEWS +index feebf61..279a1c9 100644 +--- a/gdb/NEWS ++++ b/gdb/NEWS +@@ -36,6 +36,10 @@ + Initial support for the OpenCL C language (http://www.khronos.org/opencl) + has been integrated into GDB. + ++* GDB now has support for SystemTap probes. You can set a ++ breakpoint using the new "probe:" linespec and inspect the probe ++ arguments using the new $_probe_arg family of convenience variables. ++ + * Python scripting + + ** Parameters can now be be sub-classed in Python, and in particular diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c -index d0a1014..32537cb 100644 +index ed51ab0..6851810 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c -@@ -11389,6 +11389,7 @@ ada_operator_length (const struct expression *exp, int pc, int *oplenp, +@@ -11390,6 +11390,7 @@ ada_operator_length (const struct expression *exp, int pc, int *oplenp, static int ada_operator_check (struct expression *exp, int pos, @@ -52,7 +170,7 @@ index d0a1014..32537cb 100644 int (*objfile_func) (struct objfile *objfile, void *data), void *data) { -@@ -11403,12 +11404,15 @@ ada_operator_check (struct expression *exp, int pos, +@@ -11404,12 +11405,15 @@ ada_operator_check (struct expression *exp, int pos, break; default: @@ -292,6 +410,29 @@ index a869f85..c59daa0 100644 } +diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c +index d1736e1..3e54716 100644 +--- a/gdb/ax-gdb.c ++++ b/gdb/ax-gdb.c +@@ -2001,7 +2001,8 @@ gen_expr (struct expression *exp, union exp_element **pc, + + case OP_INTERNALVAR: + { +- const char *name = internalvar_name ((*pc)[1].internalvar); ++ struct internalvar *var = (*pc)[1].internalvar; ++ const char *name = internalvar_name (var); + struct trace_state_variable *tsv; + + (*pc) += 3; +@@ -2015,7 +2016,7 @@ gen_expr (struct expression *exp, union exp_element **pc, + value->kind = axs_rvalue; + value->type = builtin_type (exp->gdbarch)->builtin_long_long; + } +- else ++ else if (! compile_internalvar_to_ax (var, ax, value)) + error (_("$%s is not a trace state variable; GDB agent " + "expressions cannot use convenience variables."), name); + } diff --git a/gdb/block.c b/gdb/block.c index 776ae53..3544cf2 100644 --- a/gdb/block.c @@ -330,10 +471,10 @@ index 07d5bc7..fad89b1 100644 + #endif /* BLOCK_H */ diff --git a/gdb/blockframe.c b/gdb/blockframe.c -index b9aaf54..e1f3242 100644 +index 5bc5930..3b546a7 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c -@@ -160,6 +160,7 @@ static CORE_ADDR cache_pc_function_low = 0; +@@ -163,6 +163,7 @@ static CORE_ADDR cache_pc_function_low = 0; static CORE_ADDR cache_pc_function_high = 0; static char *cache_pc_function_name = 0; static struct obj_section *cache_pc_function_section = NULL; @@ -341,7 +482,7 @@ index b9aaf54..e1f3242 100644 /* Clear cache, e.g. when symbol table is discarded. */ -@@ -170,6 +171,7 @@ clear_pc_function_cache (void) +@@ -173,6 +174,7 @@ clear_pc_function_cache (void) cache_pc_function_high = 0; cache_pc_function_name = (char *) 0; cache_pc_function_section = NULL; @@ -349,16 +490,34 @@ index b9aaf54..e1f3242 100644 } /* Finds the "function" (text symbol) that is smaller than PC but -@@ -185,7 +187,7 @@ clear_pc_function_cache (void) +@@ -180,17 +182,19 @@ clear_pc_function_cache (void) + *NAME and/or *ADDRESS conditionally if that pointer is non-null. + If ENDADDR is non-null, then set *ENDADDR to be the end of the + function (exclusive), but passing ENDADDR as non-null means that +- the function might cause symbols to be read. This function either +- succeeds or fails (not halfway succeeds). If it succeeds, it sets +- *NAME, *ADDRESS, and *ENDADDR to real information and returns 1. +- If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero and +- returns 0. */ ++ the function might cause symbols to be read. If IS_GNU_IFUNC_P is provided ++ *IS_GNU_IFUNC_P is set to 1 on return if the function is STT_GNU_IFUNC. ++ This function either succeeds or fails (not halfway succeeds). If it ++ succeeds, it sets *NAME, *ADDRESS, and *ENDADDR to real information and ++ returns 1. If it fails, it sets *NAME, *ADDRESS, *ENDADDR and ++ *IS_GNU_IFUNC_P to zero and returns 0. */ /* Backward compatibility, no section argument. */ --int -+enum find_pc_partial_function_type - find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, - CORE_ADDR *endaddr) + int +-find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, +- CORE_ADDR *endaddr) ++find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, char **name, ++ CORE_ADDR *address, CORE_ADDR *endaddr, ++ int *is_gnu_ifunc_p) { -@@ -237,6 +239,7 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, + struct obj_section *section; + struct symbol *f; +@@ -240,6 +244,7 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f)); cache_pc_function_name = SYMBOL_LINKAGE_NAME (f); cache_pc_function_section = section; @@ -366,12 +525,13 @@ index b9aaf54..e1f3242 100644 goto return_cached_value; } } -@@ -259,12 +262,13 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, +@@ -262,12 +267,15 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, *address = 0; if (endaddr != NULL) *endaddr = 0; -- return 0; -+ return FIND_PC_PARTIAL_FUNCTION_NOT_FOUND; ++ if (is_gnu_ifunc_p != NULL) ++ *is_gnu_ifunc_p = 0; + return 0; } cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); @@ -381,29 +541,43 @@ index b9aaf54..e1f3242 100644 /* If the minimal symbol has a size, use it for the cache. Otherwise use the lesser of the next minimal symbol in the same -@@ -327,7 +331,8 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, +@@ -330,9 +338,22 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, *endaddr = cache_pc_function_high; } -- return 1; -+ return cache_pc_function_is_gnu_ifunc ? FIND_PC_PARTIAL_FUNCTION_GNU_IFUNC -+ : FIND_PC_PARTIAL_FUNCTION_NORMAL; ++ if (is_gnu_ifunc_p) ++ *is_gnu_ifunc_p = cache_pc_function_is_gnu_ifunc; ++ + return 1; } ++/* See find_pc_partial_function_gnu_ifunc, only the IS_GNU_IFUNC_P parameter ++ is omitted here for backward API compatibility. */ ++ ++int ++find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, ++ CORE_ADDR *endaddr) ++{ ++ return find_pc_partial_function_gnu_ifunc (pc, name, address, endaddr, NULL); ++} ++ /* Return the innermost stack frame executing inside of BLOCK, or NULL + if there is no such frame. If BLOCK is NULL, just return NULL. */ + diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c -index 5bcab87..529ea62 100644 +index c55e5c0..1a71cf8 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c -@@ -63,6 +63,7 @@ +@@ -62,6 +62,8 @@ + #include "jit.h" #include "xml-syscall.h" #include "parser-defs.h" ++#include "gdb_regex.h" ++#include "stap-probe.h" #include "cli/cli-utils.h" -+#include "regcache.h" /* readline include files */ - #include "readline/readline.h" -@@ -105,6 +106,9 @@ static void break_command_1 (char *, int, int); +@@ -106,6 +108,9 @@ static void break_command_1 (char *, int, int); static void mention (struct breakpoint *); @@ -413,21 +587,13 @@ index 5bcab87..529ea62 100644 /* This function is used in gdbtk sources and thus can not be made static. */ struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch, -@@ -218,6 +222,10 @@ static void disable_trace_command (char *, int); - - static void trace_pass_command (char *, int); - -+static void gnu_ifunc_resolver_stop (struct breakpoint *b); -+ -+static void gnu_ifunc_resolver_return_stop (struct breakpoint *b); -+ - /* Assuming we're creating a static tracepoint, does S look like a - static tracepoint marker spec ("-m MARKER_ID")? */ - #define is_marker_spec(s) \ -@@ -1149,6 +1157,22 @@ watchpoint_in_thread_scope (struct breakpoint *b) +@@ -1158,6 +1163,25 @@ watchpoint_in_thread_scope (struct breakpoint *b) && !is_executing (inferior_ptid))); } ++/* Set watchpoint B to disp_del_at_next_stop, even including its possible ++ associated bp_watchpoint_scope breakpoint. */ ++ +static void +watchpoint_del_at_next_stop (struct breakpoint *b) +{ @@ -447,7 +613,7 @@ index 5bcab87..529ea62 100644 /* Assuming that B is a watchpoint: - Reparse watchpoint expression, if REPARSE is non-zero - Evaluate expression and store the result in B->val -@@ -1208,12 +1232,17 @@ update_watchpoint (struct breakpoint *b, int reparse) +@@ -1217,12 +1241,17 @@ update_watchpoint (struct breakpoint *b, int reparse) struct frame_id saved_frame_id; int frame_saved; @@ -465,7 +631,7 @@ index 5bcab87..529ea62 100644 if (b->disposition == disp_del_at_next_stop) return; -@@ -1443,13 +1472,7 @@ update_watchpoint (struct breakpoint *b, int reparse) +@@ -1452,13 +1481,7 @@ update_watchpoint (struct breakpoint *b, int reparse) Watchpoint %d deleted because the program has left the block\n\ in which its expression is valid.\n"), b->number); @@ -480,7 +646,42 @@ index 5bcab87..529ea62 100644 } /* Restore the selected frame. */ -@@ -1840,6 +1863,7 @@ insert_breakpoint_locations (void) +@@ -1500,6 +1523,24 @@ should_be_inserted (struct bp_location *bl) + return 1; + } + ++/* Set or clear a SystemTap semaphore. ARCH is the target ++ architecture; ADDRESS is the address of the semaphore, and SETTING ++ is either zero or one. */ ++ ++static void ++modify_semaphore (struct gdbarch *arch, CORE_ADDR address, int setting) ++{ ++ gdb_byte bytes[sizeof (LONGEST)]; ++ /* The ABI specifies "unsigned short". */ ++ struct type *type = builtin_type (arch)->builtin_unsigned_short; ++ ++ store_unsigned_integer (bytes, TYPE_LENGTH (type), ++ gdbarch_byte_order (arch), setting); ++ ++ /* Ignore errors. FIXME. */ ++ target_write_memory (address, bytes, TYPE_LENGTH (type)); ++} ++ + /* Insert a low-level "breakpoint" of some type. BL is the breakpoint + location. Any error messages are printed to TMP_ERROR_STREAM; and + DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems. +@@ -1595,6 +1636,9 @@ insert_bp_location (struct bp_location *bl, + else + val = target_insert_breakpoint (bl->gdbarch, + &bl->target_info); ++ ++ if (bl->semaphore != 0) ++ modify_semaphore (bl->gdbarch, bl->semaphore, 1); + } + else + { +@@ -1849,6 +1893,7 @@ insert_breakpoint_locations (void) int val = 0; int disabled_breaks = 0; int hw_breakpoint_error = 0; @@ -488,7 +689,7 @@ index 5bcab87..529ea62 100644 struct ui_file *tmp_error_stream = mem_fileopen (); struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_error_stream); -@@ -1867,9 +1891,13 @@ insert_breakpoint_locations (void) +@@ -1876,9 +1921,13 @@ insert_breakpoint_locations (void) /* For targets that support global breakpoints, there's no need to select an inferior to insert breakpoint to. In fact, even if we aren't attached to any process yet, we should still @@ -504,7 +705,7 @@ index 5bcab87..529ea62 100644 continue; val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks, -@@ -1893,13 +1921,19 @@ insert_breakpoint_locations (void) +@@ -1902,13 +1951,19 @@ insert_breakpoint_locations (void) if (bpt->disposition == disp_del_at_next_stop) continue; @@ -530,7 +731,104 @@ index 5bcab87..529ea62 100644 if (some_failed) { for (loc = bpt->loc; loc; loc = loc->next) -@@ -3479,6 +3513,8 @@ print_it_typical (bpstat bs) +@@ -2090,15 +2145,24 @@ struct breakpoint_objfile_data + /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */ + struct minimal_symbol *longjmp_msym[NUM_LONGJMP_NAMES]; + ++ /* SystemTap probe point for longjmp (if any). */ ++ const struct stap_probe *longjmp_probe; ++ + /* Minimal symbol for "std::terminate()" (if any). */ + struct minimal_symbol *terminate_msym; + + /* Minimal symbol for "_Unwind_DebugHook" (if any). */ + struct minimal_symbol *exception_msym; ++ ++ /* SystemTap probe point for unwinding (if any). */ ++ const struct stap_probe *exception_probe; + }; + + static const struct objfile_data *breakpoint_objfile_key; + ++/* SystemTap probe not found sentinel. */ ++static const struct stap_probe probe_not_found; ++ + /* Minimal symbol not found sentinel. */ + static struct minimal_symbol msym_not_found; + +@@ -2206,6 +2270,29 @@ create_longjmp_master_breakpoint (void) + + bp_objfile_data = get_breakpoint_objfile_data (objfile); + ++ if (bp_objfile_data->longjmp_probe != &probe_not_found) ++ { ++ if (bp_objfile_data->longjmp_probe == NULL) ++ bp_objfile_data->longjmp_probe ++ = find_probe_in_objfile (objfile, "libc", "longjmp"); ++ ++ if (bp_objfile_data->longjmp_probe) ++ { ++ struct breakpoint *b; ++ struct gdbarch *gdbarch = get_objfile_arch (objfile); ++ ++ b = create_internal_breakpoint (gdbarch, ++ bp_objfile_data->longjmp_probe->address, ++ bp_longjmp_master); ++ b->addr_string = xstrdup ("probe:libc:longjmp"); ++ b->enable_state = bp_disabled; ++ ++ continue; ++ } ++ else ++ bp_objfile_data->longjmp_probe = &probe_not_found; ++ } ++ + for (i = 0; i < NUM_LONGJMP_NAMES; i++) + { + struct breakpoint *b; +@@ -2314,6 +2401,31 @@ create_exception_master_breakpoint (void) + + bp_objfile_data = get_breakpoint_objfile_data (objfile); + ++ /* We prefer the SystemTap probe point if it exists. */ ++ if (bp_objfile_data->exception_probe != &probe_not_found) ++ { ++ if (bp_objfile_data->exception_probe == NULL) ++ bp_objfile_data->exception_probe ++ = find_probe_in_objfile (objfile, "libgcc", "unwind"); ++ ++ if (bp_objfile_data->exception_probe) ++ { ++ struct breakpoint *b; ++ struct gdbarch *gdbarch = get_objfile_arch (objfile); ++ ++ b = create_internal_breakpoint (gdbarch, ++ bp_objfile_data->exception_probe->address, ++ bp_exception_master); ++ b->addr_string = xstrdup ("probe:libgcc:unwind"); ++ b->enable_state = bp_disabled; ++ continue; ++ } ++ else ++ bp_objfile_data->exception_probe = &probe_not_found; ++ } ++ ++ /* Otherwise, try the hook function. */ ++ + if (msym_not_found_p (bp_objfile_data->exception_msym)) + continue; + +@@ -2532,6 +2644,9 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) + val = target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); + else + val = target_remove_breakpoint (bl->gdbarch, &bl->target_info); ++ ++ if (bl->semaphore != 0) ++ modify_semaphore (bl->gdbarch, bl->semaphore, 0); + } + else + { +@@ -3488,6 +3603,8 @@ print_it_typical (bpstat bs) case bp_tracepoint: case bp_fast_tracepoint: case bp_jit_event: @@ -539,7 +837,7 @@ index 5bcab87..529ea62 100644 default: result = PRINT_UNKNOWN; break; -@@ -3704,6 +3740,8 @@ watchpoint_check (void *p) +@@ -3713,6 +3830,8 @@ watchpoint_check (void *p) gdb_assert (bs->breakpoint_at != NULL); b = bs->breakpoint_at; @@ -548,7 +846,7 @@ index 5bcab87..529ea62 100644 /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread that was used to create the watchpoint. */ -@@ -3813,13 +3851,7 @@ watchpoint_check (void *p) +@@ -3822,13 +3941,7 @@ watchpoint_check (void *p) " deleted because the program has left the block in\n\ which its expression is valid.\n"); @@ -563,7 +861,7 @@ index 5bcab87..529ea62 100644 return WP_DELETED; } -@@ -4024,9 +4056,7 @@ bpstat_check_watchpoint (bpstat bs) +@@ -4033,9 +4146,7 @@ bpstat_check_watchpoint (bpstat bs) case 0: /* Error from catch_errors. */ printf_filtered (_("Watchpoint %d deleted.\n"), b->number); @@ -574,7 +872,7 @@ index 5bcab87..529ea62 100644 /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; break; -@@ -4232,7 +4262,7 @@ bpstat_stop_status (struct address_space *aspace, +@@ -4246,7 +4357,7 @@ bpstat_stop_status (struct address_space *aspace, watchpoint as triggered so that we will handle the out-of-scope event. We'll get to the watchpoint next iteration. */ @@ -583,7 +881,7 @@ index 5bcab87..529ea62 100644 b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; } } -@@ -4354,7 +4384,7 @@ handle_jit_event (void) +@@ -4368,7 +4479,7 @@ handle_jit_event (void) /* Decide what infrun needs to do with this bpstat. */ struct bpstat_what @@ -592,7 +890,7 @@ index 5bcab87..529ea62 100644 { struct bpstat_what retval; /* We need to defer calling `solib_add', as adding new symbols -@@ -4362,12 +4392,13 @@ bpstat_what (bpstat bs) +@@ -4376,12 +4487,13 @@ bpstat_what (bpstat bs) and hence may clear unprocessed entries in the BS chain. */ int shlib_event = 0; int jit_event = 0; @@ -607,42 +905,50 @@ index 5bcab87..529ea62 100644 { /* Extract this BS's action. After processing each BS, we check if its action overrides all we've seem so far. */ -@@ -4497,6 +4528,20 @@ bpstat_what (bpstat bs) +@@ -4511,6 +4623,16 @@ bpstat_what (bpstat bs) out already. */ internal_error (__FILE__, __LINE__, _("bpstat_what: tracepoint encountered")); + break; + case bp_gnu_ifunc_resolver: -+ /* Skip the current breakpoint but otherwise nothing happens. GDB is -+ inserting new bp_gnu_ifunc_resolver_return at this point but -+ bp_gnu_ifunc_resolver is being kept there as another -+ bp_gnu_ifunc_resolver_return may be inserted in the meantime. */ ++ /* Step over it (and insert bp_gnu_ifunc_resolver_return). */ + this_action = BPSTAT_WHAT_SINGLE; + break; + case bp_gnu_ifunc_resolver_return: -+ /* The whole bp_gnu_ifunc_resolver with its associated -+ bp_gnu_ifunc_resolver_return related_breakpoint's has been -+ resolved now, all these helper breakpoints are being removed and -+ new final bp_breakpoint is being put at the target location. */ ++ /* The breakpoint will be removed, execution will restart from the ++ PC of the former breakpoint. */ ++ this_action = BPSTAT_WHAT_KEEP_CHECKING; + break; default: internal_error (__FILE__, __LINE__, _("bpstat_what: unhandled bptype %d"), (int) bptype); -@@ -4534,6 +4579,21 @@ bpstat_what (bpstat bs) +@@ -4519,6 +4641,9 @@ bpstat_what (bpstat bs) + retval.main_action = max (retval.main_action, this_action); + } + ++ /* These operations may affect the bs->breakpoint_at state so they are ++ delayed after MAIN_ACTION is decided above. */ ++ + if (shlib_event) + { + if (debug_infrun) +@@ -4548,6 +4673,23 @@ bpstat_what (bpstat bs) handle_jit_event (); } + for (bs = bs_head; bs != NULL; bs = bs->next) + { -+ if (bs->breakpoint_at == NULL) ++ struct breakpoint *b = bs->breakpoint_at; ++ ++ if (b == NULL) + continue; -+ switch (bs->breakpoint_at->type) ++ switch (b->type) + { + case bp_gnu_ifunc_resolver: -+ gnu_ifunc_resolver_stop (bs->breakpoint_at); ++ gnu_ifunc_resolver_stop (b); + break; + case bp_gnu_ifunc_resolver_return: -+ gnu_ifunc_resolver_return_stop (bs->breakpoint_at); ++ gnu_ifunc_resolver_return_stop (b); + break; + } + } @@ -650,16 +956,16 @@ index 5bcab87..529ea62 100644 return retval; } -@@ -4689,6 +4749,8 @@ bptype_string (enum bptype type) +@@ -4703,6 +4845,8 @@ bptype_string (enum bptype type) {bp_fast_tracepoint, "fast tracepoint"}, {bp_static_tracepoint, "static tracepoint"}, {bp_jit_event, "jit events"}, -+ {bp_gnu_ifunc_resolver, "gnu-ifunc resolver"}, -+ {bp_gnu_ifunc_resolver_return, "gnu-func resolver return"}, ++ {bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"}, ++ {bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"}, }; if (((int) type >= (sizeof (bptypes) / sizeof (bptypes[0]))) -@@ -4823,6 +4885,8 @@ print_one_breakpoint_location (struct breakpoint *b, +@@ -4837,6 +4981,8 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_fast_tracepoint: case bp_static_tracepoint: case bp_jit_event: @@ -668,7 +974,7 @@ index 5bcab87..529ea62 100644 if (opts.addressprint) { annotate_field (4); -@@ -5098,7 +5162,8 @@ user_settable_breakpoint (const struct breakpoint *b) +@@ -5112,7 +5258,8 @@ user_settable_breakpoint (const struct breakpoint *b) || b->type == bp_catchpoint || b->type == bp_hardware_breakpoint || is_tracepoint (b) @@ -678,7 +984,7 @@ index 5bcab87..529ea62 100644 } /* Return true if this breakpoint was set by the user, false if it is -@@ -5594,6 +5659,8 @@ allocate_bp_location (struct breakpoint *bpt) +@@ -5608,6 +5755,8 @@ allocate_bp_location (struct breakpoint *bpt) case bp_longjmp_master: case bp_std_terminate_master: case bp_exception_master: @@ -687,7 +993,7 @@ index 5bcab87..529ea62 100644 loc->loc_type = bp_loc_software_breakpoint; break; case bp_hardware_breakpoint: -@@ -5683,6 +5750,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, +@@ -5697,6 +5846,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, b->ops = NULL; b->condition_not_parsed = 0; b->py_bp_object = NULL; @@ -695,29 +1001,39 @@ index 5bcab87..529ea62 100644 /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order of increasing numbers. */ -@@ -5701,7 +5769,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, +@@ -5713,9 +5863,12 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, + return b; + } - /* Initialize loc->function_name. */ +-/* Initialize loc->function_name. */ ++/* Initialize loc->function_name. EXPLICIT_LOC says no indirect function ++ resolutions should be made as the user specified the location explicitly ++ enough. */ ++ static void -set_breakpoint_location_function (struct bp_location *loc) +set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) { gdb_assert (loc->owner != NULL); -@@ -5709,8 +5777,29 @@ set_breakpoint_location_function (struct bp_location *loc) +@@ -5723,8 +5876,33 @@ set_breakpoint_location_function (struct bp_location *loc) || loc->owner->type == bp_hardware_breakpoint || is_tracepoint (loc->owner)) { - find_pc_partial_function (loc->address, &(loc->function_name), - NULL, NULL); -+ if (find_pc_partial_function (loc->address, &(loc->function_name), NULL, -+ NULL) == FIND_PC_PARTIAL_FUNCTION_GNU_IFUNC -+ && !explicit_loc) ++ int is_gnu_ifunc; ++ ++ find_pc_partial_function_gnu_ifunc (loc->address, &loc->function_name, ++ NULL, NULL, &is_gnu_ifunc); ++ ++ if (is_gnu_ifunc && !explicit_loc) + { + struct breakpoint *b = loc->owner; + + gdb_assert (loc->pspace == current_program_space); -+ if (resolve_gnu_ifunc (loc->function_name, &loc->requested_address)) ++ if (gnu_ifunc_resolve_name (loc->function_name, ++ &loc->requested_address)) + { + /* Recalculate ADDRESS based on new REQUESTED_ADDRESS. */ + loc->address = adjust_breakpoint_address (loc->gdbarch, @@ -736,7 +1052,15 @@ index 5bcab87..529ea62 100644 if (loc->function_name) loc->function_name = xstrdup (loc->function_name); } -@@ -5785,7 +5874,8 @@ set_raw_breakpoint (struct gdbarch *gdbarch, +@@ -5787,6 +5965,7 @@ set_raw_breakpoint (struct gdbarch *gdbarch, + b->loc->requested_address = sal.pc; + b->loc->address = adjusted_address; + b->loc->pspace = sal.pspace; ++ b->loc->semaphore = sal.semaphore; + + /* Store the program space that was used to set the breakpoint, for + breakpoint resetting. */ +@@ -5799,7 +5978,8 @@ set_raw_breakpoint (struct gdbarch *gdbarch, b->loc->section = sal.section; b->line_number = sal.line; @@ -746,7 +1070,7 @@ index 5bcab87..529ea62 100644 breakpoints_changed (); -@@ -6902,7 +6992,7 @@ clone_momentary_breakpoint (struct breakpoint *orig) +@@ -6916,13 +7096,14 @@ clone_momentary_breakpoint (struct breakpoint *orig) copy = set_raw_breakpoint_without_location (orig->gdbarch, orig->type); copy->loc = allocate_bp_location (copy); @@ -755,7 +1079,14 @@ index 5bcab87..529ea62 100644 copy->loc->gdbarch = orig->loc->gdbarch; copy->loc->requested_address = orig->loc->requested_address; -@@ -7002,6 +7092,7 @@ mention (struct breakpoint *b) + copy->loc->address = orig->loc->address; + copy->loc->section = orig->loc->section; + copy->loc->pspace = orig->loc->pspace; ++ copy->loc->semaphore = orig->loc->semaphore; + + if (orig->source_file == NULL) + copy->source_file = NULL; +@@ -7016,6 +7197,7 @@ mention (struct breakpoint *b) do_cleanups (ui_out_chain); break; case bp_breakpoint: @@ -763,7 +1094,7 @@ index 5bcab87..529ea62 100644 if (ui_out_is_mi_like_p (uiout)) { say_where = 0; -@@ -7012,6 +7103,8 @@ mention (struct breakpoint *b) +@@ -7026,6 +7208,8 @@ mention (struct breakpoint *b) else printf_filtered (_("Breakpoint")); printf_filtered (_(" %d"), b->number); @@ -772,7 +1103,7 @@ index 5bcab87..529ea62 100644 say_where = 1; break; case bp_hardware_breakpoint: -@@ -7071,6 +7164,7 @@ mention (struct breakpoint *b) +@@ -7085,6 +7269,7 @@ mention (struct breakpoint *b) case bp_longjmp_master: case bp_std_terminate_master: case bp_exception_master: @@ -780,7 +1111,11 @@ index 5bcab87..529ea62 100644 break; } -@@ -7131,7 +7225,8 @@ add_location_to_breakpoint (struct breakpoint *b, +@@ -7142,10 +7327,12 @@ add_location_to_breakpoint (struct breakpoint *b, + loc->address = adjust_breakpoint_address (loc->gdbarch, + loc->requested_address, b->type); + loc->pspace = sal->pspace; ++ loc->semaphore = sal->semaphore; gdb_assert (loc->pspace != NULL); loc->section = sal->section; @@ -790,7 +1125,7 @@ index 5bcab87..529ea62 100644 return loc; } -@@ -8566,6 +8661,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty, +@@ -8580,6 +8767,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty, b = set_raw_breakpoint_without_location (NULL, bp_type); set_breakpoint_number (internal, b); b->thread = thread; @@ -798,7 +1133,7 @@ index 5bcab87..529ea62 100644 b->disposition = disp_donttouch; b->exp = exp; b->exp_valid_block = exp_valid_block; -@@ -9728,6 +9824,9 @@ update_global_location_list (int should_insert) +@@ -9742,6 +9930,9 @@ update_global_location_list (int should_insert) int keep_in_target = 0; int removed = 0; @@ -808,7 +1143,7 @@ index 5bcab87..529ea62 100644 /* Skip LOCP entries which will definitely never be needed. Stop either at or being the one matching OLD_LOC. */ while (locp < bp_location + bp_location_count -@@ -10044,12 +10143,20 @@ delete_breakpoint (struct breakpoint *bpt) +@@ -10058,12 +10249,20 @@ delete_breakpoint (struct breakpoint *bpt) /* At least avoid this stale reference until the reference counting of breakpoints gets resolved. */ @@ -834,30 +1169,16 @@ index 5bcab87..529ea62 100644 } observer_notify_breakpoint_deleted (bpt->number); -@@ -10380,6 +10487,9 @@ update_breakpoint_locations (struct breakpoint *b, - return; +@@ -10376,7 +10575,7 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) + return sal; + } - b->loc = NULL; -+ xfree (b->source_file); -+ b->source_file = NULL; -+ b->line_number = 0; - - for (i = 0; i < sals.nelts; ++i) - { -@@ -10407,11 +10517,7 @@ update_breakpoint_locations (struct breakpoint *b, - } - } - -- if (b->source_file != NULL) -- xfree (b->source_file); -- if (sals.sals[i].symtab == NULL) -- b->source_file = NULL; -- else -+ if (sals.sals[i].symtab != NULL && b->source_file == NULL) - b->source_file = xstrdup (sals.sals[i].symtab->filename); - - if (b->line_number == 0) -@@ -10494,6 +10600,7 @@ breakpoint_re_set_one (void *bint) +-static void ++void + update_breakpoint_locations (struct breakpoint *b, + struct symtabs_and_lines sals) + { +@@ -10508,6 +10707,7 @@ breakpoint_re_set_one (void *bint) case bp_tracepoint: case bp_fast_tracepoint: case bp_static_tracepoint: @@ -865,7 +1186,7 @@ index 5bcab87..529ea62 100644 /* Do not attempt to re-set breakpoints disabled during startup. */ if (b->enable_state == bp_startup_disabled) return 0; -@@ -10664,6 +10771,7 @@ breakpoint_re_set_one (void *bint) +@@ -10678,6 +10878,7 @@ breakpoint_re_set_one (void *bint) case bp_exception: case bp_exception_resume: case bp_jit_event: @@ -873,7 +1194,7 @@ index 5bcab87..529ea62 100644 break; } -@@ -10828,11 +10936,25 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, +@@ -10844,11 +11045,25 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, ALL_BREAKPOINTS_SAFE (b, tmp) if (b->number == num) { @@ -903,7 +1224,7 @@ index 5bcab87..529ea62 100644 break; } if (match == 0) -@@ -11949,6 +12071,24 @@ all_tracepoints () +@@ -11979,6 +12194,24 @@ all_tracepoints (void) return tp_vec; } @@ -928,115 +1249,7 @@ index 5bcab87..529ea62 100644 /* This help string is used for the break, hbreak, tbreak and thbreak commands. It is defined as a macro to prevent duplication. -@@ -12034,6 +12174,107 @@ iterate_over_breakpoints (int (*callback) (struct breakpoint *, void *), - return NULL; - } - -+static void -+gnu_ifunc_resolver_stop (struct breakpoint *b) -+{ -+ struct breakpoint *b_return; -+ struct frame_info *prev_frame = get_prev_frame (get_current_frame ()); -+ struct frame_id prev_frame_id = get_stack_frame_id (prev_frame); -+ CORE_ADDR prev_pc = get_frame_pc (prev_frame); -+ int thread_id = pid_to_thread_id (inferior_ptid); -+ -+ gdb_assert (b->type == bp_gnu_ifunc_resolver); -+ -+ for (b_return = b->related_breakpoint; b_return != b; -+ b_return = b_return->related_breakpoint) -+ { -+ gdb_assert (b_return->type == bp_gnu_ifunc_resolver_return); -+ gdb_assert (b_return->loc != NULL && b_return->loc->next == NULL); -+ gdb_assert (frame_id_p (b_return->frame_id)); -+ -+ if (b_return->thread == thread_id -+ && b_return->loc->requested_address == prev_pc -+ && frame_id_eq (b_return->frame_id, prev_frame_id)) -+ break; -+ } -+ -+ if (b_return == b) -+ { -+ struct symtab_and_line sal; -+ -+ /* No need to call find_pc_line for symbols resolving as this is only -+ a helper breakpointer never shown to the user. */ -+ -+ init_sal (&sal); -+ sal.pspace = current_inferior ()->pspace; -+ sal.pc = prev_pc; -+ sal.section = find_pc_overlay (sal.pc); -+ sal.explicit_pc = 1; -+ b_return = set_momentary_breakpoint (get_frame_arch (prev_frame), sal, -+ prev_frame_id, -+ bp_gnu_ifunc_resolver_return); -+ -+ /* Add new b_return to the ring list b->related_breakpoint. */ -+ gdb_assert (b_return->related_breakpoint == b_return); -+ b_return->related_breakpoint = b->related_breakpoint; -+ b->related_breakpoint = b_return; -+ } -+} -+ -+static void -+gnu_ifunc_resolver_return_stop (struct breakpoint *b) -+{ -+ struct gdbarch *gdbarch = get_frame_arch (get_current_frame ()); -+ struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; -+ struct type *value_type = TYPE_TARGET_TYPE (func_func_type); -+ struct regcache *regcache = get_thread_regcache (inferior_ptid); -+ struct value *value; -+ CORE_ADDR resolved_address, resolved_pc; -+ struct symtab_and_line sal; -+ struct symtabs_and_lines sals; -+ -+ gdb_assert (b->type == bp_gnu_ifunc_resolver_return); -+ -+ value = allocate_value (value_type); -+ gdbarch_return_value (gdbarch, func_func_type, value_type, regcache, -+ value_contents_raw (value), NULL); -+ resolved_address = value_as_address (value); -+ resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, -+ resolved_address, -+ ¤t_target); -+ -+ while (b->related_breakpoint != b) -+ { -+ struct breakpoint *b_next = b->related_breakpoint; -+ -+ switch (b->type) -+ { -+ case bp_gnu_ifunc_resolver: -+ break; -+ case bp_gnu_ifunc_resolver_return: -+ delete_breakpoint (b); -+ break; -+ default: -+ internal_error (__FILE__, __LINE__, -+ _("handle_inferior_event: Invalid " -+ "gnu-indirect-function breakpoint type %d"), -+ (int) b->type); -+ } -+ b = b_next; -+ } -+ gdb_assert (b->type == bp_gnu_ifunc_resolver); -+ -+ gdb_assert (current_program_space == b->pspace); -+ gnu_ifunc_record_cache (gdbarch, b->addr_string, resolved_pc); -+ -+ sal = find_pc_line (resolved_pc, 0); -+ sals.nelts = 1; -+ sals.sals = &sal; -+ -+ b->type = bp_breakpoint; -+ update_breakpoint_locations (b, sals); -+} -+ - void - _initialize_breakpoint (void) - { -@@ -12568,4 +12809,7 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."), +@@ -12598,4 +12831,7 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."), automatic_hardware_breakpoints = 1; observer_attach_about_to_proceed (breakpoint_about_to_proceed); @@ -1045,19 +1258,51 @@ index 5bcab87..529ea62 100644 +#endif } diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h -index a0fea21..4b24701 100644 +index bd09713..587e3a1 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h -@@ -148,6 +148,9 @@ enum bptype +@@ -149,6 +149,19 @@ enum bptype /* Event for JIT compiled code generation or deletion. */ bp_jit_event, + ++ /* Breakpoint is placed at the STT_GNU_IFUNC resolver. When hit GDB ++ inserts new bp_gnu_ifunc_resolver_return at the caller. ++ bp_gnu_ifunc_resolver is still being kept here as a different thread ++ may still hit it before bp_gnu_ifunc_resolver_return is hit by the ++ original thread. */ + bp_gnu_ifunc_resolver, ++ ++ /* On its hit GDB now know the resolved address of the target ++ STT_GNU_IFUNC function. Associated bp_gnu_ifunc_resolver can be ++ deleted now and the breakpoint moved to the target function entry ++ point. */ + bp_gnu_ifunc_resolver_return, }; /* States of enablement of breakpoint. */ +@@ -345,6 +358,11 @@ struct bp_location + processor's architectual constraints. */ + CORE_ADDR requested_address; + ++ /* If the location comes from a SystemTap probe point, and the probe ++ has an associated semaphore variable, then this is the address of ++ the semaphore. Otherwise, this is zero. */ ++ CORE_ADDR semaphore; ++ + char *function_name; + + /* Details of the placed breakpoint, when inserted. */ +@@ -888,6 +906,9 @@ extern int breakpoint_thread_match (struct address_space *, + + extern void until_break_command (char *, int, int); + ++extern void update_breakpoint_locations (struct breakpoint *b, ++ struct symtabs_and_lines sals); ++ + extern void breakpoint_re_set (void); + + extern void breakpoint_re_set_thread (struct breakpoint *); diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index c70fa4b..6bc3397 100644 --- a/gdb/c-typeprint.c @@ -1080,6 +1325,18 @@ index c70fa4b..6bc3397 100644 fprintf_filtered (stream, "]"); c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, +diff --git a/gdb/coffread.c b/gdb/coffread.c +index b11dd73..0868a79 100644 +--- a/gdb/coffread.c ++++ b/gdb/coffread.c +@@ -2193,6 +2193,7 @@ static const struct sym_fns coff_sym_fns = + + default_symfile_relocate, /* sym_relocate: Relocate a debug + section. */ ++ NULL, /* sym_probe_fns */ + &psym_functions + }; + diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in index 11cf2e6..9a2a8f8 100644 --- a/gdb/data-directory/Makefile.in @@ -1111,6 +1368,26 @@ index 11cf2e6..9a2a8f8 100644 FLAGS_TO_PASS = \ "prefix=$(prefix)" \ +diff --git a/gdb/dbxread.c b/gdb/dbxread.c +index 8242cf8..b2db699 100644 +--- a/gdb/dbxread.c ++++ b/gdb/dbxread.c +@@ -1,6 +1,6 @@ + /* Read dbx symbol tables and convert to internal format, for GDB. + Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, +- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010. ++ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010, 2011. + Free Software Foundation, Inc. + + This file is part of GDB. +@@ -3586,6 +3586,7 @@ static const struct sym_fns aout_sym_fns = + default_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ ++ NULL, /* sym_probe_fns */ + &psym_functions + }; + diff --git a/gdb/defs.h b/gdb/defs.h index 9409dde..f0fa4c7 100644 --- a/gdb/defs.h @@ -1125,7 +1402,7 @@ index 9409dde..f0fa4c7 100644 extern char *xfullpath (const char *); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo -index a5eaa72..6cc98dc 100644 +index fcbbd6c..876749d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -1177,6 +1177,16 @@ for remote debugging. @@ -1145,7 +1422,107 @@ index a5eaa72..6cc98dc 100644 @c resolve the situation of these eventually @item -tui @cindex @code{--tui} -@@ -20677,8 +20687,6 @@ containing @code{end}. For example: +@@ -3286,6 +3296,7 @@ all breakpoints in that range are operated on. + * Conditions:: Break conditions + * Break Commands:: Breakpoint command lists + * Save Breakpoints:: How to save breakpoints in a file ++* Static Probe Points:: Listing static probe points + * Error in Breakpoints:: ``Cannot insert breakpoints'' + * Breakpoint-related Warnings:: ``Breakpoint address adjusted...'' + @end menu +@@ -4499,6 +4510,50 @@ and remove the breakpoint definitions you're not interested in, or + that can no longer be recreated. + @end table + ++@node Static Probe Points ++@subsection Static Probe Points ++ ++@cindex SystemTap static probe point ++@cindex sdt-probe ++The @sc{gnu}/Linux tool @code{SystemTap} provides a way for ++applications to embed static probes, using @file{sdt.h}. @value{GDBN} ++can list the available probes, and you can put breakpoints at the ++probe points (@pxref{Specify Location}). ++ ++You can examine the available @code{SystemTap} static probes using ++@code{info probes}: ++ ++@table @code ++@kindex info probes ++@item info probes [@var{provider} [@var{name} [@var{objfile}]]] ++List the available @code{SystemTap} static probes. ++ ++If given, @var{provider} is a regular expression used to select which ++providers to list. If omitted, all providers are listed. ++ ++If given, @var{name} is a regular expression used to select which ++probes to list. If omitted, all probes are listed. ++ ++If given, @var{objfile} is a regular expression used to select which ++object files (executable or shared libraries) to examine. If not ++given, all object files are considered. ++@end table ++ ++@vindex $_probe_arg@r{, convenience variable} ++A probe may specify up to ten arguments. These are available at the ++point at which the probe is defined---that is, when the current PC is ++at the probe's location. The arguments are available using the ++convenience variables (@pxref{Convenience Vars}) ++@code{$_probe_arg0}@dots{}@code{$_probe_arg9}. Each probe argument is ++an integer of the appropriate size; types are not preserved. The ++convenience variable @code{$_probe_argc} holds the number of arguments ++at the current probe point. ++ ++These variables are always available, but attempts to access them at ++any location other than a probe point will cause @value{GDBN} to give ++an error. ++ ++ + @c @ifclear BARETARGET + @node Error in Breakpoints + @subsection ``Cannot insert breakpoints'' +@@ -6411,6 +6466,29 @@ specify the function unambiguously, e.g., if there are several + functions with identical names in different source files. + @end table + ++@cindex SystemTap static probe point ++@item probe:@r{[}@var{objfile}:@r{]}@r{[}@var{provider}:@r{]}@var{name} ++The @sc{gnu}/Linux tool @code{SystemTap} provides a way for ++applications to embed static probes. This form of linespec specifies ++the location of such a static probe. See ++@uref{http://sourceware.org/systemtap/wiki/AddingUserSpaceProbingToApps} ++for more information on static probes. ++ ++If @var{objfile} is given, only probes coming from that shared library ++or executable are considered. If @var{provider} is given, then only ++probes from that provider are considered. ++ ++@xref{Static Probe Points}, for more information on finding and using ++static probes. ++ ++Some probes have an associated semaphore variable; for instance, this ++happens automatically if you defined your probe using a DTrace-style ++@file{.d} file. If your probe has a semaphore, @value{GDBN} will ++automatically enable it when you specify a breakpoint using the ++@samp{probe:} notation. But, if you put a breakpoint at a probe's ++location by some other method (e.g., @code{break file:line}), then ++@value{GDBN} will not automatically set the semaphore. ++ + @end table + + +@@ -8497,6 +8575,10 @@ to match the format in which the data was printed. + The variable @code{$_exitcode} is automatically set to the exit code when + the program being debugged terminates. + ++@item $_probe_argc ++@itemx $_probe_arg0@dots{}$_probe_arg9 ++Arguments to a SystemTap static probe. @xref{Static Probe Points}. ++ + @item $_sdata + @vindex $_sdata@r{, inspect, convenience variable} + The variable @code{$_sdata} contains extra collected static tracepoint +@@ -20689,8 +20771,6 @@ containing @code{end}. For example: @smallexample (@value{GDBP}) python @@ -1154,7 +1531,7 @@ index a5eaa72..6cc98dc 100644 >print 23 >end 23 -@@ -20691,6 +20699,14 @@ in a Python script. This can be controlled using @code{maint set +@@ -20703,6 +20783,14 @@ in a Python script. This can be controlled using @code{maint set python print-stack}: if @code{on}, the default, then Python stack printing is enabled; if @code{off}, then Python stack printing is disabled. @@ -1169,7 +1546,7 @@ index a5eaa72..6cc98dc 100644 @end table It is also possible to execute a Python script from the @value{GDBN} -@@ -20712,6 +20728,14 @@ and thus is always available. +@@ -20724,6 +20812,14 @@ and thus is always available. @cindex python api @cindex programming in python @@ -1330,7 +1707,7 @@ index d16c865..946ad95 100644 This observer is used for internal testing. Do not use. See testsuite/gdb.gdb/observer.exp. diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c -index afe6dde..d364b14 100644 +index 8d1810e..4a3e2f2 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -905,6 +905,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, @@ -1369,7 +1746,7 @@ index 78ff53f..c83f23d 100644 /* The current depth of dwarf expression recursion, via DW_OP_call*, DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c -index e516dfa..12f6a19 100644 +index 9fd8df0..cbfb6d6 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -134,6 +134,9 @@ struct dwarf_expr_baton @@ -1402,7 +1779,7 @@ index e516dfa..12f6a19 100644 + gdb_assert (symbaton != NULL); + *start = symbaton->data; + *length = symbaton->size; - } ++ } + else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_missing_funcs) + { + struct dwarf2_locexpr_baton *symbaton; @@ -1411,7 +1788,7 @@ index e516dfa..12f6a19 100644 + gdb_assert (symbaton == NULL); + *start = NULL; + *length = 0; /* unused */ -+ } + } + else + internal_error (__FILE__, __LINE__, + _("Unsupported SYMBOL_COMPUTED_OPS %p for \"%s\""), @@ -1425,8 +1802,8 @@ index e516dfa..12f6a19 100644 } /* Helper function for dwarf2_evaluate_loc_desc. Computes the CFA for -@@ -286,6 +299,159 @@ dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) - ctx->get_frame_pc, ctx->baton); +@@ -286,6 +299,172 @@ dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) + ctx->get_frame_pc, ctx->baton); } +static CORE_ADDR @@ -1491,6 +1868,7 @@ index e516dfa..12f6a19 100644 + struct dwarf_expr_context *ctx; + struct dwarf_expr_baton baton; + struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); ++ volatile struct gdb_exception ex; + + baton.frame = frame; + baton.per_cu = per_cu; @@ -1512,7 +1890,17 @@ index e516dfa..12f6a19 100644 + ctx->dwarf_call = dwarf_expr_dwarf_call; + ctx->get_object_address = dwarf_expr_object_address; + -+ dwarf_expr_eval (ctx, data, size); ++ TRY_CATCH (ex, RETURN_MASK_ERROR) ++ { ++ dwarf_expr_eval (ctx, data, size); ++ } ++ if (ex.reason < 0) ++ { ++ if (ex.error == NOT_AVAILABLE_ERROR) ++ return NULL; ++ else ++ throw_exception (ex); ++ } + + /* It was used only during dwarf_expr_eval. */ + ctx->baton = NULL; @@ -1532,6 +1920,8 @@ index e516dfa..12f6a19 100644 + + ctx = dwarf_expr_prep_ctx (get_selected_frame (NULL), dlbaton->data, + dlbaton->size, dlbaton->per_cu); ++ if (ctx == NULL) ++ throw_error (NOT_AVAILABLE_ERROR, _("Value not available")); + if (ctx->num_pieces > 0) + error (_("DW_OP_*piece is unsupported for DW_FORM_block")); + @@ -1585,7 +1975,7 @@ index e516dfa..12f6a19 100644 struct piece_closure { /* Reference count. */ -@@ -1045,10 +1211,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, +@@ -1072,11 +1251,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, LONGEST byte_offset) { struct value *retval; @@ -1593,17 +1983,17 @@ index e516dfa..12f6a19 100644 struct dwarf_expr_context *ctx; struct cleanup *old_chain; - struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); +- volatile struct gdb_exception ex; if (byte_offset < 0) invalid_synthetic_pointer (); -@@ -1061,25 +1225,10 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, +@@ -1089,38 +1265,14 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, return retval; } - baton.frame = frame; - baton.per_cu = per_cu; -+ old_chain = make_cleanup (null_cleanup, 0); - +- - ctx = new_dwarf_expr_context (); - old_chain = make_cleanup_free_dwarf_expr_context (ctx); - @@ -1618,13 +2008,31 @@ index e516dfa..12f6a19 100644 - ctx->get_frame_pc = dwarf_expr_frame_pc; - ctx->get_tls_address = dwarf_expr_tls_address; - ctx->dwarf_call = dwarf_expr_dwarf_call; -+ ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu); ++ old_chain = make_cleanup (null_cleanup, 0); -- dwarf_expr_eval (ctx, data, size); - if (ctx->num_pieces > 0) +- TRY_CATCH (ex, RETURN_MASK_ERROR) +- { +- dwarf_expr_eval (ctx, data, size); +- } +- if (ex.reason < 0) ++ ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu); ++ if (ctx == NULL) { - struct piece_closure *c; -@@ -1123,6 +1272,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, +- if (ex.error == NOT_AVAILABLE_ERROR) +- { +- retval = allocate_value (type); +- mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type)); +- return retval; +- } +- else +- throw_exception (ex); ++ retval = allocate_value (type); ++ mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type)); ++ return retval; + } + + if (ctx->num_pieces > 0) +@@ -1166,6 +1318,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0); int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); @@ -1640,7 +2048,7 @@ index e516dfa..12f6a19 100644 retval = allocate_value_lazy (type); VALUE_LVAL (retval) = lval_memory; if (in_stack_memory) -@@ -2807,11 +2965,51 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, +@@ -2850,11 +3011,51 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, dlbaton->per_cu); } @@ -1715,7 +2123,7 @@ index 96a490e..b0ebb06 100644 /* Compile a DWARF location expression to an agent expression. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c -index d12028f..3f45aff 100644 +index 810f66a..f8d20ac 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1211,6 +1211,9 @@ static void fill_in_loclist_baton (struct dwarf2_cu *cu, @@ -2177,7 +2585,7 @@ index d12028f..3f45aff 100644 name = dwarf2_name (die, cu); if (name) -@@ -10786,10 +10994,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, +@@ -10835,10 +11043,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, (i.e. when the value of a register or memory location is referenced, or a thread-local block, etc.). Then again, it might not be worthwhile. I'm assuming that it isn't unless performance @@ -2192,7 +2600,7 @@ index d12028f..3f45aff 100644 } /* Given a pointer to a DWARF information entry, figure out if we need -@@ -10827,6 +11037,8 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, +@@ -10876,6 +11086,8 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, else sym = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol); OBJSTAT (objfile, n_syms++); @@ -2201,7 +2609,7 @@ index d12028f..3f45aff 100644 /* Cache this symbol's name and the name's demangled form (if any). */ SYMBOL_SET_LANGUAGE (sym, cu->language); -@@ -11599,6 +11811,9 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu) +@@ -11648,6 +11860,9 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu) break; } @@ -2211,7 +2619,7 @@ index d12028f..3f45aff 100644 return this_type; } -@@ -14419,61 +14634,99 @@ fill_in_loclist_baton (struct dwarf2_cu *cu, +@@ -14468,61 +14683,99 @@ fill_in_loclist_baton (struct dwarf2_cu *cu, baton->base_address = cu->base_address; } @@ -2354,7 +2762,7 @@ index d12028f..3f45aff 100644 } } -@@ -14819,6 +15072,25 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) +@@ -14868,6 +15121,25 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) return ofs_lhs->offset == ofs_rhs->offset; } @@ -2380,7 +2788,7 @@ index d12028f..3f45aff 100644 /* Set the type associated with DIE to TYPE. Save it in CU's hash table if necessary. For convenience, return TYPE. -@@ -14844,6 +15116,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) +@@ -14893,6 +15165,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) struct objfile *objfile = cu->objfile; htab_t *type_hash_ptr; @@ -2390,18 +2798,56 @@ index d12028f..3f45aff 100644 initialized (if not already set). There are a few types where we should not be doing so, because the type-specific area is diff --git a/gdb/elfread.c b/gdb/elfread.c -index c59134b..c2c8229 100644 +index e638a36..c1893fe 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c -@@ -37,6 +37,7 @@ +@@ -37,6 +37,14 @@ #include "complaints.h" #include "demangle.h" #include "psympriv.h" ++#include "gdbtypes.h" ++#include "value.h" ++#include "infcall.h" ++#include "gdbthread.h" ++#include "regcache.h" ++#include "stap-probe.h" ++#include "arch-utils.h" +#include "gdbtypes.h" extern void _initialize_elfread (void); -@@ -183,7 +184,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, +@@ -55,8 +63,30 @@ struct elfinfo + asection *mdebugsect; /* Section pointer for .mdebug section */ + }; + ++/* Per-objfile data for Systemtap probe info. */ ++ ++static const struct objfile_data *stap_probe_key = NULL; ++ ++/* Per-objfile data about Systemtap probes. */ ++ ++struct stap_probe_per_objfile ++ { ++ /* The number of probes in this objfile. */ ++ int stap_num_probes; ++ ++ /* The probes themselves. */ ++ struct stap_probe *probes; ++ }; ++ + static void free_elfinfo (void *); + ++/* Minimal symbols located at the GOT entries for .plt - that is the real ++ pointer where the given entry will jump to. It gets updated by the real ++ function address during lazy ld.so resolving in the inferior. These ++ minimal symbols are indexed for -completion. */ ++ ++#define SYMBOL_GOT_PLT_SUFFIX "@got.plt" ++ + /* Locate the segments in ABFD. */ + + static struct symfile_segment_data * +@@ -184,7 +214,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, { struct gdbarch *gdbarch = get_objfile_arch (objfile); @@ -2411,7 +2857,7 @@ index c59134b..c2c8229 100644 address = gdbarch_smash_text_address (gdbarch, address); return prim_record_minimal_symbol_full (name, name_len, copy_name, address, -@@ -391,7 +393,10 @@ elf_symtab_read (struct objfile *objfile, int type, +@@ -393,7 +424,10 @@ elf_symtab_read (struct objfile *objfile, int type, { if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) { @@ -2423,11 +2869,16 @@ index c59134b..c2c8229 100644 } else if ((sym->name[0] == '.' && sym->name[1] == 'L') || ((sym->flags & BSF_LOCAL) -@@ -574,6 +579,250 @@ elf_symtab_read (struct objfile *objfile, int type, - } +@@ -577,6 +611,467 @@ elf_symtab_read (struct objfile *objfile, int type, + do_cleanups (back_to); } -+/* FIXME: Delay it through elf_sym_fns. */ ++/* Build minimal symbols named `function@got.plt' (see SYMBOL_GOT_PLT_SUFFIX) ++ for later look ups of which function to call when user requests ++ a STT_GNU_IFUNC function. As the STT_GNU_IFUNC type is found at the target ++ library defining `function' we cannot yet know while reading OBJFILE which ++ of the SYMBOL_GOT_PLT_SUFFIX entries will be needed and later ++ DYN_SYMBOL_TABLE is no longer easily available for OBJFILE. */ + +static void +elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) @@ -2477,8 +2928,7 @@ index c59134b..c2c8229 100644 + const char *name, *name_got_plt; + struct minimal_symbol *msym; + CORE_ADDR address; -+ const char *suffix = "@got.plt"; -+ size_t suffix_len = strlen (suffix); ++ const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); + size_t name_len; + + name = bfd_asymbol_name (*relplt->relocation[reloc].sym_ptr_ptr); @@ -2495,16 +2945,17 @@ index c59134b..c2c8229 100644 + OBJFILE the symbol is undefined and the objfile having NAME defined + may not yet have been loaded. */ + -+ if (string_buffer_size < name_len + suffix_len) ++ if (string_buffer_size < name_len + got_suffix_len) + { -+ string_buffer_size = 2 * (name_len + suffix_len); ++ string_buffer_size = 2 * (name_len + got_suffix_len); + string_buffer = xrealloc (string_buffer, string_buffer_size); + } + memcpy (string_buffer, name, name_len); -+ memcpy (&string_buffer[name_len], suffix, suffix_len); ++ memcpy (&string_buffer[name_len], SYMBOL_GOT_PLT_SUFFIX, ++ got_suffix_len); + -+ msym = record_minimal_symbol (string_buffer, name_len + suffix_len, 1, -+ address, mst_slot_got_plt, got_plt, ++ msym = record_minimal_symbol (string_buffer, name_len + got_suffix_len, ++ 1, address, mst_slot_got_plt, got_plt, + objfile); + if (msym) + MSYMBOL_SIZE (msym) = ptr_size; @@ -2513,23 +2964,64 @@ index c59134b..c2c8229 100644 + do_cleanups (back_to); +} + -+/* Function does not check for possibly created duplicities in the cache. -+ Check it by resolve_gnu_ifunc_by_cache first. */ ++/* The data pointer is htab_t for gnu_ifunc_record_cache_unchecked. */ + -+static struct minimal_symbol * -+gnu_ifunc_record_cache_unchecked (const char *function_name, -+ CORE_ADDR function_address) ++static const struct objfile_data *elf_objfile_gnu_ifunc_cache_data; ++ ++/* Map function names to CORE_ADDR in elf_objfile_gnu_ifunc_cache_data. */ ++ ++struct elf_gnu_ifunc_cache +{ -+ struct minimal_symbol *msym, *msym_new; ++ /* This is always a function entry address, not a function descriptor. */ ++ CORE_ADDR addr; ++ ++ char name[1]; ++}; ++ ++/* htab_hash for elf_objfile_gnu_ifunc_cache_data. */ ++ ++static hashval_t ++elf_gnu_ifunc_cache_hash (const void *a_voidp) ++{ ++ const struct elf_gnu_ifunc_cache *a = a_voidp; ++ ++ return htab_hash_string (a->name); ++} ++ ++/* htab_eq for elf_objfile_gnu_ifunc_cache_data. */ ++ ++static int ++elf_gnu_ifunc_cache_eq (const void *a_voidp, const void *b_voidp) ++{ ++ const struct elf_gnu_ifunc_cache *a = a_voidp; ++ const struct elf_gnu_ifunc_cache *b = b_voidp; ++ ++ return strcmp (a->name, b->name) == 0; ++} ++ ++/* Record the target function address of a STT_GNU_IFUNC function NAME is the ++ function entry address ADDR. Return 1 if NAME and ADDR are considered as ++ valid and therefore they were successfully recorded, return 0 otherwise. ++ ++ Function does not expect a duplicate entry. Use ++ elf_gnu_ifunc_resolve_by_cache first to check if the entry for NAME already ++ exists. */ ++ ++static int ++elf_gnu_ifunc_record_cache (const char *name, CORE_ADDR addr) ++{ ++ struct minimal_symbol *msym; + asection *sect; + struct objfile *objfile; -+ char *function_name_gnu_ifunc_tgt; ++ htab_t htab; ++ struct elf_gnu_ifunc_cache entry_local, *entry_p; ++ void **slot; + -+ msym = lookup_minimal_symbol_by_pc (function_address); ++ msym = lookup_minimal_symbol_by_pc (addr); + if (msym == NULL) -+ return NULL; -+ if (SYMBOL_VALUE_ADDRESS (msym) != function_address) -+ return NULL; ++ return 0; ++ if (SYMBOL_VALUE_ADDRESS (msym) != addr) ++ return 0; + /* minimal symbols have always SYMBOL_OBJ_SECTION non-NULL. */ + sect = SYMBOL_OBJ_SECTION (msym)->the_bfd_section; + objfile = SYMBOL_OBJ_SECTION (msym)->objfile; @@ -2538,67 +3030,105 @@ index c59134b..c2c8229 100644 + resolution and it has no use for GDB. Besides ".text" this symbol can + reside also in ".opd" for ppc64 function descriptor. */ + if (strcmp (bfd_get_section_name (objfile->obfd, sect), ".plt") == 0) -+ return NULL; -+ -+ function_name_gnu_ifunc_tgt = alloca (strlen (function_name) -+ + strlen ("@gnu-ifunc-tgt") + 1); -+ sprintf (function_name_gnu_ifunc_tgt, "%s@gnu-ifunc-tgt", function_name); -+ -+ /* Create new alias "@gnu-ifunc-tgt" for MSYM. */ -+ msym_new = record_minimal_symbol (function_name_gnu_ifunc_tgt, -+ strlen (function_name_gnu_ifunc_tgt), 1, -+ SYMBOL_VALUE_ADDRESS (msym), -+ MSYMBOL_TYPE (msym), sect, objfile); -+ /* Should not happen. */ -+ if (msym_new == NULL) + return 0; + -+ /* objfile->msymbols array is already allocated on obstack and it cannot be -+ easily extended. Therefore -completion on symbol names will never -+ show the @gnu-ifunc-tgt symbol. Link it at least to the hash table so -+ that resolve_gnu_ifunc_by_cache can find it. */ -+ add_minsym_to_hash_table (msym_new, objfile->msymbol_hash); -+ -+ MSYMBOL_SIZE (msym_new) = MSYMBOL_SIZE (msym); -+ return msym_new; -+} -+ -+/* Check first the cache if it - unlikely - has not been populated since -+ bp_gnu_ifunc_resolver has been created. gnu_ifunc_record_cache_unchecked -+ could create a duplicate symbol otherwise. */ -+ -+void -+gnu_ifunc_record_cache (struct gdbarch *gdbarch, const char *function_name, -+ CORE_ADDR function_address) -+{ -+ struct minimal_symbol *msym; -+ -+ msym = resolve_gnu_ifunc_by_cache (function_name); -+ if (msym == NULL) -+ gnu_ifunc_record_cache_unchecked (function_name, function_address); -+ else if (SYMBOL_VALUE_ADDRESS (msym) != function_address) ++ htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); ++ if (htab == NULL) + { -+ /* This case indicates buggy inferior program. GDB would need to update -+ its MSYM cache symbol for function_address. Anyway FUNCTION_NAME is -+ never normally found in the case as in such case no -+ bp_gnu_ifunc_resolver would be created in the first place. */ -+ -+ warning (_("gnu-indirect-function \"%s\" has changed its resolved " -+ "function_address from %s to %s; GDB is using the former one"), -+ function_name, paddress (gdbarch, SYMBOL_VALUE_ADDRESS (msym)), -+ paddress (gdbarch, function_address)); ++ htab = htab_create_alloc_ex (1, elf_gnu_ifunc_cache_hash, ++ elf_gnu_ifunc_cache_eq, ++ NULL, &objfile->objfile_obstack, ++ hashtab_obstack_allocate, ++ dummy_obstack_deallocate); ++ set_objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data, htab); + } ++ ++ entry_local.addr = addr; ++ obstack_grow (&objfile->objfile_obstack, &entry_local, ++ offsetof (struct elf_gnu_ifunc_cache, name)); ++ obstack_grow_str0 (&objfile->objfile_obstack, name); ++ entry_p = obstack_finish (&objfile->objfile_obstack); ++ ++ slot = htab_find_slot (htab, entry_p, INSERT); ++ if (*slot != NULL) ++ { ++ struct elf_gnu_ifunc_cache *entry_found_p = *slot; ++ struct gdbarch *gdbarch = objfile->gdbarch; ++ ++ if (entry_found_p->addr != addr) ++ { ++ /* This case indicates buggy inferior program, the resolved address ++ should never change. */ ++ ++ warning (_("gnu-indirect-function \"%s\" has changed its resolved " ++ "function_address from %s to %s"), ++ name, paddress (gdbarch, entry_found_p->addr), ++ paddress (gdbarch, addr)); ++ } ++ ++ /* New ENTRY_P is here leaked/duplicate in the OBJFILE obstack. */ ++ } ++ *slot = entry_p; ++ ++ return 1; +} + -+static struct minimal_symbol * -+resolve_gnu_ifunc_by_got (const char *function_name) ++/* Try to find the target resolved function entry address of a STT_GNU_IFUNC ++ function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P ++ is not NULL) and the function returns 1. It returns 0 otherwise. ++ ++ Only the elf_objfile_gnu_ifunc_cache_data hash table is searched by this ++ function. */ ++ ++static int ++elf_gnu_ifunc_resolve_by_cache (const char *name, CORE_ADDR *addr_p) +{ -+ char *function_name_got_plt; + struct objfile *objfile; + -+ function_name_got_plt = alloca (strlen (function_name) + strlen ("@got.plt") -+ + 1); -+ sprintf (function_name_got_plt, "%s@got.plt", function_name); ++ ALL_PSPACE_OBJFILES (current_program_space, objfile) ++ { ++ htab_t htab; ++ struct elf_gnu_ifunc_cache *entry_p; ++ void **slot; ++ ++ htab = objfile_data (objfile, elf_objfile_gnu_ifunc_cache_data); ++ if (htab == NULL) ++ continue; ++ ++ entry_p = alloca (sizeof (*entry_p) + strlen (name)); ++ strcpy (entry_p->name, name); ++ ++ slot = htab_find_slot (htab, entry_p, NO_INSERT); ++ if (slot == NULL) ++ continue; ++ entry_p = *slot; ++ gdb_assert (entry_p != NULL); ++ ++ if (addr_p) ++ *addr_p = entry_p->addr; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/* Try to find the target resolved function entry address of a STT_GNU_IFUNC ++ function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P ++ is not NULL) and the function returns 1. It returns 0 otherwise. ++ ++ Only the SYMBOL_GOT_PLT_SUFFIX locations are searched by this function. ++ elf_gnu_ifunc_resolve_by_cache must have been already called for NAME to ++ prevent cache entries duplicates. */ ++ ++static int ++elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) ++{ ++ char *name_got_plt; ++ struct objfile *objfile; ++ const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); ++ ++ name_got_plt = alloca (strlen (name) + got_suffix_len + 1); ++ sprintf (name_got_plt, "%s" SYMBOL_GOT_PLT_SUFFIX, name); + + ALL_PSPACE_OBJFILES (current_program_space, objfile) + { @@ -2606,12 +3136,12 @@ index c59134b..c2c8229 100644 + struct gdbarch *gdbarch = objfile->gdbarch; + struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + size_t ptr_size = TYPE_LENGTH (ptr_type); -+ CORE_ADDR pointer_address, function_address; ++ CORE_ADDR pointer_address, addr; + asection *plt; + gdb_byte *buf = alloca (ptr_size); + struct minimal_symbol *msym; + -+ msym = lookup_minimal_symbol (function_name_got_plt, NULL, objfile); ++ msym = lookup_minimal_symbol (name_got_plt, NULL, objfile); + if (msym == NULL) + continue; + if (MSYMBOL_TYPE (msym) != mst_slot_got_plt) @@ -2626,55 +3156,188 @@ index c59134b..c2c8229 100644 + continue; + if (target_read_memory (pointer_address, buf, ptr_size) != 0) + continue; -+ function_address = extract_typed_address (buf, ptr_type); ++ addr = extract_typed_address (buf, ptr_type); ++ addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ++ ¤t_target); + -+ msym = gnu_ifunc_record_cache_unchecked (function_name, function_address); -+ if (msym == NULL) -+ continue; -+ return msym; -+ } -+ -+ return NULL; -+} -+ -+struct minimal_symbol * -+resolve_gnu_ifunc_by_cache (const char *function_name) -+{ -+ char *function_name_gnu_ifunc_tgt; -+ -+ function_name_gnu_ifunc_tgt = alloca (strlen (function_name) -+ + strlen ("@gnu-ifunc-tgt") + 1); -+ sprintf (function_name_gnu_ifunc_tgt, "%s@gnu-ifunc-tgt", function_name); -+ -+ return lookup_minimal_symbol (function_name_gnu_ifunc_tgt, NULL, NULL); -+} -+ -+int -+resolve_gnu_ifunc (const char *function_name, CORE_ADDR *function_addressp) -+{ -+ struct minimal_symbol *msym; -+ -+ msym = resolve_gnu_ifunc_by_cache (function_name); -+ if (msym != NULL) -+ { -+ *function_addressp = SYMBOL_VALUE_ADDRESS (msym); -+ return 1; -+ } -+ -+ msym = resolve_gnu_ifunc_by_got (function_name); -+ if (msym != NULL) -+ { -+ *function_addressp = SYMBOL_VALUE_ADDRESS (msym); -+ return 1; ++ if (addr_p) ++ *addr_p = addr; ++ if (elf_gnu_ifunc_record_cache (name, addr)) ++ return 1; + } + + return 0; +} ++ ++/* Try to find the target resolved function entry address of a STT_GNU_IFUNC ++ function NAME. If the address is found it is stored to *ADDR_P (if ADDR_P ++ is not NULL) and the function returns 1. It returns 0 otherwise. ++ ++ Both the elf_objfile_gnu_ifunc_cache_data hash table and ++ SYMBOL_GOT_PLT_SUFFIX locations are searched by this function. */ ++ ++static int ++elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p) ++{ ++ if (elf_gnu_ifunc_resolve_by_cache (name, addr_p)) ++ return 1; ++ ++ if (elf_gnu_ifunc_resolve_by_got (name, addr_p)) ++ return 1; ++ ++ return 0; ++} ++ ++/* Call STT_GNU_IFUNC - a function returning addresss of a real function to ++ call. PC is theSTT_GNU_IFUNC resolving function entry. The value returned ++ is the entry point of the resolved STT_GNU_IFUNC target function to call. ++ */ ++ ++static CORE_ADDR ++elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) ++{ ++ char *name_at_pc; ++ CORE_ADDR start_at_pc, address; ++ struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; ++ struct value *function, *address_val; ++ ++ /* Try first any non-intrusive methods without an inferior call. */ ++ ++ if (find_pc_partial_function (pc, &name_at_pc, &start_at_pc, NULL) ++ && start_at_pc == pc) ++ { ++ if (elf_gnu_ifunc_resolve_name (name_at_pc, &address)) ++ return address; ++ } ++ else ++ name_at_pc = NULL; ++ ++ function = allocate_value (func_func_type); ++ set_value_address (function, pc); ++ ++ /* STT_GNU_IFUNC resolver functions have no parameters. FUNCTION is the ++ function entry address. ADDRESS may be a function descriptor. */ ++ ++ address_val = call_function_by_hand (function, 0, NULL); ++ address = value_as_address (address_val); ++ address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, ++ ¤t_target); ++ ++ if (name_at_pc) ++ elf_gnu_ifunc_record_cache (name_at_pc, address); ++ ++ return address; ++} ++ ++/* Handle inferior hit of bp_gnu_ifunc_resolver, see its definition. */ ++ ++static void ++elf_gnu_ifunc_resolver_stop (struct breakpoint *b) ++{ ++ struct breakpoint *b_return; ++ struct frame_info *prev_frame = get_prev_frame (get_current_frame ()); ++ struct frame_id prev_frame_id = get_stack_frame_id (prev_frame); ++ CORE_ADDR prev_pc = get_frame_pc (prev_frame); ++ int thread_id = pid_to_thread_id (inferior_ptid); ++ ++ gdb_assert (b->type == bp_gnu_ifunc_resolver); ++ ++ for (b_return = b->related_breakpoint; b_return != b; ++ b_return = b_return->related_breakpoint) ++ { ++ gdb_assert (b_return->type == bp_gnu_ifunc_resolver_return); ++ gdb_assert (b_return->loc != NULL && b_return->loc->next == NULL); ++ gdb_assert (frame_id_p (b_return->frame_id)); ++ ++ if (b_return->thread == thread_id ++ && b_return->loc->requested_address == prev_pc ++ && frame_id_eq (b_return->frame_id, prev_frame_id)) ++ break; ++ } ++ ++ if (b_return == b) ++ { ++ struct symtab_and_line sal; ++ ++ /* No need to call find_pc_line for symbols resolving as this is only ++ a helper breakpointer never shown to the user. */ ++ ++ init_sal (&sal); ++ sal.pspace = current_inferior ()->pspace; ++ sal.pc = prev_pc; ++ sal.section = find_pc_overlay (sal.pc); ++ sal.explicit_pc = 1; ++ b_return = set_momentary_breakpoint (get_frame_arch (prev_frame), sal, ++ prev_frame_id, ++ bp_gnu_ifunc_resolver_return); ++ ++ /* Add new b_return to the ring list b->related_breakpoint. */ ++ gdb_assert (b_return->related_breakpoint == b_return); ++ b_return->related_breakpoint = b->related_breakpoint; ++ b->related_breakpoint = b_return; ++ } ++} ++ ++/* Handle inferior hit of bp_gnu_ifunc_resolver_return, see its definition. */ ++ ++static void ++elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) ++{ ++ struct gdbarch *gdbarch = get_frame_arch (get_current_frame ()); ++ struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; ++ struct type *value_type = TYPE_TARGET_TYPE (func_func_type); ++ struct regcache *regcache = get_thread_regcache (inferior_ptid); ++ struct value *value; ++ CORE_ADDR resolved_address, resolved_pc; ++ struct symtab_and_line sal; ++ struct symtabs_and_lines sals; ++ ++ gdb_assert (b->type == bp_gnu_ifunc_resolver_return); ++ ++ value = allocate_value (value_type); ++ gdbarch_return_value (gdbarch, func_func_type, value_type, regcache, ++ value_contents_raw (value), NULL); ++ resolved_address = value_as_address (value); ++ resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, ++ resolved_address, ++ ¤t_target); ++ ++ while (b->related_breakpoint != b) ++ { ++ struct breakpoint *b_next = b->related_breakpoint; ++ ++ switch (b->type) ++ { ++ case bp_gnu_ifunc_resolver: ++ break; ++ case bp_gnu_ifunc_resolver_return: ++ delete_breakpoint (b); ++ break; ++ default: ++ internal_error (__FILE__, __LINE__, ++ _("handle_inferior_event: Invalid " ++ "gnu-indirect-function breakpoint type %d"), ++ (int) b->type); ++ } ++ b = b_next; ++ } ++ gdb_assert (b->type == bp_gnu_ifunc_resolver); ++ ++ gdb_assert (current_program_space == b->pspace); ++ elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc); ++ ++ sal = find_pc_line (resolved_pc, 0); ++ sals.nelts = 1; ++ sals.sals = &sal; ++ ++ b->type = bp_breakpoint; ++ update_breakpoint_locations (b, sals); ++} + struct build_id { size_t size; -@@ -814,6 +1063,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) +@@ -817,6 +1312,8 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) bfd_errmsg (bfd_get_error ())); elf_symtab_read (objfile, ST_DYNAMIC, dynsymcount, dyn_symbol_table, 0); @@ -2683,6 +3346,294 @@ index c59134b..c2c8229 100644 } /* Add synthetic symbols - for instance, names for any PLT entries. */ +@@ -1071,7 +1568,243 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst) + complaint (&symfile_complaints, + _("elf/stab section information missing for %s"), filename); + } ++ ++/* Helper function that parses the information contained in a ++ Systemtap's probe. Basically, the information consists in: ++ ++ - Probe's PC address; ++ - Link-time section address of `.stapsdt.base' section; ++ - Link-time address of the semaphore variable, or ZERO if the ++ probe doesn't have an associated semaphore; ++ - Probe's provider name; ++ - Probe's name; ++ - Probe's argument format. */ ++ ++static void ++handle_probe (struct objfile *objfile, struct sdt_note *el, ++ struct stap_probe *ret, CORE_ADDR base) ++{ ++ bfd *abfd = objfile->obfd; ++ int size = bfd_get_arch_size (abfd) / 8; ++ struct gdbarch *gdbarch = get_objfile_arch (objfile); ++ struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; ++ CORE_ADDR base_ref; ++ ++ /* Provider and the name of the probe. */ ++ ret->provider = (const char *) &el->data[3 * size]; ++ ret->name = memchr (ret->provider, '\0', ++ (unsigned long *) el->data ++ + el->size - (unsigned long *) ret->provider); ++ /* Making sure there is a name. */ ++ if (!ret->name) ++ complaint (&symfile_complaints, _("corrupt probe when reading `%s'"), ++ objfile->name); ++ else ++ ++ret->name; ++ ++ /* Retrieving the probe's address. */ ++ ret->address = extract_typed_address ((const gdb_byte *) &el->data[0], ++ ptr_type); ++ /* Link-time sh_addr of `.stapsdt.base' section. */ ++ base_ref = extract_typed_address ((const gdb_byte *) &el->data[size], ++ ptr_type); ++ /* Semaphore address. */ ++ ret->sem_addr = extract_typed_address ((const gdb_byte *) &el->data[2 * size], ++ ptr_type); ++ ++ ret->address += (ANOFFSET (objfile->section_offsets, ++ SECT_OFF_TEXT (objfile)) ++ + base - base_ref); ++ if (ret->sem_addr) ++ ret->sem_addr += (ANOFFSET (objfile->section_offsets, ++ SECT_OFF_DATA (objfile)) ++ + base - base_ref); ++ ++ /* Arguments. We can only extract the argument format if there is a valid ++ name for this probe. */ ++ if (ret->name) ++ { ++ ret->args = memchr (ret->name, '\0', ++ (unsigned long *) el->data ++ + el->size - (unsigned long *) ret->name); ++ ++ if (ret->args++ != NULL ++ || memchr (ret->args, '\0', (unsigned long *) el->data ++ + el->size - (unsigned long *) ret->name) ++ != el->data + el->size - 1) ++ complaint (&symfile_complaints, _("corrupt probe when reading `%s'"), ++ objfile->name); ++ } ++ else ++ ret->args = NULL; ++} ++ ++#define STAP_BASE_SECTION_NAME ".stapsdt.base" ++ ++static void ++get_base_address_1 (bfd *abfd, asection *sect, void *obj) ++{ ++ bfd_vma *base = (bfd_vma *) obj; ++ ++ if (*base == (bfd_vma) -1 ++ && (sect->flags & (SEC_DATA | SEC_ALLOC | SEC_HAS_CONTENTS)) ++ && sect->name && !strcmp (sect->name, STAP_BASE_SECTION_NAME)) ++ *base = sect->vma; ++} ++ ++static bfd_vma ++get_base_address (bfd *obfd) ++{ ++ bfd_vma base = (bfd_vma) -1; ++ ++ bfd_map_over_sections (obfd, get_base_address_1, (void *) &base); ++ ++ return base; ++} ++ ++/* FIXME JUST FOR TESTING **/ ++static int ++elf_get_probe_argument_count (struct objfile *objfile, ++ const struct stap_probe *probe); ++ ++static const struct stap_probe * ++elf_get_probes (struct objfile *objfile, int *num_probes) ++{ ++ struct stap_probe *ret = NULL; ++ struct stap_probe_per_objfile *probes_per_objfile; ++ ++ /* Initially, no probes. */ ++ *num_probes = 0; ++ ++ /* Have we parsed this objfile's probes already? */ ++ probes_per_objfile ++ = (struct stap_probe_per_objfile *) objfile_data (objfile, ++ stap_probe_key); ++ ++ if (!probes_per_objfile) ++ { ++ /* If we are here, then this is the first time we are parsing the ++ probe's information. We basically have to count how many probes ++ the objfile has, and then fill in the necessary information ++ for each one. */ ++ ++ bfd *obfd = objfile->obfd; ++ bfd_vma base = get_base_address (obfd); ++ struct sdt_note *iter; ++ int i; ++ int n = 0; ++ ++ if (! elf_tdata (obfd)->sdt_note_head) ++ /* There isn't any probe here. */ ++ return NULL; ++ ++ /* Allocating space for probe info. */ ++ for (iter = elf_tdata (obfd)->sdt_note_head; ++ iter; ++ iter = iter->next, ++n); ++ ++ ret = xcalloc (n, sizeof (struct stap_probe)); ++ ++ /* Parsing each probe's information. */ ++ for (iter = elf_tdata (obfd)->sdt_note_head, i = 0; ++ iter; ++ iter = iter->next, i++) ++ /* We first have to handle all the information about the ++ probe which is present in the section. */ ++ handle_probe (objfile, iter, &ret[i], base); ++ ++ /* Creating a cache for these probes in the objfile's registry. */ ++ probes_per_objfile = xmalloc (sizeof (struct stap_probe_per_objfile)); ++ ++ probes_per_objfile->stap_num_probes = n; ++ probes_per_objfile->probes = ret; ++ ++ set_objfile_data (objfile, stap_probe_key, probes_per_objfile); ++ } ++ else ++ ret = probes_per_objfile->probes; ++ ++ *num_probes = probes_per_objfile->stap_num_probes; ++ ++ return ret; ++} ++ ++static int ++elf_get_probe_argument_count (struct objfile *objfile, ++ const struct stap_probe *probe) ++{ ++ const char *pargs = probe->args; ++ ++ if (!pargs || !*pargs || *pargs == ':') ++ /* No arguments. */ ++ return 0; ++ ++ return stap_get_probe_argument_count (probe); ++} ++ ++static struct value * ++elf_evaluate_probe_argument (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct frame_info *frame, ++ int n) ++{ ++ return stap_evaluate_probe_argument (objfile, probe, frame, n); ++} ++ ++static void ++elf_compile_to_ax (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct agent_expr *expr, ++ struct axs_value *value, ++ int n) ++{ ++ stap_compile_to_ax (objfile, probe, expr, value, n); ++} ++ ++static void ++elf_symfile_relocate_probe (struct objfile *objfile, ++ struct section_offsets *new_offsets, ++ struct section_offsets *delta) ++{ ++ int i; ++ struct stap_probe_per_objfile *p ++ = (struct stap_probe_per_objfile *) objfile_data (objfile, ++ stap_probe_key); ++ ++ if (!p) ++ /* No probe to relocate. */ ++ return; ++ ++ for (i = 0; i < p->stap_num_probes; i++) ++ { ++ p->probes[i].address += ANOFFSET (delta, SECT_OFF_TEXT (objfile)); ++ if (p->probes[i].sem_addr) ++ p->probes[i].sem_addr += ANOFFSET (delta, SECT_OFF_DATA (objfile)); ++ } ++} ++ ++static void ++stap_probe_key_free (struct objfile *objfile, void *d) ++{ ++ int i; ++ struct stap_probe_per_objfile *data = (struct stap_probe_per_objfile *) d; ++ ++ for (i = 0; i < data->stap_num_probes; i++) ++ stap_free_parsed_args (data->probes[i].parsed_args); ++ xfree (data->probes); ++ xfree (data); ++} ++ + ++static const struct sym_probe_fns elf_probe_fns = ++{ ++ elf_get_probes, /* sym_get_probes */ ++ elf_get_probe_argument_count, /* sym_get_probe_argument_count */ ++ elf_evaluate_probe_argument, /* sym_evaluate_probe_argument */ ++ elf_compile_to_ax, /* sym_compile_to_ax */ ++ elf_symfile_relocate_probe, /* sym_relocate_probe */ ++}; ++ + /* Register that we are able to handle ELF object file formats. */ + + static const struct sym_fns elf_sym_fns = +@@ -1086,6 +1819,7 @@ static const struct sym_fns elf_sym_fns = + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ ++ &elf_probe_fns, /* sym_probe_fns */ + &psym_functions + }; + +@@ -1104,6 +1838,7 @@ static const struct sym_fns elf_sym_fns_lazy_psyms = + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ ++ &elf_probe_fns, /* sym_probe_fns */ + &psym_functions + }; + +@@ -1121,11 +1856,27 @@ static const struct sym_fns elf_sym_fns_gdb_index = + elf_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ ++ &elf_probe_fns, /* sym_probe_fns */ + &dwarf2_gdb_index_functions + }; + ++/* STT_GNU_IFUNC resolver vector to be installed to gnu_ifunc_fns_p. */ ++ ++static const struct gnu_ifunc_fns elf_gnu_ifunc_fns = ++{ ++ elf_gnu_ifunc_resolve_addr, ++ elf_gnu_ifunc_resolve_name, ++ elf_gnu_ifunc_resolver_stop, ++ elf_gnu_ifunc_resolver_return_stop ++}; ++ + void + _initialize_elfread (void) + { ++ stap_probe_key ++ = register_objfile_data_with_cleanup (NULL, stap_probe_key_free); + add_symtab_fns (&elf_sym_fns); ++ ++ elf_objfile_gnu_ifunc_cache_data = register_objfile_data (); ++ gnu_ifunc_fns_p = &elf_gnu_ifunc_fns; + } diff --git a/gdb/eval.c b/gdb/eval.c index 09b41a0..7c0a8f9 100644 --- a/gdb/eval.c @@ -3182,7 +4133,7 @@ index 09b41a0..7c0a8f9 100644 + } diff --git a/gdb/f-exp.y b/gdb/f-exp.y -index 02745c8..3a730e7 100644 +index d9cf3cf..3e11e57 100644 --- a/gdb/f-exp.y +++ b/gdb/f-exp.y @@ -293,7 +293,9 @@ arglist : subrange @@ -3419,7 +4370,7 @@ index 3280ddc..128d6bc 100644 switch (TYPE_CODE (type)) { diff --git a/gdb/findvar.c b/gdb/findvar.c -index 6463342..951c2fe 100644 +index 2b361ef..01e1c0d 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -35,6 +35,7 @@ @@ -3430,7 +4381,7 @@ index 6463342..951c2fe 100644 /* Basic byte-swapping routines. All 'extract' functions return a host-format integer from a target-format integer at ADDR which is -@@ -399,8 +400,11 @@ symbol_read_needs_frame (struct symbol *sym) +@@ -408,8 +409,11 @@ symbol_read_needs_frame (struct symbol *sym) /* Given a struct symbol for a variable, and a stack frame id, read the value of the variable @@ -3444,7 +4395,7 @@ index 6463342..951c2fe 100644 struct value * read_var_value (struct symbol *var, struct frame_info *frame) -@@ -408,16 +412,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -417,16 +421,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) struct value *v; struct type *type = SYMBOL_TYPE (var); CORE_ADDR addr; @@ -3461,7 +4412,7 @@ index 6463342..951c2fe 100644 if (symbol_read_needs_frame (var)) gdb_assert (frame); -@@ -427,7 +421,7 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -436,7 +430,7 @@ read_var_value (struct symbol *var, struct frame_info *frame) case LOC_CONST: /* Put the constant back in target format. */ v = allocate_value (type); @@ -3470,7 +4421,7 @@ index 6463342..951c2fe 100644 gdbarch_byte_order (get_type_arch (type)), (LONGEST) SYMBOL_VALUE (var)); VALUE_LVAL (v) = not_lval; -@@ -452,12 +446,12 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -461,12 +455,12 @@ read_var_value (struct symbol *var, struct frame_info *frame) case LOC_CONST_BYTES: v = allocate_value (type); @@ -3485,7 +4436,7 @@ index 6463342..951c2fe 100644 if (overlay_debugging) addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), SYMBOL_OBJ_SECTION (var)); -@@ -470,7 +464,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -479,7 +473,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) if (!addr) return 0; addr += SYMBOL_VALUE (var); @@ -3493,7 +4444,7 @@ index 6463342..951c2fe 100644 break; case LOC_REF_ARG: -@@ -484,14 +477,12 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -493,14 +486,12 @@ read_var_value (struct symbol *var, struct frame_info *frame) argref += SYMBOL_VALUE (var); ref = value_at (lookup_pointer_type (type), argref); addr = value_as_address (ref); @@ -3508,7 +4459,7 @@ index 6463342..951c2fe 100644 break; case LOC_TYPEDEF: -@@ -499,7 +490,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -508,7 +499,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) break; case LOC_BLOCK: @@ -3516,7 +4467,7 @@ index 6463342..951c2fe 100644 if (overlay_debugging) addr = symbol_overlayed_address (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); -@@ -524,7 +514,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -533,7 +523,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) error (_("Value of register variable not available.")); addr = value_as_address (regval); @@ -3524,7 +4475,7 @@ index 6463342..951c2fe 100644 } else { -@@ -563,7 +552,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -572,7 +561,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) if (obj_section && (obj_section->the_bfd_section->flags & SEC_THREAD_LOCAL) != 0) addr = target_translate_tls_address (obj_section->objfile, addr); @@ -3532,7 +4483,7 @@ index 6463342..951c2fe 100644 } break; -@@ -578,6 +566,10 @@ read_var_value (struct symbol *var, struct frame_info *frame) +@@ -587,6 +575,10 @@ read_var_value (struct symbol *var, struct frame_info *frame) break; } @@ -3543,12 +4494,13 @@ index 6463342..951c2fe 100644 VALUE_LVAL (v) = lval_memory; set_value_address (v, addr); return v; -@@ -617,10 +609,11 @@ struct value * +@@ -626,11 +618,12 @@ struct value * value_from_register (struct type *type, int regnum, struct frame_info *frame) { struct gdbarch *gdbarch = get_frame_arch (frame); - struct type *type1 = check_typedef (type); struct value *v; + int optim, unavail, ok; - if (gdbarch_convert_register_p (gdbarch, regnum, type1)) + type = check_typedef (type); @@ -3557,15 +4509,15 @@ index 6463342..951c2fe 100644 { /* The ISA/ABI need to something weird when obtaining the specified value from this register. It might need to -@@ -634,7 +627,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame) +@@ -643,7 +636,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame) + VALUE_LVAL (v) = lval_register; VALUE_FRAME_ID (v) = get_frame_id (frame); VALUE_REGNUM (v) = regnum; - gdbarch_register_to_value (gdbarch, -- frame, regnum, type1, value_contents_raw (v)); -+ frame, regnum, type, value_contents_raw (v)); +- ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1, ++ ok = gdbarch_register_to_value (gdbarch, frame, regnum, type, + value_contents_raw (v), &optim, + &unavail); } - else - { diff --git a/gdb/gdbinit.in b/gdb/gdbinit.in index ffb7f53..a2e7e94 100644 --- a/gdb/gdbinit.in @@ -5419,50 +6371,15 @@ index 819c6b8..bef8a35 100644 rather than setting it directly to check that the length is only set once. It also enables the 'maint set/show show-debug-regs' diff --git a/gdb/infcall.c b/gdb/infcall.c -index 75de56c..2a64a0e 100644 +index d42248e..ca23704 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c -@@ -228,6 +228,56 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg, +@@ -228,6 +228,21 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg, return value_cast (type, arg); } -+/* Call gnu-ifunc (STT_GNU_IFUNC - a function returning addresss of a real -+ function to call). PC is the gnu-ifunc function entry. Function returns -+ function entry of the gnu-ifunc-resolved function to call. If RETVAL_TYPEP -+ is not NULL fill in *RETVAL_TYPEP with return type of the gnu-ifunc-resolved -+ function to call. Keep *RETVAL_TYPEP intact if the return type could not be -+ found. */ -+ -+static CORE_ADDR -+gnu_ifunc_resolve (struct gdbarch *gdbarch, CORE_ADDR pc) -+{ -+ char *name_at_pc; -+ CORE_ADDR start_at_pc, address; -+ struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func; -+ struct value *function, *address_val; -+ -+ if (find_pc_partial_function (pc, &name_at_pc, &start_at_pc, NULL) -+ && start_at_pc == pc) -+ { -+ if (resolve_gnu_ifunc (name_at_pc, &address)) -+ return address; -+ } -+ else -+ name_at_pc = NULL; -+ -+ function = allocate_value (func_func_type); -+ set_value_address (function, pc); -+ -+ /* gnu-ifuncs have no arguments. FUNCTION is the function entry address -+ while ADDRESS is a possible function descriptor.. */ -+ address_val = call_function_by_hand (function, 0, NULL); -+ address = value_as_address (address_val); -+ -+ if (name_at_pc) -+ gnu_ifunc_record_cache (gdbarch, name_at_pc, address); -+ -+ return gdbarch_convert_from_func_ptr_addr (gdbarch, address, ¤t_target); -+} ++/* Return the return type of a function with its first instruction exactly at ++ the PC address. Return NULL otherwise. */ + +static struct type * +find_function_return_type (CORE_ADDR pc) @@ -5479,7 +6396,7 @@ index 75de56c..2a64a0e 100644 /* Determine a function's address and its return type from its value. Calls error() if the function is not valid for calling. */ -@@ -236,7 +286,6 @@ find_function_addr (struct value *function, struct type **retval_type) +@@ -236,7 +251,6 @@ find_function_addr (struct value *function, struct type **retval_type) { struct type *ftype = check_typedef (value_type (function)); struct gdbarch *gdbarch = get_type_arch (ftype); @@ -5487,7 +6404,7 @@ index 75de56c..2a64a0e 100644 struct type *value_type = NULL; CORE_ADDR funaddr; -@@ -244,24 +293,34 @@ find_function_addr (struct value *function, struct type **retval_type) +@@ -244,24 +258,34 @@ find_function_addr (struct value *function, struct type **retval_type) part of it. */ /* Determine address to call. */ @@ -5519,7 +6436,7 @@ index 75de56c..2a64a0e 100644 - funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr, - ¤t_target); - value_type = TYPE_TARGET_TYPE (ftype); -+ funaddr = gnu_ifunc_resolve (gdbarch, funaddr); ++ funaddr = gnu_ifunc_resolve_addr (gdbarch, funaddr); + + /* Skip querying the function symbol if no RETVAL_TYPE has been + asked for. */ @@ -5532,8 +6449,194 @@ index 75de56c..2a64a0e 100644 { /* Handle the case of functions lacking debugging info. Their values are characters since their addresses are char. */ +diff --git a/gdb/infrun.c b/gdb/infrun.c +index 7cee7c8..751c9ef 100644 +--- a/gdb/infrun.c ++++ b/gdb/infrun.c +@@ -54,6 +54,8 @@ + #include "inline-frame.h" + #include "jit.h" + #include "tracepoint.h" ++#include "stap-probe.h" ++#include "objfiles.h" + + /* Prototypes for local functions */ + +@@ -2247,7 +2249,7 @@ static void insert_step_resume_breakpoint_at_sal (struct gdbarch *, + struct frame_id); + static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR); + static void check_exception_resume (struct execution_control_state *, +- struct frame_info *, struct symbol *); ++ struct frame_info *); + + static void stop_stepping (struct execution_control_state *ecs); + static void prepare_to_wait (struct execution_control_state *ecs); +@@ -4164,9 +4166,17 @@ process_event_stop_test: + + if (what.is_longjmp) + { +- if (!gdbarch_get_longjmp_target_p (gdbarch) +- || !gdbarch_get_longjmp_target (gdbarch, +- frame, &jmp_buf_pc)) ++ struct value *arg_value; ++ ++ /* If we set the longjmp breakpoint via a SystemTap probe, ++ then use it to extract the arguments. The destination ++ PC is the third argument to the probe. */ ++ arg_value = stap_safe_evaluate_at_pc (frame, 2); ++ if (arg_value) ++ jmp_buf_pc = value_as_address (arg_value); ++ else if (!gdbarch_get_longjmp_target_p (gdbarch) ++ || !gdbarch_get_longjmp_target (gdbarch, ++ frame, &jmp_buf_pc)) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, +@@ -4184,12 +4194,7 @@ process_event_stop_test: + insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc); + } + else +- { +- struct symbol *func = get_frame_function (frame); +- +- if (func) +- check_exception_resume (ecs, frame, func); +- } ++ check_exception_resume (ecs, frame); + keep_going (ecs); + return; + +@@ -5263,15 +5268,64 @@ insert_exception_resume_breakpoint (struct thread_info *tp, + } + } + ++/* A helper for check_exception_resume that sets an ++ exception-breakpoint based on a SystemTap probe. */ ++ ++static void ++insert_exception_resume_from_probe (struct thread_info *tp, ++ const struct stap_probe *probe, ++ struct objfile *objfile, ++ struct frame_info *frame) ++{ ++ struct value *arg_value; ++ CORE_ADDR handler; ++ struct breakpoint *bp; ++ ++ arg_value = stap_safe_evaluate_at_pc (frame, 1); ++ if (!arg_value) ++ return; ++ ++ handler = value_as_address (arg_value); ++ ++ if (debug_infrun) ++ fprintf_unfiltered (gdb_stdlog, ++ "infrun: exception resume at %lx\n", ++ (unsigned long) handler); ++ ++ bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame), ++ handler, bp_exception_resume); ++ bp->thread = tp->num; ++ inferior_thread ()->control.exception_resume_breakpoint = bp; ++} ++ + /* This is called when an exception has been intercepted. Check to + see whether the exception's destination is of interest, and if so, + set an exception resume breakpoint there. */ + + static void + check_exception_resume (struct execution_control_state *ecs, +- struct frame_info *frame, struct symbol *func) ++ struct frame_info *frame) + { + struct gdb_exception e; ++ struct objfile *objfile; ++ const struct stap_probe *probe; ++ struct symbol *func; ++ ++ /* First see if this exception unwinding breakpoint was set via a ++ SystemTap probe point. If so, the probe has two arguments: the ++ CFA and the HANDLER. We ignore the CFA, extract the handler, and ++ set a breakpoint there. */ ++ probe = find_probe_by_pc (get_frame_pc (frame), &objfile); ++ if (probe) ++ { ++ insert_exception_resume_from_probe (ecs->event_thread, probe, ++ objfile, frame); ++ return; ++ } ++ ++ func = get_frame_function (frame); ++ if (!func) ++ return; + + TRY_CATCH (e, RETURN_MASK_ERROR) + { +@@ -6253,7 +6307,8 @@ static struct lval_funcs siginfo_value_funcs = + if there's no object available. */ + + static struct value * +-siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var) ++siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var, ++ void *ignore) + { + if (target_has_stack + && !ptid_equal (inferior_ptid, null_ptid) +@@ -6826,6 +6881,13 @@ show_schedule_multiple (struct ui_file *file, int from_tty, + "of all processes is %s.\n"), value); + } + ++static const struct internalvar_funcs siginfo_funcs = ++{ ++ siginfo_make_value, ++ NULL, ++ NULL ++}; ++ + void + _initialize_infrun (void) + { +@@ -7098,7 +7160,7 @@ Tells gdb whether to detach the child of a fork."), + value with a void typed value, and when we get here, gdbarch + isn't initialized yet. At this point, we're quite sure there + isn't another convenience variable of the same name. */ +- create_internalvar_type_lazy ("_siginfo", siginfo_make_value); ++ create_internalvar_type_lazy ("_siginfo", &siginfo_funcs, NULL); + + add_setshow_boolean_cmd ("observer", no_class, + &observer_mode_1, _("\ +diff --git a/gdb/linespec.c b/gdb/linespec.c +index 3959402..24bf534 100644 +--- a/gdb/linespec.c ++++ b/gdb/linespec.c +@@ -43,6 +43,7 @@ + #include "arch-utils.h" + #include + #include "cli/cli-utils.h" ++#include "stap-probe.h" + + /* We share this one with symtab.c, but it is not exported widely. */ + +@@ -756,6 +757,7 @@ keep_name_info (char *ptr) + PC returned is 0. + FILE:FUNCTION -- likewise, but prefer functions in that file. + *EXPR -- line in which address EXPR appears. ++ probe:[OBJFILE:][PROVIDER:]NAME -- a systemtap static probe + + This may all be followed by an "if EXPR", which we ignore. + +@@ -823,6 +825,9 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab, + if (**argptr == '*') + return decode_indirect (argptr); + ++ if (strncmp (*argptr, "probe:", 6) == 0) ++ return parse_stap_probe (argptr); ++ + is_quoted = (strchr (get_gdb_completer_quote_characters (), + **argptr) != NULL); + diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c -index 922a2cf..f7f5798 100644 +index 732812d..03b3d19 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1254,6 +1254,64 @@ iterate_over_lwps (ptid_t filter, @@ -5617,8 +6720,20 @@ index 42cb2fc..05ac11d 100644 /* Create a prototype generic GNU/Linux target. The client can override it with local methods. */ struct target_ops * linux_target (void); +diff --git a/gdb/machoread.c b/gdb/machoread.c +index dbf9ae4..3db9e16 100644 +--- a/gdb/machoread.c ++++ b/gdb/machoread.c +@@ -849,6 +849,7 @@ static const struct sym_fns macho_sym_fns = { + default_symfile_segments, /* Get segment information from a file. */ + NULL, + macho_symfile_relocate, /* Relocate a debug section. */ ++ NULL, /* sym_get_probes */ + &psym_functions + }; + diff --git a/gdb/main.c b/gdb/main.c -index 6be4805..1b00759 100644 +index ff305a1..267f0b0 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -39,6 +39,7 @@ @@ -5638,7 +6753,7 @@ index 6be4805..1b00759 100644 /* These are static so that we can take their address in an initializer. */ static int print_help; -@@ -448,10 +451,14 @@ captured_main (void *data) +@@ -451,10 +454,14 @@ captured_main (void *data) {"args", no_argument, &set_args, 1}, {"l", required_argument, 0, 'l'}, {"return-child-result", no_argument, &return_child_result, 1}, @@ -5654,7 +6769,7 @@ index 6be4805..1b00759 100644 { int option_index; -@@ -469,6 +476,9 @@ captured_main (void *data) +@@ -472,6 +479,9 @@ captured_main (void *data) case 0: /* Long option that just sets a flag. */ break; @@ -5664,7 +6779,7 @@ index 6be4805..1b00759 100644 case OPT_SE: symarg = optarg; execarg = optarg; -@@ -664,7 +674,31 @@ captured_main (void *data) +@@ -667,7 +677,31 @@ captured_main (void *data) /* Now that gdb_init has created the initial inferior, we're in position to set args for that inferior. */ @@ -5697,7 +6812,7 @@ index 6be4805..1b00759 100644 { /* The remaining options are the command-line options for the inferior. The first one is the sym/exec file, and the rest -@@ -913,7 +947,8 @@ captured_main (void *data) +@@ -916,7 +950,8 @@ captured_main (void *data) /* Read in the old history after all the command files have been read. */ @@ -5707,7 +6822,7 @@ index 6be4805..1b00759 100644 if (batch_flag) { -@@ -924,13 +959,25 @@ captured_main (void *data) +@@ -927,13 +962,25 @@ captured_main (void *data) /* Show time and/or space usage. */ do_cleanups (pre_stat_chain); @@ -5739,7 +6854,7 @@ index 6be4805..1b00759 100644 } /* No exit -- exit is through quit_command. */ } -@@ -962,7 +1009,12 @@ print_gdb_help (struct ui_file *stream) +@@ -965,7 +1012,12 @@ print_gdb_help (struct ui_file *stream) fputs_unfiltered (_("\ This is the GNU debugger. Usage:\n\n\ gdb [options] [executable-file [core-file or process-id]]\n\ @@ -5753,7 +6868,7 @@ index 6be4805..1b00759 100644 Options:\n\n\ "), stream); fputs_unfiltered (_("\ -@@ -1000,7 +1052,13 @@ Options:\n\n\ +@@ -1003,7 +1055,13 @@ Options:\n\n\ --nw Do not use a window interface.\n\ --nx Do not read "), stream); fputs_unfiltered (gdbinit, stream); @@ -5781,10 +6896,10 @@ index a401846..26dca8c 100644 varobj_update_one (var, print_values, 1 /* explicit */); diff --git a/gdb/minsyms.c b/gdb/minsyms.c -index 8497991..4635853 100644 +index 4ae7f27..97d425e 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c -@@ -338,8 +338,9 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf) +@@ -333,8 +333,9 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf) msymbol = msymbol->hash_next) { if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 && @@ -5796,11 +6911,11 @@ index 8497991..4635853 100644 { switch (MSYMBOL_TYPE (msymbol)) { -@@ -701,6 +702,16 @@ lookup_minimal_symbol_by_pc (CORE_ADDR pc) +@@ -696,6 +697,69 @@ lookup_minimal_symbol_by_pc (CORE_ADDR pc) return lookup_minimal_symbol_by_pc_section (pc, NULL); } -+/* Return non-zero iff PC is in function implementing gnu-ifunc selection. */ ++/* Return non-zero iff PC is in an STT_GNU_IFUNC function resolver. */ + +int +in_gnu_ifunc_stub (CORE_ADDR pc) @@ -5809,11 +6924,64 @@ index 8497991..4635853 100644 + + return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc; +} ++ ++/* See elf_gnu_ifunc_resolve_addr for its real implementation. */ ++ ++static CORE_ADDR ++stub_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc) ++{ ++ error (_("GDB cannot resolve STT_GNU_IFUNC symbol at address %s without " ++ "the ELF support compiled in."), ++ paddress (gdbarch, pc)); ++} ++ ++/* See elf_gnu_ifunc_resolve_name for its real implementation. */ ++ ++static int ++stub_gnu_ifunc_resolve_name (const char *function_name, ++ CORE_ADDR *function_address_p) ++{ ++ error (_("GDB cannot resolve STT_GNU_IFUNC symbol \"%s\" without " ++ "the ELF support compiled in."), ++ function_name); ++} ++ ++/* See elf_gnu_ifunc_resolver_stop for its real implementation. */ ++ ++static void ++stub_gnu_ifunc_resolver_stop (struct breakpoint *b) ++{ ++ internal_error (__FILE__, __LINE__, ++ _("elf_gnu_ifunc_resolver_stop cannot be reached.")); ++} ++ ++/* See elf_gnu_ifunc_resolver_return_stop for its real implementation. */ ++ ++static void ++stub_gnu_ifunc_resolver_return_stop (struct breakpoint *b) ++{ ++ internal_error (__FILE__, __LINE__, ++ _("elf_gnu_ifunc_resolver_return_stop cannot be reached.")); ++} ++ ++/* See elf_gnu_ifunc_fns for its real implementation. */ ++ ++static const struct gnu_ifunc_fns stub_gnu_ifunc_fns = ++{ ++ stub_gnu_ifunc_resolve_addr, ++ stub_gnu_ifunc_resolve_name, ++ stub_gnu_ifunc_resolver_stop, ++ stub_gnu_ifunc_resolver_return_stop, ++}; ++ ++/* A placeholder for &elf_gnu_ifunc_fns. */ ++ ++const struct gnu_ifunc_fns *gnu_ifunc_fns_p = &stub_gnu_ifunc_fns; + /* Find the minimal symbol named NAME, and return both the minsym struct and its objfile. This only checks the linkage name. Sets *OBJFILE_P and returns the minimal symbol, if it is found. If it -@@ -770,6 +781,7 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address, +@@ -765,6 +829,7 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address, switch (ms_type) { case mst_text: @@ -5821,7 +6989,7 @@ index 8497991..4635853 100644 case mst_file_text: case mst_solib_trampoline: section = SECT_OFF_TEXT (objfile); -@@ -1235,7 +1247,8 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc) +@@ -1230,7 +1295,8 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc) { ALL_MSYMBOLS (objfile, msymbol) { @@ -5831,8 +6999,36 @@ index 8497991..4635853 100644 && strcmp (SYMBOL_LINKAGE_NAME (msymbol), SYMBOL_LINKAGE_NAME (tsymbol)) == 0) return SYMBOL_VALUE_ADDRESS (msymbol); +diff --git a/gdb/mipsread.c b/gdb/mipsread.c +index 74d795d..7e05317 100644 +--- a/gdb/mipsread.c ++++ b/gdb/mipsread.c +@@ -402,6 +402,7 @@ static const struct sym_fns ecoff_sym_fns = + default_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ ++ NULL, /* sym_probe_fns */ + &psym_functions + }; + +diff --git a/gdb/objfiles.c b/gdb/objfiles.c +index f3259dd..1309cdb 100644 +--- a/gdb/objfiles.c ++++ b/gdb/objfiles.c +@@ -846,6 +846,11 @@ objfile_relocate1 (struct objfile *objfile, + obj_section_addr (s)); + } + ++ /* Relocating Systemtap probes. */ ++ if (objfile->sf && objfile->sf->sym_probe_fns) ++ objfile->sf->sym_probe_fns->sym_relocate_probe (objfile, ++ new_offsets, delta); ++ + /* Data changed. */ + return 1; + } diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c -index 618fc17..1180b2f 100644 +index d2efa5b..d98b3a4 100644 --- a/gdb/p-valprint.c +++ b/gdb/p-valprint.c @@ -39,6 +39,7 @@ @@ -5912,10 +7108,10 @@ index 618fc17..1180b2f 100644 } diff --git a/gdb/parse.c b/gdb/parse.c -index 856c24d..6db71c3 100644 +index 02a7d89..81f3f0c 100644 --- a/gdb/parse.c +++ b/gdb/parse.c -@@ -487,9 +487,21 @@ write_exp_msymbol (struct minimal_symbol *msymbol) +@@ -487,9 +487,22 @@ write_exp_msymbol (struct minimal_symbol *msymbol) pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target); if (pc != addr) { @@ -5929,8 +7125,9 @@ index 856c24d..6db71c3 100644 + && SYMBOL_VALUE_ADDRESS (ifunc_msym) == pc) + { + /* A function descriptor has been resolved but PC is still in the -+ gnu-ifunc resolver body (such as because inferior does not run to -+ be able to call it). */ ++ STT_GNU_IFUNC resolver body (such as because inferior does not ++ run to be able to call it). */ ++ + type = mst_text_gnu_ifunc; + } + else @@ -5938,7 +7135,7 @@ index 856c24d..6db71c3 100644 section = NULL; addr = pc; } -@@ -521,6 +533,11 @@ write_exp_msymbol (struct minimal_symbol *msymbol) +@@ -521,6 +534,11 @@ write_exp_msymbol (struct minimal_symbol *msymbol) write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol); break; @@ -5950,7 +7147,7 @@ index 856c24d..6db71c3 100644 case mst_data: case mst_file_data: case mst_bss: -@@ -528,6 +545,10 @@ write_exp_msymbol (struct minimal_symbol *msymbol) +@@ -528,6 +546,10 @@ write_exp_msymbol (struct minimal_symbol *msymbol) write_exp_elt_type (objfile_type (objfile)->nodebug_data_symbol); break; @@ -5961,7 +7158,7 @@ index 856c24d..6db71c3 100644 default: write_exp_elt_type (objfile_type (objfile)->nodebug_unknown_symbol); break; -@@ -1480,6 +1501,7 @@ parser_fprintf (FILE *x, const char *y, ...) +@@ -1480,6 +1502,7 @@ parser_fprintf (FILE *x, const char *y, ...) int operator_check_standard (struct expression *exp, int pos, @@ -5969,7 +7166,7 @@ index 856c24d..6db71c3 100644 int (*objfile_func) (struct objfile *objfile, void *data), void *data) -@@ -1521,7 +1543,7 @@ operator_check_standard (struct expression *exp, int pos, +@@ -1521,7 +1544,7 @@ operator_check_standard (struct expression *exp, int pos, struct type *type = elts[pos + 2 + arg].type; struct objfile *objfile = TYPE_OBJFILE (type); @@ -5978,7 +7175,7 @@ index 856c24d..6db71c3 100644 return 1; } } -@@ -1539,7 +1561,8 @@ operator_check_standard (struct expression *exp, int pos, +@@ -1539,7 +1562,8 @@ operator_check_standard (struct expression *exp, int pos, /* Check objfile where the variable itself is placed. SYMBOL_OBJ_SECTION (symbol) may be NULL. */ @@ -5988,7 +7185,7 @@ index 856c24d..6db71c3 100644 return 1; /* Check objfile where is placed the code touching the variable. */ -@@ -1552,24 +1575,27 @@ operator_check_standard (struct expression *exp, int pos, +@@ -1552,24 +1576,27 @@ operator_check_standard (struct expression *exp, int pos, /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */ @@ -6024,7 +7221,7 @@ index 856c24d..6db71c3 100644 int (*objfile_func) (struct objfile *objfile, void *data), void *data) { -@@ -1584,7 +1610,9 @@ exp_iterate (struct expression *exp, +@@ -1584,7 +1611,9 @@ exp_iterate (struct expression *exp, pos = endpos - oplen; if (exp->language_defn->la_exp_desc->operator_check (exp, pos, @@ -6035,7 +7232,7 @@ index 856c24d..6db71c3 100644 return 1; endpos = pos; -@@ -1615,8 +1643,29 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile) +@@ -1615,8 +1644,29 @@ exp_uses_objfile (struct expression *exp, struct objfile *objfile) { gdb_assert (objfile->separate_debug_objfile_backlink == NULL); @@ -6243,10 +7440,10 @@ index 049cde8..f3d35ec 100644 return ret; diff --git a/gdb/printcmd.c b/gdb/printcmd.c -index 12249a0..69aae01 100644 +index 81360ad..8fa9a99 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c -@@ -970,6 +970,11 @@ print_command_1 (char *exp, int inspect, int voidprint) +@@ -977,6 +977,11 @@ print_command_1 (char *exp, int inspect, int voidprint) else val = access_value_history (0); @@ -6258,7 +7455,7 @@ index 12249a0..69aae01 100644 if (voidprint || (val && value_type (val) && TYPE_CODE (value_type (val)) != TYPE_CODE_VOID)) { -@@ -1471,6 +1476,24 @@ x_command (char *exp, int from_tty) +@@ -1478,6 +1483,24 @@ x_command (char *exp, int from_tty) set_internalvar (lookup_internalvar ("__"), last_examine_value); } } @@ -6283,7 +7480,7 @@ index 12249a0..69aae01 100644 /* Add an expression to the auto-display chain. -@@ -2864,4 +2887,8 @@ Show printing of source filename and line number with ."), NULL, +@@ -2872,4 +2895,8 @@ Show printing of source filename and line number with ."), NULL, add_com ("eval", no_class, eval_command, _("\ Convert \"printf format string\", arg1, arg2, arg3, ..., argn to\n\ a command line, and call it.")); @@ -7318,7 +8515,7 @@ index c010420..3f4a261 100644 diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c -index 515eaec..5d483ed 100644 +index 4381d52..5dff3e2 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -28,6 +28,7 @@ @@ -7361,7 +8558,7 @@ index 515eaec..5d483ed 100644 diff --git a/gdb/python/python.c b/gdb/python/python.c -index 3b10d8c..7485d14 100644 +index 90d5dc8..ec4823e 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -49,8 +49,11 @@ static int gdbpy_should_print_stack = 1; @@ -7376,7 +8573,7 @@ index 3b10d8c..7485d14 100644 static PyMethodDef GdbMethods[]; -@@ -723,6 +726,53 @@ gdbpy_print_stack (void) +@@ -769,6 +772,53 @@ gdbpy_print_stack (void) /* Return the current Progspace. There always is one. */ @@ -7430,7 +8627,7 @@ index 3b10d8c..7485d14 100644 static PyObject * gdbpy_get_current_progspace (PyObject *unused1, PyObject *unused2) -@@ -1108,6 +1158,8 @@ static PyMethodDef GdbMethods[] = +@@ -1194,6 +1244,8 @@ static PyMethodDef GdbMethods[] = "Get a value from history" }, { "execute", (PyCFunction) execute_gdb_command, METH_VARARGS | METH_KEYWORDS, "Execute a gdb command" }, @@ -7440,10 +8637,10 @@ index 3b10d8c..7485d14 100644 "Return a gdb parameter's value" }, diff --git a/gdb/python/python.h b/gdb/python/python.h -index 58d97fc..93d56ef 100644 +index ce0eb35..14572f4 100644 --- a/gdb/python/python.h +++ b/gdb/python/python.h -@@ -30,6 +30,8 @@ void eval_python_from_control_command (struct command_line *); +@@ -32,6 +32,8 @@ void eval_python_from_control_command (struct command_line *); void source_python_script (FILE *stream, const char *file); @@ -7466,8 +8663,20 @@ index 432da99..78c6b1c 100644 } /* Given an executable's ABFD and target, compute the entry-point +diff --git a/gdb/somread.c b/gdb/somread.c +index 70831a0..baf68ea 100644 +--- a/gdb/somread.c ++++ b/gdb/somread.c +@@ -439,6 +439,7 @@ static const struct sym_fns som_sym_fns = + default_symfile_segments, /* Get segment information from a file. */ + NULL, + default_symfile_relocate, /* Relocate a debug section. */ ++ NULL, /* sym_get_probes */ + &psym_functions + }; + diff --git a/gdb/stack.c b/gdb/stack.c -index 6e59cd0..0eacac9 100644 +index 0888b69..c3efd5b 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -366,6 +366,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame, @@ -7492,6 +8701,2147 @@ index 6e59cd0..0eacac9 100644 ui_out_field_stream (uiout, "value", stb); } else +diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c +new file mode 100644 +index 0000000..eb2fb7f +--- /dev/null ++++ b/gdb/stap-probe.c +@@ -0,0 +1,1939 @@ ++/* Systemtap probe support for GDB. ++ ++ Copyright (C) 2011 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ 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 . */ ++ ++#include "defs.h" ++#include "stap-probe.h" ++#include "vec.h" ++#include "ui-out.h" ++#include "gdb_regex.h" ++#include "objfiles.h" ++#include "arch-utils.h" ++#include "command.h" ++#include "filenames.h" ++#include "value.h" ++#include "exceptions.h" ++#include "ax.h" ++#include "ax-gdb.h" ++#include "user-regs.h" ++#include "complaints.h" ++#include "cli/cli-utils.h" ++ ++#include ++ ++enum stap_arg_bitness ++{ ++ STAP_ARG_BITNESS_UNDEFINED, ++ STAP_ARG_BITNESS_32BIT_UNSIGNED, ++ STAP_ARG_BITNESS_32BIT_SIGNED, ++ STAP_ARG_BITNESS_64BIT_UNSIGNED, ++ STAP_ARG_BITNESS_64BIT_SIGNED, ++}; ++ ++struct stap_probe_arg ++{ ++ /* The bitness of this argument. */ ++ enum stap_arg_bitness bitness; ++ ++ /* The string representing this argument. */ ++ char *arg_str; ++}; ++ ++#define STAP_MAX_ARGS 10 ++ ++struct stap_args_info ++{ ++ /* The number of valid parsed arguments. */ ++ int n_args; ++ ++ /* The probe to which these arguments belong. */ ++ struct stap_probe *probe; ++ ++ /* Information about each argument. */ ++ struct stap_probe_arg *arg; ++}; ++ ++/* Struct that contains all the necessary information to evaluate ++ an expression. */ ++ ++struct stap_evaluation_info ++{ ++ /* The constant pointer which holds the expression. This is primarily ++ used for printing error messages. Evaluation functions should ++ not modify this pointer directly; instead, they should use the ++ EXP_BUFFER pointer below. */ ++ const char *saved_expr; ++ ++ /* Modifiable version of the above pointer. */ ++ char *exp_buf; ++ ++ /* The pointer to the current gdbarch. */ ++ struct gdbarch *gdbarch; ++ ++ /* The pointer to the current frame, used when accessing registers' ++ contents. */ ++ struct frame_info *frame; ++ ++ /* The bitness specified for this argument. */ ++ enum stap_arg_bitness bitness; ++ ++ /* Flag to indicate if we are compiling an agent expression. */ ++ int compiling_p; ++ ++ /* If the above flag is true (one), this field will contain the ++ pointer to the agent expression. */ ++ struct agent_expr *aexpr; ++ ++ /* The value we are modifying (for agent expression). */ ++ struct axs_value *value; ++}; ++ ++/* This dummy variable is used when parsing a probe's argument fails. ++ In this case, the number of arguments for this probe is zero, so that's ++ why this variable is useful. */ ++ ++static struct stap_args_info dummy_stap_args_info = ++ { 0, NULL, NULL }; ++ ++/* Evaluation function for probe's argument expressions. LHS represents ++ the left side of the expression, and PREC is the precedence of the ++ last operator identified before calling the function. */ ++ ++static struct value * ++stap_evaluate_probe_argument_2 (struct stap_evaluation_info *eval_info, ++ struct value *lhs, int prec); ++ ++static struct value * ++stap_evaluate_conditionally (struct stap_evaluation_info *eval_info); ++ ++static void ++stap_skip_whitespace_cond (char **s, int inside_paren) ++{ ++ if (inside_paren) ++ *s = skip_spaces (*s); ++} ++ ++static int ++stap_parse_arg (const char **p) ++{ ++ char *cur = (char *) *p; ++ int done = 0; ++ int paren_open = 0; ++ ++ while (!done) ++ { ++ switch (*cur) ++ { ++ case ' ': case 0: ++ /* If we're here, then we have already parsed everything ++ from this argument. */ ++ if (paren_open) ++ return 0; ++ done = 1; ++ break; ++ ++ case '(': ++ ++paren_open; ++ ++cur; ++ stap_skip_whitespace_cond (&cur, paren_open); ++ break; ++ ++ case ')': ++ if (!paren_open) ++ return 0; ++ ++ --paren_open; ++ ++cur; ++ if (paren_open) ++ cur = skip_spaces (cur); ++ break; ++ ++ case '+': case '-': ++ case '*': case '/': ++ case '>': case '<': case '|': case '&': ++ case '^': case '!': ++ { ++ char c = *cur; ++ ++ ++cur; ++ switch (*cur) ++ { ++ case '>': ++ if (c != '<' && c != '>') ++ return 0; ++ ++ ++cur; ++ break; ++ ++ case '<': ++ if (c != '<') ++ return 0; ++ ++ ++cur; ++ break; ++ ++ case '=': ++ if (c != '=' && c != '<' && c != '>' && c != '!') ++ return 0; ++ ++ ++cur; ++ break; ++ ++ case '|': ++ if (c != '|') ++ return 0; ++ ++ ++cur; ++ break; ++ ++ case '&': ++ if (c != '&') ++ return 0; ++ ++ ++cur; ++ break; ++ ++ default: ++ break; ++ } ++ /* Infix operators take two arguments, one on either ++ side. Skipping the whitespaces that may happen on the ++ right side. */ ++ stap_skip_whitespace_cond (&cur, paren_open); ++ } ++ break; ++ ++ case '%': ++ { ++ ++cur; ++ stap_skip_whitespace_cond (&cur, paren_open); ++ if (*cur >= 'a' && *cur <= 'z') ++ { ++ /* We're dealing with a register name. */ ++ while (isalnum (*cur)) ++ ++cur; ++ ++ stap_skip_whitespace_cond (&cur, paren_open); ++ ++ /* Some registers (e.g. floating-point register stack ++ registers on Intel i386) have the following syntax: ++ ++ `%st(0)', `%st(1)', and so on. ++ ++ So it's ok to expect parenthesis here. */ ++ if (*cur == '(') ++ { ++ ++cur; ++ stap_skip_whitespace_cond (&cur, paren_open); ++ if (!isdigit (*cur)) ++ /* This is an error, since we only expect numbers ++ inside this parenthesis. */ ++ return 0; ++ ++cur; ++ stap_skip_whitespace_cond (&cur, paren_open); ++ if (*cur != ')') ++ /* We only expect one number. */ ++ return 0; ++ ++cur; ++ stap_skip_whitespace_cond (&cur, paren_open); ++ } ++ } ++ } ++ break; ++ ++ case '$': ++ { ++ /* This is an integer constant. */ ++ ++cur; ++ stap_skip_whitespace_cond (&cur, paren_open); ++ ++ while (isdigit (*cur)) ++ ++cur; ++ ++ stap_skip_whitespace_cond (&cur, paren_open); ++ } ++ break; ++ ++ case '0': case '1': case '2': case '3': case '4': ++ case '5': case '6': case '7': case '8': case '9': ++ { ++ char *old = cur; ++ ++ /* Number. */ ++ while (isdigit (*cur)) ++ ++cur; ++ ++ /* We have to do a lookahead here, because the user may ++ input `2 + 2' (with spaces), and this is not an error. */ ++ cur = skip_spaces (cur); ++ ++ switch (*cur) ++ { ++ case '+': case '-': ++ /* We may find the `@' sign, and it means that the ++ argument has finished, so we shouldn't advance the ++ pointer. */ ++ if (cur[1] && (cur[1] == '4' || cur[1] == '8') ++ && cur[2] && cur[2] == '@') ++ { ++ cur = old; ++ goto fin; ++ } ++ break; ++ ++ case '*': case '/': case '>': case '<': ++ case '|': case '&': case '^': case '!': ++ /* This is a binary operation, which means we'll ++ have to find another number after the operator. */ ++ break; ++ ++ case '(': ++ /* We may also have sentences in the form: ++ ++ `4 (%rax)' */ ++ break; ++ } ++ } ++fin: ++ break; ++ } ++ } ++ ++ *p = cur; ++ ++ return 1; ++} ++ ++static void ++stap_free_args_info (void *args_info_ptr) ++{ ++ struct stap_args_info *a = (struct stap_args_info *) args_info_ptr; ++ int i; ++ ++ for (i = 0; i < STAP_MAX_ARGS; i++) ++ { ++ xfree (a->arg->arg_str); ++ } ++ ++ xfree (a->arg); ++ xfree (a); ++} ++ ++void ++stap_parse_probe_arguments (struct stap_probe *probe) ++{ ++ struct stap_args_info *args_info; ++ struct cleanup *back_to; ++ const char *cur = probe->args; ++ int current_arg = -1; ++ enum ++ { ++ NEW_ARG, ++ BITNESS, ++ PARSE_ARG, ++ } current_state; ++ ++ /* For now, we assume everything is not going to work. */ ++ probe->parsed_args = &dummy_stap_args_info; ++ ++ if (!cur || !*cur || *cur == ':') ++ return; ++ ++ args_info = xmalloc (sizeof (struct stap_args_info)); ++ back_to = make_cleanup (stap_free_args_info, args_info); ++ args_info->arg = xcalloc (STAP_MAX_ARGS, sizeof (struct stap_probe_arg)); ++ ++ /* Ok, let's start. */ ++ current_state = NEW_ARG; ++ ++ while (*cur) ++ { ++ switch (current_state) ++ { ++ case NEW_ARG: ++ ++current_arg; ++ ++ if (current_arg >= STAP_MAX_ARGS) ++ { ++ complaint (&symfile_complaints, ++ _("probe `%s' has more arguments than the maximum " ++ "allowed"), probe->name); ++ do_cleanups (back_to); ++ return; ++ } ++ ++ current_state = BITNESS; ++ break; ++ ++ case BITNESS: ++ { ++ enum stap_arg_bitness b; ++ int got_minus = 0; ++ ++ /* We expect to find something like: ++ ++ N@OP ++ ++ Where `N' can be [+,-][4,8]. This is not mandatory, so ++ we check it here. If we don't find it, go to the next ++ state. */ ++ if ((*cur == '-' && cur[1] && cur[2] != '@') ++ && cur[1] != '@') ++ { ++ current_state = PARSE_ARG; ++ args_info->arg[current_arg].bitness ++ = STAP_ARG_BITNESS_UNDEFINED; ++ break; ++ } ++ ++ if (*cur == '-') ++ { ++ /* Discard the `-'. */ ++ ++cur; ++ got_minus = 1; ++ } ++ ++ if (*cur == '4') ++ b = got_minus ? STAP_ARG_BITNESS_32BIT_SIGNED ++ : STAP_ARG_BITNESS_32BIT_UNSIGNED; ++ else if (*cur == '8') ++ b = got_minus ? STAP_ARG_BITNESS_64BIT_SIGNED ++ : STAP_ARG_BITNESS_64BIT_UNSIGNED; ++ else ++ { ++ /* We have an error, because we don't expect anything ++ except 4 and 8. */ ++ complaint (&symfile_complaints, ++ _("unrecognized bitness `%c' for probe `%s'"), ++ *cur, probe->name); ++ do_cleanups (back_to); ++ return; ++ } ++ ++ args_info->arg[current_arg].bitness = b; ++ /* Discard the number and the `@' sign. */ ++ cur += 2; ++ /* Move on. */ ++ current_state = PARSE_ARG; ++ } ++ break; ++ ++ case PARSE_ARG: ++ { ++ const char *start = cur; ++ ++ if (!stap_parse_arg (&cur)) ++ { ++ /* We have tried to parse this argument, but it's ++ malformed. This is an error. */ ++ do_cleanups (back_to); ++ return; ++ } ++ ++ args_info->arg[current_arg].arg_str ++ = savestring (start, cur - start); ++ /* Start it over again. */ ++ cur = skip_spaces ((char *) cur); ++ current_state = NEW_ARG; ++ } ++ break; ++ } ++ ++ if (!*cur && current_state != NEW_ARG) ++ { ++ /* We reached the end of the argument string, but we're ++ still in the middle of the process of parsing an argument. ++ It means the argument string is malformed. */ ++ complaint (&symfile_complaints, ++ _("malformed argument for probe `%s'"), ++ probe->name); ++ do_cleanups (back_to); ++ return; ++ } ++ } ++ ++ args_info->n_args = current_arg + 1; ++ args_info->arg = xrealloc (args_info->arg, ++ args_info->n_args ++ * sizeof (struct stap_probe_arg)); ++ args_info->probe = probe; ++ ++ probe->parsed_args = args_info; ++ ++ discard_cleanups (back_to); ++} ++ ++int ++stap_get_probe_argument_count (const struct stap_probe *probe) ++{ ++ if (!probe->parsed_args) ++ stap_parse_probe_arguments ((struct stap_probe *) probe); ++ ++ return probe->parsed_args->n_args; ++} ++ ++/* Returns the operator precedence level of OP, or zero if the operator ++ code was not recognized. ++ The levels were taken from the gas manual. */ ++ ++static int ++stap_get_operator_prec (enum exp_opcode op) ++{ ++ switch (op) ++ { ++ case BINOP_LOGICAL_OR: ++ return 1; ++ ++ case BINOP_LOGICAL_AND: ++ return 2; ++ ++ case BINOP_ADD: case BINOP_SUB: ++ case BINOP_EQUAL: case BINOP_NOTEQUAL: ++ case BINOP_LESS: case BINOP_LEQ: ++ case BINOP_GTR: case BINOP_GEQ: ++ return 3; ++ ++ case BINOP_BITWISE_IOR: case BINOP_BITWISE_AND: ++ case BINOP_BITWISE_XOR: case UNOP_LOGICAL_NOT: ++ return 4; ++ ++ case BINOP_MUL: case BINOP_DIV: case BINOP_REM: ++ case BINOP_LSH: case BINOP_RSH: ++ return 5; ++ ++ default: ++ return 0; ++ } ++} ++ ++/* Given S, this function reads the operator in it and fills the OP ++ pointer with its code. Returns 1 on success, zero if the operator ++ was not recognized. */ ++ ++static int ++stap_get_opcode (char **s, enum exp_opcode *op) ++{ ++ char c = **s; ++ int ret = 1; ++ ++ *s += 1; ++ ++ switch (c) ++ { ++ case '*': ++ *op = BINOP_MUL; ++ break; ++ ++ case '/': ++ *op = BINOP_DIV; ++ break; ++ ++ case '%': ++ { ++ if (isalpha (**s)) ++ { ++ /* Dealing with a register name. */ ++ ret = 0; ++ break; ++ } ++ ++ *op = BINOP_REM; ++ } ++ break; ++ ++ case '<': ++ *op = BINOP_LESS; ++ if (**s == '<') ++ { ++ *s += 1; ++ *op = BINOP_LSH; ++ } ++ else if (**s == '=') ++ { ++ *s += 1; ++ *op = BINOP_LEQ; ++ } ++ else if (**s == '>') ++ { ++ *s += 1; ++ *op = BINOP_NOTEQUAL; ++ } ++ break; ++ ++ case '>': ++ *op = BINOP_GTR; ++ if (**s == '>') ++ { ++ *s += 1; ++ *op = BINOP_RSH; ++ } ++ else if (**s == '=') ++ { ++ *s += 1; ++ *op = BINOP_GEQ; ++ } ++ break; ++ ++ case '|': ++ *op = BINOP_BITWISE_IOR; ++ if (**s == '|') ++ { ++ *s += 1; ++ *op = BINOP_LOGICAL_OR; ++ } ++ break; ++ ++ case '&': ++ *op = BINOP_BITWISE_AND; ++ if (**s == '&') ++ { ++ *s += 1; ++ *op = BINOP_LOGICAL_AND; ++ } ++ break; ++ ++ case '^': ++ *op = BINOP_BITWISE_XOR; ++ break; ++ ++ case '!': ++ *op = UNOP_LOGICAL_NOT; ++ break; ++ ++ case '+': ++ *op = BINOP_ADD; ++ break; ++ ++ case '-': ++ *op = BINOP_SUB; ++ break; ++ ++ case '=': ++ if (**s != '=') ++ { ++ ret = 0; ++ break; ++ } ++ *op = BINOP_EQUAL; ++ break; ++ ++ default: ++ /* We didn't find any operator. */ ++ *s -= 1; ++ return 0; ++ } ++ ++ return ret; ++} ++ ++static void ++stap_opcode_to_ax (struct stap_evaluation_info *eval_info, ++ enum exp_opcode opcode) ++{ ++ struct agent_expr *expr = eval_info->aexpr; ++ ++ switch (opcode) ++ { ++ case BINOP_MUL: ++ ax_simple (expr, aop_mul); ++ break; ++ ++ case BINOP_DIV: ++ /* FIXME: Should we sign-extend the operands? */ ++ ax_simple (expr, aop_div_signed); ++ break; ++ ++ case BINOP_REM: ++ ax_simple (expr, aop_rem_unsigned); ++ break; ++ ++ case BINOP_LESS: ++ /* FIXME: Should we sign-extend the operands? */ ++ ax_simple (expr, aop_less_signed); ++ break; ++ ++ case BINOP_LEQ: ++ /* A <= B is !(B < A) */ ++ ax_simple (expr, aop_swap); ++ ax_simple (expr, aop_less_signed); ++ ax_simple (expr, aop_log_not); ++ break; ++ ++ case BINOP_GTR: ++ /* A > B is B < A */ ++ ax_simple (expr, aop_swap); ++ ax_simple (expr, aop_less_signed); ++ break; ++ ++ case BINOP_GEQ: ++ /* A >= B is !(A < B) */ ++ ax_simple (expr, aop_less_signed); ++ ax_simple (expr, aop_log_not); ++ break; ++ ++ case BINOP_NOTEQUAL: ++ ax_simple (expr, aop_equal); ++ ax_simple (expr, aop_log_not); ++ break; ++ ++ case BINOP_LSH: ++ ax_simple (expr, aop_lsh); ++ break; ++ ++ case BINOP_RSH: ++ ax_simple (expr, aop_rsh_unsigned); ++ break; ++ ++ case BINOP_BITWISE_IOR: ++ ax_simple (expr, aop_bit_or); ++ break; ++ ++ case BINOP_LOGICAL_OR: ++ /* FIXME: ????? */ ++// ax_simple (expr, aop_ ++ break; ++ ++ case BINOP_BITWISE_AND: ++ ax_simple (expr, aop_bit_and); ++ break; ++ ++ case BINOP_LOGICAL_AND: ++ /* FIXME: ???? */ ++ break; ++ ++ case BINOP_BITWISE_XOR: ++ ax_simple (expr, aop_bit_xor); ++ break; ++ ++ case UNOP_LOGICAL_NOT: ++ ax_simple (expr, aop_log_not); ++ break; ++ ++ case BINOP_ADD: ++ ax_simple (expr, aop_add); ++ break; ++ ++ case BINOP_SUB: ++ ax_simple (expr, aop_sub); ++ break; ++ ++ case BINOP_EQUAL: ++ ax_simple (expr, aop_equal); ++ break; ++ ++ default: ++ error (_("Invalid operator.")); ++ } ++} ++ ++/* Returns 1 if *S is an operator, zero otherwise. */ ++ ++static int ++stap_is_operator (char *s) ++{ ++ char op; ++ ++ if (!s || !*s) ++ return 0; ++ ++ op = *s; ++ ++ if (*s == '%' && isalpha (s[1])) ++ /* Register name. */ ++ return 0; ++ ++ return (op == '+' || op == '-' || op == '*' || op == '/' ++ || op == '>' || op == '<' || op == '!' || op == '^' ++ || op == '|' || op == '&' || op == '%' || op == '='); ++} ++ ++/* This function fetches the value of the register whose ++ name starts in the expression buffer. It also applies any register ++ displacements (e.g., `-4(%eax)'), and indirects the contents of the ++ register (e.g., `(%eax)'). It returns RET if the operation has succeeded, ++ or calls `error' otherwise. */ ++ ++static struct value * ++stap_fetch_reg_value (struct stap_evaluation_info *eval_info, ++ struct value *displacement) ++{ ++ const char *start; ++ char *s = eval_info->exp_buf; ++ struct gdbarch *gdbarch = eval_info->gdbarch; ++ struct frame_info *frame = eval_info->frame; ++ enum stap_arg_bitness bitness = eval_info->bitness; ++#define REG_NAME_MAX_SIZE 20 ++ char regname[REG_NAME_MAX_SIZE + 1]; ++ int len, regnum, indirect_p = 0; ++ struct value *ret; ++ ++ /* The function which called us did not check if the expression ++ buffer was empty. */ ++ gdb_assert (s && *s); ++ ++ /* Valid register name on x86 platforms are: ++ ++ [paren]%{a-z0-9}[paren] ++ ++ Let's check for that here. */ ++ if (*s == '(') ++ { ++ ++s; ++ if (!*s || *s != '%' ++ || (*s == '%' && !isalpha (s[1]))) ++ error (_("Invalid register name on expression `%s'."), ++ eval_info->saved_expr); ++ ++s; ++ /* The presence of parenthesis means that we want to indirect ++ the register. */ ++ indirect_p = 1; ++ } ++ else if (*s == '%') ++ { ++ ++s; ++ if (!*s || !isalpha (*s)) ++ error (_("Invalid register name on expression `%s'."), ++ eval_info->saved_expr); ++ } ++ else ++ error (_("Invalid register name on expression `%s'."), ++ eval_info->saved_expr); ++ ++ if (displacement && !indirect_p) ++ /* We cannot apply displacement to non-indirect register access. */ ++ error (_("Trying to apply displacement without indirecting register " ++ "on expression `%s'."), eval_info->saved_expr); ++ ++ /* Ok, let's calculate the size of the register name. */ ++ start = s; ++ while (isalnum (*s)) ++ ++s; ++ ++ len = s - start; ++ ++ if (*s == ')') ++ ++s; ++ ++ if (len >= REG_NAME_MAX_SIZE) ++ error (_("The register name is greater than the supported size " ++ "on expression `%s'."), eval_info->saved_expr); ++ ++ strncpy (regname, start, len); ++ regname[len] = '\0'; ++ ++ /* Translating the register name into the corresponding number. */ ++ regnum = user_reg_map_name_to_regnum (gdbarch, regname, len); ++ ++ if (regnum == -1) ++ error (_("Invalid register name `%s' on expression `%s'."), ++ regname, eval_info->saved_expr); ++ ++ if (eval_info->compiling_p) ++ ax_reg (eval_info->aexpr, regnum); ++ else ++ ret = value_of_register (regnum, frame); ++ ++ if (indirect_p) ++ { ++ struct type *t = NULL; ++ enum agent_op aop; ++ ++ /* If the user has specified that the register must be indirected, ++ we should know what's the correct type to cast it before making ++ the indirection. This type corresponds to the bitness specified ++ before the `@' sign on the argument string, or it defaults to ++ `unsigned long' if the `@' were not present. */ ++ ++ switch (bitness) ++ { ++ case STAP_ARG_BITNESS_UNDEFINED: ++ if (eval_info->compiling_p) ++ aop = aop_ref32; ++ else ++ t = lookup_pointer_type ++ (builtin_type (gdbarch)->builtin_unsigned_long); ++ break; ++ ++ case STAP_ARG_BITNESS_32BIT_SIGNED: ++ if (eval_info->compiling_p) ++ aop = aop_ref32; ++ else ++ t = lookup_pointer_type ++ (builtin_type (gdbarch)->builtin_int32); ++ break; ++ ++ case STAP_ARG_BITNESS_32BIT_UNSIGNED: ++ if (eval_info->compiling_p) ++ aop = aop_ref32; ++ else ++ t = lookup_pointer_type ++ (builtin_type (gdbarch)->builtin_uint32); ++ break; ++ ++ case STAP_ARG_BITNESS_64BIT_SIGNED: ++ if (eval_info->compiling_p) ++ aop = aop_ref64; ++ else ++ t = lookup_pointer_type ++ (builtin_type (gdbarch)->builtin_int64); ++ break; ++ ++ case STAP_ARG_BITNESS_64BIT_UNSIGNED: ++ if (eval_info->compiling_p) ++ aop = aop_ref64; ++ else ++ t = lookup_pointer_type ++ (builtin_type (gdbarch)->builtin_uint64); ++ break; ++ ++ default: ++ internal_error (__FILE__, __LINE__, ++ _("Undefined bitness for probe.")); ++ break; ++ } ++ ++ if (displacement) ++ { ++ if (eval_info->compiling_p) ++ { ++ ax_const_l (eval_info->aexpr, value_as_long (displacement)); ++ /* FIXME: Is this correct? */ ++ ax_simple (eval_info->aexpr, aop_add); ++ } ++ else ++ ret = value_ptradd (ret, value_as_long (displacement)); ++ } ++ ++ if (eval_info->compiling_p) ++ ax_simple (eval_info->aexpr, aop); ++ else ++ { ++ ret = value_cast (t, ret); ++ ret = value_ind (ret); ++ } ++ } ++ ++ /* Updating the expression buffer pointer, because we have made ++ some modifications to it before. */ ++ eval_info->exp_buf = s; ++ ++ return eval_info->compiling_p ? (struct value *) 1 : ret; ++} ++ ++/* This function tries to evaluate a single operand of the expression. ++ ++ Single operands can be: ++ ++ - unary operators `-' and `~'; ++ - integer constants (beginning with `$'); ++ - register access, with/out displacement and indirection. */ ++ ++static struct value * ++stap_evaluate_single_operand (struct stap_evaluation_info *eval_info) ++{ ++ struct gdbarch *gdbarch = eval_info->gdbarch; ++ struct frame_info *frame = eval_info->frame; ++ enum stap_arg_bitness bitness = eval_info->bitness; ++ struct value *res; ++ ++ switch (*eval_info->exp_buf) ++ { ++ case '-': case '~': ++ { ++ char c = *eval_info->exp_buf; ++ ++ /* This is a binary operator (either `-' or `~'). ++ ++ If it is followed by a parenthesis, and this parenthesis ++ is NOT followed by a `%', then we are dealing with an expression ++ like `-(2 + 3)' or `~(2 + 3)'. We just have to treat separately ++ and return the result after applying the operation (`-' or `~'). ++ ++ If it is followed by a digit, then we have only one choice: it ++ is a displacement argument for a register access, like ++ `-4(%eax)'. It also means that the operator can *only* be `-', ++ and the characters immediately after the number *must* be `(%'. ++ ++ If it is followed by a `$', then it is an integer constant, and ++ we should apply the correct operation to it. */ ++ ++ ++eval_info->exp_buf; ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ if (*eval_info->exp_buf ++ && *eval_info->exp_buf == '(' ++ && eval_info->exp_buf[1] != '%') ++ { ++ struct value *tmp_res; ++ ++ /* We're not dealing with a register name, but with an ++ expression like `-(2 + 3)' or `~(2 + 3)'. We first have ++ to evaluate the right side of the expression (i.e., the ++ parenthesis), and then apply the specified operation ++ (either `-' or `~') to it. */ ++ tmp_res = stap_evaluate_conditionally (eval_info); ++ ++ if (c == '-') ++ { ++ if (eval_info->compiling_p) ++ { ++ /* We have to add `-1' to the stack, and multiply ++ the two values. */ ++ ax_const_l (eval_info->aexpr, -1); ++ ax_simple (eval_info->aexpr, aop_mul); ++ } ++ else ++ res = value_neg (tmp_res); ++ } ++ else ++ { ++ if (eval_info->compiling_p) ++ ax_simple (eval_info->aexpr, aop_bit_not); ++ else ++ res = value_complement (tmp_res); ++ } ++ } ++ else if (isdigit (*eval_info->exp_buf)) ++ { ++ int number; ++ ++ /* This is a number, so it MUST be a register displacement. ++ The only operator allowed here is `-', it MUST be ++ followed by a number, and the number MUST be followed by ++ `(%'. */ ++ if (c != '-') ++ error (_("Invalid operator `%c' for register displacement " ++ "on expression `%s'."), c, eval_info->saved_expr); ++ ++ number = strtol (eval_info->exp_buf, ++ &eval_info->exp_buf, 0) * -1; ++ ++ if (!*eval_info->exp_buf ++ || *eval_info->exp_buf != '(' ++ || (*eval_info->exp_buf == '(' ++ && eval_info->exp_buf[1] != '%')) ++ error (_("Invalid method of indirecting a register on " ++ "expression `%s'."), eval_info->saved_expr); ++ ++ res ++ = value_from_longest (builtin_type (gdbarch)->builtin_int, ++ number); ++ ++ res = stap_fetch_reg_value (eval_info, res); ++ } ++ else if (*eval_info->exp_buf == '$') ++ { ++ int number; ++ ++ /* Last case. We are dealing with an integer constant, so ++ we must read it and then apply the necessary operation, ++ either `-' or `~'. */ ++ ++eval_info->exp_buf; ++ number = strtol (eval_info->exp_buf, ++ &eval_info->exp_buf, 0); ++ ++ if (!eval_info->compiling_p) ++ res ++ = value_from_longest (builtin_type (gdbarch)->builtin_int, ++ number); ++ ++ if (eval_info->compiling_p) ++ ax_const_l (eval_info->aexpr, number); ++ ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ ++ if (c == '-') ++ { ++ if (eval_info->compiling_p) ++ ax_simple (eval_info->aexpr, aop_log_not); ++ else ++ res = value_neg (res); ++ } ++ else ++ { ++ if (eval_info->compiling_p) ++ ax_simple (eval_info->aexpr, aop_bit_not); ++ else ++ res = value_complement (res); ++ } ++ } ++ else ++ error (_("Invalid operand to unary operator `%c' on " ++ "expression `%s'."), c, eval_info->saved_expr); ++ } ++ break; ++ ++ case '0': case '1': case '2': case '3': case '4': ++ case '5': case '6': case '7': case '8': case '9': ++ { ++ int number = strtol (eval_info->exp_buf, &eval_info->exp_buf, 0); ++ ++ /* This is a register displacement with a positive value. We read ++ the number, and then check for the mandatory `(%' part. */ ++ if (!*eval_info->exp_buf ++ || !(*eval_info->exp_buf == '(' ++ && eval_info->exp_buf[1] == '%')) ++ error (_("Invalid register access on expression `%s'."), ++ eval_info->saved_expr); ++ ++ res = value_from_longest (builtin_type (gdbarch)->builtin_int, ++ number); ++ ++ res = stap_fetch_reg_value (eval_info, res); ++ } ++ break; ++ ++ case '$': ++ { ++ int number; ++ ++ /* This is an integer constant. We just have to read the number ++ and return it. */ ++ ++eval_info->exp_buf; ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ ++ number = strtol (eval_info->exp_buf, &eval_info->exp_buf, 0); ++ ++ if (eval_info->compiling_p) ++ ax_const_l (eval_info->aexpr, number); ++ else ++ res = value_from_longest (builtin_type (gdbarch)->builtin_int, ++ number); ++ ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ } ++ break; ++ ++ case '(': case '%': ++ { ++ /* Register access, with or without indirection. */ ++ res = stap_fetch_reg_value (eval_info, /*displacement=*/NULL); ++ } ++ break; ++ ++ default: ++ { ++ error (_("Operator `%c' not recognized on expression `%s'."), ++ *eval_info->exp_buf, eval_info->saved_expr); ++ } ++ } ++ ++ return eval_info->compiling_p ? (struct value *) 1 : res; ++} ++ ++/* This function is responsible for checking the necessary type of evaluation ++ depending on what is the next "thing" in the buffer. Valid values are: ++ ++ - Unary operators; ++ - Integer constants; ++ - Register displacement, indirection, and direct access; ++ - Parenthesized operand. */ ++ ++static struct value * ++stap_evaluate_conditionally (struct stap_evaluation_info *eval_info) ++{ ++ char *s = eval_info->exp_buf; ++ struct value *ret = NULL; ++ ++ if (*s == '-' || *s == '~' /* Unary operators. */ ++ || *s == '$' /* Number (integer constant). */ ++ || (isdigit (*s) && s[1] == '(' && s[2] == '%') /* Displacement. */ ++ || (*s == '(' && s[1] == '%') /* Register indirection. */ ++ || (*s == '%' && isalpha (s[1]))) /* Register value. */ ++ /* This is a single operand, so just evaluate it and return. */ ++ ret = stap_evaluate_single_operand (eval_info); ++ else if (*s == '(') ++ { ++ /* We are dealing with a parenthesized operand. It means we ++ have to evaluate it as it was a separate expression, without ++ left-side or precedence. */ ++ ++eval_info->exp_buf; ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ ++ ret = stap_evaluate_probe_argument_2 (eval_info, ++ /*lhs=*/NULL, /*prec=*/0); ++ ++ if (*eval_info->exp_buf != ')') ++ error (_("Missign close-paren on expression `%s'."), ++ eval_info->saved_expr); ++ ++eval_info->exp_buf; ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ } ++ else ++ error (_("Cannot evaluate expression `%s'."), ++ eval_info->saved_expr); ++ ++ return ret; ++} ++ ++static struct value * ++stap_evaluate_probe_argument_2 (struct stap_evaluation_info *eval_info, ++ struct value *lhs, int prec) ++{ ++ struct value *rhs = NULL; ++ int compiling_p = eval_info->compiling_p; ++ ++ /* This is an operator-precedence parser and evaluator. ++ ++ We work with left- and right-sides of expressions, and ++ evaluate them depending on the precedence of the operators ++ we find. */ ++ ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ ++ if (!lhs) ++ /* We were called without a left-side, either because this is the ++ first call, or because we were called to evaluate a parenthesized ++ expression. It doesn't really matter; we have to evaluate the ++ left-side in order to continue the process. */ ++ lhs = stap_evaluate_conditionally (eval_info); ++ ++ /* Start to evaluate the right-side, and to "join" left and right sides ++ depending on the operation specified. ++ ++ This loop shall continue until we run out of characters in the input, ++ or until we find a close-parenthesis, which means that we've reached ++ the end of a sub-expression. */ ++ while (eval_info->exp_buf ++ && *eval_info->exp_buf ++ && *eval_info->exp_buf != ')') ++ { ++ char *tmp_exp_buf; ++ enum exp_opcode opcode; ++ int cur_prec; ++ ++ if (!stap_is_operator (eval_info->exp_buf)) ++ error (_("Invalid operator `%c' on expression `%s'."), ++ *eval_info->exp_buf, eval_info->saved_expr); ++ ++ /* We have to save the current value of the expression buffer because ++ the `stap_get_opcode' modifies it in order to get the current ++ operator. If this operator's precedence is lower than PREC, we ++ should return and not advance the expression buffer pointer. */ ++ tmp_exp_buf = eval_info->exp_buf; ++ stap_get_opcode (&tmp_exp_buf, &opcode); ++ ++ cur_prec = stap_get_operator_prec (opcode); ++ if (cur_prec < prec) ++ /* If the precedence of the operator that we are seeing now is ++ lower than the precedence of the first operator seen before ++ this evaluation process began, it means we should stop evaluating ++ and return. */ ++ break; ++ ++ eval_info->exp_buf = tmp_exp_buf; ++ eval_info->exp_buf = skip_spaces (eval_info->exp_buf); ++ ++ /* Evaluate the right-side of the expression. */ ++ rhs = stap_evaluate_conditionally (eval_info); ++ ++ /* While we still have operators, try to evaluate another ++ right-side, but using the current right-side as a left-side. */ ++ while (*eval_info->exp_buf ++ && stap_is_operator (eval_info->exp_buf)) ++ { ++ enum exp_opcode lookahead_opcode; ++ int lookahead_prec; ++ ++ /* Saving the current expression buffer position. The explanation ++ is the same as above. */ ++ tmp_exp_buf = eval_info->exp_buf; ++ stap_get_opcode (&tmp_exp_buf, &lookahead_opcode); ++ lookahead_prec = stap_get_operator_prec (lookahead_opcode); ++ ++ if (lookahead_prec <= prec) ++ /* If we are dealing with an operator whose precedence is lower ++ than the first one, just abandon the attempt. */ ++ break; ++ ++ rhs = stap_evaluate_probe_argument_2 (eval_info, ++ rhs, lookahead_prec); ++ } ++ ++ /* Now, "join" both left and right sides into one left-side, using ++ the specified operator. */ ++ if (compiling_p) ++ stap_opcode_to_ax (eval_info, opcode); ++ else ++ lhs = value_binop (lhs, rhs, opcode); ++ } ++ ++ return lhs; ++} ++ ++/* This function fills the necessary arguments for the evaluation function ++ to work. */ ++ ++#define TEST 0 ++static struct value * ++stap_evaluate_probe_argument_1 (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct frame_info *frame, ++ int n) ++{ ++ struct stap_evaluation_info eval_info; ++ char *s = (char *) probe->parsed_args->arg[n].arg_str; ++ struct value *res, *vs[4]; ++#if TEST /*TESTING*/ ++ const char *args[4] = { "$2", ++ "$2 + $3 * $4 + $5", ++ "-($2 + $3)", ++ "(~($2) * $3) / ($1 + $1)" }; ++ int i; ++#endif ++ ++ /* Filling necessary information for evaluation function. */ ++ eval_info.saved_expr = s; ++ eval_info.exp_buf = s; ++ eval_info.gdbarch = get_objfile_arch (objfile); ++ eval_info.frame = frame; ++ eval_info.bitness = probe->parsed_args->arg[n].bitness; ++ /* We are not compiling to an agent expression. */ ++ eval_info.compiling_p = 0; ++ eval_info.aexpr = NULL; ++ ++ res = stap_evaluate_probe_argument_2 (&eval_info, ++ /*lhs=*/NULL, /*prec=*/0); ++#if TEST /* TESTING */ ++ for (i = 0; i < 4; i++) ++ { ++ eval_info.saved_expr = (const char *) args[i]; ++ eval_info.exp_buf = (char *) args[i]; ++ vs[i] = stap_evaluate_probe_argument_2 (&eval_info, ++ /*lhs=*/NULL, /*prec=*/0); ++ ++ fprintf_unfiltered (gdb_stdout, "%ld\n", value_as_long (vs[i])); ++ } ++#endif ++ ++ if (!res) ++ error (_("Could not evaluate expression `%s'."), ++ eval_info.saved_expr); ++ ++ return res; ++} ++ ++struct value * ++stap_evaluate_probe_argument (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct frame_info *frame, ++ int n) ++{ ++ if (!probe->parsed_args) ++ stap_parse_probe_arguments ((struct stap_probe *) probe); ++ ++ if (!probe->parsed_args->arg ++ || n >= probe->parsed_args->n_args) ++ return NULL; ++ ++ return stap_evaluate_probe_argument_1 (objfile, probe, frame, n); ++} ++ ++static void ++stap_compile_to_ax_1 (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct agent_expr *expr, ++ struct axs_value *value, ++ int n) ++{ ++ struct stap_evaluation_info eval_info; ++ char *s = (char *) probe->parsed_args->arg[n].arg_str; ++ ++ /* Filling necessary information for evaluation function. */ ++ eval_info.saved_expr = s; ++ eval_info.exp_buf = s; ++ eval_info.gdbarch = expr->gdbarch; ++ eval_info.frame = NULL; ++ eval_info.bitness = probe->parsed_args->arg[n].bitness; ++ /* We are compiling to an agent expression. */ ++ eval_info.compiling_p = 1; ++ eval_info.aexpr = expr; ++ ++ stap_evaluate_probe_argument_2 (&eval_info, ++ /*lhs=*/NULL, /*prec=*/0); ++} ++ ++void ++stap_compile_to_ax (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct agent_expr *expr, ++ struct axs_value *value, ++ int n) ++{ ++ if (!probe->parsed_args) ++ stap_parse_probe_arguments ((struct stap_probe *) probe); ++ ++ if (!probe->parsed_args->arg ++ || n >= probe->parsed_args->n_args) ++ return; ++ ++ stap_compile_to_ax_1 (objfile, probe, expr, value, n); ++} ++ ++/* See documentation in stap-probe.h. */ ++ ++struct value * ++stap_safe_evaluate_at_pc (struct frame_info *frame, int n) ++{ ++ const struct stap_probe *probe; ++ struct objfile *objfile; ++ int n_probes; ++ ++ probe = find_probe_by_pc (get_frame_pc (frame), &objfile); ++ if (!probe) ++ return NULL; ++ gdb_assert (objfile->sf && objfile->sf->sym_probe_fns); ++ ++ n_probes ++ = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, ++ probe); ++ if (n >= n_probes) ++ return NULL; ++ ++ return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile, ++ probe, ++ frame, ++ n); ++} ++ ++void ++stap_free_parsed_args (struct stap_args_info *parsed_args) ++{ ++ if (!parsed_args ++ || parsed_args == &dummy_stap_args_info ++ || parsed_args->n_args == 0) ++ return; ++ ++ xfree (parsed_args->arg); ++ xfree (parsed_args); ++} ++ ++/* A helper function to extract an argument from *ARG. An argument is ++ delimited by whitespace. The return value is either NULL if no ++ argument was found, or an xmalloc'd string. */ ++ ++static char * ++extract_arg (char **arg) ++{ ++ char *result, *copy; ++ ++ if (!*arg) ++ return NULL; ++ ++ /* Find the start of the argument. */ ++ *arg = skip_spaces (*arg); ++ if (! **arg) ++ return NULL; ++ result = *arg; ++ ++ /* Find the end of the argument. */ ++ *arg = skip_to_space (*arg + 1); ++ ++ if (result == *arg) ++ return NULL; ++ ++ copy = xmalloc (*arg - result + 1); ++ memcpy (copy, result, *arg - result); ++ copy[*arg - result] = '\0'; ++ ++ return copy; ++} ++ ++/* A utility structure. A VEC of these is built when handling "info ++ probes". */ ++ ++struct stap_probe_and_objfile ++{ ++ /* The probe. */ ++ const struct stap_probe *probe; ++ /* The probe's objfile. */ ++ struct objfile *objfile; ++}; ++ ++typedef struct stap_probe_and_objfile stap_entry; ++DEF_VEC_O (stap_entry); ++ ++/* A helper function for collect_probes that compiles a regexp and ++ throws an exception on error. This installs a cleanup to free the ++ resulting pattern on success. If RX is NULL, this does nothing. */ ++ ++static void ++compile_rx_or_error (regex_t *pattern, const char *rx, const char *message) ++{ ++ int code; ++ ++ if (!rx) ++ return; ++ ++ code = regcomp (pattern, rx, REG_NOSUB); ++ if (code == 0) ++ make_regfree_cleanup (pattern); ++ else ++ { ++ char *err = get_regcomp_error (code, pattern); ++ ++ make_cleanup (xfree, err); ++ error (_("%s: %s"), message, err); ++ } ++} ++ ++/* Make a vector of probes matching OBJNAME, PROVIDER, and PROBE. ++ Each argument is a regexp, or NULL, which matches anything. */ ++ ++static VEC (stap_entry) * ++collect_probes (char *objname, char *provider, char *probe) ++{ ++ struct objfile *objfile; ++ VEC (stap_entry) *result = NULL; ++ struct cleanup *cleanup; ++ regex_t obj_pat, prov_pat, probe_pat; ++ ++ cleanup = make_cleanup (VEC_cleanup (stap_entry), &result); ++ ++ compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp")); ++ compile_rx_or_error (&probe_pat, probe, _("Invalid probe regexp")); ++ compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp")); ++ ++ ALL_OBJFILES (objfile) ++ { ++ const struct stap_probe *probes; ++ int i, num_probes; ++ ++ if (! objfile->sf || ! objfile->sf->sym_probe_fns) ++ continue; ++ ++ if (objname) ++ { ++ if (regexec (&obj_pat, objfile->name, 0, NULL, 0) != 0) ++ continue; ++ } ++ ++ probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile, &num_probes); ++ for (i = 0; i < num_probes; ++i) ++ { ++ stap_entry entry; ++ ++ if (provider) ++ { ++ if (regexec (&prov_pat, probes[i].provider, 0, NULL, 0) != 0) ++ continue; ++ } ++ ++ if (probe) ++ { ++ if (regexec (&probe_pat, probes[i].name, 0, NULL, 0) != 0) ++ continue; ++ } ++ ++ entry.probe = &probes[i]; ++ entry.objfile = objfile; ++ VEC_safe_push (stap_entry, result, &entry); ++ } ++ } ++ ++ discard_cleanups (cleanup); ++ return result; ++} ++ ++/* A qsort comparison function for stap_entry objects. */ ++ ++static int ++compare_entries (const void *a, const void *b) ++{ ++ const stap_entry *ea = a; ++ const stap_entry *eb = b; ++ int v; ++ ++ v = strcmp (ea->probe->provider, eb->probe->provider); ++ if (v) ++ return v; ++ ++ v = strcmp (ea->probe->name, eb->probe->name); ++ if (v) ++ return v; ++ ++ if (ea->probe->address < eb->probe->address) ++ return -1; ++ if (ea->probe->address > eb->probe->address) ++ return 1; ++ ++ return strcmp (ea->objfile->name, eb->objfile->name); ++} ++ ++/* Implementation of the "info probes" command. */ ++ ++static void ++info_probes_command (char *arg, int from_tty) ++{ ++ char *provider, *probe = NULL, *objname = NULL; ++ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); ++ VEC (stap_entry) *items; ++ int i, addr_width, any_found; ++ stap_entry *entry; ++ ++ provider = extract_arg (&arg); ++ if (provider) ++ { ++ make_cleanup (xfree, provider); ++ ++ probe = extract_arg (&arg); ++ if (probe) ++ { ++ make_cleanup (xfree, probe); ++ ++ objname = extract_arg (&arg); ++ if (objname) ++ make_cleanup (xfree, objname); ++ } ++ } ++ ++ items = collect_probes (objname, provider, probe); ++ make_cleanup (VEC_cleanup (stap_entry), &items); ++ make_cleanup_ui_out_table_begin_end (uiout, 5, ++ VEC_length (stap_entry, items), ++ "SystemTapProbes"); ++ ++ if (! VEC_empty (stap_entry, items)) ++ qsort (VEC_address (stap_entry, items), ++ VEC_length (stap_entry, items), ++ sizeof (stap_entry), ++ compare_entries); ++ ++ addr_width = 4 + (gdbarch_ptr_bit (get_current_arch ()) / 4); ++ ++ ui_out_table_header (uiout, 10, ui_left, "provider", _("Provider")); ++ ui_out_table_header (uiout, 10, ui_left, "name", _("Name")); ++ ui_out_table_header (uiout, addr_width - 1, ui_left, "addr", _("Where")); ++ ui_out_table_header (uiout, addr_width - 1, ui_left, "semaphore", ++ _("Semaphore")); ++ ui_out_table_header (uiout, 30, ui_left, "object", _("Object")); ++ ui_out_table_body (uiout); ++ ++ for (i = 0; VEC_iterate (stap_entry, items, i, entry); ++i) ++ { ++ struct cleanup *inner; ++ ++ inner = make_cleanup_ui_out_tuple_begin_end (uiout, "probe"); ++ ++ ui_out_field_string (uiout, "provider", entry->probe->provider); ++ ui_out_field_string (uiout, "name", entry->probe->name); ++ ui_out_field_core_addr (uiout, "addr", get_current_arch (), ++ entry->probe->address); ++ if (entry->probe->sem_addr == 0) ++ ui_out_field_skip (uiout, "semaphore"); ++ else ++ ui_out_field_core_addr (uiout, "semaphore", get_current_arch (), ++ entry->probe->sem_addr); ++ ui_out_field_string (uiout, "object", entry->objfile->name); ++ ui_out_text (uiout, "\n"); ++ ++ do_cleanups (inner); ++ } ++ ++ any_found = ! VEC_empty (stap_entry, items); ++ do_cleanups (cleanup); ++ ++ if (! any_found) ++ ui_out_message (uiout, 0, _("No probes matched.\n")); ++} ++ ++ ++ ++const struct stap_probe * ++find_probe_in_objfile (struct objfile *objfile, ++ const char *provider, ++ const char *name) ++{ ++ const struct stap_probe *probes; ++ int i, num_probes; ++ ++ if (! objfile->sf || ! objfile->sf->sym_probe_fns) ++ return NULL; ++ ++ probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile, &num_probes); ++ for (i = 0; i < num_probes; ++i) ++ { ++ if (strcmp (probes[i].provider, provider) != 0) ++ continue; ++ ++ if (strcmp (probes[i].name, name) != 0) ++ continue; ++ ++ return &probes[i]; ++ } ++ ++ return NULL; ++} ++ ++struct symtabs_and_lines ++parse_stap_probe (char **argptr) ++{ ++ char *arg = extract_arg (argptr); ++ char *objfile_name = NULL, *provider = NULL, *name, *p; ++ struct cleanup *cleanup; ++ struct symtabs_and_lines result; ++ struct objfile *objfile; ++ ++ result.sals = NULL; ++ result.nelts = 0; ++ ++ /* The caller ensured that this starts with 'probe:'. */ ++ gdb_assert (arg && strncmp (arg, "probe:", 6) == 0); ++ cleanup = make_cleanup (xfree, arg); ++ arg += 6; ++ ++ /* Extract each word from the argument, separated by ":"s. */ ++ p = strchr (arg, ':'); ++ if (p == NULL) ++ { ++ /* This is `probe:name'. */ ++ name = arg; ++ } ++ else ++ { ++ char *hold = p + 1; ++ ++ *p = '\0'; ++ p = strchr (hold, ':'); ++ if (p == NULL) ++ { ++ /* This is `probe:provider:name'. */ ++ provider = arg; ++ name = hold; ++ } ++ else ++ { ++ /* This is `probe:objfile:provider:name'. */ ++ *p = '\0'; ++ objfile_name = arg; ++ provider = hold; ++ name = p + 1; ++ } ++ } ++ ++ if (*name == '\0') ++ error (_("no probe name specified")); ++ if (provider && *provider == '\0') ++ error (_("invalid provider name")); ++ if (objfile_name && *objfile_name == '\0') ++ error (_("invalid objfile name")); ++ ++ ALL_OBJFILES (objfile) ++ { ++ const struct stap_probe *probes; ++ int i, num_probes; ++ ++ if (! objfile->sf || ! objfile->sf->sym_probe_fns) ++ continue; ++ ++ if (objfile_name ++ && FILENAME_CMP (objfile->name, objfile_name) != 0 ++ && FILENAME_CMP (lbasename (objfile->name), objfile_name) != 0) ++ continue; ++ ++ probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile, &num_probes); ++ for (i = 0; i < num_probes; ++i) ++ { ++ struct symtab_and_line *sal; ++ ++ if (provider && strcmp (probes[i].provider, provider) != 0) ++ continue; ++ ++ if (strcmp (probes[i].name, name) != 0) ++ continue; ++ ++ ++result.nelts; ++ result.sals = xrealloc (result.sals, ++ result.nelts * sizeof (struct symtab_and_line)); ++ sal = &result.sals[result.nelts - 1]; ++ ++ init_sal (sal); ++ ++ sal->pc = probes[i].address; ++ sal->explicit_pc = 1; ++ sal->section = find_pc_overlay (sal->pc); ++ sal->pspace = current_program_space; ++ sal->semaphore = probes[i].sem_addr; ++ } ++ } ++ ++ if (result.nelts == 0) ++ throw_error (NOT_FOUND_ERROR, ++ _("No probe matching objfile=`%s', provider=`%s', name=`%s'"), ++ objfile_name ? objfile_name : _(""), ++ provider ? provider : _(""), ++ name); ++ ++ do_cleanups (cleanup); ++ ++ return result; ++} ++ ++ ++ ++const struct stap_probe * ++find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out) ++{ ++ struct objfile *objfile; ++ ++ ALL_OBJFILES (objfile) ++ { ++ const struct stap_probe *probes; ++ int i, num_probes; ++ stap_entry entry; ++ ++ if (! objfile->sf || ! objfile->sf->sym_probe_fns) ++ continue; ++ ++ /* If this proves too inefficient, we can replace with a hash. */ ++ probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile, &num_probes); ++ for (i = 0; i < num_probes; ++i) ++ { ++ if (probes[i].address == pc) ++ { ++ *objfile_out = objfile; ++ return &probes[i]; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++/* This is called to compute the value of one of the $_probe_arg* ++ convenience variables. */ ++ ++static struct value * ++compute_probe_arg (struct gdbarch *arch, struct internalvar *ivar, ++ void *data) ++{ ++ struct frame_info *frame = get_selected_frame (_("No frame selected")); ++ CORE_ADDR pc = get_frame_pc (frame); ++ int sel = (int) (uintptr_t) data; ++ struct objfile *objfile; ++ const struct stap_probe *pc_probe; ++ int n_probes; ++ ++ /* SEL==10 means "_probe_argc". */ ++ gdb_assert (sel >= 0 && sel <= 10); ++ ++ pc_probe = find_probe_by_pc (pc, &objfile); ++ if (pc_probe == NULL) ++ error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc)); ++ ++ n_probes ++ = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, ++ pc_probe); ++ if (sel == 10) ++ return value_from_longest (builtin_type (arch)->builtin_int, n_probes); ++ ++ gdb_assert (sel >= 0); ++ if (sel >= n_probes) ++ error (_("Invalid probe argument %d -- probe has %d arguments available"), ++ sel, n_probes); ++ ++ return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile, ++ pc_probe, ++ frame, sel); ++} ++ ++/* This is called to compile one of the $_probe_arg* convenience ++ variables into an agent expression. */ ++ ++static void ++compile_probe_arg (struct internalvar *ivar, struct agent_expr *expr, ++ struct axs_value *value, void *data) ++{ ++ CORE_ADDR pc = expr->scope; ++ int sel = (int) (uintptr_t) data; ++ struct objfile *objfile; ++ const struct stap_probe *pc_probe; ++ int n_probes; ++ ++ /* SEL==10 means "_probe_argc". */ ++ gdb_assert (sel >= 0 && sel <= 10); ++ ++ pc_probe = find_probe_by_pc (pc, &objfile); ++ if (pc_probe == NULL) ++ error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc)); ++ ++ n_probes ++ = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, ++ pc_probe); ++ if (sel == 10) ++ { ++ value->kind = axs_rvalue; ++ value->type = builtin_type (expr->gdbarch)->builtin_int; ++ ax_const_l (expr, n_probes); ++ return; ++ } ++ ++ gdb_assert (sel >= 0); ++ if (sel >= n_probes) ++ error (_("Invalid probe argument %d -- probe has %d arguments available"), ++ sel, n_probes); ++ ++ /* FIXME: this is temporary until AX translation is implemented. */ ++ if (!objfile->sf->sym_probe_fns->sym_compile_to_ax) ++ error (_("cannot translate `$_probe_arg%d' to bytecode"), sel); ++ objfile->sf->sym_probe_fns->sym_compile_to_ax (objfile, pc_probe, ++ expr, value, sel); ++} ++ ++ ++ ++static const struct internalvar_funcs probe_funcs = ++{ ++ compute_probe_arg, ++ compile_probe_arg, ++ NULL ++}; ++ ++void ++_initialize_stap_probe (void) ++{ ++ add_info ("probes", info_probes_command, _("\ ++Show available static probes.\n\ ++Usage: info probes [PROVIDER [NAME [OBJECT]]]\n\ ++Each argument is a regular expression, used to select probes.\n\ ++PROVIDER matches probe provider names.\n\ ++NAME matches the probe names.\n\ ++OBJECT match the executable or shared library name.")); ++ ++ create_internalvar_type_lazy ("_probe_argc", &probe_funcs, ++ (void *) (uintptr_t) 10); ++ create_internalvar_type_lazy ("_probe_arg0", &probe_funcs, ++ (void *) (uintptr_t) 0); ++ create_internalvar_type_lazy ("_probe_arg1", &probe_funcs, ++ (void *) (uintptr_t) 1); ++ create_internalvar_type_lazy ("_probe_arg2", &probe_funcs, ++ (void *) (uintptr_t) 2); ++ create_internalvar_type_lazy ("_probe_arg3", &probe_funcs, ++ (void *) (uintptr_t) 3); ++ create_internalvar_type_lazy ("_probe_arg4", &probe_funcs, ++ (void *) (uintptr_t) 4); ++ create_internalvar_type_lazy ("_probe_arg5", &probe_funcs, ++ (void *) (uintptr_t) 5); ++ create_internalvar_type_lazy ("_probe_arg6", &probe_funcs, ++ (void *) (uintptr_t) 6); ++ create_internalvar_type_lazy ("_probe_arg7", &probe_funcs, ++ (void *) (uintptr_t) 7); ++ create_internalvar_type_lazy ("_probe_arg8", &probe_funcs, ++ (void *) (uintptr_t) 8); ++ create_internalvar_type_lazy ("_probe_arg9", &probe_funcs, ++ (void *) (uintptr_t) 9); ++} +diff --git a/gdb/stap-probe.h b/gdb/stap-probe.h +new file mode 100644 +index 0000000..3a7941f +--- /dev/null ++++ b/gdb/stap-probe.h +@@ -0,0 +1,110 @@ ++/* Systemtap probe support for GDB. ++ ++ Copyright (C) 2011 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ 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 . */ ++ ++#if !defined (STAP_PROBE_H) ++#define STAP_PROBE_H 1 ++ ++struct stap_args_info; ++struct axs_value; ++ ++struct stap_probe ++{ ++ /* The provider of this probe. */ ++ const char *provider; ++ ++ /* The name of the probe. */ ++ const char *name; ++ ++ /* The address where the probe is inserted. */ ++ CORE_ADDR address; ++ ++ /* The address of the probe's semaphore, or 0 if this probe does not ++ have an associated semaphore. */ ++ CORE_ADDR sem_addr; ++ ++ /* Probe's arguments. Users should generally not examine this, but ++ should instead extract information about the arguments using the ++ methods provided in sym_probe_fns. */ ++ const char *args; ++ ++ /* Probe's arguments after parsing. This is an opaque structure that ++ will hold information about the arguments pointed by ARGS. */ ++ struct stap_args_info *parsed_args; ++}; ++ ++ ++/* A helper for linespec that decodes a stap probe specification. It ++ returns a symtabs_and_lines object and updates *ARGPTR or throws an ++ error. */ ++ ++extern struct symtabs_and_lines parse_stap_probe (char **argptr); ++ ++/* Search OBJFILE for a probe with the given PROVIDER and NAME. If a ++ probe is found, return it. If no probe is found, return NULL. */ ++ ++extern const struct stap_probe *find_probe_in_objfile (struct objfile *objfile, ++ const char *provider, ++ const char *name); ++ ++/* Given a PC, find an associated SystemTap probe. If a probe is ++ found, set *OBJFILE_OUT to the probe's objfile, and return the ++ probe. If no probe is found, return NULL. */ ++ ++extern const struct stap_probe *find_probe_by_pc (CORE_ADDR pc, ++ struct objfile **objfile_out); ++ ++/* Given PROBE, this function will parse its arguments and fill the ++ `struct stap_args_info' with proper information about them. */ ++ ++extern void stap_parse_probe_arguments (struct stap_probe *probe); ++ ++/* Given PROBE, returns the number of arguments present in that probe's ++ argument string. */ ++ ++extern int stap_get_probe_argument_count (const struct stap_probe *probe); ++ ++/* Given PARSED_ARGS, frees the space allocated to hold information about ++ the probe's parsed arguments. */ ++ ++extern void stap_free_parsed_args (struct stap_args_info *parsed_args); ++ ++/* Evaluates the probe's argument N, returning a value corresponding ++ to it. */ ++ ++extern struct value *stap_evaluate_probe_argument (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct frame_info *frame, ++ int n); ++ ++/* Compile the probe's argument N to agent expression. */ ++ ++extern void stap_compile_to_ax (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct agent_expr *expr, ++ struct axs_value *value, ++ int n); ++ ++/* A convenience function that finds a probe at the PC in FRAME and ++ evaluates argument N. If there is no probe at that location, or if ++ the probe does not have enough arguments, this returns NULL. */ ++ ++extern struct value *stap_safe_evaluate_at_pc (struct frame_info *frame, ++ int n); ++ ++#endif /* !defined (STAP_PROBE_H) */ +diff --git a/gdb/symfile.h b/gdb/symfile.h +index a0151ea..752c46a 100644 +--- a/gdb/symfile.h ++++ b/gdb/symfile.h +@@ -31,6 +31,11 @@ struct objfile; + struct obj_section; + struct obstack; + struct block; ++struct stap_probe; ++struct value; ++struct frame_info; ++struct agent_expr; ++struct axs_value; + + /* Comparison function for symbol look ups. */ + +@@ -296,6 +301,52 @@ struct quick_symbol_functions + void *data); + }; + ++/* Structure of functions used for SystemTap probe support. If one of ++ these functions is provided, all must be. */ ++ ++struct sym_probe_fns ++{ ++ /* If non-NULL, return an array of SystemTap probe objects. The ++ number of objects is returned in *NUM_PROBES. */ ++ const struct stap_probe *(*sym_get_probes) (struct objfile *, ++ int *num_probes); ++ ++ /* Return the number of arguments available to PROBE. PROBE will ++ have come from a call to this objfile's sym_get_probes method. ++ If you provide an implementation of sym_get_probes, you must ++ implement this method as well. */ ++ int (*sym_get_probe_argument_count) (struct objfile *objfile, ++ const struct stap_probe *probe); ++ ++ /* Evaluate the Nth argument available to PROBE. PROBE will have ++ come from a call to this objfile's sym_get_probes method. N will ++ be between 0 and the number of arguments available to this probe. ++ FRAME is the frame in which the evaluation is done; the frame's ++ PC will match the address of the probe. If you provide an ++ implementation of sym_get_probes, you must implement this method ++ as well. */ ++ struct value *(*sym_evaluate_probe_argument) (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct frame_info *frame, ++ int n); ++ ++ /* Compile the Nth probe argument to an agent expression. PROBE ++ will have come from a call to this objfile's sym_get_probes ++ method. N will be between 0 and the number of arguments ++ available to this probe. EXPR and VALUE are the agent expression ++ that is being updated. */ ++ void (*sym_compile_to_ax) (struct objfile *objfile, ++ const struct stap_probe *probe, ++ struct agent_expr *expr, ++ struct axs_value *value, ++ int n); ++ ++ /* Relocate the probe section of OBJFILE. */ ++ void (*sym_relocate_probe) (struct objfile *objfile, ++ struct section_offsets *new_offsets, ++ struct section_offsets *delta); ++}; ++ + /* Structure to keep track of symbol reading functions for various + object file types. */ + +@@ -366,6 +417,10 @@ struct sym_fns + + bfd_byte *(*sym_relocate) (struct objfile *, asection *sectp, bfd_byte *buf); + ++ /* If non-NULL, this objfile has probe support, and all the probe ++ functions referred to here will be non-NULL. */ ++ const struct sym_probe_fns *sym_probe_fns; ++ + /* The "quick" (aka partial) symbol functions for this symbol + reader. */ + const struct quick_symbol_functions *qf; diff --git a/gdb/symmisc.c b/gdb/symmisc.c index 4be8106..081b532 100644 --- a/gdb/symmisc.c @@ -7507,10 +10857,18 @@ index 4be8106..081b532 100644 ms_type = 'S'; break; diff --git a/gdb/symtab.c b/gdb/symtab.c -index 60bc585..5ee0459 100644 +index 60bc585..734d312 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c -@@ -3006,7 +3006,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], +@@ -770,6 +770,7 @@ init_sal (struct symtab_and_line *sal) + sal->end = 0; + sal->explicit_pc = 0; + sal->explicit_line = 0; ++ sal->semaphore = 0; + } + + +@@ -3006,7 +3007,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], static const enum minimal_symbol_type types3[] = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; static const enum minimal_symbol_type types4[] @@ -7520,7 +10878,7 @@ index 60bc585..5ee0459 100644 enum minimal_symbol_type ourtype2; enum minimal_symbol_type ourtype3; diff --git a/gdb/symtab.h b/gdb/symtab.h -index e946c65..f40e3d4 100644 +index e946c65..6239f7f 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -290,6 +290,9 @@ enum minimal_symbol_type @@ -7529,47 +10887,69 @@ index e946c65..f40e3d4 100644 mst_text, /* Generally executable instructions */ + mst_text_gnu_ifunc, /* Executable code returning address + of executable code */ -+ mst_slot_got_plt, ++ mst_slot_got_plt, /* GOT entries for .plt sections */ mst_data, /* Generally initialized data */ mst_bss, /* Generally uninitialized data */ mst_abs, /* Generally absolute (nonrelocatable) */ -@@ -955,11 +958,25 @@ extern struct symbol *find_pc_sect_function (CORE_ADDR, struct obj_section *); +@@ -953,6 +956,11 @@ extern struct symbol *find_pc_function (CORE_ADDR); + extern struct symbol *find_pc_sect_function (CORE_ADDR, struct obj_section *); + ++extern int find_pc_partial_function_gnu_ifunc (CORE_ADDR pc, char **name, ++ CORE_ADDR *address, ++ CORE_ADDR *endaddr, ++ int *is_gnu_ifunc_p); ++ /* lookup function from address, return name, start addr and end addr. */ --extern int find_pc_partial_function (CORE_ADDR, char **, CORE_ADDR *, -- CORE_ADDR *); -+extern enum find_pc_partial_function_type -+ { -+ FIND_PC_PARTIAL_FUNCTION_NOT_FOUND = 0, -+ FIND_PC_PARTIAL_FUNCTION_NORMAL, -+ FIND_PC_PARTIAL_FUNCTION_GNU_IFUNC -+ } find_pc_partial_function (CORE_ADDR, char **, CORE_ADDR *, CORE_ADDR *); - - extern void clear_pc_function_cache (void); - -+extern int resolve_gnu_ifunc (const char *function_name, -+ CORE_ADDR *function_addressp); -+ -+extern struct minimal_symbol *resolve_gnu_ifunc_by_cache -+ (const char *function_name); -+ -+extern void gnu_ifunc_record_cache (struct gdbarch *gdbarch, -+ const char *function_name, -+ CORE_ADDR function_address); -+ - /* lookup partial symbol table by address and section. */ - - extern struct symtab *find_pc_sect_symtab_via_partial (CORE_ADDR, -@@ -1034,6 +1051,8 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name + extern int find_pc_partial_function (CORE_ADDR, char **, CORE_ADDR *, +@@ -1034,6 +1042,35 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR); +extern int in_gnu_ifunc_stub (CORE_ADDR pc); ++ ++/* Functions for resolving STT_GNU_IFUNC symbols which are implemented only ++ for ELF symbol files. */ ++ ++struct gnu_ifunc_fns ++{ ++ /* See elf_gnu_ifunc_resolve_addr for its real implementation. */ ++ CORE_ADDR (*gnu_ifunc_resolve_addr) (struct gdbarch *gdbarch, CORE_ADDR pc); ++ ++ /* See elf_gnu_ifunc_resolve_name for its real implementation. */ ++ int (*gnu_ifunc_resolve_name) (const char *function_name, ++ CORE_ADDR *function_address_p); ++ ++ /* See elf_gnu_ifunc_resolver_stop for its real implementation. */ ++ void (*gnu_ifunc_resolver_stop) (struct breakpoint *b); ++ ++ /* See elf_gnu_ifunc_resolver_return_stop for its real implementation. */ ++ void (*gnu_ifunc_resolver_return_stop) (struct breakpoint *b); ++}; ++ ++#define gnu_ifunc_resolve_addr gnu_ifunc_fns_p->gnu_ifunc_resolve_addr ++#define gnu_ifunc_resolve_name gnu_ifunc_fns_p->gnu_ifunc_resolve_name ++#define gnu_ifunc_resolver_stop gnu_ifunc_fns_p->gnu_ifunc_resolver_stop ++#define gnu_ifunc_resolver_return_stop \ ++ gnu_ifunc_fns_p->gnu_ifunc_resolver_return_stop ++ ++extern const struct gnu_ifunc_fns *gnu_ifunc_fns_p; + extern struct minimal_symbol * lookup_minimal_symbol_and_objfile (const char *, struct objfile **); +@@ -1072,6 +1109,10 @@ struct symtab_and_line + CORE_ADDR end; + int explicit_pc; + int explicit_line; ++ ++ /* If non-zero, the semaphore location associated with a SystemTap ++ probe. */ ++ CORE_ADDR semaphore; + }; + + extern void init_sal (struct symtab_and_line *sal); diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S new file mode 100644 index 0000000..83faaf6 @@ -8772,13 +12152,13 @@ index d8ee5c0..de4ba75 100644 +} diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-lib.c b/gdb/testsuite/gdb.base/gnu-ifunc-lib.c new file mode 100644 -index 0000000..680530a +index 0000000..dc6710e --- /dev/null +++ b/gdb/testsuite/gdb.base/gnu-ifunc-lib.c @@ -0,0 +1,33 @@ +/* This testcase is part of GDB, the GNU debugger. + -+ Copyright 2009, 2010 Free Software Foundation, Inc. ++ Copyright 2009, 2010, 2011 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 @@ -8811,13 +12191,13 @@ index 0000000..680530a +} diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.c b/gdb/testsuite/gdb.base/gnu-ifunc.c new file mode 100644 -index 0000000..106271f +index 0000000..0ee741f --- /dev/null +++ b/gdb/testsuite/gdb.base/gnu-ifunc.c @@ -0,0 +1,61 @@ +/* This testcase is part of GDB, the GNU debugger. + -+ Copyright 2009, 2010 Free Software Foundation, Inc. ++ Copyright 2009, 2010, 2011 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 @@ -8878,11 +12258,11 @@ index 0000000..106271f +} diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.exp b/gdb/testsuite/gdb.base/gnu-ifunc.exp new file mode 100644 -index 0000000..de59785 +index 0000000..4fcc3bf --- /dev/null +++ b/gdb/testsuite/gdb.base/gnu-ifunc.exp -@@ -0,0 +1,130 @@ -+# Copyright (C) 2009, 2010 Free Software Foundation, Inc. +@@ -0,0 +1,146 @@ ++# Copyright (C) 2009, 2010, 2011 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 @@ -8911,7 +12291,7 @@ index 0000000..de59785 +set libfile "${testfile}-lib" +set libsrc ${libfile}.c +set lib_so ${objdir}/${subdir}/${libfile}.so -+# $lib_o must not have {debug}, it would override the gnu-ifunc ELF markers. ++# $lib_o must not have {debug}, it would override the STT_GNU_IFUNC ELF markers. +set lib_o ${objdir}/${subdir}/${libfile}.o + +# We need DWARF for the "final" function as we "step" into the function and GDB @@ -8919,13 +12299,14 @@ index 0000000..de59785 +# information (DWARF) available. +# +# We must not have DWARF for the "gnu_ifunc" function as DWARF has no way to -+# express the gnu-ifunc type and it would be considered as a regular function -+# due to DWARF by GDB. In ELF gnu-ifunc is expressed by the STT_GNU_IFUNC type. ++# express the STT_GNU_IFUNC type and it would be considered as a regular ++# function due to DWARF by GDB. In ELF gnu-ifunc is expressed by the ++# STT_GNU_IFUNC type. +# +# Both functions need to be in the same shared library file but +# gdb_compile_shlib has no way to specify source-specific compilation options. +# -+# Therefore $libfile contains only the gnu-ifunc function with no DWARF ++# Therefore $libfile contains only the STT_GNU_IFUNC function with no DWARF +# referencing all the other parts from the main executable with DWARF. + +set lib_opts {} @@ -8936,10 +12317,8 @@ index 0000000..de59785 +} + +if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_so $lib_opts] != "" -+ || [gdb_compile ${srcdir}/${subdir}/$srcfile $binfile executable $exec_opts] != "" -+ || [gdb_compile ${srcdir}/${subdir}/$libsrc $lib_o object {}] != "" -+ || [gdb_compile "${srcdir}/${subdir}/$srcfile $lib_o" $staticbinfile executable {debug}] != ""} { -+ untested "Could not compile either $libsrc or $srcfile." ++ || [gdb_compile ${srcdir}/${subdir}/$srcfile $binfile executable $exec_opts] != ""} { ++ untested "Could not compile dynamic executable $binfile." + return -1 +} + @@ -8986,10 +12365,18 @@ index 0000000..de59785 +gdb_test "frame" "#0 +(0x\[0-9a-f\]+ in +)?final \\(.*" "nextcall gnu_ifunc skipped" + + -+# Check any commands not doing an inferior call still compute with address of -+# the gnu-ifunc resolver. ++# Check any commands not doing an inferior call access the address of the ++# STT_GNU_IFUNC resolver, not the target function. + -+gdb_test "p gnu_ifunc" " = {} 0x\[0-9a-f\]+ " "p gnu_ifunc executing" ++if {[istarget powerpc64-*] && [is_lp64_target]} { ++ # With only minimal symbols GDB provides the function descriptors. With ++ # full debug info the function code would be displayed. ++ set func_prefix {\.} ++} else { ++ set func_prefix {} ++} ++ ++gdb_test "p gnu_ifunc" " = {} 0x\[0-9a-f\]+ <${func_prefix}gnu_ifunc>" "p gnu_ifunc executing" +gdb_test "info sym gnu_ifunc" "gnu_ifunc in section .*" "info sym gnu_ifunc executing" + +set test "info addr gnu_ifunc" @@ -9005,6 +12392,15 @@ index 0000000..de59785 +# https://bugzilla.redhat.com/show_bug.cgi?id=624967 + +if ![target_info exists gdb_stub] { ++ ++ # Compile $staticbinfile separately as it may exit on error (ld/12595). ++ ++ if { [gdb_compile ${srcdir}/${subdir}/$libsrc $lib_o object {}] != "" ++ || [gdb_compile "${srcdir}/${subdir}/$srcfile $lib_o" $staticbinfile executable {debug}] != "" } { ++ untested "Could not compile static executable $staticbinfile." ++ return -1 ++ } ++ + clean_restart $staticexecutable + + gdb_breakpoint "gnu_ifunc" @@ -9070,6 +12466,159 @@ index 0000000..6d82e73 + +gdb_test {set $varstruct = staticstruct} +gdb_test {p $varstruct.field} " = 1" +diff --git a/gdb/testsuite/gdb.base/stap-probe.c b/gdb/testsuite/gdb.base/stap-probe.c +new file mode 100644 +index 0000000..47e4b39 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/stap-probe.c +@@ -0,0 +1,69 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2011 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 . */ ++ ++#if USE_PROBES ++ ++#define _SDT_HAS_SEMAPHORES ++__extension__ unsigned short teste_user_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); ++#define TEST teste_user_semaphore ++ ++__extension__ unsigned short teste_two_semaphore __attribute__ ((unused)) __attribute__ ((section (".probes"))); ++#define TEST2 teste_two_semaphore ++ ++#else ++ ++#define TEST 1 ++#define TEST2 1 ++ ++#endif ++ ++#include ++ ++/* We only support SystemTap and only the v3 form. */ ++#if _SDT_NOTE_TYPE != 3 ++#error "not using SystemTap v3 probes" ++#endif ++ ++void ++m1 (void) ++{ ++ if (TEST2) ++ STAP_PROBE (teste, two); ++} ++ ++void ++m2 (void) ++{ ++ if (TEST2) ++ STAP_PROBE (teste, two); ++} ++ ++int ++f (int x) ++{ ++ if (TEST) ++ STAP_PROBE1(teste, user, x); ++ return x+5; ++} ++ ++int ++main() ++{ ++ f(f(23)); ++ m1(); ++ m2(); ++} +diff --git a/gdb/testsuite/gdb.base/stap-probe.exp b/gdb/testsuite/gdb.base/stap-probe.exp +new file mode 100644 +index 0000000..bc3d40c +--- /dev/null ++++ b/gdb/testsuite/gdb.base/stap-probe.exp +@@ -0,0 +1,72 @@ ++# Copyright (C) 2011 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 . ++ ++set testfile stap-probe ++ ++# Run the tests. We run the tests two different ways: once with a ++# plain probe, and once with a probe that has an associated semaphore. ++# This returns -1 on failure to compile or start, 0 otherwise. ++proc stap_test {{arg ""}} { ++ global testfile hex ++ ++ if {$arg != ""} { ++ set arg "additional_flags=$arg" ++ set addendum ", with semaphore" ++ } else { ++ set addendum ", no semaphore" ++ } ++ ++ if {[prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c \ ++ [concat $arg debug]]} { ++ return -1 ++ } ++ ++ if ![runto_main] { ++ return -1 ++ } ++ ++ gdb_test "print \$_probe_argc" "No SystemTap probe at PC $hex" \ ++ "check argument not at probe point$addendum" ++ ++ gdb_test "info probes" \ ++ "teste *user *$hex .*" \ ++ "info probes$addendum" ++ ++ if {[runto "probe:teste:user"]} { ++ pass "run to probe:teste:user$addendum" ++ } else { ++ fail "run to probe:teste:user$addendum" ++ } ++ ++ # Test probe arguments. ++ gdb_test "print \$_probe_argc" " = 1" "print \$_probe_argc$addendum" ++ gdb_test "print \$_probe_arg0 == x" " = 1" "check \$_probe_arg0$addendum" ++ gdb_test "print \$_probe_arg1" \ ++ "Invalid probe argument 1 -- probe has 1 arguments available" \ ++ "check \$_probe_arg1$addendum" ++ ++ # Set a breakpoint with multiple probe locations. ++ gdb_test "break probe:teste:two" \ ++ "Breakpoint .* at $hex.*Breakpoint .* at $hex.*" \ ++ "set multi-location probe breakpoint$addendum" ++ ++ return 0 ++} ++ ++if {[stap_test] == -1} { ++ untested stap-probe.exp ++ return -1 ++} ++stap_test "-DUSE_PROBES" diff --git a/gdb/testsuite/gdb.base/vla-overflow.c b/gdb/testsuite/gdb.base/vla-overflow.c new file mode 100644 index 0000000..c5d5ee0 @@ -9352,13 +12901,13 @@ index 0000000..5da7378 +gdb_test "p temp3" " = '3' " "second: print temp3" diff --git a/gdb/testsuite/gdb.base/watchpoint-delete.c b/gdb/testsuite/gdb.base/watchpoint-delete.c new file mode 100644 -index 0000000..031ef92 +index 0000000..20c9929 --- /dev/null +++ b/gdb/testsuite/gdb.base/watchpoint-delete.c @@ -0,0 +1,33 @@ +/* This testcase is part of GDB, the GNU debugger. + -+ Copyright 2010 Free Software Foundation, Inc. ++ Copyright 2010, 2011 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 @@ -9391,11 +12940,11 @@ index 0000000..031ef92 +} diff --git a/gdb/testsuite/gdb.base/watchpoint-delete.exp b/gdb/testsuite/gdb.base/watchpoint-delete.exp new file mode 100644 -index 0000000..45bc650 +index 0000000..7aadf4e --- /dev/null +++ b/gdb/testsuite/gdb.base/watchpoint-delete.exp @@ -0,0 +1,38 @@ -+# Copyright 2010 Free Software Foundation, Inc. ++# Copyright 2010, 2011 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 @@ -9433,6 +12982,28 @@ index 0000000..45bc650 +gdb_test "watch x" {Watchpoint [0-9]+: x} + +gdb_test_no_output {delete $bpnum} +diff --git a/gdb/testsuite/gdb.cp/nextoverthrow.exp b/gdb/testsuite/gdb.cp/nextoverthrow.exp +index 89c02d6..a970bb9 100644 +--- a/gdb/testsuite/gdb.cp/nextoverthrow.exp ++++ b/gdb/testsuite/gdb.cp/nextoverthrow.exp +@@ -53,6 +53,17 @@ gdb_test_multiple "print _Unwind_DebugHook" "check for unwinder hook" { + } + } + if {!$ok} { ++ gdb_test_multiple "info probe" "check for stap probe in unwinder" { ++ -re ".*libgcc.*unwind.*\r\n$gdb_prompt $" { ++ pass "check for stap probe in unwinder" ++ set ok 1 ++ } ++ -re "\r\n$gdb_prompt $" { ++ } ++ } ++} ++ ++if {!$ok} { + unsupported "nextoverthrow.exp could not find _Unwind_DebugHook" + return -1 + } diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.S b/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.S new file mode 100644 index 0000000..aac3baa @@ -10697,6 +14268,101 @@ index 30a71dd..4bb8e7d 100644 -re ".*pre_stat_chain = make_command_stats_cleanup.*$gdb_prompt $" { set description "next over make_command_stats_cleanup and everything it calls" set command "next" +diff --git a/gdb/testsuite/gdb.mi/mi2-var-stale-type.c b/gdb/testsuite/gdb.mi/mi2-var-stale-type.c +new file mode 100644 +index 0000000..ebced3c +--- /dev/null ++++ b/gdb/testsuite/gdb.mi/mi2-var-stale-type.c +@@ -0,0 +1,26 @@ ++/* Copyright 2011 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ 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 . */ ++ ++int ++main (int argc, char **argv) ++{ ++ char vla[argc]; ++ ++ vla[0] = 0; /* break-here */ ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.mi/mi2-var-stale-type.exp b/gdb/testsuite/gdb.mi/mi2-var-stale-type.exp +new file mode 100644 +index 0000000..74a104e +--- /dev/null ++++ b/gdb/testsuite/gdb.mi/mi2-var-stale-type.exp +@@ -0,0 +1,57 @@ ++# Copyright 2011 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 mi-support.exp ++set MIFLAGS "-i=mi2" ++ ++gdb_exit ++if [mi_gdb_start] { ++ continue ++} ++ ++set testfile "mi2-var-stale-type" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} { ++ return -1 ++} ++ ++mi_delete_breakpoints ++mi_gdb_reinitialize_dir $srcdir/$subdir ++mi_gdb_load ${binfile} ++ ++mi_gdb_test {-interpreter-exec console "maintenance set internal-error quit yes"} \ ++ {\^done} \ ++ "maintenance set internal-error quit yes" ++ ++mi_gdb_test {-interpreter-exec console "maintenance set internal-error corefile yes"} \ ++ {\^done} \ ++ "maintenance set internal-error corefile yes" ++ ++set line [gdb_get_line_number "break-here"] ++set func "main" ++ ++mi_gdb_test "-break-insert -t $srcfile:$line" \ ++ "\\^done,bkpt=\{number=\"\[0-9\]+\",type=\"breakpoint\",disp=\"del\",enabled=\"y\",addr=\"$hex\",func=\"$func\(\\\(.*\\\)\)?\",file=\".*\",line=\"$line\",times=\"0\",original-location=\".*\"\}" \ ++ "breakpoint at $func" ++ ++if { [mi_run_cmd] < 0 } { ++ return -1 ++} ++mi_expect_stop "breakpoint-hit" $func ".*" ".*" "\[0-9\]+" { "" "disp=\"del\"" } "stop after initializing vla" ++ ++mi_create_varobj "vla" "vla" "create local variable vla" ++ ++mi_gdb_test "-var-update *" "\\^done,changelist=.*" "-var-update *" diff --git a/gdb/testsuite/gdb.multi/watchpoint-multi.c b/gdb/testsuite/gdb.multi/watchpoint-multi.c new file mode 100644 index 0000000..153c18b @@ -11881,11 +15547,11 @@ index 0000000..31f7656 +extern void marker (void); +extern void forkoff (int nr); diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp -index 44d449a..d8c50f2 100644 +index 6a2f1a2..c75a7f0 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp -@@ -140,6 +140,11 @@ proc gdb_unload {} { - verbose "\t\tKilling previous program being debugged" +@@ -141,6 +141,11 @@ proc gdb_unload {} { + send_gdb "y\n" exp_continue } + -re "A program is being debugged already..*Are you sure you want to change the file.*y or n. $"\ @@ -11931,8 +15597,43 @@ index 891da37..236c5ca 100644 } set pascal_init_done 1 } +diff --git a/gdb/thread.c b/gdb/thread.c +index 6ad1807..91fe056 100644 +--- a/gdb/thread.c ++++ b/gdb/thread.c +@@ -1438,7 +1438,8 @@ update_thread_list (void) + no thread is selected, or no threads exist. */ + + static struct value * +-thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) ++thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var, ++ void *ignore) + { + struct thread_info *tp = find_thread_ptid (inferior_ptid); + +@@ -1449,6 +1450,13 @@ thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) + /* Commands with a prefix of `thread'. */ + struct cmd_list_element *thread_cmd_list = NULL; + ++static struct internalvar_funcs thread_funcs = ++{ ++ thread_id_make_value, ++ NULL, ++ NULL ++}; ++ + void + _initialize_thread (void) + { +@@ -1494,5 +1502,5 @@ Show printing of thread events (such as thread start and exit)."), NULL, + show_print_thread_events, + &setprintlist, &showprintlist); + +- create_internalvar_type_lazy ("_thread", thread_id_make_value); ++ create_internalvar_type_lazy ("_thread", &thread_funcs, NULL); + } diff --git a/gdb/top.c b/gdb/top.c -index df2b163..6061b33 100644 +index a25550f..87f0b41 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -343,6 +343,9 @@ void @@ -11945,6 +15646,43 @@ index df2b163..6061b33 100644 /* With multiple threads running while the one we're examining is stopped, the dcache can get stale without us being able to detect +diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c +index 3ae35d0..e1d2e82 100644 +--- a/gdb/tracepoint.c ++++ b/gdb/tracepoint.c +@@ -4497,7 +4497,8 @@ info_static_tracepoint_markers_command (char *arg, int from_tty) + available. */ + + static struct value * +-sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var) ++sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var, ++ void *ignore) + { + LONGEST size; + gdb_byte *buf; +@@ -4676,6 +4677,13 @@ traceframe_available_memory (VEC(mem_range_s) **result, + return 0; + } + ++static const struct internalvar_funcs sdata_funcs = ++{ ++ sdata_make_value, ++ NULL, ++ NULL ++}; ++ + /* module initialization */ + void + _initialize_tracepoint (void) +@@ -4686,7 +4694,7 @@ _initialize_tracepoint (void) + value with a void typed value, and when we get here, gdbarch + isn't initialized yet. At this point, we're quite sure there + isn't another convenience variable of the same name. */ +- create_internalvar_type_lazy ("_sdata", sdata_make_value); ++ create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL); + + traceframe_number = -1; + tracepoint_number = -1; diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 03e6332..ce6d1e0 100644 --- a/gdb/typeprint.c @@ -12003,7 +15741,7 @@ index 03e6332..ce6d1e0 100644 static void diff --git a/gdb/utils.c b/gdb/utils.c -index 91e6af4..88b82f5 100644 +index e688d19..f1fc507 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -2243,6 +2243,36 @@ set_batch_flag_and_make_cleanup_restore_page_info (void) @@ -12071,7 +15809,7 @@ index 68f649f..aaa4487 100644 } diff --git a/gdb/valops.c b/gdb/valops.c -index 0c07e5c..5749cce 100644 +index b9f5508..1b7ed76 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -47,6 +47,7 @@ @@ -12174,7 +15912,7 @@ index 0c07e5c..5749cce 100644 } else if (VALUE_LVAL (val) == lval_register) { -@@ -1520,7 +1588,18 @@ address_of_variable (struct symbol *var, struct block *b) +@@ -1528,7 +1596,18 @@ address_of_variable (struct symbol *var, struct block *b) if ((VALUE_LVAL (val) == lval_memory && value_lazy (val)) || TYPE_CODE (type) == TYPE_CODE_FUNC) { @@ -12194,7 +15932,7 @@ index 0c07e5c..5749cce 100644 return value_from_pointer (lookup_pointer_type (type), addr); } -@@ -1627,6 +1706,7 @@ struct value * +@@ -1635,6 +1714,7 @@ struct value * value_coerce_array (struct value *arg1) { struct type *type = check_typedef (value_type (arg1)); @@ -12202,7 +15940,7 @@ index 0c07e5c..5749cce 100644 /* If the user tries to do something requiring a pointer with an array that has not yet been pushed to the target, then this would -@@ -1636,8 +1716,12 @@ value_coerce_array (struct value *arg1) +@@ -1644,8 +1724,12 @@ value_coerce_array (struct value *arg1) if (VALUE_LVAL (arg1) != lval_memory) error (_("Attempt to take address of value not located in memory.")); @@ -12216,7 +15954,7 @@ index 0c07e5c..5749cce 100644 } /* Given a value which is a function, return a value which is a pointer -@@ -3680,6 +3764,8 @@ value_slice (struct value *array, int lowbound, int length) +@@ -3688,6 +3772,8 @@ value_slice (struct value *array, int lowbound, int length) TYPE_TARGET_TYPE (range_type), lowbound, lowbound + length - 1); @@ -12299,7 +16037,7 @@ index 286ef9e..1fe58b1 100644 /* Read LEN bytes of target memory at address MEMADDR, placing the diff --git a/gdb/value.c b/gdb/value.c -index 2acb1df..d1db8f5 100644 +index 2acb1df..abe774e 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -43,6 +43,7 @@ @@ -12371,7 +16109,86 @@ index 2acb1df..d1db8f5 100644 /* Internal variables. These are variables within the debugger that hold values assigned by debugger commands. -@@ -1963,6 +1998,38 @@ call_internal_function (struct gdbarch *gdbarch, +@@ -1530,7 +1565,14 @@ struct internalvar + struct value *value; + + /* The call-back routine used with INTERNALVAR_MAKE_VALUE. */ +- internalvar_make_value make_value; ++ struct ++ { ++ /* The functions to call. */ ++ const struct internalvar_funcs *functions; ++ ++ /* The function's user-data. */ ++ void *data; ++ } make_value; + + /* The internal function used with INTERNALVAR_FUNCTION. */ + struct +@@ -1629,18 +1671,37 @@ create_internalvar (const char *name) + /* Create an internal variable with name NAME and register FUN as the + function that value_of_internalvar uses to create a value whenever + this variable is referenced. NAME should not normally include a +- dollar sign. */ ++ dollar sign. DATA is passed uninterpreted to FUN when it is ++ called. CLEANUP, if not NULL, is called when the internal variable ++ is destroyed. It is passed DATA as its only argument. */ + + struct internalvar * +-create_internalvar_type_lazy (char *name, internalvar_make_value fun) ++create_internalvar_type_lazy (const char *name, ++ const struct internalvar_funcs *funcs, ++ void *data) + { + struct internalvar *var = create_internalvar (name); + + var->kind = INTERNALVAR_MAKE_VALUE; +- var->u.make_value = fun; ++ var->u.make_value.functions = funcs; ++ var->u.make_value.data = data; + return var; + } + ++int ++compile_internalvar_to_ax (struct internalvar *var, ++ struct agent_expr *expr, ++ struct axs_value *value) ++{ ++ if (var->kind != INTERNALVAR_MAKE_VALUE ++ || var->u.make_value.functions->compile_to_ax == NULL) ++ return 0; ++ ++ var->u.make_value.functions->compile_to_ax (var, expr, value, ++ var->u.make_value.data); ++ return 1; ++} ++ + /* Look up an internal variable with name NAME. NAME should not + normally include a dollar sign. + +@@ -1713,7 +1774,8 @@ value_of_internalvar (struct gdbarch *gdbarch, struct internalvar *var) + break; + + case INTERNALVAR_MAKE_VALUE: +- val = (*var->u.make_value) (gdbarch, var); ++ val = (*var->u.make_value.functions->make_value) (gdbarch, var, ++ var->u.make_value.data); + break; + + default: +@@ -1909,6 +1971,11 @@ clear_internalvar (struct internalvar *var) + xfree (var->u.string); + break; + ++ case INTERNALVAR_MAKE_VALUE: ++ if (var->u.make_value.functions->destroy != NULL) ++ var->u.make_value.functions->destroy (var->u.make_value.data); ++ break; ++ + default: + break; + } +@@ -1963,6 +2030,38 @@ call_internal_function (struct gdbarch *gdbarch, return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv); } @@ -12410,7 +16227,7 @@ index 2acb1df..d1db8f5 100644 /* The 'function' command. This does nothing -- it is just a placeholder to let "help function NAME" work. This is also used as the implementation of the sub-command that is created when -@@ -2010,11 +2077,10 @@ preserve_one_value (struct value *value, struct objfile *objfile, +@@ -2010,11 +2109,10 @@ preserve_one_value (struct value *value, struct objfile *objfile, htab_t copied_types) { if (TYPE_OBJFILE (value->type) == objfile) @@ -12424,7 +16241,7 @@ index 2acb1df..d1db8f5 100644 copied_types); } -@@ -2029,7 +2095,7 @@ preserve_one_internalvar (struct internalvar *var, struct objfile *objfile, +@@ -2029,7 +2127,7 @@ preserve_one_internalvar (struct internalvar *var, struct objfile *objfile, case INTERNALVAR_INTEGER: if (var->u.integer.type && TYPE_OBJFILE (var->u.integer.type) == objfile) var->u.integer.type @@ -12433,7 +16250,7 @@ index 2acb1df..d1db8f5 100644 break; case INTERNALVAR_VALUE: -@@ -3047,7 +3113,24 @@ value_from_history_ref (char *h, char **endp) +@@ -3047,7 +3145,24 @@ value_from_history_ref (char *h, char **endp) struct value * coerce_ref (struct value *arg) { @@ -12459,7 +16276,7 @@ index 2acb1df..d1db8f5 100644 if (TYPE_CODE (value_type_arg_tmp) == TYPE_CODE_REF) arg = value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp), -@@ -3145,4 +3228,10 @@ VARIABLE is already initialized.")); +@@ -3145,4 +3260,10 @@ VARIABLE is already initialized.")); add_prefix_cmd ("function", no_class, function_command, _("\ Placeholder command for showing help on convenience functions."), &functionlist, "function ", 0, &cmdlist); @@ -12471,7 +16288,7 @@ index 2acb1df..d1db8f5 100644 +#endif } diff --git a/gdb/value.h b/gdb/value.h -index 0889cef..1be7f0b 100644 +index 0889cef..4b51a4a 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -473,6 +473,10 @@ extern struct value *value_from_decfloat (struct type *type, @@ -12485,3 +16302,105 @@ index 0889cef..1be7f0b 100644 extern struct value *value_at (struct type *type, CORE_ADDR addr); extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr); +@@ -697,10 +701,52 @@ extern struct internalvar *lookup_only_internalvar (const char *name); + + extern struct internalvar *create_internalvar (const char *name); + +-typedef struct value * (*internalvar_make_value) (struct gdbarch *, +- struct internalvar *); ++/* An internalvar can be dynamically computed by supplying a vector of ++ function pointers to perform various operations. */ ++ ++struct internalvar_funcs ++{ ++ /* Compute the value of the variable. The DATA argument passed to ++ the function is the same argument that was passed to ++ `create_internalvar_type_lazy'. */ ++ ++ struct value *(*make_value) (struct gdbarch *arch, ++ struct internalvar *var, ++ void *data); ++ ++ /* Update the agent expression EXPR with bytecode to compute the ++ value. VALUE is the agent value we are updating. The DATA ++ argument passed to this function is the same argument that was ++ passed to `create_internalvar_type_lazy'. If this pointer is ++ NULL, then the internalvar cannot be compiled to an agent ++ expression. */ ++ ++ void (*compile_to_ax) (struct internalvar *var, ++ struct agent_expr *expr, ++ struct axs_value *value, ++ void *data); ++ ++ /* If non-NULL, this is called to destroy DATA. The DATA argument ++ passed to this function is the same argument that was passed to ++ `create_internalvar_type_lazy'. */ ++ ++ void (*destroy) (void *data); ++}; ++ + extern struct internalvar * +- create_internalvar_type_lazy (char *name, internalvar_make_value fun); ++create_internalvar_type_lazy (const char *name, ++ const struct internalvar_funcs *funcs, ++ void *data); ++ ++/* Compile an internal variable to an agent expression. VAR is the ++ variable to compile; EXPR and VALUE are the agent expression we are ++ updating. This will return 0 if there is no known way to compile ++ VAR, and 1 if VAR was successfully compiled. It may also throw an ++ exception on error. */ ++ ++extern int compile_internalvar_to_ax (struct internalvar *var, ++ struct agent_expr *expr, ++ struct axs_value *value); + + extern struct internalvar *lookup_internalvar (const char *name); + +diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c +index 31ddd14..b36e4ca 100644 +--- a/gdb/windows-tdep.c ++++ b/gdb/windows-tdep.c +@@ -268,7 +268,7 @@ static struct lval_funcs tlb_value_funcs = + if there's no object available. */ + + static struct value * +-tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var) ++tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var, void *ignore) + { + if (target_has_stack && !ptid_equal (inferior_ptid, null_ptid)) + { +@@ -425,6 +425,13 @@ init_w32_command_list (void) + } + } + ++static const struct internalvar_funcs tlb_funcs = ++{ ++ tlb_make_value, ++ NULL, ++ NULL ++}; ++ + void + _initialize_windows_tdep (void) + { +@@ -451,5 +458,5 @@ even if their meaning is unknown."), + value with a void typed value, and when we get here, gdbarch + isn't initialized yet. At this point, we're quite sure there + isn't another convenience variable of the same name. */ +- create_internalvar_type_lazy ("_tlb", tlb_make_value); ++ create_internalvar_type_lazy ("_tlb", &tlb_funcs, NULL); + } +diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c +index 081080c..f71dbfe 100644 +--- a/gdb/xcoffread.c ++++ b/gdb/xcoffread.c +@@ -3090,6 +3090,7 @@ static const struct sym_fns xcoff_sym_fns = + default_symfile_segments, /* Get segment information from a file. */ + aix_process_linenos, + default_symfile_relocate, /* Relocate a debug section. */ ++ NULL, /* sym_probe_fns */ + &psym_functions + }; + diff --git a/gdb-physname-pr11734-1of2.patch b/gdb-physname-pr11734-1of2.patch deleted file mode 100644 index f2a69b7..0000000 --- a/gdb-physname-pr11734-1of2.patch +++ /dev/null @@ -1,619 +0,0 @@ -http://sourceware.org/ml/gdb-patches/2010-12/msg00263.html - -Index: gdb-7.2.50.20110206/gdb/cp-support.c -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/cp-support.c 2011-02-06 23:12:16.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/cp-support.c 2011-02-06 23:12:22.000000000 +0100 -@@ -35,6 +35,7 @@ - #include "exceptions.h" - #include "expression.h" - #include "value.h" -+#include "language.h" - - #include "safe-ctype.h" - -@@ -936,7 +937,8 @@ make_symbol_overload_list_qualified (con - ALL_OBJFILES (objfile) - { - if (objfile->sf) -- objfile->sf->qf->expand_symtabs_for_function (objfile, func_name); -+ objfile->sf->qf->expand_symtabs_for_function (objfile, func_name, -+ language_cplus); - } - - /* Search upwards from currently selected frame (so that we can -Index: gdb-7.2.50.20110206/gdb/dwarf2read.c -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/dwarf2read.c 2011-02-06 23:12:22.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/dwarf2read.c 2011-02-06 23:12:22.000000000 +0100 -@@ -2373,7 +2373,8 @@ dw2_lookup_symtab (struct objfile *objfi - - static struct symtab * - dw2_lookup_symbol (struct objfile *objfile, int block_index, -- const char *name, domain_enum domain) -+ const char *name, domain_enum domain, -+ enum language language) - { - /* We do all the work in the pre_expand_symtabs_matching hook - instead. */ -@@ -2449,7 +2450,8 @@ dw2_relocate (struct objfile *objfile, s - - static void - dw2_expand_symtabs_for_function (struct objfile *objfile, -- const char *func_name) -+ const char *func_name, -+ enum language language) - { - dw2_do_expand_symtabs_matching (objfile, func_name); - } -@@ -2509,7 +2511,8 @@ dw2_expand_symtabs_with_filename (struct - } - - static const char * --dw2_find_symbol_file (struct objfile *objfile, const char *name) -+dw2_find_symbol_file (struct objfile *objfile, const char *name, -+ enum language language) - { - struct dwarf2_per_cu_data *per_cu; - offset_type *vec; -Index: gdb-7.2.50.20110206/gdb/linespec.c -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/linespec.c 2011-02-06 23:12:16.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/linespec.c 2011-02-06 23:12:26.000000000 +0100 -@@ -1226,7 +1226,7 @@ decode_objc (char **argptr, int funfirst - - static struct symtabs_and_lines - decode_compound (char **argptr, int funfirstline, char ***canonical, -- char *saved_arg, char *p, int *not_found_ptr) -+ char *the_real_saved_arg, char *p, int *not_found_ptr) - { - struct symtabs_and_lines values; - char *p2; -@@ -1237,7 +1237,23 @@ decode_compound (char **argptr, int funf - struct symbol *sym_class; - struct type *t; - char *saved_java_argptr = NULL; -+ char *saved_arg; - -+ /* THE_REAL_SAVED_ARG cannot be altered, so make a copy that can be. */ -+ saved_arg = alloca (strlen (the_real_saved_arg) + 1); -+ strcpy (saved_arg, the_real_saved_arg); -+ -+ /* If the user specified "'foo::bar(baz)'" (note the quotes -- often -+ added to workaround completer issues) -- saved_arg will be -+ encapsulated in single-quotes. They are superfluous, so just strip -+ them off. */ -+ if (*saved_arg == '\'') -+ { -+ char *end = skip_quoted (saved_arg); -+ memmove (saved_arg, saved_arg + 1, end - saved_arg); -+ memmove (end - 2, end, strlen (saved_arg) + 1); -+ } -+ - /* First check for "global" namespace specification, of the form - "::foo". If found, skip over the colons and jump to normal - symbol processing. I.e. the whole line specification starts with -@@ -1489,7 +1505,7 @@ decode_compound (char **argptr, int funf - up. The quotes are important if copy is empty. */ - if (not_found_ptr) - *not_found_ptr = 1; -- cplusplus_error (saved_arg, -+ cplusplus_error (the_real_saved_arg, - "Can't find member of namespace, " - "class, struct, or union named \"%s\"\n", - copy); -Index: gdb-7.2.50.20110206/gdb/psymtab.c -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/psymtab.c 2011-02-06 23:12:16.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/psymtab.c 2011-02-06 23:12:54.000000000 +0100 -@@ -33,6 +33,8 @@ - #include "readline/readline.h" - #include "gdb_regex.h" - #include "dictionary.h" -+#include "language.h" -+#include "cp-support.h" - - #ifndef DEV_TTY - #define DEV_TTY "/dev/tty" -@@ -55,7 +57,8 @@ static struct partial_symbol *match_part - - static struct partial_symbol *lookup_partial_symbol (struct partial_symtab *, - const char *, int, -- domain_enum); -+ domain_enum, -+ enum language); - - static char *psymtab_to_fullname (struct partial_symtab *ps); - -@@ -418,15 +421,35 @@ fixup_psymbol_section (struct partial_sy - static struct symtab * - lookup_symbol_aux_psymtabs (struct objfile *objfile, - int block_index, const char *name, -- const domain_enum domain) -+ const domain_enum domain, enum language language) - { - struct partial_symtab *ps; - const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0); - - ALL_OBJFILE_PSYMTABS (objfile, ps) - { -- if (!ps->readin && lookup_partial_symbol (ps, name, psymtab_index, domain)) -- return PSYMTAB_TO_SYMTAB (ps); -+ if (!ps->readin -+ && lookup_partial_symbol (ps, name, psymtab_index, domain, language)) -+ { -+ struct symbol *sym; -+ struct symtab *stab = PSYMTAB_TO_SYMTAB (ps); -+ sym = NULL; -+ -+ /* Some caution must be observed with overloaded functions -+ and methods, since the psymtab will not contain any overload -+ information (but NAME might contain it). */ -+ if (stab->primary) -+ { -+ struct blockvector *bv = BLOCKVECTOR (stab); -+ struct block *block = BLOCKVECTOR_BLOCK (bv, block_index); -+ sym = lookup_block_symbol (block, name, domain); -+ } -+ -+ if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0) -+ return stab; -+ -+ /* Keep looking through other psymtabs. */ -+ } - } - - return NULL; -@@ -519,22 +542,58 @@ pre_expand_symtabs_matching_psymtabs (st - /* Nothing. */ - } - -+/* Returns the name used to search psymtabs. Unlike symtabs, psymtabs do -+ not contain any method/function instance information (since this would -+ force reading type information while reading psymtabs). Therefore, -+ if NAME contains overload information, it must be stripped before searching -+ psymtabs. -+ -+ The caller is responsible for freeing the return result. */ -+ -+static const char * -+psymtab_search_name (const char *name, enum language language) -+{ -+ switch (language) -+ { -+ case language_cplus: -+ case language_java: -+ { -+ if (strchr (name, '(')) -+ { -+ char *ret = cp_remove_params (name); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ default: -+ break; -+ } -+ -+ return xstrdup (name); -+} -+ - /* Look, in partial_symtab PST, for symbol whose natural name is NAME. - Check the global symbols if GLOBAL, the static symbols if not. */ - - static struct partial_symbol * - lookup_partial_symbol (struct partial_symtab *pst, const char *name, -- int global, domain_enum domain) -+ int global, domain_enum domain, enum language language) - { - struct partial_symbol **start, **psym; - struct partial_symbol **top, **real_top, **bottom, **center; - int length = (global ? pst->n_global_syms : pst->n_static_syms); - int do_linear_search = 1; -+ const char *search_name; -+ struct cleanup *cleanup; - - if (length == 0) - { - return (NULL); - } -+ -+ search_name = psymtab_search_name (name, language); -+ cleanup = make_cleanup (xfree, (void *) search_name); - start = (global ? - pst->objfile->global_psymbols.list + pst->globals_offset : - pst->objfile->static_psymbols.list + pst->statics_offset); -@@ -563,7 +622,8 @@ lookup_partial_symbol (struct partial_sy - { - do_linear_search = 1; - } -- if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), name) >= 0) -+ if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center), -+ search_name) >= 0) - { - top = center; - } -@@ -577,11 +637,14 @@ lookup_partial_symbol (struct partial_sy - _("failed internal consistency check")); - - while (top <= real_top -- && SYMBOL_MATCHES_SEARCH_NAME (*top, name)) -+ && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name)) - { - if (symbol_matches_domain (SYMBOL_LANGUAGE (*top), - SYMBOL_DOMAIN (*top), domain)) -- return (*top); -+ { -+ do_cleanups (cleanup); -+ return (*top); -+ } - top++; - } - } -@@ -595,11 +658,15 @@ lookup_partial_symbol (struct partial_sy - { - if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym), - SYMBOL_DOMAIN (*psym), domain) -- && SYMBOL_MATCHES_SEARCH_NAME (*psym, name)) -- return (*psym); -+ && SYMBOL_MATCHES_SEARCH_NAME (*psym, search_name)) -+ { -+ do_cleanups (cleanup); -+ return (*psym); -+ } - } - } - -+ do_cleanups (cleanup); - return (NULL); - } - -@@ -911,7 +978,8 @@ dump_psymtabs_for_objfile (struct objfil - by matching FUNC_NAME. Make sure we read that symbol table in. */ - - static void --read_symtabs_for_function (struct objfile *objfile, const char *func_name) -+read_symtabs_for_function (struct objfile *objfile, const char *func_name, -+ enum language language) - { - struct partial_symtab *ps; - -@@ -920,9 +988,9 @@ read_symtabs_for_function (struct objfil - if (ps->readin) - continue; - -- if ((lookup_partial_symbol (ps, func_name, 1, VAR_DOMAIN) -+ if ((lookup_partial_symbol (ps, func_name, 1, VAR_DOMAIN, language) - != NULL) -- || (lookup_partial_symbol (ps, func_name, 0, VAR_DOMAIN) -+ || (lookup_partial_symbol (ps, func_name, 0, VAR_DOMAIN, language) - != NULL)) - psymtab_to_symtab (ps); - } -@@ -1042,13 +1110,14 @@ psymtab_to_fullname (struct partial_symt - } - - static const char * --find_symbol_file_from_partial (struct objfile *objfile, const char *name) -+find_symbol_file_from_partial (struct objfile *objfile, const char *name, -+ enum language language) - { - struct partial_symtab *pst; - - ALL_OBJFILE_PSYMTABS (objfile, pst) - { -- if (lookup_partial_symbol (pst, name, 1, VAR_DOMAIN)) -+ if (lookup_partial_symbol (pst, name, 1, VAR_DOMAIN, language)) - return pst->filename; - } - return NULL; -Index: gdb-7.2.50.20110206/gdb/symfile.h -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/symfile.h 2011-02-06 23:12:16.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/symfile.h 2011-02-06 23:12:22.000000000 +0100 -@@ -167,14 +167,15 @@ struct quick_symbol_functions - /* Check to see if the symbol is defined in a "partial" symbol table - of OBJFILE. KIND should be either GLOBAL_BLOCK or STATIC_BLOCK, - depending on whether we want to search global symbols or static -- symbols. NAME is the name of the symbol to look for. DOMAIN -- indicates what sort of symbol to search for. -+ symbols. NAME (valid in LANGUAGE) is the name of the symbol to look for. -+ DOMAIN indicates what sort of symbol to search for. - - Returns the newly-expanded symbol table in which the symbol is - defined, or NULL if no such symbol table exists. */ - struct symtab *(*lookup_symbol) (struct objfile *objfile, - int kind, const char *name, -- domain_enum domain); -+ domain_enum domain, -+ enum language language); - - /* This is called to expand symbol tables before looking up a - symbol. A backend can choose to implement this and then have its -@@ -200,10 +201,11 @@ struct quick_symbol_functions - struct section_offsets *new_offsets, - struct section_offsets *delta); - -- /* Find all the symbols in OBJFILE named FUNC_NAME, and ensure that -- the corresponding symbol tables are loaded. */ -+ /* Find all the symbols in OBJFILE named FUNC_NAME (valid in LANGUAGE), -+ and ensure that the corresponding symbol tables are loaded. */ - void (*expand_symtabs_for_function) (struct objfile *objfile, -- const char *func_name); -+ const char *func_name, -+ enum language language); - - /* Read all symbol tables associated with OBJFILE. */ - void (*expand_all_symtabs) (struct objfile *objfile); -@@ -217,8 +219,10 @@ struct quick_symbol_functions - const char *filename); - - /* Return the file name of the file holding the symbol in OBJFILE -- named NAME. If no such symbol exists in OBJFILE, return NULL. */ -- const char *(*find_symbol_file) (struct objfile *objfile, const char *name); -+ named NAME (valid in LANGUAGE). If no such symbol exists in OBJFILE, -+ return NULL. */ -+ const char *(*find_symbol_file) (struct objfile *objfile, const char *name, -+ enum language language); - - /* Find global or static symbols in all tables that are in NAMESPACE - and for which MATCH (symbol name, NAME) == 0, passing each to -Index: gdb-7.2.50.20110206/gdb/symtab.c -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/symtab.c 2011-02-06 23:12:16.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/symtab.c 2011-02-06 23:12:22.000000000 +0100 -@@ -1380,7 +1380,8 @@ lookup_symbol_aux_quick (struct objfile - - if (!objfile->sf) - return NULL; -- symtab = objfile->sf->qf->lookup_symbol (objfile, kind, name, domain); -+ symtab = objfile->sf->qf->lookup_symbol (objfile, kind, name, domain, -+ current_language->la_language); - if (!symtab) - return NULL; - -@@ -1554,7 +1555,8 @@ basic_lookup_transparent_type_quick (str - - if (!objfile->sf) - return NULL; -- symtab = objfile->sf->qf->lookup_symbol (objfile, kind, name, STRUCT_DOMAIN); -+ symtab = objfile->sf->qf->lookup_symbol (objfile, kind, name, STRUCT_DOMAIN, -+ current_language->la_language); - if (!symtab) - return NULL; - -@@ -1686,7 +1688,8 @@ find_main_filename (void) - - if (!objfile->sf) - continue; -- result = objfile->sf->qf->find_symbol_file (objfile, name); -+ result = objfile->sf->qf->find_symbol_file (objfile, name, -+ current_language->la_language); - if (result) - return result; - } -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-1.cc -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-1.cc 2011-02-06 23:12:22.000000000 +0100 -@@ -0,0 +1,30 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2010 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 . -+ -+ Please email any bugs, comments, and/or additions to this file to: -+ bug-gdb@gnu.org */ -+ -+#include "pr11734.h" -+ -+int -+main () -+{ -+ pr11734 *p = new pr11734; -+ p->foo (); -+ return 0; -+} -+ -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-2.cc -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-2.cc 2011-02-06 23:12:22.000000000 +0100 -@@ -0,0 +1,27 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2010 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 . -+ -+ Please email any bugs, comments, and/or additions to this file to: -+ bug-gdb@gnu.org */ -+ -+#include "pr11734.h" -+ -+void -+pr11734::foo(void) -+{ -+} -+ -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-3.cc -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-3.cc 2011-02-06 23:12:22.000000000 +0100 -@@ -0,0 +1,27 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2010 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 . -+ -+ Please email any bugs, comments, and/or additions to this file to: -+ bug-gdb@gnu.org */ -+ -+#include "pr11734.h" -+ -+void -+pr11734::foo (int a) -+{ -+} -+ -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-4.cc -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734-4.cc 2011-02-06 23:12:22.000000000 +0100 -@@ -0,0 +1,27 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2010 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 . -+ -+ Please email any bugs, comments, and/or additions to this file to: -+ bug-gdb@gnu.org */ -+ -+#include "pr11734.h" -+ -+void -+pr11734::foo (char *a) -+{ -+} -+ -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734.exp -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734.exp 2011-02-06 23:12:22.000000000 +0100 -@@ -0,0 +1,55 @@ -+# Copyright 2010 Free Software Foundation, Inc. -+# -+# Contributed by Red Hat, originally written by Keith Seitz. -+# -+# 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 . -+ -+# This file is part of the gdb testsuite. -+ -+if { [skip_cplus_tests] } { continue } -+ -+set testfile "pr11734" -+set class $testfile -+ -+set srcfiles {} -+for {set i 1} {$i < 5} {incr i} { -+ lappend srcfiles $testfile-$i.cc -+} -+ -+prepare_for_testing pr11734 $testfile $srcfiles {c++ debug} -+ -+if {![runto_main]} { -+ perror "couldn't run to breakpoint" -+ continue -+} -+ -+# An array holding the overload types for the method pr11734::foo. The -+# first element is the overloaded method parameter. The second element -+# is the expected source file number, e.g. "pr11734-?.cc". -+array set tests { -+ "char*" 4 -+ "int" 3 -+ "" 2 -+} -+ -+# Test each overload instance twice: once quoted, once unquoted -+foreach ovld [array names tests] { -+ set method "${class}::foo\($ovld\)" -+ set result "Breakpoint (\[0-9\]).*file .*/$class-$tests($ovld).*" -+ gdb_test "break $method" $result -+ gdb_test "break '$method'" $result -+} -+ -+gdb_exit -+return 0 -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr11734.h 2011-02-06 23:12:22.000000000 +0100 -@@ -0,0 +1,28 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2010 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 . -+ -+ Please email any bugs, comments, and/or additions to this file to: -+ bug-gdb@gnu.org */ -+ -+class pr11734 -+{ -+ public: -+ void foo (); -+ void foo (int); -+ void foo (char *); -+}; -+ diff --git a/gdb-physname-pr11734-2of2.patch b/gdb-physname-pr11734-2of2.patch deleted file mode 100644 index b3eec9f..0000000 --- a/gdb-physname-pr11734-2of2.patch +++ /dev/null @@ -1,18 +0,0 @@ -http://sourceware.org/ml/gdb-patches/2011-01/msg00460.html - -Index: gdb-7.2/gdb/linespec.c -=================================================================== ---- gdb-7.2.orig/gdb/linespec.c 2011-02-03 22:59:46.000000000 +0100 -+++ gdb-7.2/gdb/linespec.c 2011-02-03 23:03:28.000000000 +0100 -@@ -1230,7 +1230,10 @@ decode_compound (char **argptr, int funf - { - char *end = skip_quoted (saved_arg); - memmove (saved_arg, saved_arg + 1, end - saved_arg); -- memmove (end - 2, end, strlen (saved_arg) + 1); -+ if (&end[-2] >= saved_arg && end[-2] == '\'') -+ memmove (end - 2, end, strlen (end) + 1); -+ else -+ memmove (end - 1, end, strlen (end) + 1); - } - - /* First check for "global" namespace specification, of the form diff --git a/gdb-physname-pr12273.patch b/gdb-physname-pr12273.patch deleted file mode 100644 index ccec62b..0000000 --- a/gdb-physname-pr12273.patch +++ /dev/null @@ -1,207 +0,0 @@ -http://sourceware.org/ml/gdb-patches/2010-12/msg00264.html - -Index: gdb-7.2.50.20110206/gdb/linespec.c -=================================================================== ---- gdb-7.2.50.20110206.orig/gdb/linespec.c 2011-02-06 23:06:26.000000000 +0100 -+++ gdb-7.2.50.20110206/gdb/linespec.c 2011-02-06 23:08:23.000000000 +0100 -@@ -1057,6 +1057,10 @@ locate_first_half (char **argptr, int *i - error (_("malformed template specification in command")); - p = temp_end; - } -+ -+ if (p[0] == '(') -+ p = find_method_overload_end (p); -+ - /* Check for a colon and a plus or minus and a [ (which - indicates an Objective-C method). */ - if (is_objc_method_format (p)) -@@ -1272,8 +1276,10 @@ decode_compound (char **argptr, int funf - find_method. - - 2) AAA::inA isn't the name of a class. In that case, either the -- user made a typo or AAA::inA is the name of a namespace. -- Either way, we just look up AAA::inA::fun with lookup_symbol. -+ user made a typo, AAA::inA is the name of a namespace, or it is -+ the name of a minimal symbol. -+ We just look up AAA::inA::fun with lookup_symbol. If that fails, -+ try lookup_minimal_symbol. - - Thus, our first task is to find everything before the last set of - double-colons and figure out if it's the name of a class. So we -@@ -1294,6 +1300,8 @@ decode_compound (char **argptr, int funf - - while (1) - { -+ static char *break_characters = " \t\'("; -+ - /* Move pointer up to next possible class/namespace token. */ - - p = p2 + 1; /* Restart with old value +1. */ -@@ -1304,8 +1312,7 @@ decode_compound (char **argptr, int funf - /* PASS2: p2->"::fun", p->":fun" */ - - /* Move pointer ahead to next double-colon. */ -- while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\'') -- && (*p != '(')) -+ while (*p && strchr (break_characters, *p) == NULL) - { - if (current_language->la_language == language_cplus) - p += cp_validate_operator (p); -@@ -1329,9 +1336,12 @@ decode_compound (char **argptr, int funf - else if ((p[0] == ':') && (p[1] == ':')) - break; /* Found double-colon. */ - else -- /* PASS2: We'll keep getting here, until p->"", at which point -- we exit this loop. */ -- p++; -+ { -+ /* PASS2: We'll keep getting here, until P points to one of the -+ break characters, at which point we exit this loop. */ -+ if (strchr (break_characters, *p) == NULL) -+ p++; -+ } - } - - if (*p != ':') -@@ -1340,7 +1350,7 @@ decode_compound (char **argptr, int funf - unsuccessfully all the components of the - string, and p->""(PASS2). */ - -- /* We get here if p points to ' ', '\t', '\'', "::" or ""(i.e -+ /* We get here if p points to one of the break characters or ""(i.e - string ended). */ - /* Save restart for next time around. */ - p2 = p; -@@ -1491,6 +1501,18 @@ decode_compound (char **argptr, int funf - /* We couldn't find a class, so we're in case 2 above. We check the - entire name as a symbol instead. */ - -+ if (current_language->la_language == language_cplus -+ || current_language->la_language == language_java) -+ { -+ char *paren = strchr (p, '('); -+ if (paren != NULL) -+ p = find_method_overload_end (paren); -+ -+ /* Make sure we keep important kewords like "const" */ -+ if (strncmp (p, " const", 6) == 0) -+ p += 6; -+ } -+ - copy = (char *) alloca (p - saved_arg2 + 1); - memcpy (copy, saved_arg2, p - saved_arg2); - /* Note: if is_quoted should be true, we snuff out quote here -@@ -1503,9 +1525,18 @@ decode_compound (char **argptr, int funf - sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0); - if (sym) - return symbol_found (funfirstline, canonical, copy, sym, NULL); -+ else -+ { -+ struct minimal_symbol *msym; -+ -+ /* Couldn't find any interpretation as classes/namespaces. As a last -+ resort, try the minimal symbol tables. */ -+ msym = lookup_minimal_symbol (copy, NULL, NULL); -+ if (msym != NULL) -+ return minsym_found (funfirstline, msym); -+ } - -- /* Couldn't find any interpretation as classes/namespaces, so give -- up. The quotes are important if copy is empty. */ -+ /* Couldn't find a minimal symbol, either, so give up. */ - if (not_found_ptr) - *not_found_ptr = 1; - cplusplus_error (the_real_saved_arg, -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr12273.cc -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr12273.cc 2011-02-06 23:07:19.000000000 +0100 -@@ -0,0 +1,37 @@ -+/* This test case is part of GDB, the GNU debugger. -+ -+ Copyright 2010 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 . */ -+ -+template -+class GDB -+{ -+ public: -+ static int simple (void) { return 0; } -+ static int harder (T a) { return 1; } -+ template -+ static X even_harder (T a) { return static_cast (a); } -+ int operator == (GDB const& other) -+ { return 1; } -+}; -+ -+int main(int argc, char **argv) -+{ -+ GDB a, b; -+ if (a == b) -+ return GDB::harder('a') + GDB::harder(3) -+ + GDB::even_harder ('a'); -+ return GDB::simple (); -+} -Index: gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr12273.exp -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-7.2.50.20110206/gdb/testsuite/gdb.cp/pr12273.exp 2011-02-06 23:07:19.000000000 +0100 -@@ -0,0 +1,46 @@ -+# Copyright 2010 Free Software Foundation, Inc. -+# -+# Contributed by Red Hat, originally written by Keith Seitz. -+# -+# 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 . -+ -+# This file is part of the gdb testsuite. -+ -+if {[skip_cplus_tests]} { continue } -+ -+set testfile "pr12273" -+# Do NOT compile with debug flag. -+prepare_for_testing pr12273 $testfile $testfile.cc {c++} -+ -+gdb_test_no_output "set language c++" -+ -+# A list of minimal symbol names to check. -+# Note that GDB::even_harder(char) is quoted and includes -+# the return type. This is necessary because this is the demangled name -+# of the minimal symbol. -+set min_syms [list \ -+ "GDB::operator ==" \ -+ "GDB::operator==(GDB const&)" \ -+ "GDB::harder(char)" \ -+ "GDB::harder(int)" \ -+ {"int GDB::even_harder(char)"} \ -+ "GDB::simple()"] -+ -+foreach sym $min_syms { -+ if {[gdb_breakpoint $sym]} { -+ pass "setting breakpoint at $sym" -+ } -+} -+ -+gdb_exit diff --git a/gdb-python-newbacktrace.patch b/gdb-python-newbacktrace.patch deleted file mode 100644 index c07757c..0000000 --- a/gdb-python-newbacktrace.patch +++ /dev/null @@ -1,153 +0,0 @@ -http://sourceware.org/ml/archer/2011-q1/msg00024.html -Subject: [patch] Fix RH BZ 672235 - - -Bug: - -http://bugzilla.redhat.com/show_bug.cgi?id=672235 - -The latter half of this bug was caused by removing the value function -from gdb.Symbol. This happened quite some time ago, so I am a little -surprised it took this long to surface. - -The old Symbol.value function never returned anything except a gdb.Block -if the symbol happened to represent a function a block. Anything else -raised an error. Way back when, I removed this function as it was an -obvious stub, and it was superseded by frame.read_var() which is a more -accurate method of determining the value of a symbol. - -Wind forward to today, and it turns out one of the unported -archer-tromey-python scripts we ship in Fedora relies on this (symbol -> -block) API. I thought about ways of trying to fix this. I thought about -just changing FrameWrapper to just take a block instead of a symbol -representing a function. But FrameWrapper has an API that we shipped. -I tried to find the block through the existing API, but that did not -work too well. The gdb.Block method block_for_pc can return a block -from a pc but this just turned out to be expensive and convoluted. I -eventually just elected to add a block() function to gdb.Symbol which, -if the symbol represented a method or a function, would return the block. -Yet I am still not entirely satisfied. It seems weird to ask the user -to retrieve symbol value from frame.read_var for most symbols, but in -the case of a function or method, use block(). I tried to use read_var -for this, but it returns a gdb.Value, and I could not figure out a way to -transform a gdb.Value to a gdb.Block. - -Before I submit this for upstream review I'd like to see if anyone has -any comments. - -Cheers - -Phil - --- - -Index: gdb-7.2.50.20110305/gdb/doc/gdb.texinfo -=================================================================== ---- gdb-7.2.50.20110305.orig/gdb/doc/gdb.texinfo 2011-03-05 08:27:09.000000000 +0100 -+++ gdb-7.2.50.20110305/gdb/doc/gdb.texinfo 2011-03-05 08:28:33.000000000 +0100 -@@ -22919,6 +22919,13 @@ The result is a @code{gdb.Symbol} object - is not found. - @end defun - -+A @code{gdb.Symbol} object has the following methods: -+ -+@defmethod Symbol block -+Returns a @code{gdb.Block} object if the symbol is a function or a -+method. @xref{Blocks In Python}. -+@end defmethod -+ - A @code{gdb.Symbol} object has the following attributes: - - @table @code -Index: gdb-7.2.50.20110305/gdb/python/lib/gdb/FrameWrapper.py -=================================================================== ---- gdb-7.2.50.20110305.orig/gdb/python/lib/gdb/FrameWrapper.py 2011-03-05 08:26:12.000000000 +0100 -+++ gdb-7.2.50.20110305/gdb/python/lib/gdb/FrameWrapper.py 2011-03-05 08:27:22.000000000 +0100 -@@ -46,7 +46,7 @@ class FrameWrapper: - return - - first = True -- block = func.value -+ block = func.block () - - for sym in block: - if sym.is_argument: -@@ -60,7 +60,7 @@ class FrameWrapper: - return - - first = True -- block = func.value -+ block = func.block () - - for sym in block: - if not sym.is_argument: -Index: gdb-7.2.50.20110305/gdb/python/py-symbol.c -=================================================================== ---- gdb-7.2.50.20110305.orig/gdb/python/py-symbol.c 2011-02-26 03:07:09.000000000 +0100 -+++ gdb-7.2.50.20110305/gdb/python/py-symbol.c 2011-03-05 08:27:22.000000000 +0100 -@@ -167,6 +167,27 @@ sympy_is_variable (PyObject *self, void - || class == LOC_OPTIMIZED_OUT)); - } - -+static PyObject * -+sympy_get_block (PyObject *self, PyObject *args) -+{ -+ struct symbol *symbol = NULL; -+ -+ SYMPY_REQUIRE_VALID (self, symbol); -+ -+ if (SYMBOL_CLASS (symbol) == LOC_BLOCK) -+ { -+ struct symtab *symt = SYMBOL_SYMTAB (symbol); -+ -+ return block_to_block_object (SYMBOL_BLOCK_VALUE (symbol), -+ symt->objfile); -+ } -+ else -+ PyErr_SetString (PyExc_RuntimeError, -+ _("Symbol is not a block class.")); -+ -+ return NULL; -+} -+ - /* Given a symbol, and a symbol_object that has previously been - allocated and initialized, populate the symbol_object with the - struct symbol data. Also, register the symbol_object life-cycle -@@ -396,6 +417,13 @@ gdbpy_initialize_symbols (void) - - - -+static PyMethodDef symbol_object_methods[] = { -+ { "block", sympy_get_block, METH_NOARGS, -+ "block () -> gdb.Block.\n\ -+Return the block of this symbol, if the symbol represents a function." }, -+ {NULL} /* Sentinel */ -+}; -+ - static PyGetSetDef symbol_object_getset[] = { - { "symtab", sympy_get_symtab, NULL, - "Symbol table in which the symbol appears.", NULL }, -@@ -449,7 +477,7 @@ PyTypeObject symbol_object_type = { - 0, /*tp_weaklistoffset */ - 0, /*tp_iter */ - 0, /*tp_iternext */ -- 0, /*tp_methods */ -+ symbol_object_methods, /*tp_methods */ - 0, /*tp_members */ - symbol_object_getset /*tp_getset */ - }; -Index: gdb-7.2.50.20110305/gdb/testsuite/gdb.python/py-symbol.exp -=================================================================== ---- gdb-7.2.50.20110305.orig/gdb/testsuite/gdb.python/py-symbol.exp 2011-02-22 23:48:12.000000000 +0100 -+++ gdb-7.2.50.20110305/gdb/testsuite/gdb.python/py-symbol.exp 2011-03-05 08:27:22.000000000 +0100 -@@ -76,6 +76,10 @@ gdb_test "python print func.print_name" - gdb_test "python print func.linkage_name" "func" "Test func.linkage_name" - gdb_test "python print func.addr_class == gdb.SYMBOL_LOC_BLOCK" "True" "Test func.addr_class" - -+# Test block() method -+gdb_py_test_silent_cmd "python func = frame.block().function" "Get block" 0 -+gdb_test "python print func.block().function.name" "func" "Test block method" -+ - gdb_breakpoint [gdb_get_line_number "Break at end."] - gdb_continue_to_breakpoint "Break at end." - gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "Get Frame" 0 diff --git a/gdb-stap-warnings.patch b/gdb-stap-warnings.patch new file mode 100755 index 0000000..8e07e08 --- /dev/null +++ b/gdb-stap-warnings.patch @@ -0,0 +1,59 @@ +http://sourceware.org/ml/archer/2011-q1/msg00136.html +Subject: archer-sergiodj-stap -O2 -Wall warnings=errors + +Hi Sergio, + +with -O2 (+some -Wall or so options possibly - what applies for Fedora builds) +one gets: + +gcc-4.6.0-0.14.fc15.x86_64 +stap-probe.c: In function ‘stap_fetch_reg_value’: +stap-probe.c:923:12: error: ‘aop’ may be used uninitialized in this function [-Werror=uninitialized] +stap-probe.c:919:10: error: ‘ret’ may be used uninitialized in this function [-Werror=uninitialized] +stap-probe.c: In function ‘stap_evaluate_conditionally’: +stap-probe.c:1184:3: error: ‘res’ may be used uninitialized in this function [-Werror=uninitialized] + +The attached patch needs a review, I have only briefly checked it is not +completely bogus. + + +Thanks, +Jan + + +--- a/gdb/stap-probe.c ++++ b/gdb/stap-probe.c +@@ -780,7 +780,9 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info, + #define REG_NAME_MAX_SIZE 20 + char regname[REG_NAME_MAX_SIZE + 1]; + int len, regnum, indirect_p = 0; +- struct value *ret; ++ /* GCC false warning: ‘ret’ may be used uninitialized in this function ++ */ ++ struct value *ret = NULL; + + /* The function which called us did not check if the expression + buffer was empty. */ +@@ -851,7 +853,9 @@ stap_fetch_reg_value (struct stap_evaluation_info *eval_info, + if (indirect_p) + { + struct type *t = NULL; +- enum agent_op aop; ++ /* GCC false warning: ‘aop’ may be used uninitialized in this function. ++ */ ++ enum agent_op aop = 0; + + /* If the user has specified that the register must be indirected, + we should know what's the correct type to cast it before making +@@ -949,7 +953,9 @@ stap_evaluate_single_operand (struct stap_evaluation_info *eval_info) + struct gdbarch *gdbarch = eval_info->gdbarch; + struct frame_info *frame = eval_info->frame; + enum stap_arg_bitness bitness = eval_info->bitness; +- struct value *res; ++ /* GCC false warning: ‘res’ may be used uninitialized in this function ++ */ ++ struct value *res = NULL; + + switch (*eval_info->exp_buf) + { + diff --git a/gdb-upstream.patch b/gdb-upstream.patch deleted file mode 100644 index 1e349df..0000000 --- a/gdb-upstream.patch +++ /dev/null @@ -1,66 +0,0 @@ -http://sourceware.org/ml/gdb-cvs/2011-03/msg00077.html - -### src/gdb/gdbserver/ChangeLog 2011/03/04 06:31:54 1.463 -### src/gdb/gdbserver/ChangeLog 2011/03/05 03:45:26 1.464 -## -1,3 +1,10 @@ -+2011-03-05 Yao Qi -+ -+ * Makefile.in (CLEANDIRS, REQUIRED_SUBDIRS): New variable. -+ (subdir_do): New make target. Copied from gdb/Makefile. -+ (maintainer-clean, realclean, distclean, clean): Call corresponding -+ make targets in common/Makefile. -+ - 2011-03-04 Yao Qi - - * Makefile.in: Remove GNU make feature --directory. ---- src/gdb/gdbserver/Makefile.in 2011/03/04 06:31:54 1.104 -+++ src/gdb/gdbserver/Makefile.in 2011/03/05 03:45:26 1.105 -@@ -136,6 +136,9 @@ - LIBCOMMON = $(LIBCOMMON_DIR)/libcommon.a - LIBCOMMON_SRC = $(srcdir)/$(LIBCOMMON_DIR) - -+CLEANDIRS = $(LIBCOMMON_DIR) -+REQUIRED_SUBDIRS = $(LIBCOMMON_DIR) -+ - SOURCES = $(SFILES) - TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS} - -@@ -291,6 +294,7 @@ - tags: TAGS - - clean: -+ @$(MAKE) $(FLAGS_TO_PASS) DO=clean "DODIRS=$(CLEANDIRS)" subdir_do - rm -f *.o ${ADD_FILES} *~ - rm -f version.c - rm -f gdbserver$(EXEEXT) gdbreplay$(EXEEXT) core make.log -@@ -314,6 +318,7 @@ - rm -f i386-mmx.c i386-mmx-linux.c - - maintainer-clean realclean distclean: clean -+ @$(MAKE) $(FLAGS_TO_PASS) DO=$@ "DODIRS=$(CLEANDIRS)" subdir_do - rm -f nm.h tm.h xm.h config.status config.h stamp-h config.log - rm -f Makefile - -@@ -321,6 +326,22 @@ - stamp-h: config.in config.status - CONFIG_FILES="" CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status - -+subdir_do: force -+ @for i in $(DODIRS); do \ -+ case $$i in \ -+ $(REQUIRED_SUBDIRS)) \ -+ if [ ! -f ./$$i/Makefile ] ; then \ -+ echo "Missing $$i/Makefile" >&2 ; \ -+ exit 1 ; \ -+ fi ;; \ -+ esac ; \ -+ if [ -f ./$$i/Makefile ] ; then \ -+ if (cd ./$$i; \ -+ $(MAKE) $(FLAGS_TO_PASS) $(DO)) ; then true ; \ -+ else exit 1 ; fi ; \ -+ else true ; fi ; \ -+ done -+ - Makefile: Makefile.in config.status - CONFIG_HEADERS="" $(SHELL) ./config.status - diff --git a/gdb.spec b/gdb.spec index 93db69a..488c69a 100644 --- a/gdb.spec +++ b/gdb.spec @@ -23,11 +23,11 @@ Name: gdb%{?_with_debug:-debug} # Set version to contents of gdb/version.in. # NOTE: the FSF gdb versions are numbered N.M for official releases, like 6.3 # and, since January 2005, X.Y.Z.date for daily snapshots, like 6.3.50.20050112 # (daily snapshot from mailine), or 6.3.0.20040112 (head of the release branch). -Version: 7.2.50.20110305 +Version: 7.2.50.20110320 # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 28%{?_with_upstream:.upstream}%{?dist} +Release: 29%{?_with_upstream:.upstream}%{?dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain Group: Development/Debuggers @@ -264,7 +264,7 @@ Patch231: gdb-6.3-bz202689-exec-from-pthread-test.patch # Backported fixups post the source tarball. #Xdrop: Just backports. -Patch232: gdb-upstream.patch +#Patch232: gdb-upstream.patch # Testcase for PPC Power6/DFP instructions disassembly (BZ 230000). #=fedoratest+ppc @@ -549,18 +549,15 @@ Patch555: gdb-gcc46-typedef.patch # =push Patch556: gdb-gcc46-stdarg-prologue.patch -# Fix Python new-backtrace command (BZ 672235, Phil Muldoon). -# =push -Patch557: gdb-python-newbacktrace.patch - -# Fix regressions on C++ names resolving (PR 11734, PR 12273, Keith Seitz). -Patch565: gdb-physname-pr11734-1of2.patch -Patch566: gdb-physname-pr11734-2of2.patch -Patch567: gdb-physname-pr12273.patch - # Fix attach/core-load of {,un}prelinked i386 libs (bugreport by Michal Toman). Patch571: gdb-prelink-rela.patch +# [stap] Fix -O2 warnings. +Patch576: gdb-stap-warnings.patch + +# Fix Ada support crash on uninitialized gdbarch. +Patch577: gdb-ada-gdbarch-crash.patch + BuildRequires: ncurses-devel%{?_isa} texinfo gettext flex bison expat-devel%{?_isa} Requires: readline%{?_isa} BuildRequires: readline-devel%{?_isa} @@ -717,7 +714,7 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %if 0%{!?_with_upstream:1} -%patch232 -p1 +#patch232 -p1 %patch349 -p1 %patch1 -p1 %patch3 -p1 @@ -828,11 +825,9 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch554 -p1 %patch555 -p1 %patch556 -p1 -%patch557 -p1 -%patch565 -p1 -%patch566 -p1 -%patch567 -p1 %patch571 -p1 +%patch576 -p1 +%patch577 -p1 %patch390 -p1 %patch393 -p1 @@ -1258,6 +1253,12 @@ fi %{_infodir}/gdb.info* %changelog +* Sun Mar 20 2011 Jan Kratochvil - 7.2.50.20110320-29.fc15 +- Rebase to FSF GDB 7.2.50.20110320 (which is a 7.3 pre-release). +- Merge archer-sergiodj-stap, the SystemTap probes breakpoints feature. + - [stap] Fix -O2 warnings. +- Fix Ada support crash on uninitialized gdbarch. + * Sat Mar 5 2011 Jan Kratochvil - 7.2.50.20110305-28.fc15 - Rebase to FSF GDB 7.2.50.20110305 (which is a 7.3 pre-release). diff --git a/sources b/sources index d29a2bd..fec21c3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 04e5c4b1b9e633422cc48990fe61958d libstdc++-v3-python-r155978.tar.bz2 -143ab09e8724b0058fbf882832f6d2f3 gdb-7.2.50.20110305.tar.bz2 +cc48d62b23b53816eb9639a8e9504d47 gdb-7.2.50.20110320.tar.bz2