From c9dcc18f8ded97ed7cd1dd64da8c7b37b86f61bb Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 16 Nov 2021 14:14:56 -0800 Subject: [PATCH] elfedit: Add --output-abiversion option to update ABIVERSION * NEWS: Mention --output-abiversion. * elfedit.c (input_elf_abiversion): New. (output_elf_abiversion): Likewise. (update_elf_header): Update EI_ABIVERSION. (command_line_switch): Add OPTION_INPUT_ABIVERSION and OPTION_OUTPUT_ABIVERSION. (options): Add --input-abiversion and --output-abiversion. (usage): Likewise. (main): Handle --input-abiversion and --output-abiversion. * doc/binutils.texi: Document --input-abiversion and --output-abiversion. * testsuite/binutils-all/elfedit.exp: Run elfedit-6. * testsuite/binutils-all/elfedit-6.d: New file. --- binutils/NEWS | 2 + binutils/doc/binutils.texi | 12 +++++ binutils/elfedit.c | 56 +++++++++++++++++++-- binutils/testsuite/binutils-all/elfedit-6.d | 15 ++++++ binutils/testsuite/binutils-all/elfedit.exp | 1 + 5 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 binutils/testsuite/binutils-all/elfedit-6.d diff --git a/binutils/NEWS b/binutils/NEWS index f3881250fce..6a2eba87e27 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,7 @@ -*- text -*- +* elfedit: Add --output-abiversion option to update ABIVERSION. + * Add support for the LoongArch instruction set. * Tools which display symbols or strings (readelf, strings, nm, objdump) diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 5de0631f3f4..fb5dc8ed568 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -5206,9 +5206,11 @@ objdump(1), and the Info entries for @file{binutils}. elfedit [@option{--input-mach=}@var{machine}] [@option{--input-type=}@var{type}] [@option{--input-osabi=}@var{osabi}] + [@option{--input-abiversion=}@var{version}] @option{--output-mach=}@var{machine} @option{--output-type=}@var{type} @option{--output-osabi=}@var{osabi} + @option{--output-abiversion=}@var{version} @option{--enable-x86-feature=}@var{feature} @option{--disable-x86-feature=}@var{feature} [@option{-v}|@option{--version}] @@ -5233,6 +5235,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{--enable-x86-feature} and @option{--disable-x86-feature} options must be given. @@ -5274,6 +5277,15 @@ The supported ELF OSABIs are, @var{none}, @var{HPUX}, @var{NetBSD}, Change the ELF OSABI in the ELF header to @var{osabi}. The supported ELF OSABI are the same as @option{--input-osabi}. +@item --input-abiversion=@var{version} +Set the matching input ELF file ABIVERSION to @var{version}. +@var{version} must be between 0 and 255. If @option{--input-abiversion} +isn't specified, it will match any ELF ABIVERSIONs. + +@item --output-abiversion=@var{version} +Change the ELF ABIVERSION in the ELF header to @var{version}. +@var{version} must be between 0 and 255. + @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 e33c340d758..374a648c266 100644 --- a/binutils/elfedit.c +++ b/binutils/elfedit.c @@ -56,6 +56,8 @@ static int input_elf_type = -1; static int output_elf_type = -1; static int input_elf_osabi = -1; static int output_elf_osabi = -1; +static int input_elf_abiversion = -1; +static int output_elf_abiversion = -1; enum elfclass { ELF_CLASS_UNKNOWN = -1, @@ -309,7 +311,7 @@ elf_class (int mach) static int update_elf_header (const char *file_name, FILE *file) { - int class, machine, type, status, osabi; + int class, machine, type, status, osabi, abiversion; if (elf_header.e_ident[EI_VERSION] != EV_CURRENT) { @@ -380,6 +382,18 @@ update_elf_header (const char *file_name, FILE *file) return 0; } + abiversion = elf_header.e_ident[EI_ABIVERSION]; + + /* Skip if ABIVERSION doesn't match. */ + if (input_elf_abiversion != -1 + && abiversion != input_elf_abiversion) + { + error + (_("%s: Unmatched EI_ABIVERSION: %d is not %d\n"), + file_name, abiversion, input_elf_abiversion); + return 0; + } + /* Update e_machine, e_type and EI_OSABI. */ switch (class) { @@ -394,6 +408,8 @@ update_elf_header (const char *file_name, FILE *file) BYTE_PUT (ehdr32.e_type, output_elf_type); if (output_elf_osabi != -1) ehdr32.e_ident[EI_OSABI] = output_elf_osabi; + if (output_elf_abiversion != -1) + ehdr32.e_ident[EI_ABIVERSION] = output_elf_abiversion; status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1; break; case ELFCLASS64: @@ -403,6 +419,8 @@ update_elf_header (const char *file_name, FILE *file) BYTE_PUT (ehdr64.e_type, output_elf_type); if (output_elf_osabi != -1) ehdr64.e_ident[EI_OSABI] = output_elf_osabi; + if (output_elf_abiversion != -1) + ehdr64.e_ident[EI_ABIVERSION] = output_elf_abiversion; status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1; break; } @@ -884,6 +902,8 @@ enum command_line_switch OPTION_OUTPUT_TYPE, OPTION_INPUT_OSABI, OPTION_OUTPUT_OSABI, + OPTION_INPUT_ABIVERSION, + OPTION_OUTPUT_ABIVERSION, #ifdef HAVE_MMAP OPTION_ENABLE_X86_FEATURE, OPTION_DISABLE_X86_FEATURE, @@ -898,6 +918,8 @@ static struct option options[] = {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE}, {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI}, {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI}, + {"input-abiversion", required_argument, 0, OPTION_INPUT_ABIVERSION}, + {"output-abiversion", required_argument, 0, OPTION_OUTPUT_ABIVERSION}, #ifdef HAVE_MMAP {"enable-x86-feature", required_argument, 0, OPTION_ENABLE_X86_FEATURE}, @@ -934,7 +956,11 @@ usage (FILE *stream, int exit_status) --input-osabi [%s]\n\ Set input OSABI\n\ --output-osabi [%s]\n\ - Set output OSABI\n"), + Set output OSABI\n\ + --input-abiversion [0-255]\n\ + Set input ABIVERSION\n\ + --output-abiversion [0-255]\n\ + Set output ABIVERSION\n"), osabi, osabi); #ifdef HAVE_MMAP fprintf (stream, _("\ @@ -958,6 +984,7 @@ int main (int argc, char ** argv) { int c, status; + char *end; #ifdef HAVE_LC_MESSAGES setlocale (LC_MESSAGES, ""); @@ -1015,6 +1042,28 @@ main (int argc, char ** argv) return 1; break; + case OPTION_INPUT_ABIVERSION: + input_elf_abiversion = strtoul (optarg, &end, 0); + if (*end != '\0' + || input_elf_abiversion < 0 + || input_elf_abiversion > 255) + { + error (_("Invalid ABIVERSION: %s\n"), optarg); + return 1; + } + break; + + case OPTION_OUTPUT_ABIVERSION: + output_elf_abiversion = strtoul (optarg, &end, 0); + if (*end != '\0' + || output_elf_abiversion < 0 + || output_elf_abiversion > 255) + { + error (_("Invalid ABIVERSION: %s\n"), optarg); + return 1; + } + break; + #ifdef HAVE_MMAP case OPTION_ENABLE_X86_FEATURE: if (elf_x86_feature (optarg, 1) < 0) @@ -1046,7 +1095,8 @@ main (int argc, char ** argv) && ! disable_x86_features #endif && output_elf_type == -1 - && output_elf_osabi == -1)) + && output_elf_osabi == -1 + && output_elf_abiversion == -1)) usage (stderr, 1); status = 0; diff --git a/binutils/testsuite/binutils-all/elfedit-6.d b/binutils/testsuite/binutils-all/elfedit-6.d new file mode 100644 index 00000000000..d30c6dc7ab1 --- /dev/null +++ b/binutils/testsuite/binutils-all/elfedit-6.d @@ -0,0 +1,15 @@ +#PROG: elfedit +#elfedit: --output-abiversion 20 +#source: empty.s +#readelf: -h +#name: Update ELF header 6 +#target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi + +#... +ELF Header: + Magic: 7f 45 4c 46 .* +#... + Version:[ \t]+1 \(current\) +#... + ABI Version:[ \t]+20 +#... diff --git a/binutils/testsuite/binutils-all/elfedit.exp b/binutils/testsuite/binutils-all/elfedit.exp index 8ce8c8b592a..6531984bc7b 100644 --- a/binutils/testsuite/binutils-all/elfedit.exp +++ b/binutils/testsuite/binutils-all/elfedit.exp @@ -25,3 +25,4 @@ run_dump_test "elfedit-2" run_dump_test "elfedit-3" run_dump_test "elfedit-4" run_dump_test "elfedit-5" +run_dump_test "elfedit-6"