diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/c-exp.y | 38 | ||||
-rw-r--r-- | gdb/minsyms.c | 17 | ||||
-rw-r--r-- | gdb/minsyms.h | 4 | ||||
-rw-r--r-- | gdb/symtab.c | 19 | ||||
-rw-r--r-- | gdb/symtab.h | 7 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/symbol-alias.c | 31 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/symbol-alias.exp | 37 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/symbol-alias2.c | 34 |
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"))); |