diff options
-rw-r--r-- | gdb/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/blockframe.c | 35 | ||||
-rw-r--r-- | gdb/symtab.h | 5 |
3 files changed, 44 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3dd8938..8c156e1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,16 @@ 2011-03-28 Jan Kratochvil <jan.kratochvil@redhat.com> + GDB find_pc_partial_function support for STT_GNU_IFUNC. + * blockframe.c (cache_pc_function_is_gnu_ifunc): New variable. + (clear_pc_function_cache): Clear it. + (find_pc_partial_function): Rename to ... + (find_pc_partial_function_gnu_ifunc): ... this function. New + parameter is_gnu_ifunc_p, describe it. Set *IS_GNU_IFUNC_P. + (find_pc_partial_function): New wrapper for this function. + * symtab.h (find_pc_partial_function_gnu_ifunc): New declaration. + +2011-03-28 Jan Kratochvil <jan.kratochvil@redhat.com> + GDB internal type support for STT_GNU_IFUNC. * elfread.c (record_minimal_symbol): Support mst_text_gnu_ifunc. (elf_symtab_read): Set mst_text_gnu_ifunc for diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 5bc5930..3b546a7 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -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; +static int cache_pc_function_is_gnu_ifunc = 0; /* Clear cache, e.g. when symbol table is discarded. */ @@ -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; + cache_pc_function_is_gnu_ifunc = 0; } /* Finds the "function" (text symbol) that is smaller than PC but @@ -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 -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) { 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; + cache_pc_function_is_gnu_ifunc = TYPE_GNU_IFUNC (SYMBOL_TYPE (f)); goto return_cached_value; } } @@ -262,12 +267,15 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, *address = 0; if (endaddr != NULL) *endaddr = 0; + if (is_gnu_ifunc_p != NULL) + *is_gnu_ifunc_p = 0; return 0; } cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol); cache_pc_function_name = SYMBOL_LINKAGE_NAME (msymbol); cache_pc_function_section = section; + cache_pc_function_is_gnu_ifunc = MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc; /* If the minimal symbol has a size, use it for the cache. Otherwise use the lesser of the next minimal symbol in the same @@ -330,9 +338,22 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, *endaddr = cache_pc_function_high; } + 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/symtab.h b/gdb/symtab.h index 9e24828..0645515 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -956,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 *, |