diff options
author | Pedro Alves <palves@redhat.com> | 2017-11-29 19:25:58 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-11-29 19:25:58 +0000 |
commit | 4024cf2b8d864279ff87af1a2ade77ab6d710d50 (patch) | |
tree | dac0340225b6677d3fecda4ebd6f64df7dcbf0d6 /gdb/linespec.c | |
parent | 5dcf52c19f7045fb179f703426d345b8a81d2210 (diff) |
Fix setting-breakpoints regression on PPC64 (function descriptors)
The recent-ish commit e5f25bc5d6db ('Fix "list ambiguous_variable"')
caused a serious regression on PPC64. See
<https://sourceware.org/ml/gdb-patches/2017-11/msg00666.html>.
Basically, after that patch, GDB sets breakpoints in function
descriptors instead of where the descriptors point to, which is
incorrect.
The problem is that GDB now only runs a minsym's address through
gdbarch_convert_from_func_ptr_addr if msymbol_is_text returns true.
However, if the symbol points to a function descriptor,
msymbol_is_text is false since function descriptors are in fact
outside the text section.
The fix is to also run a non-text address through
gdbarch_convert_from_func_ptr_addr, and if that detects that it was
indeed a function descriptor, treat the resulting address as a
function.
While implementing that directly in linespec.c:minsym_found (where the
bad msymbol_is_text check is) fixes the issue, I noticed that
linespec.c:add_minsym has some code that also basically needs to do
the same checks, however it's implemented differently. Also,
add_minsym is calling find_pc_sect_line on non-function symbols, which
also doesn't look right.
So I introduced msymbol_is_function, so that we have a simple place to
consider minsyms and function descriptors.
And then, the only other use of msymbol_is_text is in
find_function_alias_target, which turns out to also be incorrect.
Changing that one to use msymbol_is_function, i.e., to consider
function descriptors too fixes (on PPC64):
-FAIL: gdb.base/symbol-alias.exp: p func_alias
-FAIL: gdb.base/symbol-alias.exp: p *func_alias()
+PASS: gdb.base/symbol-alias.exp: p func_alias
+PASS: gdb.base/symbol-alias.exp: p *func_alias()
And then after that, msymbol_is_text is no longer used anywhere, so it
can be removed.
Tested on x86_64 GNU/Linux, no regressions. Tested on PPC64 GNU/Linux
and results compared to a testrun of e5f25bc5d6db^ (before the
offending commit), also no regressions. (there's a couple new FAILs
and some new symbol name matching unit tests are crashing, but that
looks unrelated).
gdb/ChangeLog:
2017-11-29 Pedro Alves <palves@redhat.com>
* linespec.c (minsym_found, add_minsym): Use msymbol_is_function.
* minsyms.c (msymbol_is_text): Delete.
(msymbol_is_function): New function.
* minsyms.h (msymbol_is_text): Delete.
(msymbol_is_function): New declaration.
* symtab.c (find_function_alias_target): Use msymbol_is_function.
Diffstat (limited to 'gdb/linespec.c')
-rw-r--r-- | gdb/linespec.c | 79 |
1 files changed, 19 insertions, 60 deletions
diff --git a/gdb/linespec.c b/gdb/linespec.c index 3f7f171358..f1e1ea9774 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -4309,22 +4309,12 @@ minsym_found (struct linespec_state *self, struct objfile *objfile, struct minimal_symbol *msymbol, std::vector<symtab_and_line> *result) { - struct gdbarch *gdbarch = get_objfile_arch (objfile); - CORE_ADDR pc; struct symtab_and_line sal; - if (msymbol_is_text (msymbol)) + CORE_ADDR func_addr; + if (msymbol_is_function (objfile, msymbol, &func_addr)) { - sal = find_pc_sect_line (MSYMBOL_VALUE_ADDRESS (objfile, msymbol), - (struct obj_section *) 0, 0); - sal.section = MSYMBOL_OBJ_SECTION (objfile, msymbol); - - /* The minimal symbol might point to a function descriptor; - resolve it to the actual code address instead. */ - pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, - ¤t_target); - if (pc != sal.pc) - sal = find_pc_sect_line (pc, NULL, 0); + sal = find_pc_sect_line (func_addr, NULL, 0); if (self->funfirstline) { @@ -4332,14 +4322,9 @@ minsym_found (struct linespec_state *self, struct objfile *objfile, && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab)) || SYMTAB_LANGUAGE (sal.symtab) == language_asm)) { - /* If gdbarch_convert_from_func_ptr_addr does not apply then - sal.SECTION, sal.LINE&co. will stay correct from above. - If gdbarch_convert_from_func_ptr_addr applies then - sal.SECTION is cleared from above and sal.LINE&co. will - stay correct from the last find_pc_sect_line above. */ - sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol); - sal.pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, - ¤t_target); + struct gdbarch *gdbarch = get_objfile_arch (objfile); + + sal.pc = func_addr; if (gdbarch_skip_entrypoint_p (gdbarch)) sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc); } @@ -4424,52 +4409,26 @@ static void add_minsym (struct minimal_symbol *minsym, void *d) { struct collect_minsyms *info = (struct collect_minsyms *) d; - bound_minimal_symbol_d mo; - - mo.minsym = minsym; - mo.objfile = info->objfile; if (info->symtab != NULL) { - CORE_ADDR pc; - struct symtab_and_line sal; - struct gdbarch *gdbarch = get_objfile_arch (info->objfile); - - sal = find_pc_sect_line (MSYMBOL_VALUE_ADDRESS (info->objfile, minsym), - NULL, 0); - sal.section = MSYMBOL_OBJ_SECTION (info->objfile, minsym); - pc - = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, ¤t_target); - if (pc != sal.pc) - sal = find_pc_sect_line (pc, NULL, 0); + /* We're looking for a label for which we don't have debug + info. */ + CORE_ADDR func_addr; + if (msymbol_is_function (info->objfile, minsym, &func_addr)) + { + symtab_and_line sal = find_pc_sect_line (func_addr, NULL, 0); - if (info->symtab != sal.symtab) - return; + if (info->symtab != sal.symtab) + return; + } } - /* Exclude data symbols when looking for breakpoint locations. */ - if (!info->list_mode) - switch (minsym->type) - { - case mst_slot_got_plt: - case mst_data: - case mst_bss: - case mst_abs: - case mst_file_data: - case mst_file_bss: - { - /* Make sure this minsym is not a function descriptor - before we decide to discard it. */ - struct gdbarch *gdbarch = get_objfile_arch (info->objfile); - CORE_ADDR addr = gdbarch_convert_from_func_ptr_addr - (gdbarch, BMSYMBOL_VALUE_ADDRESS (mo), - ¤t_target); - - if (addr == BMSYMBOL_VALUE_ADDRESS (mo)) - return; - } - } + /* Exclude data symbols when looking for breakpoint locations. */ + if (!info->list_mode && !msymbol_is_function (info->objfile, minsym)) + return; + bound_minimal_symbol_d mo = {minsym, info->objfile}; VEC_safe_push (bound_minimal_symbol_d, info->msyms, &mo); } |