Re: linker stub symbols for ELF32 secured ABI

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: linker stub symbols for ELF32 secured ABI

Alan Modra
On Sun, Dec 04, 2005 at 03:31:25PM +0200, Yaakov Yaari wrote:
> Hi Alan,
> A while ago I asked you to add linker stub symbols for ELF64.  The form of
> such symbols is <address>.<linker stub type>.<target func name>
> This was implemented in the linker that came with RHEL4.
> >From looking at the code generated by the 20050923 tool chain it seems this
> is not implemented for ELF32 secured ABI.
> Can you fix that?

Sure.  Let me know if the names I chose here are bad for some reason.
If OK, I'll commit this patch.

bfd/
        * elf32-ppc.c (struct ppc_elf_link_hash_table): Add emit_stub_syms.
        (ppc_elf_select_plt_layout): Add emit_stub_syms param, save to htab.
        (add_stub_sym): New function.
        (allocate_dynrelocs): Call add_stub_sym.
        (ppc_elf_size_dynamic_sections): Emit __glink and __glink_PLTresolve
        when emit_stub_syms.
        * elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype.
ld/
        * emultempl/ppc32elf.em (emit_stub_syms): New var.
        (ppc_after_open): Pass it to ppc_elf_select_plt_layout.
        (PARSE_AND_LIST_PROLOGUE <OPTION_STUBSYMS>): Define.
        (PARSE_AND_LIST_LONGOPTS): Add emit-stub-syms.
        (PARSE_AND_LIST_OPTIONS): Describe emit-stub-syms.
        (PARSE_AND_LIST_OPTIONS): Handle it.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.183
diff -u -p -r1.183 elf32-ppc.c
--- bfd/elf32-ppc.c 25 Oct 2005 16:19:06 -0000 1.183
+++ bfd/elf32-ppc.c 5 Dec 2005 13:17:49 -0000
@@ -2353,6 +2353,9 @@ struct ppc_elf_link_hash_table
   unsigned int new_plt:1;
   unsigned int old_plt:1;
 
