From dd35de74344bc1dad410ed21fedd14671ab57aff Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 8 Jan 2010 18:50:39 +0000 Subject: [PATCH] Add --input-type and --output-type to elfedit binutils/ 2010-01-08 H.J. Lu * elfedit.c (input_elf_type): New. (output_elf_type): Likewise. (elf_type): Likewise. (update_elf_header): Support updating ELF file type. (command_line_switch): Add OPTION_INPUT_TYPE and OPTION_OUTPUT_TYPE. (options): Likewise. (usage): Add --input-type and --output-type. (main): Handle OPTION_INPUT_TYPE and OPTION_OUTPUT_TYPE. Check one of --output-mach and --output-type must be specified. * doc/binutils.texi: Document --input-type and --output-type for elfedit. binutils/testsuite/ 2010-01-08 H.J. Lu * binutils-all/elfedit-2.d: New. * binutils-all/elfedit.exp: Run elfedit-2. --- binutils/ChangeLog | 16 +++++ binutils/doc/binutils.texi | 27 ++++++-- binutils/elfedit.c | 72 +++++++++++++++++++-- binutils/testsuite/ChangeLog | 6 ++ binutils/testsuite/binutils-all/elfedit-2.d | 15 +++++ binutils/testsuite/binutils-all/elfedit.exp | 1 + 6 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 binutils/testsuite/binutils-all/elfedit-2.d diff --git a/binutils/ChangeLog b/binutils/ChangeLog index bbe4ec2b1fb..b5417446fef 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,19 @@ +2010-01-08 H.J. Lu + + * elfedit.c (input_elf_type): New. + (output_elf_type): Likewise. + (elf_type): Likewise. + (update_elf_header): Support updating ELF file type. + (command_line_switch): Add OPTION_INPUT_TYPE and + OPTION_OUTPUT_TYPE. + (options): Likewise. + (usage): Add --input-type and --output-type. + (main): Handle OPTION_INPUT_TYPE and OPTION_OUTPUT_TYPE. Check + one of --output-mach and --output-type must be specified. + + * doc/binutils.texi: Document --input-type and --output-type + for elfedit. + 2010-01-08 H.J. Lu * doc/binutils.texi: Fix a typo. diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 4d9a23f7e05..aedb80f9263 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -4107,7 +4107,9 @@ objdump(1), and the Info entries for @file{binutils}. @smallexample @c man begin SYNOPSIS elfedit elfedit [@option{--input-mach=}@var{machine}] + [@option{--input-type=}@var{type}] @option{--output-mach=}@var{machine} + @option{--output-type=}@var{type} [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] @var{elffile}@dots{} @@ -4116,9 +4118,9 @@ elfedit [@option{--input-mach=}@var{machine}] @c man begin DESCRIPTION elfedit -@command{elfedit} updates the ELF header of ELF files. The -options control how and which fields in the ELF header should be -updated. +@command{elfedit} updates the ELF header of ELF files which have +the matching ELF machine and file types. The options control how and +which fields in the ELF header should be updated. @var{elffile}@dots{} are the ELF files to be updated. 32-bit and 64-bit ELF files are supported, as are archives containing ELF files. @@ -4127,14 +4129,15 @@ updated. @c man begin OPTIONS elfedit The long and short forms of options, shown here as alternatives, are -equivalent. The @option{--output-mach} option must be given. +equivalent. At least one of the @option{--output-mach} and +@option{--output-type} options must be given. @table @env @itemx --input-mach=@var{machine} -Only the input files with ELF machine type, @var{machine}, will be -updated. If @option{--input-mach} isn't specified, any ELF file -will be updated. +Set the matching input ELF machine type to @var{machine}. If +@option{--input-mach} isn't specified, it will match any ELF +machine types. The supported ELF machine types are, @var{L1OM} and @var{x86-64}. @@ -4142,6 +4145,16 @@ The supported ELF machine types are, @var{L1OM} and @var{x86-64}. Change the ELF machine type in the ELF header to @var{machine}. The supported ELF machine types are the same as @option{--input-mach}. +@itemx --input-type=@var{type} +Set the matching input ELF file type to @var{type}. If +@option{--input-type} isn't specified, it will match any ELF file types. + +The supported ELF file types are, @var{rel}, @var{exec} and @var{dyn}. + +@itemx --output-type=@var{type} +Change the ELF file type in the ELF header to @var{type}. The +supported ELF types are the same as @option{--input-type}. + @item -v @itemx --version Display the version number of @command{elfedit}. diff --git a/binutils/elfedit.c b/binutils/elfedit.c index 410d89af273..b71990ce261 100644 --- a/binutils/elfedit.c +++ b/binutils/elfedit.c @@ -55,6 +55,8 @@ static Elf32_External_Ehdr ehdr32; static Elf64_External_Ehdr ehdr64; static int input_elf_machine = -1; static int output_elf_machine = -1; +static int input_elf_type = -1; +static int output_elf_type = -1; static int input_elf_class = -1; #define streq(a,b) (strcmp ((a), (b)) == 0) @@ -228,7 +230,7 @@ byte_put_big_endian (unsigned char * field, bfd_vma value, int size) static int update_elf_header (const char *file_name, FILE *file) { - int class, machine, status; + int class, machine, type, status; if (elf_header.e_ident[EI_MAG0] != ELFMAG0 || elf_header.e_ident[EI_MAG1] != ELFMAG1 @@ -276,7 +278,18 @@ update_elf_header (const char *file_name, FILE *file) return 0; } - /* Update e_machine. */ + type = elf_header.e_type; + + /* Skip if e_type doesn't match. */ + if (input_elf_type != -1 && type != input_elf_type) + { + non_fatal + (_("%s: Unmatched e_type: %d is not %d\n"), + file_name, type, input_elf_type); + return 0; + } + + /* Update e_machine and e_type. */ switch (class) { default: @@ -284,11 +297,17 @@ update_elf_header (const char *file_name, FILE *file) abort (); break; case ELFCLASS32: - BYTE_PUT (ehdr32.e_machine, output_elf_machine); + if (output_elf_machine != -1) + BYTE_PUT (ehdr32.e_machine, output_elf_machine); + if (output_elf_type != -1) + BYTE_PUT (ehdr32.e_type, output_elf_type); status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1; break; case ELFCLASS64: - BYTE_PUT (ehdr64.e_machine, output_elf_machine); + if (output_elf_machine != -1) + BYTE_PUT (ehdr64.e_machine, output_elf_machine); + if (output_elf_type != -1) + BYTE_PUT (ehdr64.e_type, output_elf_type); status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1; break; } @@ -1015,16 +1034,39 @@ elf_class (int mach) } } +/* Return ET_XXX for a type string, TYPE. */ + +static int +elf_type (const char *type) +{ + if (strcasecmp (type, "rel") == 0) + return ET_REL; + if (strcasecmp (type, "exec") == 0) + return ET_EXEC; + if (strcasecmp (type, "dyn") == 0) + return ET_DYN; + if (strcasecmp (type, "none") == 0) + return ET_NONE; + + non_fatal (_("Unknown type: %s\n"), type); + + return -1; +} + enum command_line_switch { OPTION_INPUT_MACH = 150, - OPTION_OUTPUT_MACH + OPTION_OUTPUT_MACH, + OPTION_INPUT_TYPE, + OPTION_OUTPUT_TYPE }; static struct option options[] = { {"input-mach", required_argument, 0, OPTION_INPUT_MACH}, {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH}, + {"input-type", required_argument, 0, OPTION_INPUT_TYPE}, + {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {0, no_argument, 0, 0} @@ -1033,13 +1075,15 @@ static struct option options[] = static void usage (FILE *stream, int exit_status) { - fprintf (stream, _("Usage: %s [option(s)] --output-mach elffile(s)\n"), + fprintf (stream, _("Usage: %s [option(s)] {--output-mach |--output-type } elffile(s)\n"), program_name); fprintf (stream, _(" Update the ELF header of ELF files\n")); fprintf (stream, _(" The options are:\n")); fprintf (stream, _("\ --input-mach Set input machine type to \n\ --output-mach Set output machine type to \n\ + --input-type Set input file type to \n\ + --output-type Set output file type to \n\ -h --help Display this information\n\ -v --version Display the version number of %s\n\ "), @@ -1085,6 +1129,18 @@ main (int argc, char ** argv) return 1; break; + case OPTION_INPUT_TYPE: + input_elf_type = elf_type (optarg); + if (input_elf_type < 0) + return 1; + break; + + case OPTION_OUTPUT_TYPE: + output_elf_type = elf_type (optarg); + if (output_elf_type < 0) + return 1; + break; + case 'h': usage (stdout, 0); @@ -1097,7 +1153,9 @@ main (int argc, char ** argv) } } - if (optind == argc || output_elf_machine == -1) + if (optind == argc + || (output_elf_machine == -1 + && output_elf_type == -1)) usage (stderr, 1); status = 0; diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index bd066e1f10b..4ebc7e931cd 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-01-08 H.J. Lu + + * binutils-all/elfedit-2.d: New. + + * binutils-all/elfedit.exp: Run elfedit-2. + 2010-01-06 H.J. Lu PR binutils/11131 diff --git a/binutils/testsuite/binutils-all/elfedit-2.d b/binutils/testsuite/binutils-all/elfedit-2.d new file mode 100644 index 00000000000..af07c1db297 --- /dev/null +++ b/binutils/testsuite/binutils-all/elfedit-2.d @@ -0,0 +1,15 @@ +#PROG: elfedit +#elfedit: --output-type exec +#source: empty.s +#readelf: -h +#name: Update ELF header 2 +#target: *-*-linux* + +#... +ELF Header: + Magic: 7f 45 4c 46 .* +#... + Version:[ \t]+1 \(current\) +#... + Type:[ \t]+EXEC \(Executable file\) +#... diff --git a/binutils/testsuite/binutils-all/elfedit.exp b/binutils/testsuite/binutils-all/elfedit.exp index d43c31a476f..23d52924474 100644 --- a/binutils/testsuite/binutils-all/elfedit.exp +++ b/binutils/testsuite/binutils-all/elfedit.exp @@ -29,3 +29,4 @@ if ![is_remote host] { } run_dump_test "elfedit-1" +run_dump_test "elfedit-2" -- 2.30.2