aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/c-exp.y38
-rw-r--r--gdb/minsyms.c17
-rw-r--r--gdb/minsyms.h4
-rw-r--r--gdb/symtab.c19
-rw-r--r--gdb/symtab.h7
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.base/symbol-alias.c31
-rw-r--r--gdb/testsuite/gdb.base/symbol-alias.exp37
-rw-r--r--gdb/testsuite/gdb.base/symbol-alias2.c34
10 files changed, 194 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fae7150..db53fcb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2017-08-21 Pedro Alves <palves@redhat.com>
+ PR gdb/19487
+ * c-exp.y (variable production): Handle function aliases.
+ * minsyms.c (msymbol_is_text): New function.
+ * minsyms.h (msymbol_is_text): Declare.
+ * symtab.c (find_function_alias_target): New function.
+ * symtab.h (find_function_alias_target): Declare.
+
+2017-08-21 Pedro Alves <palves@redhat.com>
+
* eval.c (evaluate_subexp_standard) <OP_TYPE>: Don't dig past
typedefs.
* typeprint.c (whatis_exp): If handling "whatis", and expression
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 24a2fbd..a1f9fee 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -1038,18 +1038,38 @@ variable: name_not_typename
}
else
{
- struct bound_minimal_symbol msymbol;
char *arg = copy_name ($1.stoken);
- msymbol =
- lookup_bound_minimal_symbol (arg);
- if (msymbol.minsym != NULL)
- write_exp_msymbol (pstate, msymbol);
- else if (!have_full_symbols () && !have_partial_symbols ())
- error (_("No symbol table is loaded. Use the \"file\" command."));
+ bound_minimal_symbol msymbol
+ = lookup_bound_minimal_symbol (arg);
+ if (msymbol.minsym == NULL)
+ {
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error (_("No symbol table is loaded. Use the \"file\" command."));
+ else
+ error (_("No symbol \"%s\" in current context."),
+ copy_name ($1.stoken));
+ }
+
+ /* This minsym might be an alias for
+ another function. See if we can find
+ the debug symbol for the target, and
+ if so, use it instead, since it has
+ return type / prototype info. This
+ is important for example for "p
+ *__errno_location()". */
+ symbol *alias_target
+ = find_function_alias_target (msymbol);
+ if (alias_target != NULL)
+ {
+ write_exp_elt_opcode (pstate, OP_VAR_VALUE);
+ write_exp_elt_block
+ (pstate, SYMBOL_BLOCK_VALUE (alias_target));
+ write_exp_elt_sym (pstate, alias_target);
+ write_exp_elt_opcode (pstate, OP_VAR_VALUE);
+ }
else
- error (_("No symbol \"%s\" in current context."),
- copy_name ($1.stoken));
+ write_exp_msymbol (pstate, msymbol);
}
}
;
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index c93eaa3..69b9e40 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -52,6 +52,23 @@
#include "cli/cli-utils.h"
#include "symbol.h"
+/* See minsyms.h. */
+
+bool
+msymbol_is_text (minimal_symbol *msymbol)
+{
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_text:
+ case mst_text_gnu_ifunc:
+ case mst_solib_trampoline:
+ case mst_file_text:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE.
At the end, copy them all into one newly allocated location on an objfile's
per-BFD storage obstack. */
diff --git a/gdb/minsyms.h b/gdb/minsyms.h
index b82a22a..e763f62 100644
--- a/gdb/minsyms.h
+++ b/gdb/minsyms.h
@@ -157,6 +157,10 @@ void terminate_minimal_symbol_table (struct objfile *objfile);
+/* Return whether MSYMBOL is a function/method. */
+
+bool msymbol_is_text (minimal_symbol *msymbol);
+
/* Compute a hash code for the string argument. */
unsigned int msymbol_hash (const char *);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index ccf31cc..2c19b53 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3830,6 +3830,25 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
/* Don't return END_PC, which is past the end of the function. */
return prologue_sal.pc;
}
+
+/* See symtab.h. */
+
+symbol *
+find_function_alias_target (bound_minimal_symbol msymbol)
+{
+ if (!msymbol_is_text (msymbol.minsym))
+ return NULL;
+
+ CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
+ symbol *sym = find_pc_function (addr);
+ if (sym != NULL
+ && SYMBOL_CLASS (sym) == LOC_BLOCK
+ && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == addr)
+ return sym;
+
+ return NULL;
+}
+
/* If P is of the form "operator[ \t]+..." where `...' is
some legitimate operator text, return a pointer to the
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 35949f0..8cbf4d6 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -1556,6 +1556,13 @@ extern CORE_ADDR skip_prologue_using_sal (struct gdbarch *gdbarch,
extern struct symbol *fixup_symbol_section (struct symbol *,
struct objfile *);
+/* If MSYMBOL is an text symbol, look for a function debug symbol with
+ the same address. Returns NULL if not found. This is necessary in
+ case a function is an alias to some other function, because debug
+ information is only emitted for the alias target function's
+ definition, not for the alias. */
+extern symbol *find_function_alias_target (bound_minimal_symbol msymbol);
+
/* Symbol searching */
/* Note: struct symbol_search, search_symbols, et.al. are declared here,
instead of making them local to symtab.c, for gdbtk's sake. */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 03e825e..f147731 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2017-08-21 Pedro Alves <palves@redhat.com>
+ PR gdb/19487
+ * gdb.base/symbol-alias.c: New.
+ * gdb.base/symbol-alias2.c: New.
+ * gdb.base/symbol-alias.exp: New.
+
+2017-08-21 Pedro Alves <palves@redhat.com>
+
* gdb.base/dfp-test.c
(d32_t, d64_t, d128_t, d32_t2, d64_t2, d128_t2, v_d32_t, v_d64_t)
(v_d128_t, v_d32_t2, v_d64_t2, v_d128_t2): New.
diff --git a/gdb/testsuite/gdb.base/symbol-alias.c b/gdb/testsuite/gdb.base/symbol-alias.c
new file mode 100644
index 0000000..cc5d104
--- /dev/null
+++ b/gdb/testsuite/gdb.base/symbol-alias.c
@@ -0,0 +1,31 @@
+/* This test is part of GDB, the GNU debugger.
+
+ Copyright 2017 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+struct S
+{
+ int field1;
+ int field2;
+};
+
+extern struct S *func_alias (void);
+
+int
+main (void)
+{
+ struct S *s = func_alias ();
+ return s->field1 - s->field1;
+}
diff --git a/gdb/testsuite/gdb.base/symbol-alias.exp b/gdb/testsuite/gdb.base/symbol-alias.exp
new file mode 100644
index 0000000..dc63eb1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/symbol-alias.exp
@@ -0,0 +1,37 @@
+# Test for printing alias symbols.
+# Copyright 2017 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile symbol-alias.c symbol-alias2.c
+
+if { [prepare_for_testing "failed to prepare" ${testfile} [list $srcfile $srcfile2]] } {
+ return -1
+}
+
+if ![runto_main] then {
+ fail "can't run to main"
+ continue
+}
+
+# Functions.
+foreach f {"func" "func_alias"} {
+ gdb_test "p $f" " = {struct S \\*\\(void\\)} $hex <func>"
+ gdb_test "p *${f}()" "= {field1 = 1, field2 = 2}"
+}
+
+# Variables.
+foreach v {"g_var_s" "g_var_s_alias"} {
+ gdb_test "p $v" "= {field1 = 1, field2 = 2}"
+}
diff --git a/gdb/testsuite/gdb.base/symbol-alias2.c b/gdb/testsuite/gdb.base/symbol-alias2.c
new file mode 100644
index 0000000..aedd520
--- /dev/null
+++ b/gdb/testsuite/gdb.base/symbol-alias2.c
@@ -0,0 +1,34 @@
+/* This test is part of GDB, the GNU debugger.
+
+ Copyright 2017 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+struct S
+{
+ int field1;
+ int field2;
+};
+
+struct S g_var_s = { 1, 2 };
+
+static struct S *
+func (void)
+{
+ return &g_var_s;
+}
+
+struct S *func_alias (void) __attribute__ ((alias ("func")));
+
+extern struct S g_var_s_alias __attribute__ ((alias ("g_var_s")));