[PATCH] ld: Properly check static link of dynamic object

Fangrui Song i@maskray.me
Thu Mar 12 04:09:20 GMT 2020


> When -static is passed to gcc, gcc passes it to linker before any input
> files to create static executable.  If -Bdynamic is also passed to linker
> from command-line, linker should issue an error if dynamic object is used.
> 
> include/
> 
> 	PR ld/24920
> 	* bfdlink.h (bfd_link_info): Add static_exec.
> 
> ld/
> 
> 	PR ld/24920
> 	* ldfile.c (ldfile_try_open_bfd): Also check link_info.static_exec
> 	for static link of dynamic object.
> 	* lexsup.c (parse_args): Set link_info.static_exec to true if we
> 	see -static before any input files.
> 	* testsuite/ld-elf/pr24920.err: New file.
> 	* testsuite/ld-elf/shared.exp: Run ld/24920 tests.
> ---
>  include/bfdlink.h               |  3 +++
>  ld/ldfile.c                     |  6 ++++--
>  ld/lexsup.c                     |  4 ++++
>  ld/testsuite/ld-elf/pr24920.err |  1 +
>  ld/testsuite/ld-elf/shared.exp  | 18 ++++++++++++++++++
>  5 files changed, 30 insertions(+), 2 deletions(-)
>  create mode 100644 ld/testsuite/ld-elf/pr24920.err
> 
> diff --git a/include/bfdlink.h b/include/bfdlink.h
> index 8d85530e39..a850c6102c 100644
> --- a/include/bfdlink.h
> +++ b/include/bfdlink.h
> @@ -322,6 +322,9 @@ struct bfd_link_info
>    /* Output type.  */
>    ENUM_BITFIELD (output_type) type : 2;
>  
> +  /* TRUE if building a static executable.  */
> +  unsigned int static_exec : 1;
> +
>    /* TRUE if BFD should pre-bind symbols in a shared object.  */
>    unsigned int symbolic: 1;
>  
> diff --git a/ld/ldfile.c b/ld/ldfile.c
> index aa84906992..7b57bd9fb7 100644
> --- a/ld/ldfile.c
> +++ b/ld/ldfile.c
> @@ -164,7 +164,8 @@ ldfile_try_open_bfd (const char *attempt,
>       checks out compatible, do not exit early returning TRUE, or
>       the plugins will not get a chance to claim the file.  */
>  
> -  if (entry->flags.search_dirs || !entry->flags.dynamic)
> +  if (entry->flags.search_dirs
> +      || (link_info.static_exec || !entry->flags.dynamic))
>      {
>        bfd *check;
>  
> @@ -274,7 +275,8 @@ ldfile_try_open_bfd (const char *attempt,
>  	      goto success;
>  	    }
>  
> -	  if (!entry->flags.dynamic && (entry->the_bfd->flags & DYNAMIC) != 0)
> +	  if ((link_info.static_exec || !entry->flags.dynamic)
> +	      && (entry->the_bfd->flags & DYNAMIC) != 0)
>  	    {
>  	      einfo (_("%F%P: attempted static link of dynamic object `%s'\n"),
>  		     attempt);
> diff --git a/ld/lexsup.c b/ld/lexsup.c
> index 3d15cc491d..aeddc52466 100644
> --- a/ld/lexsup.c
> +++ b/ld/lexsup.c
> @@ -786,6 +786,10 @@ parse_args (unsigned argc, char **argv)
>  	  break;
>  	case OPTION_NON_SHARED:
>  	  input_flags.dynamic = FALSE;
> +	  /* If we see -static before any input files, we are building
> +	     a static executable.  */
> +	  if (!lang_has_input_file)
> +	    link_info.static_exec = TRUE;
>  	  break;
>  	case OPTION_CREF:
>  	  command_line.cref = TRUE;
> diff --git a/ld/testsuite/ld-elf/pr24920.err b/ld/testsuite/ld-elf/pr24920.err
> new file mode 100644
> index 0000000000..8f5cab9167
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/pr24920.err
> @@ -0,0 +1 @@
> +.*: attempted static link of dynamic object `tmpdir/pr24920.so'
> diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
> index b1762aff9b..0b8024dd1a 100644
> --- a/ld/testsuite/ld-elf/shared.exp
> +++ b/ld/testsuite/ld-elf/shared.exp
> @@ -114,6 +114,24 @@ run_ld_link_tests [list \
>  	{} \
>  	"pr22649-1.so" \
>      ] \
> +    [list \
> +	"Build pr24920.so" \
> +	"$LFLAGS -shared" \
> +	"" \
> +	"$AFLAGS_PIC" \
> +	{dummy.s} \
> +	{} \
> +	"pr24920.so" \
> +    ] \
> +    [list \
> +	"Build pr24920" \
> +	"$LFLAGS -static " \
> +	"-Bdynamic tmpdir/pr24920.so" \
> +	"" \
> +	{start.s} \
> +	{{ld pr24920.err}} \
> +	"pr24920" \
> +    ] \
>  ]
>  
>  if { [check_gc_sections_available] } {
> -- 
> 2.24.1

Does the patch reject valid use case like:

ld -Bstatic a.o -Bdynamic b.so

If the gcc driver detects the input file type, I think such an error should be emitted on its side.?


-static = -Bstatic. There is no need to teach it to know that the first -static/-Bstatic is different.



More information about the Binutils mailing list