+  /* Set if we should emit symbols for stubs.  */
+  unsigned int emit_stub_syms:1;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 
@@ -3593,7 +3596,8 @@ ppc_elf_merge_private_bfd_data (bfd *ibf
 int
 ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
    struct bfd_link_info *info,
-   int force_old_plt)
+   int force_old_plt,
+   int emit_stub_syms)
 {
   struct ppc_elf_link_hash_table *htab;
   flagword flags;
@@ -3602,6 +3606,8 @@ ppc_elf_select_plt_layout (bfd *output_b
   if (force_old_plt || !htab->new_plt)
     htab->old_plt = 1;
 
+  htab->emit_stub_syms = emit_stub_syms;
+
   if (htab->is_vxworks)
     {
       /* The VxWorks PLT is a loaded section with contents.  */
@@ -4207,6 +4213,51 @@ ppc_elf_adjust_dynamic_symbol (struct bf
   return TRUE;
 }
 
+/* Generate a symbol to mark plt call stubs, of the form
+   xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0,
+   specifying the addend on the plt relocation, or for -fPIC,
+   xxxxxxxx.got2_plt_call_<callee>.  */
+
+static bfd_boolean
+add_stub_sym (struct plt_entry *ent,
+      struct elf_link_hash_entry *h,
+      struct ppc_elf_link_hash_table *htab)
+{
+  struct elf_link_hash_entry *sh;
+  size_t len1, len2, len3;
+  char *name;
+
+  len1 = strlen (h->root.root.string);
+  len2 = sizeof ("plt_call_") - 1;
+  len3 = 0;
+  if (ent->sec)
+    len3 = strlen (ent->sec->name);
+  name = bfd_malloc (len1 + len2 + len3 + 10);
+  if (name == NULL)
+    return FALSE;
+  sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff);
+  if (ent->sec)
+    memcpy (name + 8, ent->sec->name, len3);
+  name[len3 + 8] = '_';
+  memcpy (name + len3 + 9, "plt_call_", len2);
+  memcpy (name + len3 + 9 + len2, h->root.root.string, len1 + 1);
+  sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+  if (sh == NULL)
+    return FALSE;
+  if (sh->root.type == bfd_link_hash_new)
+    {
+      sh->root.type = bfd_link_hash_defined;
+      sh->root.u.def.section = htab->glink;
+      sh->root.u.def.value = ent->glink_offset;
+      sh->ref_regular = 1;
+      sh->def_regular = 1;
+      sh->ref_regular_nonweak = 1;
+      sh->forced_local = 1;
+      sh->non_elf = 0;
+    }
+  return TRUE;
+}
+
 /* Allocate NEED contiguous space in .got, and return the offset.
    Handles allocation of the got header when crossing 32k.  */
 
@@ -4308,6 +4359,10 @@ allocate_dynrelocs (struct elf_link_hash
  h->root.u.def.value = glink_offset;
       }
     ent->glink_offset = glink_offset;
+
+    if (htab->emit_stub_syms
+ && !add_stub_sym (ent, h, htab))
+      return FALSE;
   }
  else
   {
@@ -4747,6 +4802,41 @@ ppc_elf_size_dynamic_sections (bfd *outp
       /* Pad out to align the start of PLTresolve.  */
       htab->glink->size += -htab->glink->size & 15;
       htab->glink->size += GLINK_PLTRESOLVE;
+
+      if (htab->emit_stub_syms)
+ {
+  struct elf_link_hash_entry *sh;
+  sh = elf_link_hash_lookup (&htab->elf, "__glink",
+     TRUE, FALSE, FALSE);
+  if (sh == NULL)
+    return FALSE;
+  if (sh->root.type == bfd_link_hash_new)
+    {
+      sh->root.type = bfd_link_hash_defined;
+      sh->root.u.def.section = htab->glink;
+      sh->root.u.def.value = htab->glink_pltresolve;
+      sh->ref_regular = 1;
+      sh->def_regular = 1;
+      sh->ref_regular_nonweak = 1;
+      sh->forced_local = 1;
+      sh->non_elf = 0;
+    }
+  sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve",
+     TRUE, FALSE, FALSE);
+  if (sh == NULL)
+    return FALSE;
+  if (sh->root.type == bfd_link_hash_new)
+    {
+      sh->root.type = bfd_link_hash_defined;
+      sh->root.u.def.section = htab->glink;
+      sh->root.u.def.value = htab->glink->size - GLINK_PLTRESOLVE;
+      sh->ref_regular = 1;
+      sh->def_regular = 1;
+      sh->ref_regular_nonweak = 1;
+      sh->forced_local = 1;
+      sh->non_elf = 0;
+    }
+ }
     }
 
   /* We've now determined the sizes of the various dynamic sections.
Index: bfd/elf32-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.h,v
retrieving revision 1.8
diff -u -p -r1.8 elf32-ppc.h
--- bfd/elf32-ppc.h 16 Jul 2005 03:30:23 -0000 1.8
+++ bfd/elf32-ppc.h 5 Dec 2005 13:17:49 -0000
@@ -17,7 +17,7 @@ You should have received a copy of the G
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int);
+int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int, int);
 asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
 bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
 void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
Index: ld/emultempl/ppc32elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc32elf.em,v
retrieving revision 1.10
diff -u -p -r1.10 ppc32elf.em
--- ld/emultempl/ppc32elf.em 4 Aug 2005 06:22:13 -0000 1.10
+++ ld/emultempl/ppc32elf.em 5 Dec 2005 13:17:49 -0000
@@ -41,6 +41,9 @@ is_ppc_elf32_vec(const bfd_target * vec)
 /* Whether to run tls optimization.  */
 static int notlsopt = 0;
 
+/* Whether to emit symbols for stubs.  */
+static int emit_stub_syms = 0;
+
 /* Chooses the correct place for .plt and .got.  */
 static int old_plt = 0;
 static int old_got = 0;
@@ -58,7 +61,9 @@ ppc_after_open (void)
       lang_output_section_statement_type *plt_os[2];
       lang_output_section_statement_type *got_os[2];
 
-      new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt);
+      emit_stub_syms |= link_info.emitrelocations;
+      new_plt = ppc_elf_select_plt_layout (output_bfd, &link_info, old_plt,
+   emit_stub_syms);
       if (new_plt < 0)
  einfo ("%X%P: select_plt_layout problem %E\n");
 
@@ -126,9 +131,11 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_TLS_OPT 301
 #define OPTION_OLD_PLT 302
 #define OPTION_OLD_GOT 303
+#define OPTION_STUBSYMS 304
 '
 
 PARSE_AND_LIST_LONGOPTS='
