On Tue, Aug 18, 2015 at 09:30:56AM -0700, H.J. Lu wrote:
> On Tue, Aug 18, 2015 at 9:08 AM, Rich Felker <dal...@libc.org> wrote:
> > On Tue, Aug 18, 2015 at 08:56:00AM -0700, H.J. Lu wrote:
> >> On Mon, Aug 17, 2015 at 8:44 PM, Rich Felker <dal...@libc.org> wrote:
> >> > 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 <dal...@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.
> >>
> >> + case OPTION_NO_DYNAMIC_LINKER:
> >> +  command_line.interpreter = NULL;
> >> +  link_info.nointerp = 1;
> >>
> >> No need to clear command_line.interpreter and please add a simple
> >> testcase to verify it works correctly.
> >
> > OK. Do I also need to update it to be against the new output_type
> > stuff you just committed?
> >
> 
> That is a good idea.

I've updated the patch to cover the changes needed for all the
elf??-*.c target files (lots of code duplication already there), skip
the clearing of command_line.interpreter, and based it on current git
master with your output_type changes.

I haven't done a test case yet -- I looked briefly but couldn't find
documentation on how to add one. Is there a guide or template I should
look at? And do I need to open a BZ issue for the feature request, or
can non-bug changes like this skip BZ?

Rich
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index bd4b576..41803c2 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -13786,7 +13786,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd 
ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-bfin.c b/bfd/elf32-bfin.c
index 49ef360..8346d57 100644
--- a/bfd/elf32-bfin.c
+++ b/bfd/elf32-bfin.c
@@ -4257,7 +4257,7 @@ elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
   if (htab->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c
index 5d8ffbc..497630e 100644
--- a/bfd/elf32-cr16.c
+++ b/bfd/elf32-cr16.c
@@ -2464,7 +2464,7 @@ _bfd_cr16_elf_size_dynamic_sections (bfd * output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
         {
 #if 0
           s = bfd_get_linker_section (dynobj, ".interp");
diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c
index 3031173..5b40524 100644
--- a/bfd/elf32-cris.c
+++ b/bfd/elf32-cris.c
@@ -3764,7 +3764,7 @@ elf_cris_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c
index b55a7ab..ef72c23 100644
--- a/bfd/elf32-frv.c
+++ b/bfd/elf32-frv.c
@@ -5444,7 +5444,7 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 41bf5c5..62c7cf6 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -2215,7 +2215,7 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->etab.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          sec = bfd_get_linker_section (dynobj, ".interp");
          if (sec == NULL)
diff --git a/bfd/elf32-i370.c b/bfd/elf32-i370.c
index 7fba4d1..458f694 100644
--- a/bfd/elf32-i370.c
+++ b/bfd/elf32-i370.c
@@ -594,7 +594,7 @@ i370_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 7642d0f..b0844c8 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2834,7 +2834,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct 
bfd_link_info *info)
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf32-lm32.c b/bfd/elf32-lm32.c
index 23f6e5e..0805e3c 100644
--- a/bfd/elf32-lm32.c
+++ b/bfd/elf32-lm32.c
@@ -2141,7 +2141,7 @@ lm32_elf_size_dynamic_sections (bfd *output_bfd,
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c
index 155d079..a2e3c7c 100644
--- a/bfd/elf32-m32r.c
+++ b/bfd/elf32-m32r.c
@@ -2170,7 +2170,7 @@ m32r_elf_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c
index 10d2fcb..489f3f1 100644
--- a/bfd/elf32-m68k.c
+++ b/bfd/elf32-m68k.c
@@ -3257,7 +3257,7 @@ elf_m68k_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 9c54a71..755c431 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -2848,7 +2848,7 @@ elf_metag_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->etab.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index 5b8e9d6..6c76ff2 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -3980,7 +3980,7 @@ nds32_elf_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (!bfd_link_pic (info))
+      if (!bfd_link_pic (info) && !info->nointerp)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index fd70007..2a2b3a6 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -5849,7 +5849,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c
index d4f92b7..a1eba09 100644
--- a/bfd/elf32-or1k.c
+++ b/bfd/elf32-or1k.c
@@ -2447,7 +2447,7 @@ or1k_elf_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
         {
           s = bfd_get_section_by_name (dynobj, ".interp");
           BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 8415f1e..5597051 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -6191,7 +6191,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (htab->elf.dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index de37ca4..a1e628c 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -2039,7 +2039,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf32-score.c b/bfd/elf32-score.c
index a976a15..ce9c377 100644
--- a/bfd/elf32-score.c
+++ b/bfd/elf32-score.c
@@ -3269,7 +3269,7 @@ s3_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, 
struct bfd_link_info *i
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (!bfd_link_pic (info))
+      if (!bfd_link_pic (info) && !info->nointerp)
         {
           s = bfd_get_linker_section (dynobj, ".interp");
           BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-score7.c b/bfd/elf32-score7.c
index 1af034e..b0e75bb 100644
--- a/bfd/elf32-score7.c
+++ b/bfd/elf32-score7.c
@@ -3078,7 +3078,7 @@ s7_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, 
struct bfd_link_info *i
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (!bfd_link_pic (info))
+      if (!bfd_link_pic (info) && !info->nointerp)
         {
           s = bfd_get_linker_section (dynobj, ".interp");
           BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index 012ee4e..a51453f 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -3349,7 +3349,7 @@ sh_elf_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c
index b6640ea..380ab8d 100644
--- a/bfd/elf32-tic6x.c
+++ b/bfd/elf32-tic6x.c
@@ -3300,7 +3300,7 @@ elf32_tic6x_size_dynamic_sections (bfd *output_bfd, 
struct bfd_link_info *info)
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf32-tilepro.c b/bfd/elf32-tilepro.c
index cb3f896..d55be2d 100644
--- a/bfd/elf32-tilepro.c
+++ b/bfd/elf32-tilepro.c
@@ -2463,7 +2463,7 @@ tilepro_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c
index 6089e8c..893ea8d 100644
--- a/bfd/elf32-vax.c
+++ b/bfd/elf32-vax.c
@@ -1124,7 +1124,7 @@ elf_vax_size_dynamic_sections (bfd *output_bfd, struct 
bfd_link_info *info)
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 73538cd..37ea5da 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -1637,7 +1637,7 @@ elf_xtensa_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
                  && htab->sgotloc != NULL);
 
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index f67b0af..1973cd0 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -2877,7 +2877,7 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index 6f40b88..3b628b4 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -1558,7 +1558,7 @@ elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct 
bfd_link_info *info)
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          sec = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (sec != NULL);
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 8cff990..851845f 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -9748,7 +9748,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 2e505f3..406bb66 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -1989,7 +1989,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elf64-sh64.c b/bfd/elf64-sh64.c
index e460895..d920598 100644
--- a/bfd/elf64-sh64.c
+++ b/bfd/elf64-sh64.c
@@ -3404,7 +3404,7 @@ sh64_elf64_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index f15d33e..870aadf 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -3181,7 +3181,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
   if (htab->elf.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 7f04271..5b3438d 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -246,7 +246,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct 
bfd_link_info *info)
 
   /* A dynamically linked executable has a .interp section, but a
      shared library does not.  */
-  if (bfd_link_executable (info))
+  if (bfd_link_executable (info) && !info->nointerp)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".interp",
                                              flags | SEC_READONLY);
@@ -5763,7 +5763,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       bfd_boolean all_defined;
 
       *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info));
+      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || 
info->nointerp);
 
       if (soname != NULL)
        {
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index beedb70..599f9cf 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -7674,7 +7674,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
 
   if (htab->root.dynamic_sections_created)
     {
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          if (s == NULL)
diff --git a/bfd/elfnn-ia64.c b/bfd/elfnn-ia64.c
index c45fa28..3b304d5 100644
--- a/bfd/elfnn-ia64.c
+++ b/bfd/elfnn-ia64.c
@@ -2992,7 +2992,7 @@ elfNN_ia64_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
 
   /* Set the contents of the .interp section to the interpreter.  */
   if (ia64_info->root.dynamic_sections_created
-      && bfd_link_executable (info))
+      && bfd_link_executable (info) && !info->nointerp)
     {
       sec = bfd_get_linker_section (dynobj, ".interp");
       BFD_ASSERT (sec != NULL);
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index be1e59a..329dec3 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -9579,7 +9579,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 9bb71a9..db0d4f1 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2559,7 +2559,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c
index 59a2f7e..6f7485a 100644
--- a/bfd/elfxx-tilegx.c
+++ b/bfd/elfxx-tilegx.c
@@ -2724,7 +2724,7 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd 
ATTRIBUTE_UNUSED,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (bfd_link_executable (info))
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 797a465..cf533dd 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -433,6 +433,9 @@ struct bfd_link_info
   /* 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.  */
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 59bd14f..8b57f84 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -33,6 +33,7 @@ enum option_values
   OPTION_DEFSYM,
   OPTION_DEMANGLE,
   OPTION_DYNAMIC_LINKER,
+  OPTION_NO_DYNAMIC_LINKER,
   OPTION_SYSROOT,
   OPTION_EB,
   OPTION_EL,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 777d6e2..1b992f7 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -138,6 +138,9 @@ static const struct ld_option ld_options[] =
   { {"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'},
@@ -762,6 +765,10 @@ parse_args (unsigned argc, char **argv)
        case 'I':               /* Used on Solaris.  */
        case OPTION_DYNAMIC_LINKER:
          command_line.interpreter = optarg;
+         link_info.nointerp = 0;
+         break;
+       case OPTION_NO_DYNAMIC_LINKER:
+         link_info.nointerp = 1;
          break;
        case OPTION_SYSROOT:
          /* Already handled in ldmain.c.  */

Reply via email to