public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Xi Ruoyao <xry111@xry111.site>
To: WANG Xuerui <i.swmail@xen0n.name>, binutils@sourceware.org
Cc: Chenghua Xu <xuchenghua@loongson.cn>,
	Zhensong Liu <liuzhensong@loongson.cn>,
	 Qinggang Meng <mengqinggang@loongson.cn>,
	WANG Xuerui <git@xen0n.name>
Subject: Re: [PATCH] elfedit: add support for editing e_flags
Date: Thu, 02 Mar 2023 16:20:20 +0800	[thread overview]
Message-ID: <502da978c3a38a5216a0d9abbbe3ebf22f8688e5.camel@xry111.site> (raw)
In-Reply-To: <20230302080137.3346439-1-i.swmail@xen0n.name>

On Thu, 2023-03-02 at 16:01 +0800, WANG Xuerui wrote:

> I have to pick up the work because I was trying to make AMDGPU DCN work
> on LoongArch, but that piece of code requires hard-float support while
> the LoongArch Linux kernel is compiled in the soft-float ABI, leading to
> link-time failures intermixing the two.

IMO we should keep soft-float ABI while enabling the FPU (i. e.
-mabi=lp64s -mfpu=64).  But ouch, this does not work properly with
current GCC...  -mfpu=64 silently enables using FPR to pass arg and
return value, w/o even a warning.  Not sure about Clang.

<rant>I remember I've been saying "floating ABI and floating instruction
set should be de-coupled" multiple times: "I" in "ABI" stands for
"interface" anyway and all the interfaces are just designed for hiding
implementation details.  But it seems nobody took it seriously.</rant>