+  { "emit-stub-syms", no_argument, NULL, OPTION_STUBSYMS },
   { "no-tls-optimize", no_argument, NULL, OPTION_NO_TLS_OPT },
   { "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
   { "sdata-got", no_argument, NULL, OPTION_OLD_GOT },
@@ -136,6 +143,7 @@ PARSE_AND_LIST_LONGOPTS='
 
 PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("\
+  --emit-stub-syms      Label linker stubs with a symbol.\n\
   --no-tls-optimize     Don'\''t try to optimize TLS accesses.\n\
   --bss-plt             Force old-style BSS PLT.\n\
   --sdata-got           Force GOT location just before .sdata.\n"
@@ -143,6 +151,10 @@ PARSE_AND_LIST_OPTIONS='
 '
 
 PARSE_AND_LIST_ARGS_CASES='
+    case OPTION_STUBSYMS:
+      emit_stub_syms = 1;
+      break;
+
     case OPTION_NO_TLS_OPT:
       notlsopt = 1;
       break;

--
Alan Modra
IBM OzLabs - Linux Technology Centre
Reply | Threaded
Open this post in threaded view
|

Re: linker stub symbols for ELF32 secured ABI

Alan Modra
On Sat, Dec 10, 2005 at 11:34:24PM +0200, Yaakov Yaari wrote:
> The standard we have with ELF64 is <hexstubaddr>.<stubtype>.<callee>
> So in the following...
>   xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0,
> ..., one problem is that the stub type is not delimited in dots,

OK, fixed.

> and the
> second is that the type used, 'plt_call', is already used by ELF64 plt call

Why does this matter?  The linker won't ever generate a mixed 32/64-bit
PLT!  I'm just curious, there isn't any difficulty in using a different
string.

> stub. Using 'xxxxxxxx' invariably as 00000000 (or any other 8-chars hex
> sequence) is OK though.
> I can see three ELF32 plt call stub types:
> 1. 'plt_call32', for non-PIC form ('lis r11,off, lwz r11,off(r11), mtctr,
> bctr" sequence),
> 2. 'plt_call32PS', for short PIC sequence ('lwz r11,off(r30), mtctr,
> bctr'), and
> 3. 'plt_call32PL', for long PIC sequence, ('lis r11,r30,off, lwz
> r11,off(r30), mtctr, bctr').

I can't reliably differentiate the short PIC sequence from the long
one without changing the ppc32 linker quite significantly.  The problem
is that the decision about short/long sequence depends on final PLT and
GOT location, which we don't have at the time the symbols are created.
It wouldn't be impossible to do, but I'd rather not do this unless it is
vital for FDPR.  I imagine you can quite easily differentiate the two
sequences yourself by code reading.

--
Alan Modra
IBM OzLabs - Linux Technology Centre
Reply | Threaded
Open this post in threaded view
|

Re: linker stub symbols for ELF32 secured ABI

Alan Modra
On Mon, Dec 12, 2005 at 11:18:50AM +1030, Alan Modra wrote:
> On Sat, Dec 10, 2005 at 11:34:24PM +0200, Yaakov Yaari wrote:
> > The standard we have with ELF64 is <hexstubaddr>.<stubtype>.<callee>
> > So in the following...
> >   xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0,
> > ..., one problem is that the stub type is not delimited in dots,
>
> OK, fixed.

And now applied, so not just fixed in my local tree..

> > and the
> > second is that the type used, 'plt_call', is already used by ELF64 plt call

        * elf32-ppc.c (add_stub_sym): Pass info rather than htab.
        Use different names for pic vs non-pic, '.' instead of '_'.
        (allocate_dynrelocs): Adjust add_stub_sym call.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.184
diff -u -p -r1.184 elf32-ppc.c
--- bfd/elf32-ppc.c 8 Dec 2005 11:41:11 -0000 1.184
+++ bfd/elf32-ppc.c 24 Dec 2005 12:28:04 -0000
@@ -4213,34 +4213,41 @@ ppc_elf_adjust_dynamic_symbol (struct bf
   return TRUE;
 }
 
-/* Generate a symbol to mark plt call stubs, of the form
-   xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0,
-   specifying the addend on the plt relocation, or for -fPIC,
-   xxxxxxxx.got2_plt_call_<callee>.  */
+/* Generate a symbol to mark plt call stubs.  For non-PIC code the sym is
+   xxxxxxxx.plt_call32.<callee> where xxxxxxxx is a hex number, usually 0,
+   specifying the addend on the plt relocation.  For -fpic code, the sym
+   is xxxxxxxx.plt_pic32.<callee>, and for -fPIC
+   xxxxxxxx.got2.plt_pic32.<callee>.  */
 
 static bfd_boolean
 add_stub_sym (struct plt_entry *ent,
       struct elf_link_hash_entry *h,
-      struct ppc_elf_link_hash_table *htab)
+      struct bfd_link_info *info)
 {
   struct elf_link_hash_entry *sh;
   size_t len1, len2, len3;
   char *name;
+  const char *stub;
+  struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+
+  if (info->shared || info->pie)
+    stub = ".plt_pic32.";
+  else
+    stub = ".plt_call32.";
 
   len1 = strlen (h->root.root.string);
-  len2 = sizeof ("plt_call_") - 1;
+  len2 = strlen (stub);
   len3 = 0;
   if (ent->sec)
     len3 = strlen (ent->sec->name);
-  name = bfd_malloc (len1 + len2 + len3 + 10);
+  name = bfd_malloc (len1 + len2 + len3 + 9);
   if (name == NULL)
     return FALSE;
   sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff);
   if (ent->sec)
     memcpy (name + 8, ent->sec->name, len3);
-  name[len3 + 8] = '_';
-  memcpy (name + len3 + 9, "plt_call_", len2);
-  memcpy (name + len3 + 9 + len2, h->root.root.string, len1 + 1);
+  memcpy (name + 8 + len3, stub, len2);
+  memcpy (name + 8 + len3 + len2, h->root.root.string, len1 + 1);
   sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
   if (sh == NULL)
     return FALSE;
@@ -4361,7 +4368,7 @@ allocate_dynrelocs (struct elf_link_hash
     ent->glink_offset = glink_offset;
 
     if (htab->emit_stub_syms
- && !add_stub_sym (ent, h, htab))
+ && !add_stub_sym (ent, h, info))
       return FALSE;
   }
  else

--
Alan Modra
IBM OzLabs - Linux Technology Centre