public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] archer-jankratochvil-ifunc: more fixes
@ 2010-03-21 19:16 jkratoch
0 siblings, 0 replies; only message in thread
From: jkratoch @ 2010-03-21 19:16 UTC (permalink / raw)
To: archer-commits
The branch, archer-jankratochvil-ifunc has been updated
via 2e6a55fcce3aaac63ecc5cfe0a8639fd9c06e267 (commit)
from 67f0af148874dfeb8113562513bf71c34e19b5d4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit 2e6a55fcce3aaac63ecc5cfe0a8639fd9c06e267
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date: Sun Mar 21 20:11:42 2010 +0100
more fixes
-----------------------------------------------------------------------
Summary of changes:
gdb/blockframe.c | 56 -------------------
gdb/breakpoint.c | 23 ++++++--
gdb/elfread.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/gdbtypes.c | 6 ++
gdb/gdbtypes.h | 1 +
gdb/infcall.c | 25 ++++++---
gdb/parse.c | 4 ++
gdb/symtab.h | 12 +++-
8 files changed, 212 insertions(+), 73 deletions(-)
First 500 lines of diff:
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
index b7d298c..938f56d 100644
--- a/gdb/blockframe.c
+++ b/gdb/blockframe.c
@@ -332,62 +332,6 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
: FIND_PC_PARTIAL_FUNCTION_NORMAL;
}
-int
-resolve_gnu_ifunc_by_got (struct program_space *pspace,
- const char *function_name,
- CORE_ADDR *function_addressp)
-{
- struct objfile *objfile;
- char *function_name_got_plt;
-
- 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 (pspace, objfile)
- {
- bfd *obfd = objfile->obfd;
- struct minimal_symbol *msym;
- CORE_ADDR pointer_address, function_address;
- asection *plt;
-
- msym = lookup_minimal_symbol (function_name_got_plt, NULL, objfile);
- if (msym == NULL)
- continue;
- if (MSYMBOL_TYPE (msym) != mst_slot_got_plt)
- continue;
- pointer_address = SYMBOL_VALUE_ADDRESS (msym);
-
- plt = bfd_get_section_by_name (obfd, ".plt");
- if (plt == NULL)
- continue;
-
- {
- struct gdbarch *gdbarch = objfile->gdbarch;
- struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
- size_t ptr_size = TYPE_LENGTH (ptr_type);
- gdb_byte *buf = alloca (ptr_size);
-
- if (MSYMBOL_SIZE (msym) != ptr_size)
- continue;
- if (target_read_memory (pointer_address, buf, ptr_size) != 0)
- continue;
- function_address = extract_typed_address (buf, ptr_type);
- }
-
- /* If .plt jumps back to .plt the symbol is still deferred for later
- resolution and it has no use for GDB. */
- if (bfd_get_section_vma (obfd, plt) <= function_address
- && function_address < bfd_get_section_vma (obfd, plt)
- + bfd_get_section_size (plt))
- continue;
-
- *function_addressp = function_address;
- return 1;
- }
- return 0;
-}
-
/* 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 382197e..f6c0770 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5179,11 +5179,21 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc)
{
struct breakpoint *b = loc->owner;
- if (!resolve_gnu_ifunc_by_got (loc->pspace, loc->function_name,
- &loc->address)
- && b->type == bp_breakpoint && b->loc == loc && loc->next == NULL
- && b->related_breakpoint == b)
- b->type = bp_gnu_ifunc_resolver;
+ gdb_assert (loc->pspace == current_program_space);
+ if (resolve_gnu_ifunc (loc->function_name, &loc->requested_address))
+ {
+ /* Recalculate ADDRESS based on new REQUESTED_ADDRESS. */
+ loc->address = adjust_breakpoint_address (loc->gdbarch,
+ loc->requested_address,
+ b->type);
+ }
+ else if (b->type == bp_breakpoint && b->loc == loc
+ && loc->next == NULL && b->related_breakpoint == b)
+ {
+ /* Create only the whole new breakpoint of this type but do not
+ mess more complicated breakpoints with multiple locations. */
+ b->type = bp_gnu_ifunc_resolver;
+ }
}
if (loc->function_name)
@@ -10627,6 +10637,9 @@ gnu_ifunc_resolver_return_stop (struct breakpoint *b)
}
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;
diff --git a/gdb/elfread.c b/gdb/elfread.c
index fa374cd..182dd40 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -660,6 +660,164 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table)
do_cleanups (back_to);
}
+/* Function does not check for possibly created duplicities in the cache.
+ Check it by resolve_gnu_ifunc_by_cache first. */
+
+static struct minimal_symbol *
+gnu_ifunc_record_cache_unchecked (const char *function_name,
+ CORE_ADDR function_address)
+{
+ struct minimal_symbol *msym, *msym_new;
+ asection *sect;
+ struct objfile *objfile;
+ char *function_name_gnu_ifunc_tgt;
+
+ msym = lookup_minimal_symbol_by_pc (function_address);
+ if (msym == NULL)
+ return NULL;
+ if (SYMBOL_VALUE_ADDRESS (msym) != function_address)
+ return NULL;
+ /* minimal symbols have always SYMBOL_OBJ_SECTION non-NULL. */
+ sect = SYMBOL_OBJ_SECTION (msym)->the_bfd_section;
+ objfile = SYMBOL_OBJ_SECTION (msym)->objfile;
+
+ /* If .plt jumps back to .plt the symbol is still deferred for later
+ 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 <tab>-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)
+ {
+ /* 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));
+ }
+}
+
+static struct minimal_symbol *
+resolve_gnu_ifunc_by_got (const char *function_name)
+{
+ 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)
+ {
+ bfd *obfd = objfile->obfd;
+ 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;
+ asection *plt;
+ gdb_byte *buf = alloca (ptr_size);
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol (function_name_got_plt, NULL, objfile);
+ if (msym == NULL)
+ continue;
+ if (MSYMBOL_TYPE (msym) != mst_slot_got_plt)
+ continue;
+ pointer_address = SYMBOL_VALUE_ADDRESS (msym);
+
+ plt = bfd_get_section_by_name (obfd, ".plt");
+ if (plt == NULL)
+ continue;
+
+ if (MSYMBOL_SIZE (msym) != ptr_size)
+ continue;
+ if (target_read_memory (pointer_address, buf, ptr_size) != 0)
+ continue;
+ function_address = extract_typed_address (buf, ptr_type);
+
+ 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;
+ }
+
+ return 0;
+}
+
struct build_id
{
size_t size;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 00e33b1..1329e0b 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -3602,6 +3602,12 @@ objfile_type (struct objfile *objfile)
objfile);
TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol)
= objfile_type->nodebug_text_symbol;
+ objfile_type->nodebug_got_plt_symbol
+ = init_type (TYPE_CODE_PTR, gdbarch_addr_bit (gdbarch) / 8, 0,
+ "<text from jump slot in .got.plt, no debug info>",
+ objfile);
+ TYPE_TARGET_TYPE (objfile_type->nodebug_got_plt_symbol)
+ = objfile_type->nodebug_text_symbol;
objfile_type->nodebug_data_symbol
= init_type (TYPE_CODE_INT,
gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0,
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 95c9dd6..773f7a7 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1169,6 +1169,7 @@ struct objfile_type
/* Types used for symbols with no debug information. */
struct type *nodebug_text_symbol;
struct type *nodebug_text_gnu_ifunc_symbol;
+ struct type *nodebug_got_plt_symbol;
struct type *nodebug_data_symbol;
struct type *nodebug_unknown_symbol;
struct type *nodebug_tls_symbol;
diff --git a/gdb/infcall.c b/gdb/infcall.c
index d72a64f..a9b0724 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -236,24 +236,31 @@ static CORE_ADDR
gnu_ifunc_resolve (struct gdbarch *gdbarch, CORE_ADDR pc)
{
char *name_at_pc;
- CORE_ADDR start_at_pc, retval;
+ CORE_ADDR start_at_pc, address;
struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
- struct value *function, *address;
+ struct value *function, *address_val;
if (find_pc_partial_function (pc, &name_at_pc, &start_at_pc, NULL)
- && start_at_pc == pc
- && resolve_gnu_ifunc_by_got (current_program_space, name_at_pc, &retval))
- return retval;
+ && 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 = call_function_by_hand (function, 0, NULL);
- return gdbarch_convert_from_func_ptr_addr (gdbarch,
- value_as_address (address),
- ¤t_target);
+ 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);
}
static struct type *
diff --git a/gdb/parse.c b/gdb/parse.c
index cc90199..80bed03 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -547,6 +547,10 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
write_exp_elt_type (objfile_type (objfile)->nodebug_data_symbol);
break;
+ case mst_slot_got_plt:
+ write_exp_elt_type (objfile_type (objfile)->nodebug_got_plt_symbol);
+ break;
+
default:
write_exp_elt_type (objfile_type (objfile)->nodebug_unknown_symbol);
break;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index d01e3da..5da72c6 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -922,9 +922,15 @@ extern enum find_pc_partial_function_type
extern void clear_pc_function_cache (void);
-extern int resolve_gnu_ifunc_by_got (struct program_space *pspace,
- const char *function_name,
- CORE_ADDR *function_addressp);
+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 */
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2010-03-21 19:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-21 19:16 [SCM] archer-jankratochvil-ifunc: more fixes jkratoch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).