Adding static-PIE support to binutils

Rich Felker dalias@libc.org
Tue Aug 18 03:44:00 GMT 2015


On Mon, Aug 17, 2015 at 10:42:56PM -0400, Rich Felker wrote:
> On Mon, Aug 17, 2015 at 02:19:34PM -0700, H.J. Lu wrote:
> > On Tue, Jun 23, 2015 at 9:18 PM, Rich Felker <dalias@libc.org> wrote:
> > > For background on the static PIE model I'm working with, see the
> > > following post to the GCC list:
> > >
> > > https://gcc.gnu.org/ml/gcc/2015-06/msg00008.html
> > >
> > > So far, I've been prototyping static PIE support by having GCC pass
> > > the following options to ld instead of -static -pie:
> > >
> > >         -static -shared -Bsymbolic
> > >
> > > This partly works, but since ld does not know it's producing a main
> > > executable, it misses important details, including the ability to link
> > > initial-exec and local-exec model TLS code correctly, as well as
> > > various linking optimizations. So I think the right way forward is
> > > making ld accept -static and -pie together to do the right thing.
> > >
> > > In elflink.c, _bfd_elf_link_create_dynamic_sections assumes that
> > > executables should always have a .interp section.
> > > bfd_elf_size_dynamic_sections asserts this assumption again, and the
> > > individual elf??-*.c files also do so in *_elf_size_dynamic_sections
> > > where they set a default interpreter. (Is this even useful? Most of
> > > the names are out of touch with reality, and GCC always passes an
> > > explicit -dynamic-linker anyway, so I think this code should just be
> > > removed.)
> > >
> > > Now I have a working prototype by changing the info->executable
> > > condition to info->executable && info->dynamic, and having lexsup.c
> > > store the value of input_flags.dynamic in link_info.dynamic after
> > > processing the command line, but I'm not sure if this is the right
> > > approach.
> > 
> > It is OK to use -static/-Bstatic/-non_shared with -shared and -pie.
> > I think you want --no-dynamic-linker.
> 
> I see two overall approaches to making the option to omit .interp:
> 
> 1. In elflink.c, make the creation of the .interp section conditional
>    on a new field in link_info.
> 
> 2. In ld code (ldlang.c? elf32.em?), check the command line option and
>    remove the .interp section before it can be processed.
> 
> I think option 1 is a lot cleaner, but it's also going to be a lot
> more invasive, because every single target arch (elf32-*.c and
> elf64-*.c) has its own ASSERT that the .interp section exists. These
> would also need to be updated to either check the new field in
> link_info, or to replace the ASSERT with a conditional.
> 
> Before I spend a lot of time implementing one or the other, do you
> have any feelings on which way would be appropriate?

I went ahead and did option 1 modulo all the target code except sh
which is where I'm testing it. My work-in-progress patch is attached.
This is obviously not ready to submit but I would appreciate any
feedback that's possible at this stage.

Rich
-------------- next part --------------
--- binutils-2.25.1.orig/bfd/elf32-sh.c
+++ binutils-2.25.1/bfd/elf32-sh.c
@@ -3344,7 +3344,7 @@
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (info->executable && !info->nointerp)
 	{
 	  s = bfd_get_linker_section (dynobj, ".interp");
 	  BFD_ASSERT (s != NULL);
--- binutils-2.25.1.orig/bfd/elflink.c
+++ binutils-2.25.1/bfd/elflink.c
@@ -206,7 +206,7 @@
 
   /* A dynamically linked executable has a .interp section, but a
      shared library does not.  */
-  if (info->executable)
+  if (info->executable && !info->nointerp)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".interp",
 					      flags | SEC_READONLY);
@@ -5620,7 +5620,7 @@
       bfd_boolean all_defined;
 
       *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || !info->executable);
+      BFD_ASSERT (*sinterpptr != NULL || !info->executable || info->nointerp);
 
       if (soname != NULL)
 	{
--- binutils-2.25.1.orig/include/bfdlink.h
+++ binutils-2.25.1/include/bfdlink.h
@@ -426,6 +426,9 @@
   /* TRUE if BND prefix in PLT entries is always generated.  */
   unsigned int bndplt: 1;
 
+  /* TRUE if generation of .interp/PT_INTERP should be suppressed.  */
+  unsigned int nointerp: 1;
+
   /* Char that may appear as the first char of a symbol, but should be
      skipped (like symbol_leading_char) when looking up symbols in
      wrap_hash.  Used by PowerPC Linux for 'dot' symbols.  */
--- binutils-2.25.1.orig/ld/ldlex.h
+++ binutils-2.25.1/ld/ldlex.h
@@ -33,6 +33,7 @@
   OPTION_DEFSYM,
   OPTION_DEMANGLE,
   OPTION_DYNAMIC_LINKER,
+  OPTION_NO_DYNAMIC_LINKER,
   OPTION_SYSROOT,
   OPTION_EB,
   OPTION_EL,
--- binutils-2.25.1.orig/ld/lexsup.c
+++ binutils-2.25.1/ld/lexsup.c
@@ -138,6 +138,9 @@
   { {"dynamic-linker", required_argument, NULL, OPTION_DYNAMIC_LINKER},
     'I', N_("PROGRAM"), N_("Set PROGRAM as the dynamic linker to use"),
     TWO_DASHES },
+  { {"no-dynamic-linker", no_argument, NULL, OPTION_NO_DYNAMIC_LINKER},
+    '\0', NULL, N_("Produce an executable with no program interpreter header"),
+    TWO_DASHES },
   { {"library", required_argument, NULL, 'l'},
     'l', N_("LIBNAME"), N_("Search for library LIBNAME"), TWO_DASHES },
   { {"library-path", required_argument, NULL, 'L'},
@@ -747,6 +750,11 @@
 	case 'I':		/* Used on Solaris.  */
 	case OPTION_DYNAMIC_LINKER:
 	  command_line.interpreter = optarg;
+	  link_info.nointerp = 0;
+	  break;
+	case OPTION_NO_DYNAMIC_LINKER:
+	  command_line.interpreter = NULL;
+	  link_info.nointerp = 1;
 	  break;
 	case OPTION_SYSROOT:
 	  /* Already handled in ldmain.c.  */


More information about the Binutils mailing list