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
BSF_GNU_INDIRECT_FUNCTION.
* eval.c (evaluate_subexp_standard): Support TYPE_GNU_IFUNC.
* gdbtypes.c (init_type): Support TYPE_FLAG_GNU_IFUNC,
builtin_func_func, nodebug_text_gnu_ifunc_symbol and
nodebug_got_plt_symbol.
* gdbtypes.h (enum type_flag_value): New entry TYPE_FLAG_GNU_IFUNC.
(TYPE_GNU_IFUNC): New.
(struct main_type): New field flag_gnu_ifunc.
(struct builtin_type): New field builtin_func_func.
(struct objfile_type): New fields nodebug_text_gnu_ifunc_symbol and
nodebug_got_plt_symbol.
* minsyms.c (lookup_minimal_symbol_text): Support mst_text_gnu_ifunc.
(in_gnu_ifunc_stub): New.
(prim_record_minimal_symbol, find_solib_trampoline_target): Support
mst_text_gnu_ifunc.
* parse.c (write_exp_msymbol): New variable ifunc_msym. Detect and
support mst_text_gnu_ifunc. Support mst_slot_got_plt.
* solib-svr4.c (svr4_in_dynsym_resolve_code): Return true also for
in_gnu_ifunc_stub.
* symmisc.c (dump_msymbols): Support mst_text_gnu_ifunc.
* symtab.c (search_symbols): Likewise.
* symtab.h (enum minimal_symbol_type): New fields mst_text_gnu_ifunc
and mst_slot_got_plt.
(in_gnu_ifunc_stub): 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
+ BSF_GNU_INDIRECT_FUNCTION.
+ * eval.c (evaluate_subexp_standard): Support TYPE_GNU_IFUNC.
+ * gdbtypes.c (init_type): Support TYPE_FLAG_GNU_IFUNC,
+ builtin_func_func, nodebug_text_gnu_ifunc_symbol and
+ nodebug_got_plt_symbol.
+ * gdbtypes.h (enum type_flag_value): New entry TYPE_FLAG_GNU_IFUNC.
+ (TYPE_GNU_IFUNC): New.
+ (struct main_type): New field flag_gnu_ifunc.
+ (struct builtin_type): New field builtin_func_func.
+ (struct objfile_type): New fields nodebug_text_gnu_ifunc_symbol and
+ nodebug_got_plt_symbol.
+ * minsyms.c (lookup_minimal_symbol_text): Support mst_text_gnu_ifunc.
+ (in_gnu_ifunc_stub): New.
+ (prim_record_minimal_symbol, find_solib_trampoline_target): Support
+ mst_text_gnu_ifunc.
+ * parse.c (write_exp_msymbol): New variable ifunc_msym. Detect and
+ support mst_text_gnu_ifunc. Support mst_slot_got_plt.
+ * solib-svr4.c (svr4_in_dynsym_resolve_code): Return true also for
+ in_gnu_ifunc_stub.
+ * symmisc.c (dump_msymbols): Support mst_text_gnu_ifunc.
+ * symtab.c (search_symbols): Likewise.
+ * symtab.h (enum minimal_symbol_type): New fields mst_text_gnu_ifunc
+ and mst_slot_got_plt.
+ (in_gnu_ifunc_stub): New declaration.
+
2011-03-28 Jan Kratochvil <jan.kratochvil@redhat.com>
Support a ring of related breakpoints.
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- if (ms_type == mst_text || ms_type == mst_file_text)
+ if (ms_type == mst_text || ms_type == mst_file_text
+ || ms_type == mst_text_gnu_ifunc)
address = gdbarch_smash_text_address (gdbarch, address);
return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
{
if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
{
- ms_type = mst_text;
+ if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
+ ms_type = mst_text_gnu_ifunc;
+ else
+ ms_type = mst_text;
}
else if ((sym->name[0] == '.' && sym->name[1] == 'L')
|| ((sym->flags & BSF_LOCAL)
return value_zero (builtin_type (exp->gdbarch)->builtin_int,
not_lval);
}
+ else if (TYPE_GNU_IFUNC (ftype))
+ return allocate_value (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype)));
else if (TYPE_TARGET_TYPE (ftype))
return allocate_value (TYPE_TARGET_TYPE (ftype));
else
TYPE_STUB_SUPPORTED (type) = 1;
if (flags & TYPE_FLAG_FIXED_INSTANCE)
TYPE_FIXED_INSTANCE (type) = 1;
+ if (flags & TYPE_FLAG_GNU_IFUNC)
+ TYPE_GNU_IFUNC (type) = 1;
if (name)
TYPE_NAME (type) = obsavestring (name, strlen (name),
= lookup_pointer_type (builtin_type->builtin_void);
builtin_type->builtin_func_ptr
= lookup_pointer_type (lookup_function_type (builtin_type->builtin_void));
+ builtin_type->builtin_func_func
+ = lookup_function_type (builtin_type->builtin_func_ptr);
/* This type represents a GDB internal function. */
builtin_type->internal_fn
"<text variable, no debug info>", objfile);
TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol)
= objfile_type->builtin_int;
+ objfile_type->nodebug_text_gnu_ifunc_symbol
+ = init_type (TYPE_CODE_FUNC, 1, TYPE_FLAG_GNU_IFUNC,
+ "<text gnu-indirect-function variable, no debug info>",
+ 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,
TYPE_FLAG_VECTOR = (1 << 15),
TYPE_FLAG_FIXED_INSTANCE = (1 << 16),
TYPE_FLAG_STUB_SUPPORTED = (1 << 17),
+ TYPE_FLAG_GNU_IFUNC = (1 << 18),
/* Used for error-checking. */
TYPE_FLAG_MIN = TYPE_FLAG_UNSIGNED
#define TYPE_NOTTEXT(t) (TYPE_INSTANCE_FLAGS (t) & TYPE_INSTANCE_FLAG_NOTTEXT)
+/* Used only for TYPE_CODE_FUNC where it specifies the real function
+ address is returned by this function call. TYPE_TARGET_TYPE determines the
+ final returned function type to be presented to user. */
+
+#define TYPE_GNU_IFUNC(t) (TYPE_MAIN_TYPE (t)->flag_gnu_ifunc)
+
/* Type owner. If TYPE_OBJFILE_OWNED is true, the type is owned by
the objfile retrieved as TYPE_OBJFILE. Otherweise, the type is
owned by an architecture; TYPE_OBJFILE is NULL in this case. */
unsigned int flag_varargs : 1;
unsigned int flag_vector : 1;
unsigned int flag_stub_supported : 1;
+ unsigned int flag_gnu_ifunc : 1;
unsigned int flag_fixed_instance : 1;
unsigned int flag_objfile_owned : 1;
/* True if this type was declared with "class" rather than
(*) () can server as a generic function pointer. */
struct type *builtin_func_ptr;
+ /* `function returning pointer to function (returning void)' type.
+ The final void return type is not significant for it. */
+ struct type *builtin_func_func;
+
/* Special-purpose types. */
/* 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;
msymbol = msymbol->hash_next)
{
if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 &&
- (MSYMBOL_TYPE (msymbol) == mst_text ||
- MSYMBOL_TYPE (msymbol) == mst_file_text))
+ (MSYMBOL_TYPE (msymbol) == mst_text
+ || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc
+ || MSYMBOL_TYPE (msymbol) == mst_file_text))
{
switch (MSYMBOL_TYPE (msymbol))
{
return lookup_minimal_symbol_by_pc_section (pc, NULL);
}
+/* Return non-zero iff PC is in an STT_GNU_IFUNC function resolver. */
+
+int
+in_gnu_ifunc_stub (CORE_ADDR pc)
+{
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+
+ return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc;
+}
+
/* Find the minimal symbol named NAME, and return both the minsym
struct and its objfile. This only checks the linkage name. Sets
*OBJFILE_P and returns the minimal symbol, if it is found. If it
switch (ms_type)
{
case mst_text:
+ case mst_text_gnu_ifunc:
case mst_file_text:
case mst_solib_trampoline:
section = SECT_OFF_TEXT (objfile);
{
ALL_MSYMBOLS (objfile, msymbol)
{
- if (MSYMBOL_TYPE (msymbol) == mst_text
+ if ((MSYMBOL_TYPE (msymbol) == mst_text
+ || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc)
&& strcmp (SYMBOL_LINKAGE_NAME (msymbol),
SYMBOL_LINKAGE_NAME (tsymbol)) == 0)
return SYMBOL_VALUE_ADDRESS (msymbol);
pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target);
if (pc != addr)
{
+ struct minimal_symbol *ifunc_msym = lookup_minimal_symbol_by_pc (pc);
+
/* In this case, assume we have a code symbol instead of
a data symbol. */
- type = mst_text;
+
+ if (ifunc_msym != NULL && MSYMBOL_TYPE (ifunc_msym) == mst_text_gnu_ifunc
+ && SYMBOL_VALUE_ADDRESS (ifunc_msym) == pc)
+ {
+ /* A function descriptor has been resolved but PC is still in the
+ STT_GNU_IFUNC resolver body (such as because inferior does not
+ run to be able to call it). */
+
+ type = mst_text_gnu_ifunc;
+ }
+ else
+ type = mst_text;
section = NULL;
addr = pc;
}
write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol);
break;
+ case mst_text_gnu_ifunc:
+ write_exp_elt_type (objfile_type (objfile)
+ ->nodebug_text_gnu_ifunc_symbol);
+ break;
+
case mst_data:
case mst_file_data:
case mst_bss:
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;
&& pc < info->interp_text_sect_high)
|| (pc >= info->interp_plt_sect_low
&& pc < info->interp_plt_sect_high)
- || in_plt_section (pc, NULL));
+ || in_plt_section (pc, NULL)
+ || in_gnu_ifunc_stub (pc));
}
/* Given an executable's ABFD and target, compute the entry-point
case mst_text:
ms_type = 'T';
break;
+ case mst_text_gnu_ifunc:
+ ms_type = 'i';
+ break;
case mst_solib_trampoline:
ms_type = 'S';
break;
static const enum minimal_symbol_type types3[]
= {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
static const enum minimal_symbol_type types4[]
- = {mst_file_bss, mst_text, mst_abs, mst_unknown};
+ = {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown};
enum minimal_symbol_type ourtype;
enum minimal_symbol_type ourtype2;
enum minimal_symbol_type ourtype3;
{
mst_unknown = 0, /* Unknown type, the default */
mst_text, /* Generally executable instructions */
+ mst_text_gnu_ifunc, /* Executable code returning address
+ of executable code */
+ mst_slot_got_plt, /* GOT entries for .plt sections */
mst_data, /* Generally initialized data */
mst_bss, /* Generally uninitialized data */
mst_abs, /* Generally absolute (nonrelocatable) */
extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR);
+extern int in_gnu_ifunc_stub (CORE_ADDR pc);
+
extern struct minimal_symbol *
lookup_minimal_symbol_and_objfile (const char *,
struct objfile **);