gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 28 Mar 2011 20:21:04 +0000 (20:21 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 28 Mar 2011 20:21:04 +0000 (20:21 +0000)
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.

gdb/ChangeLog
gdb/elfread.c
gdb/eval.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/minsyms.c
gdb/parse.c
gdb/solib-svr4.c
gdb/symmisc.c
gdb/symtab.c
gdb/symtab.h

index 9547bc4f5b37f24b493774567708046aaa91dd29..3dd893818d051a0ee134c85fb59c49ad1f25c1e0 100644 (file)
@@ -1,3 +1,33 @@
+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.
index dacc6f054834d933a9ce97c9da8610c1e3b27ce6..200b82fac1c6cdeebdd586d9c341a39bca9bb57b 100644 (file)
@@ -185,7 +185,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name,
 {
   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,
@@ -394,7 +395,10 @@ elf_symtab_read (struct objfile *objfile, int type,
            {
              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)
index 09b41a0fbc2fe6a633d9a63cbaa7c77bdd6bed4b..bbc7b8a71f80661438d9a4d6a1c9cd3e7e1fedb2 100644 (file)
@@ -1832,6 +1832,8 @@ evaluate_subexp_standard (struct type *expect_type,
              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
index 91fafa21524fea912fd2b985185feec52dc8b1db..3b459312d28c3c2830f68269458d689da4fd6163 100644 (file)
@@ -1902,6 +1902,8 @@ init_type (enum type_code code, int length, int flags,
     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),
@@ -3772,6 +3774,8 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
     = 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
@@ -3885,6 +3889,18 @@ objfile_type (struct objfile *objfile)
                 "<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,
index 5f89feccd93f14eab8620c8d10f74b59c2d8c096..39ca1b465cee10c5988459bd7ded4154e2b22a86 100644 (file)
@@ -170,6 +170,7 @@ enum type_flag_value
   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
@@ -271,6 +272,12 @@ enum type_instance_flag_value
 
 #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.  */
@@ -387,6 +394,7 @@ struct main_type
   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
@@ -1178,6 +1186,10 @@ struct builtin_type
      (*) () 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.  */
 
@@ -1218,6 +1230,8 @@ 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;
index 4551b078adf135e7676f56a91c8a534ae1a63f19..534a8b20cbf833cc87e5cc72e95b5b422bfd61d3 100644 (file)
@@ -334,8 +334,9 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
               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))
                    {
@@ -697,6 +698,16 @@ lookup_minimal_symbol_by_pc (CORE_ADDR pc)
   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
@@ -766,6 +777,7 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
   switch (ms_type)
     {
     case mst_text:
+    case mst_text_gnu_ifunc:
     case mst_file_text:
     case mst_solib_trampoline:
       section = SECT_OFF_TEXT (objfile);
@@ -1231,7 +1243,8 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc)
     {
       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);
index 02a7d894f7219ceb5a84995f66eadcf240fc12ac..4815854c83105cedc92a8f6b6e688e2c4455be24 100644 (file)
@@ -487,9 +487,22 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
   pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, &current_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;
     }
@@ -521,6 +534,11 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
       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:
@@ -528,6 +546,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;
index 432da9963ebe1b0c14797e6a21e7a112ada13b28..78c6b1c3ee1493049c7806dbca873e3cc9c12d79 100644 (file)
@@ -1276,7 +1276,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR pc)
           && 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
index 74e49414cbec7b5f144c2ce938fe709e272ab8de..66c2f05adb806008e49c4c1426e1e6764f136eeb 100644 (file)
@@ -265,6 +265,9 @@ dump_msymbols (struct objfile *objfile, struct ui_file *outfile)
        case mst_text:
          ms_type = 'T';
          break;
+       case mst_text_gnu_ifunc:
+         ms_type = 'i';
+         break;
        case mst_solib_trampoline:
          ms_type = 'S';
          break;
index 3061f3cb4270e4108a69ce8ac14e173d098aeba1..8aa692d6c3bd7fca73ba6c50c6b4900cbe0c2942 100644 (file)
@@ -3006,7 +3006,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
   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;
index e946c65fea3ecd147c87105cf864eda74c2295bc..9e248280948b9fb820afe5efba4472e4bc0bfb20 100644 (file)
@@ -290,6 +290,9 @@ enum minimal_symbol_type
 {
   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) */
@@ -1034,6 +1037,8 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name
 
 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 **);