> Since the hard-float code in
> question doesn't pass around FP arguments across the boundary between
> object files, but rather only internally, it is safe to just edit the
> e_flags of the hard-float objects to make their ABI look like LP64S.
> Which led to me discovering the previous similar work [1] has stalled...
> And that's why a bunch of LoongArch-related folks are on the CC list.
> 
> [1]: https://sourceware.org/pipermail/binutils/2022-April/120413.html
> 
>  binutils/doc/binutils.texi                  | 13 +++++-
>  binutils/elfedit.c                          | 52 +++++++++++++++++++-
> -
>  binutils/testsuite/binutils-all/elfedit-7.d | 10 ++++
>  binutils/testsuite/binutils-all/elfedit-8.d | 10 ++++
>  binutils/testsuite/binutils-all/elfedit.exp |  2 +
>  5 files changed, 83 insertions(+), 4 deletions(-)
>  create mode 100644 binutils/testsuite/binutils-all/elfedit-7.d
>  create mode 100644 binutils/testsuite/binutils-all/elfedit-8.d
> 
> diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
> index b1982a95704..a261af48254 100644
> --- a/binutils/doc/binutils.texi
> +++ b/binutils/doc/binutils.texi
> @@ -5297,10 +5297,12 @@ elfedit [@option{--input-mach=}@var{machine}]
>          [@option{--input-type=}@var{type}]
>          [@option{--input-osabi=}@var{osabi}]
>          [@option{--input-abiversion=}@var{version}]
> +        [@option{--input-flags=}@var{flags}]
>          @option{--output-mach=}@var{machine}
>          @option{--output-type=}@var{type}
>          @option{--output-osabi=}@var{osabi}
>          @option{--output-abiversion=}@var{version}
> +        @option{--output-flags=}@var{flags}
>          @option{--enable-x86-feature=}@var{feature}
>          @option{--disable-x86-feature=}@var{feature}
>          [@option{-v}|@option{--version}]
> @@ -5325,7 +5327,7 @@ should be updated.
>  The long and short forms of options, shown here as alternatives, are
>  equivalent. At least one of the @option{--output-mach},
>  @option{--output-type}, @option{--output-osabi},
> -@option{--output-abiversion},
> +@option{--output-abiversion}, @option{--output-flags},
>  @option{--enable-x86-feature} and @option{--disable-x86-feature}
>  options must be given.
>  
> @@ -5376,6 +5378,15 @@ isn't specified, it will match any ELF
> ABIVERSIONs.
>  Change the ELF ABIVERSION in the ELF header to @var{version}.
>  @var{version} must be between 0 and 255.
>  
> +@item --input-flags=@var{flags}
> +Set the matching input ELF file @var{e_flags} value to @var{flags}.
> +@var{flags} must be an unsigned 32-bit integer.  If @option{--input-
> flags}
> +isn't specified, it will match any e_flags value.
> +
> +@item --output-flags=@var{flags}
> +Change the @var{e_flags} field in the ELF header to @var{flags}.
> +@var{version} must be an unsigned 32-bit integer.
> +
>  @item --enable-x86-feature=@var{feature}
>  Set the @var{feature} bit in program property in @var{exec} or
> @var{dyn}
>  ELF files with machine types of @var{i386} or @var{x86-64}.  The
> diff --git a/binutils/elfedit.c b/binutils/elfedit.c
> index 117e67639a0..512e075f16a 100644
> --- a/binutils/elfedit.c
> +++ b/binutils/elfedit.c
> @@ -68,6 +68,10 @@ enum elfclass
>    };
>  static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
>  static enum elfclass output_elf_class = ELF_CLASS_BOTH;
> +static int check_elf_flags = 0;
> +static unsigned long input_elf_flags = 0;
> +static int write_elf_flags = 0;
> +static unsigned long output_elf_flags = 0;
>  
>  #ifdef HAVE_MMAP
>  #include <sys/mman.h>
> @@ -394,7 +398,16 @@ update_elf_header (const char *file_name, FILE
> *file)
>        return 0;
>      }
>  
> -  /* Update e_machine, e_type and EI_OSABI.  */
> +  /* Skip if e_flags doesn't match. */
> +  if (check_elf_flags && elf_header.e_flags != input_elf_flags)
> +    {
> +      error
> +       (_("%s: Unmatched e_flags: 0x%lx is not 0x%lx\n"),
> +        file_name, elf_header.e_flags, input_elf_flags);
> +      return 0;
> +    }
> +
> +  /* Update e_machine, e_type, OSABI, ABIVERSION and e_flags.  */
>    switch (class)
>      {
>      default:
> @@ -410,6 +423,8 @@ update_elf_header (const char *file_name, FILE
> *file)
>         ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
>        if (output_elf_abiversion != -1)
>         ehdr32.e_ident[EI_ABIVERSION] = output_elf_abiversion;
> +      if (write_elf_flags)
> +       BYTE_PUT (ehdr32.e_flags, output_elf_flags);
>        status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
>        break;
>      case ELFCLASS64:
> @@ -421,6 +436,8 @@ update_elf_header (const char *file_name, FILE
> *file)
>         ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
>        if (output_elf_abiversion != -1)
>         ehdr64.e_ident[EI_ABIVERSION] = output_elf_abiversion;
> +      if (write_elf_flags)
> +       BYTE_PUT (ehdr64.e_flags, output_elf_flags);
>        status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
>        break;
>      }
> @@ -904,6 +921,8 @@ enum command_line_switch
>      OPTION_OUTPUT_OSABI,
>      OPTION_INPUT_ABIVERSION,
>      OPTION_OUTPUT_ABIVERSION,
> +    OPTION_INPUT_FLAGS,
> +    OPTION_OUTPUT_FLAGS,
>  #ifdef HAVE_MMAP
>      OPTION_ENABLE_X86_FEATURE,
>      OPTION_DISABLE_X86_FEATURE,
> @@ -920,6 +939,8 @@ static struct option options[] =
>    {"output-osabi",     required_argument, 0, OPTION_OUTPUT_OSABI},
>    {"input-abiversion", required_argument, 0,
> OPTION_INPUT_ABIVERSION},
>    {"output-abiversion",        required_argument, 0,
> OPTION_OUTPUT_ABIVERSION},
> +  {"input-flags",      required_argument, 0, OPTION_INPUT_FLAGS},
> +  {"output-flags",     required_argument, 0, OPTION_OUTPUT_FLAGS},
>  #ifdef HAVE_MMAP
>    {"enable-x86-feature",
>                         required_argument, 0,
> OPTION_ENABLE_X86_FEATURE},
> @@ -958,7 +979,11 @@ usage (FILE *stream, int exit_status)
>    --output-osabi [%s]\n\
>                                Set output OSABI\n\
>    --input-abiversion [0-255]  Set input ABIVERSION\n\
> -  --output-abiversion [0-255] Set output ABIVERSION\n"),
> +  --output-abiversion [0-255] Set output ABIVERSION\n\
> +  --input-flags [32-bit unsigned integer]\n\
> +                              Set input e_flags\n\
> +  --output-flags [32-bit unsigned integer]\n\
> +                              Set output e_flags\n"),
>            osabi, osabi);
>  #ifdef HAVE_MMAP
>    fprintf (stream, _("\
> @@ -1062,6 +1087,26 @@ main (int argc, char ** argv)
>             }
>           break;
>  
> +       case OPTION_INPUT_FLAGS:
> +         check_elf_flags = 1;
> +         input_elf_flags = strtoul (optarg, &end, 0);
> +         if (*end != '\0' || input_elf_flags > 0xffffffff)
> +           {
> +             error (_("Invalid e_flags: %s\n"), optarg);
> +             return 1;
> +           }
> +         break;
> +
> +       case OPTION_OUTPUT_FLAGS:
> +         write_elf_flags = 1;
> +         output_elf_flags = strtoul (optarg, &end, 0);
> +         if (*end != '\0' || output_elf_flags > 0xffffffff)
> +           {
> +             error (_("Invalid e_flags: %s\n"), optarg);
> +             return 1;
> +           }
> +         break;
> +
>  #ifdef HAVE_MMAP
>         case OPTION_ENABLE_X86_FEATURE:
>           if (elf_x86_feature (optarg, 1) < 0)
> @@ -1094,7 +1139,8 @@ main (int argc, char ** argv)
>  #endif
>           && output_elf_type == -1
>           && output_elf_osabi == -1
> -         && output_elf_abiversion == -1))
> +         && output_elf_abiversion == -1
> +         && ! write_elf_flags))
>      usage (stderr, 1);
>  
>    status = 0;
> diff --git a/binutils/testsuite/binutils-all/elfedit-7.d
> b/binutils/testsuite/binutils-all/elfedit-7.d
> new file mode 100644
> index 00000000000..8e5a8b7d019
> --- /dev/null
> +++ b/binutils/testsuite/binutils-all/elfedit-7.d
> @@ -0,0 +1,10 @@
> +#PROG: elfedit
> +#elfedit: --output-flags 0xfedcba98
> +#source: empty.s
> +#readelf: -h
> +#name: Update ELF header 7 (hexadecimal e_flags value)
> +#target: *-*-linux* *-*-gnu*
> +
> +#...
> +  Flags:[ \t]+0xfedcba98.*
> +#...
> diff --git a/binutils/testsuite/binutils-all/elfedit-8.d
> b/binutils/testsuite/binutils-all/elfedit-8.d
> new file mode 100644
> index 00000000000..9538f4486b8
> --- /dev/null
> +++ b/binutils/testsuite/binutils-all/elfedit-8.d
> @@ -0,0 +1,10 @@
> +#PROG: elfedit
> +#elfedit: --output-flags 12345678
> +#source: empty.s
> +#readelf: -h
> +#name: Update ELF header 8 (decimal e_flags value)
> +#target: *-*-linux* *-*-gnu*
> +
> +#...
> +  Flags:[ \t]+0xbc614e.*
> +#...
> diff --git a/binutils/testsuite/binutils-all/elfedit.exp
> b/binutils/testsuite/binutils-all/elfedit.exp
> index 33f4bb05529..47e94e5a775 100644
> --- a/binutils/testsuite/binutils-all/elfedit.exp
> +++ b/binutils/testsuite/binutils-all/elfedit.exp
> @@ -26,3 +26,5 @@ run_dump_test "elfedit-3"
>  run_dump_test "elfedit-4"
>  run_dump_test "elfedit-5"
>  run_dump_test "elfedit-6"
> +run_dump_test "elfedit-7"
> +run_dump_test "elfedit-8"

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

  reply	other threads:[~2023-03-02  8:20 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-02  8:01 WANG Xuerui
2023-03-02  8:20 ` Xi Ruoyao [this message]
2023-03-02  8:53   ` WANG Xuerui
2023-03-02  9:04     ` Xi Ruoyao
2023-03-02 10:42       ` Xi Ruoyao
2023-03-02 11:02         ` WANG Xuerui
2023-03-02 11:21           ` Xi Ruoyao
2023-03-03  1:28             ` Weining Lu
2023-03-02 16:11           ` Xi Ruoyao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=502da978c3a38a5216a0d9abbbe3ebf22f8688e5.camel@xry111.site \
    --to=xry111@xry111.site \
    --cc=binutils@sourceware.org \
    --cc=git@xen0n.name \
    --cc=i.swmail@xen0n.name \
    --cc=liuzhensong@loongson.cn \
    --cc=mengqinggang@loongson.cn \
    --cc=xuchenghua@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).