elfedit: Move ELF header magic bytes check to get_file_header
[external/binutils.git] / binutils / elfedit.c
index d9e23a1..a9f7c9d 100644 (file)
@@ -1,6 +1,5 @@
 /* elfedit.c -- Update the ELF header of an ELF format file
-   Copyright 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright (C) 2010-2018 Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
 
@@ -55,24 +54,43 @@ 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_class = -1;
+enum elfclass
+  {
+    ELF_CLASS_UNKNOWN = -1,
+    ELF_CLASS_NONE = ELFCLASSNONE,
+    ELF_CLASS_32 = ELFCLASS32,
+    ELF_CLASS_64 = ELFCLASS64,
+    ELF_CLASS_BOTH
+  };
+static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
+static enum elfclass output_elf_class = ELF_CLASS_BOTH;
+
+/* Return ELF class for a machine type, MACH.  */
+
+static enum elfclass
+elf_class (int mach)
+{
+  switch (mach)
+    {
+    case EM_386:
+    case EM_IAMCU:
+      return ELF_CLASS_32;
+    case EM_L1OM:
+    case EM_K1OM:
+      return ELF_CLASS_64;
+    case EM_X86_64:
+    case EM_NONE:
+      return ELF_CLASS_BOTH;
+    default:
+      return ELF_CLASS_BOTH;
+    }
+}
 
 static int
 update_elf_header (const char *file_name, FILE *file)
 {
   int class, machine, type, status, osabi;
 
-  if (elf_header.e_ident[EI_MAG0] != ELFMAG0
-      || elf_header.e_ident[EI_MAG1] != ELFMAG1
-      || elf_header.e_ident[EI_MAG2] != ELFMAG2
-      || elf_header.e_ident[EI_MAG3] != ELFMAG3)
-    {
-      error
-       (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
-        file_name);
-      return 0;
-    }
-
   if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
     {
       error
@@ -87,17 +105,29 @@ update_elf_header (const char *file_name, FILE *file)
     return 1;
 
   class = elf_header.e_ident[EI_CLASS];
+  machine = elf_header.e_machine;
 
   /* Skip if class doesn't match. */
-  if (input_elf_class != -1 && class != input_elf_class)
+  if (input_elf_class == ELF_CLASS_UNKNOWN)
+    input_elf_class = elf_class (machine);
+
+  if (input_elf_class != ELF_CLASS_BOTH
+      && (int) input_elf_class != class)
     {
       error
-       (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
+       (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
         file_name, class, input_elf_class);
       return 0;
     }
 
-  machine = elf_header.e_machine;
+  if (output_elf_class != ELF_CLASS_BOTH
+      && (int) output_elf_class != class)
+    {
+      error
+       (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
+        file_name, class, output_elf_class);
+      return 0;
+    }
 
   /* Skip if e_machine doesn't match. */
   if (input_elf_machine != -1 && machine != input_elf_machine)
@@ -171,6 +201,12 @@ get_file_header (FILE * file)
   if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
     return 0;
 
+  if (elf_header.e_ident[EI_MAG0] != ELFMAG0
+      || elf_header.e_ident[EI_MAG1] != ELFMAG1
+      || elf_header.e_ident[EI_MAG2] != ELFMAG2
+      || elf_header.e_ident[EI_MAG3] != ELFMAG3)
+    return 0;
+
   /* Determine how to read the rest of the header.  */
   switch (elf_header.e_ident[EI_DATA])
     {
@@ -191,8 +227,6 @@ get_file_header (FILE * file)
   switch (elf_header.e_ident[EI_CLASS])
     {
     default:
-      error (_("Unsupported EI_CLASS: %d\n"),
-                elf_header.e_ident[EI_CLASS]);
       return 0;
 
     case ELFCLASS32:
@@ -552,6 +586,10 @@ elf_osabi (const char *osabi)
 static int
 elf_machine (const char *mach)
 {
+  if (strcasecmp (mach, "i386") == 0)
+    return EM_386;
+  if (strcasecmp (mach, "iamcu") == 0)
+    return EM_IAMCU;
   if (strcasecmp (mach, "l1om") == 0)
     return EM_L1OM;
   if (strcasecmp (mach, "k1om") == 0)
@@ -568,25 +606,6 @@ elf_machine (const char *mach)
   return -1;
 }
 
-/* Return ELF class for a machine type, MACH.  */
-
-static int
-elf_class (int mach)
-{
-  switch (mach)
-    {
-    case EM_L1OM:
-    case EM_K1OM:
-    case EM_X86_64:
-      return ELFCLASS64;
-    case EM_NONE:
-      return ELFCLASSNONE;
-    default:
-      error (_("Unknown machine type: %d\n"), mach);
-      return -1;
-    }
-}
-
 /* Return ET_XXX for a type string, TYPE.  */
 
 static int
@@ -629,7 +648,7 @@ static struct option options[] =
   {0,                  no_argument, 0, 0}
 };
 
-static void
+ATTRIBUTE_NORETURN static void
 usage (FILE *stream, int exit_status)
 {
   fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
@@ -678,7 +697,7 @@ main (int argc, char ** argv)
          if (input_elf_machine < 0)
            return 1;
          input_elf_class = elf_class (input_elf_machine);
-         if (input_elf_class < 0)
+         if (input_elf_class == ELF_CLASS_UNKNOWN)
            return 1;
          break;
 
@@ -686,6 +705,9 @@ main (int argc, char ** argv)
          output_elf_machine = elf_machine (optarg);
          if (output_elf_machine < 0)
            return 1;
+         output_elf_class = elf_class (output_elf_machine);
+         if (output_elf_class == ELF_CLASS_UNKNOWN)
+           return 1;
          break;
 
        case OPTION_INPUT_TYPE: