1*a9fa9459Szrj /* elfedit.c -- Update the ELF header of an ELF format file 2*a9fa9459Szrj Copyright (C) 2010-2016 Free Software Foundation, Inc. 3*a9fa9459Szrj 4*a9fa9459Szrj This file is part of GNU Binutils. 5*a9fa9459Szrj 6*a9fa9459Szrj This program is free software; you can redistribute it and/or modify 7*a9fa9459Szrj it under the terms of the GNU General Public License as published by 8*a9fa9459Szrj the Free Software Foundation; either version 3 of the License, or 9*a9fa9459Szrj (at your option) any later version. 10*a9fa9459Szrj 11*a9fa9459Szrj This program is distributed in the hope that it will be useful, 12*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of 13*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*a9fa9459Szrj GNU General Public License for more details. 15*a9fa9459Szrj 16*a9fa9459Szrj You should have received a copy of the GNU General Public License 17*a9fa9459Szrj along with this program; if not, write to the Free Software 18*a9fa9459Szrj Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 19*a9fa9459Szrj 02110-1301, USA. */ 20*a9fa9459Szrj 21*a9fa9459Szrj #include "sysdep.h" 22*a9fa9459Szrj #include <assert.h> 23*a9fa9459Szrj 24*a9fa9459Szrj #if __GNUC__ >= 2 25*a9fa9459Szrj /* Define BFD64 here, even if our default architecture is 32 bit ELF 26*a9fa9459Szrj as this will allow us to read in and parse 64bit and 32bit ELF files. 27*a9fa9459Szrj Only do this if we believe that the compiler can support a 64 bit 28*a9fa9459Szrj data type. For now we only rely on GCC being able to do this. */ 29*a9fa9459Szrj #define BFD64 30*a9fa9459Szrj #endif 31*a9fa9459Szrj 32*a9fa9459Szrj #include "bfd.h" 33*a9fa9459Szrj #include "elfcomm.h" 34*a9fa9459Szrj #include "bucomm.h" 35*a9fa9459Szrj 36*a9fa9459Szrj #include "elf/common.h" 37*a9fa9459Szrj #include "elf/external.h" 38*a9fa9459Szrj #include "elf/internal.h" 39*a9fa9459Szrj 40*a9fa9459Szrj #include "getopt.h" 41*a9fa9459Szrj #include "libiberty.h" 42*a9fa9459Szrj #include "safe-ctype.h" 43*a9fa9459Szrj #include "filenames.h" 44*a9fa9459Szrj 45*a9fa9459Szrj char * program_name = "elfedit"; 46*a9fa9459Szrj static long archive_file_offset; 47*a9fa9459Szrj static unsigned long archive_file_size; 48*a9fa9459Szrj static Elf_Internal_Ehdr elf_header; 49*a9fa9459Szrj static Elf32_External_Ehdr ehdr32; 50*a9fa9459Szrj static Elf64_External_Ehdr ehdr64; 51*a9fa9459Szrj static int input_elf_machine = -1; 52*a9fa9459Szrj static int output_elf_machine = -1; 53*a9fa9459Szrj static int input_elf_type = -1; 54*a9fa9459Szrj static int output_elf_type = -1; 55*a9fa9459Szrj static int input_elf_osabi = -1; 56*a9fa9459Szrj static int output_elf_osabi = -1; 57*a9fa9459Szrj enum elfclass 58*a9fa9459Szrj { 59*a9fa9459Szrj ELF_CLASS_UNKNOWN = -1, 60*a9fa9459Szrj ELF_CLASS_NONE = ELFCLASSNONE, 61*a9fa9459Szrj ELF_CLASS_32 = ELFCLASS32, 62*a9fa9459Szrj ELF_CLASS_64 = ELFCLASS64, 63*a9fa9459Szrj ELF_CLASS_BOTH 64*a9fa9459Szrj }; 65*a9fa9459Szrj static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN; 66*a9fa9459Szrj static enum elfclass output_elf_class = ELF_CLASS_BOTH; 67*a9fa9459Szrj 68*a9fa9459Szrj /* Return ELF class for a machine type, MACH. */ 69*a9fa9459Szrj 70*a9fa9459Szrj static enum elfclass 71*a9fa9459Szrj elf_class (int mach) 72*a9fa9459Szrj { 73*a9fa9459Szrj switch (mach) 74*a9fa9459Szrj { 75*a9fa9459Szrj case EM_386: 76*a9fa9459Szrj case EM_IAMCU: 77*a9fa9459Szrj return ELF_CLASS_32; 78*a9fa9459Szrj case EM_L1OM: 79*a9fa9459Szrj case EM_K1OM: 80*a9fa9459Szrj return ELF_CLASS_64; 81*a9fa9459Szrj case EM_X86_64: 82*a9fa9459Szrj case EM_NONE: 83*a9fa9459Szrj return ELF_CLASS_BOTH; 84*a9fa9459Szrj default: 85*a9fa9459Szrj return ELF_CLASS_BOTH; 86*a9fa9459Szrj } 87*a9fa9459Szrj } 88*a9fa9459Szrj 89*a9fa9459Szrj static int 90*a9fa9459Szrj update_elf_header (const char *file_name, FILE *file) 91*a9fa9459Szrj { 92*a9fa9459Szrj int class, machine, type, status, osabi; 93*a9fa9459Szrj 94*a9fa9459Szrj if (elf_header.e_ident[EI_MAG0] != ELFMAG0 95*a9fa9459Szrj || elf_header.e_ident[EI_MAG1] != ELFMAG1 96*a9fa9459Szrj || elf_header.e_ident[EI_MAG2] != ELFMAG2 97*a9fa9459Szrj || elf_header.e_ident[EI_MAG3] != ELFMAG3) 98*a9fa9459Szrj { 99*a9fa9459Szrj error 100*a9fa9459Szrj (_("%s: Not an ELF file - wrong magic bytes at the start\n"), 101*a9fa9459Szrj file_name); 102*a9fa9459Szrj return 0; 103*a9fa9459Szrj } 104*a9fa9459Szrj 105*a9fa9459Szrj if (elf_header.e_ident[EI_VERSION] != EV_CURRENT) 106*a9fa9459Szrj { 107*a9fa9459Szrj error 108*a9fa9459Szrj (_("%s: Unsupported EI_VERSION: %d is not %d\n"), 109*a9fa9459Szrj file_name, elf_header.e_ident[EI_VERSION], 110*a9fa9459Szrj EV_CURRENT); 111*a9fa9459Szrj return 0; 112*a9fa9459Szrj } 113*a9fa9459Szrj 114*a9fa9459Szrj /* Return if e_machine is the same as output_elf_machine. */ 115*a9fa9459Szrj if (output_elf_machine == elf_header.e_machine) 116*a9fa9459Szrj return 1; 117*a9fa9459Szrj 118*a9fa9459Szrj class = elf_header.e_ident[EI_CLASS]; 119*a9fa9459Szrj machine = elf_header.e_machine; 120*a9fa9459Szrj 121*a9fa9459Szrj /* Skip if class doesn't match. */ 122*a9fa9459Szrj if (input_elf_class == ELF_CLASS_UNKNOWN) 123*a9fa9459Szrj input_elf_class = elf_class (machine); 124*a9fa9459Szrj 125*a9fa9459Szrj if (input_elf_class != ELF_CLASS_BOTH 126*a9fa9459Szrj && (int) input_elf_class != class) 127*a9fa9459Szrj { 128*a9fa9459Szrj error 129*a9fa9459Szrj (_("%s: Unmatched input EI_CLASS: %d is not %d\n"), 130*a9fa9459Szrj file_name, class, input_elf_class); 131*a9fa9459Szrj return 0; 132*a9fa9459Szrj } 133*a9fa9459Szrj 134*a9fa9459Szrj if (output_elf_class != ELF_CLASS_BOTH 135*a9fa9459Szrj && (int) output_elf_class != class) 136*a9fa9459Szrj { 137*a9fa9459Szrj error 138*a9fa9459Szrj (_("%s: Unmatched output EI_CLASS: %d is not %d\n"), 139*a9fa9459Szrj file_name, class, output_elf_class); 140*a9fa9459Szrj return 0; 141*a9fa9459Szrj } 142*a9fa9459Szrj 143*a9fa9459Szrj /* Skip if e_machine doesn't match. */ 144*a9fa9459Szrj if (input_elf_machine != -1 && machine != input_elf_machine) 145*a9fa9459Szrj { 146*a9fa9459Szrj error 147*a9fa9459Szrj (_("%s: Unmatched e_machine: %d is not %d\n"), 148*a9fa9459Szrj file_name, machine, input_elf_machine); 149*a9fa9459Szrj return 0; 150*a9fa9459Szrj } 151*a9fa9459Szrj 152*a9fa9459Szrj type = elf_header.e_type; 153*a9fa9459Szrj 154*a9fa9459Szrj /* Skip if e_type doesn't match. */ 155*a9fa9459Szrj if (input_elf_type != -1 && type != input_elf_type) 156*a9fa9459Szrj { 157*a9fa9459Szrj error 158*a9fa9459Szrj (_("%s: Unmatched e_type: %d is not %d\n"), 159*a9fa9459Szrj file_name, type, input_elf_type); 160*a9fa9459Szrj return 0; 161*a9fa9459Szrj } 162*a9fa9459Szrj 163*a9fa9459Szrj osabi = elf_header.e_ident[EI_OSABI]; 164*a9fa9459Szrj 165*a9fa9459Szrj /* Skip if OSABI doesn't match. */ 166*a9fa9459Szrj if (input_elf_osabi != -1 && osabi != input_elf_osabi) 167*a9fa9459Szrj { 168*a9fa9459Szrj error 169*a9fa9459Szrj (_("%s: Unmatched EI_OSABI: %d is not %d\n"), 170*a9fa9459Szrj file_name, osabi, input_elf_osabi); 171*a9fa9459Szrj return 0; 172*a9fa9459Szrj } 173*a9fa9459Szrj 174*a9fa9459Szrj /* Update e_machine, e_type and EI_OSABI. */ 175*a9fa9459Szrj switch (class) 176*a9fa9459Szrj { 177*a9fa9459Szrj default: 178*a9fa9459Szrj /* We should never get here. */ 179*a9fa9459Szrj abort (); 180*a9fa9459Szrj break; 181*a9fa9459Szrj case ELFCLASS32: 182*a9fa9459Szrj if (output_elf_machine != -1) 183*a9fa9459Szrj BYTE_PUT (ehdr32.e_machine, output_elf_machine); 184*a9fa9459Szrj if (output_elf_type != -1) 185*a9fa9459Szrj BYTE_PUT (ehdr32.e_type, output_elf_type); 186*a9fa9459Szrj if (output_elf_osabi != -1) 187*a9fa9459Szrj ehdr32.e_ident[EI_OSABI] = output_elf_osabi; 188*a9fa9459Szrj status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1; 189*a9fa9459Szrj break; 190*a9fa9459Szrj case ELFCLASS64: 191*a9fa9459Szrj if (output_elf_machine != -1) 192*a9fa9459Szrj BYTE_PUT (ehdr64.e_machine, output_elf_machine); 193*a9fa9459Szrj if (output_elf_type != -1) 194*a9fa9459Szrj BYTE_PUT (ehdr64.e_type, output_elf_type); 195*a9fa9459Szrj if (output_elf_osabi != -1) 196*a9fa9459Szrj ehdr64.e_ident[EI_OSABI] = output_elf_osabi; 197*a9fa9459Szrj status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1; 198*a9fa9459Szrj break; 199*a9fa9459Szrj } 200*a9fa9459Szrj 201*a9fa9459Szrj if (status != 1) 202*a9fa9459Szrj error (_("%s: Failed to update ELF header: %s\n"), 203*a9fa9459Szrj file_name, strerror (errno)); 204*a9fa9459Szrj 205*a9fa9459Szrj return status; 206*a9fa9459Szrj } 207*a9fa9459Szrj 208*a9fa9459Szrj static int 209*a9fa9459Szrj get_file_header (FILE * file) 210*a9fa9459Szrj { 211*a9fa9459Szrj /* Read in the identity array. */ 212*a9fa9459Szrj if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1) 213*a9fa9459Szrj return 0; 214*a9fa9459Szrj 215*a9fa9459Szrj /* Determine how to read the rest of the header. */ 216*a9fa9459Szrj switch (elf_header.e_ident[EI_DATA]) 217*a9fa9459Szrj { 218*a9fa9459Szrj default: /* fall through */ 219*a9fa9459Szrj case ELFDATANONE: /* fall through */ 220*a9fa9459Szrj case ELFDATA2LSB: 221*a9fa9459Szrj byte_get = byte_get_little_endian; 222*a9fa9459Szrj byte_put = byte_put_little_endian; 223*a9fa9459Szrj break; 224*a9fa9459Szrj case ELFDATA2MSB: 225*a9fa9459Szrj byte_get = byte_get_big_endian; 226*a9fa9459Szrj byte_put = byte_put_big_endian; 227*a9fa9459Szrj break; 228*a9fa9459Szrj } 229*a9fa9459Szrj 230*a9fa9459Szrj /* Read in the rest of the header. For now we only support 32 bit 231*a9fa9459Szrj and 64 bit ELF files. */ 232*a9fa9459Szrj switch (elf_header.e_ident[EI_CLASS]) 233*a9fa9459Szrj { 234*a9fa9459Szrj default: 235*a9fa9459Szrj error (_("Unsupported EI_CLASS: %d\n"), 236*a9fa9459Szrj elf_header.e_ident[EI_CLASS]); 237*a9fa9459Szrj return 0; 238*a9fa9459Szrj 239*a9fa9459Szrj case ELFCLASS32: 240*a9fa9459Szrj if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 241*a9fa9459Szrj 1, file) != 1) 242*a9fa9459Szrj return 0; 243*a9fa9459Szrj 244*a9fa9459Szrj elf_header.e_type = BYTE_GET (ehdr32.e_type); 245*a9fa9459Szrj elf_header.e_machine = BYTE_GET (ehdr32.e_machine); 246*a9fa9459Szrj elf_header.e_version = BYTE_GET (ehdr32.e_version); 247*a9fa9459Szrj elf_header.e_entry = BYTE_GET (ehdr32.e_entry); 248*a9fa9459Szrj elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff); 249*a9fa9459Szrj elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff); 250*a9fa9459Szrj elf_header.e_flags = BYTE_GET (ehdr32.e_flags); 251*a9fa9459Szrj elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize); 252*a9fa9459Szrj elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize); 253*a9fa9459Szrj elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum); 254*a9fa9459Szrj elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize); 255*a9fa9459Szrj elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum); 256*a9fa9459Szrj elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx); 257*a9fa9459Szrj 258*a9fa9459Szrj memcpy (&ehdr32, &elf_header, EI_NIDENT); 259*a9fa9459Szrj break; 260*a9fa9459Szrj 261*a9fa9459Szrj case ELFCLASS64: 262*a9fa9459Szrj /* If we have been compiled with sizeof (bfd_vma) == 4, then 263*a9fa9459Szrj we will not be able to cope with the 64bit data found in 264*a9fa9459Szrj 64 ELF files. Detect this now and abort before we start 265*a9fa9459Szrj overwriting things. */ 266*a9fa9459Szrj if (sizeof (bfd_vma) < 8) 267*a9fa9459Szrj { 268*a9fa9459Szrj error (_("This executable has been built without support for a\n\ 269*a9fa9459Szrj 64 bit data type and so it cannot process 64 bit ELF files.\n")); 270*a9fa9459Szrj return 0; 271*a9fa9459Szrj } 272*a9fa9459Szrj 273*a9fa9459Szrj if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 274*a9fa9459Szrj 1, file) != 1) 275*a9fa9459Szrj return 0; 276*a9fa9459Szrj 277*a9fa9459Szrj elf_header.e_type = BYTE_GET (ehdr64.e_type); 278*a9fa9459Szrj elf_header.e_machine = BYTE_GET (ehdr64.e_machine); 279*a9fa9459Szrj elf_header.e_version = BYTE_GET (ehdr64.e_version); 280*a9fa9459Szrj elf_header.e_entry = BYTE_GET (ehdr64.e_entry); 281*a9fa9459Szrj elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff); 282*a9fa9459Szrj elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff); 283*a9fa9459Szrj elf_header.e_flags = BYTE_GET (ehdr64.e_flags); 284*a9fa9459Szrj elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize); 285*a9fa9459Szrj elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize); 286*a9fa9459Szrj elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum); 287*a9fa9459Szrj elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize); 288*a9fa9459Szrj elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum); 289*a9fa9459Szrj elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx); 290*a9fa9459Szrj 291*a9fa9459Szrj memcpy (&ehdr64, &elf_header, EI_NIDENT); 292*a9fa9459Szrj break; 293*a9fa9459Szrj } 294*a9fa9459Szrj return 1; 295*a9fa9459Szrj } 296*a9fa9459Szrj 297*a9fa9459Szrj /* Process one ELF object file according to the command line options. 298*a9fa9459Szrj This file may actually be stored in an archive. The file is 299*a9fa9459Szrj positioned at the start of the ELF object. */ 300*a9fa9459Szrj 301*a9fa9459Szrj static int 302*a9fa9459Szrj process_object (const char *file_name, FILE *file) 303*a9fa9459Szrj { 304*a9fa9459Szrj /* Rememeber where we are. */ 305*a9fa9459Szrj long offset = ftell (file); 306*a9fa9459Szrj 307*a9fa9459Szrj if (! get_file_header (file)) 308*a9fa9459Szrj { 309*a9fa9459Szrj error (_("%s: Failed to read ELF header\n"), file_name); 310*a9fa9459Szrj return 1; 311*a9fa9459Szrj } 312*a9fa9459Szrj 313*a9fa9459Szrj /* Go to the position of the ELF header. */ 314*a9fa9459Szrj if (fseek (file, offset, SEEK_SET) != 0) 315*a9fa9459Szrj { 316*a9fa9459Szrj error (_("%s: Failed to seek to ELF header\n"), file_name); 317*a9fa9459Szrj } 318*a9fa9459Szrj 319*a9fa9459Szrj if (! update_elf_header (file_name, file)) 320*a9fa9459Szrj return 1; 321*a9fa9459Szrj 322*a9fa9459Szrj return 0; 323*a9fa9459Szrj } 324*a9fa9459Szrj 325*a9fa9459Szrj /* Process an ELF archive. 326*a9fa9459Szrj On entry the file is positioned just after the ARMAG string. */ 327*a9fa9459Szrj 328*a9fa9459Szrj static int 329*a9fa9459Szrj process_archive (const char * file_name, FILE * file, 330*a9fa9459Szrj bfd_boolean is_thin_archive) 331*a9fa9459Szrj { 332*a9fa9459Szrj struct archive_info arch; 333*a9fa9459Szrj struct archive_info nested_arch; 334*a9fa9459Szrj size_t got; 335*a9fa9459Szrj int ret; 336*a9fa9459Szrj 337*a9fa9459Szrj /* The ARCH structure is used to hold information about this archive. */ 338*a9fa9459Szrj arch.file_name = NULL; 339*a9fa9459Szrj arch.file = NULL; 340*a9fa9459Szrj arch.index_array = NULL; 341*a9fa9459Szrj arch.sym_table = NULL; 342*a9fa9459Szrj arch.longnames = NULL; 343*a9fa9459Szrj 344*a9fa9459Szrj /* The NESTED_ARCH structure is used as a single-item cache of information 345*a9fa9459Szrj about a nested archive (when members of a thin archive reside within 346*a9fa9459Szrj another regular archive file). */ 347*a9fa9459Szrj nested_arch.file_name = NULL; 348*a9fa9459Szrj nested_arch.file = NULL; 349*a9fa9459Szrj nested_arch.index_array = NULL; 350*a9fa9459Szrj nested_arch.sym_table = NULL; 351*a9fa9459Szrj nested_arch.longnames = NULL; 352*a9fa9459Szrj 353*a9fa9459Szrj if (setup_archive (&arch, file_name, file, is_thin_archive, FALSE) != 0) 354*a9fa9459Szrj { 355*a9fa9459Szrj ret = 1; 356*a9fa9459Szrj goto out; 357*a9fa9459Szrj } 358*a9fa9459Szrj 359*a9fa9459Szrj ret = 0; 360*a9fa9459Szrj 361*a9fa9459Szrj while (1) 362*a9fa9459Szrj { 363*a9fa9459Szrj char * name; 364*a9fa9459Szrj size_t namelen; 365*a9fa9459Szrj char * qualified_name; 366*a9fa9459Szrj 367*a9fa9459Szrj /* Read the next archive header. */ 368*a9fa9459Szrj if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0) 369*a9fa9459Szrj { 370*a9fa9459Szrj error (_("%s: failed to seek to next archive header\n"), 371*a9fa9459Szrj file_name); 372*a9fa9459Szrj return 1; 373*a9fa9459Szrj } 374*a9fa9459Szrj got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file); 375*a9fa9459Szrj if (got != sizeof arch.arhdr) 376*a9fa9459Szrj { 377*a9fa9459Szrj if (got == 0) 378*a9fa9459Szrj break; 379*a9fa9459Szrj error (_("%s: failed to read archive header\n"), 380*a9fa9459Szrj file_name); 381*a9fa9459Szrj ret = 1; 382*a9fa9459Szrj break; 383*a9fa9459Szrj } 384*a9fa9459Szrj if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0) 385*a9fa9459Szrj { 386*a9fa9459Szrj error (_("%s: did not find a valid archive header\n"), 387*a9fa9459Szrj arch.file_name); 388*a9fa9459Szrj ret = 1; 389*a9fa9459Szrj break; 390*a9fa9459Szrj } 391*a9fa9459Szrj 392*a9fa9459Szrj arch.next_arhdr_offset += sizeof arch.arhdr; 393*a9fa9459Szrj 394*a9fa9459Szrj archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10); 395*a9fa9459Szrj if (archive_file_size & 01) 396*a9fa9459Szrj ++archive_file_size; 397*a9fa9459Szrj 398*a9fa9459Szrj name = get_archive_member_name (&arch, &nested_arch); 399*a9fa9459Szrj if (name == NULL) 400*a9fa9459Szrj { 401*a9fa9459Szrj error (_("%s: bad archive file name\n"), file_name); 402*a9fa9459Szrj ret = 1; 403*a9fa9459Szrj break; 404*a9fa9459Szrj } 405*a9fa9459Szrj namelen = strlen (name); 406*a9fa9459Szrj 407*a9fa9459Szrj qualified_name = make_qualified_name (&arch, &nested_arch, name); 408*a9fa9459Szrj if (qualified_name == NULL) 409*a9fa9459Szrj { 410*a9fa9459Szrj error (_("%s: bad archive file name\n"), file_name); 411*a9fa9459Szrj ret = 1; 412*a9fa9459Szrj break; 413*a9fa9459Szrj } 414*a9fa9459Szrj 415*a9fa9459Szrj if (is_thin_archive && arch.nested_member_origin == 0) 416*a9fa9459Szrj { 417*a9fa9459Szrj /* This is a proxy for an external member of a thin archive. */ 418*a9fa9459Szrj FILE *member_file; 419*a9fa9459Szrj char *member_file_name = adjust_relative_path (file_name, 420*a9fa9459Szrj name, namelen); 421*a9fa9459Szrj if (member_file_name == NULL) 422*a9fa9459Szrj { 423*a9fa9459Szrj ret = 1; 424*a9fa9459Szrj break; 425*a9fa9459Szrj } 426*a9fa9459Szrj 427*a9fa9459Szrj member_file = fopen (member_file_name, "r+b"); 428*a9fa9459Szrj if (member_file == NULL) 429*a9fa9459Szrj { 430*a9fa9459Szrj error (_("Input file '%s' is not readable\n"), 431*a9fa9459Szrj member_file_name); 432*a9fa9459Szrj free (member_file_name); 433*a9fa9459Szrj ret = 1; 434*a9fa9459Szrj break; 435*a9fa9459Szrj } 436*a9fa9459Szrj 437*a9fa9459Szrj archive_file_offset = arch.nested_member_origin; 438*a9fa9459Szrj 439*a9fa9459Szrj ret |= process_object (qualified_name, member_file); 440*a9fa9459Szrj 441*a9fa9459Szrj fclose (member_file); 442*a9fa9459Szrj free (member_file_name); 443*a9fa9459Szrj } 444*a9fa9459Szrj else if (is_thin_archive) 445*a9fa9459Szrj { 446*a9fa9459Szrj /* This is a proxy for a member of a nested archive. */ 447*a9fa9459Szrj archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr; 448*a9fa9459Szrj 449*a9fa9459Szrj /* The nested archive file will have been opened and setup by 450*a9fa9459Szrj get_archive_member_name. */ 451*a9fa9459Szrj if (fseek (nested_arch.file, archive_file_offset, 452*a9fa9459Szrj SEEK_SET) != 0) 453*a9fa9459Szrj { 454*a9fa9459Szrj error (_("%s: failed to seek to archive member\n"), 455*a9fa9459Szrj nested_arch.file_name); 456*a9fa9459Szrj ret = 1; 457*a9fa9459Szrj break; 458*a9fa9459Szrj } 459*a9fa9459Szrj 460*a9fa9459Szrj ret |= process_object (qualified_name, nested_arch.file); 461*a9fa9459Szrj } 462*a9fa9459Szrj else 463*a9fa9459Szrj { 464*a9fa9459Szrj archive_file_offset = arch.next_arhdr_offset; 465*a9fa9459Szrj arch.next_arhdr_offset += archive_file_size; 466*a9fa9459Szrj 467*a9fa9459Szrj ret |= process_object (qualified_name, file); 468*a9fa9459Szrj } 469*a9fa9459Szrj 470*a9fa9459Szrj free (qualified_name); 471*a9fa9459Szrj } 472*a9fa9459Szrj 473*a9fa9459Szrj out: 474*a9fa9459Szrj if (nested_arch.file != NULL) 475*a9fa9459Szrj fclose (nested_arch.file); 476*a9fa9459Szrj release_archive (&nested_arch); 477*a9fa9459Szrj release_archive (&arch); 478*a9fa9459Szrj 479*a9fa9459Szrj return ret; 480*a9fa9459Szrj } 481*a9fa9459Szrj 482*a9fa9459Szrj static int 483*a9fa9459Szrj check_file (const char *file_name, struct stat *statbuf_p) 484*a9fa9459Szrj { 485*a9fa9459Szrj struct stat statbuf; 486*a9fa9459Szrj 487*a9fa9459Szrj if (statbuf_p == NULL) 488*a9fa9459Szrj statbuf_p = &statbuf; 489*a9fa9459Szrj 490*a9fa9459Szrj if (stat (file_name, statbuf_p) < 0) 491*a9fa9459Szrj { 492*a9fa9459Szrj if (errno == ENOENT) 493*a9fa9459Szrj error (_("'%s': No such file\n"), file_name); 494*a9fa9459Szrj else 495*a9fa9459Szrj error (_("Could not locate '%s'. System error message: %s\n"), 496*a9fa9459Szrj file_name, strerror (errno)); 497*a9fa9459Szrj return 1; 498*a9fa9459Szrj } 499*a9fa9459Szrj 500*a9fa9459Szrj if (! S_ISREG (statbuf_p->st_mode)) 501*a9fa9459Szrj { 502*a9fa9459Szrj error (_("'%s' is not an ordinary file\n"), file_name); 503*a9fa9459Szrj return 1; 504*a9fa9459Szrj } 505*a9fa9459Szrj 506*a9fa9459Szrj return 0; 507*a9fa9459Szrj } 508*a9fa9459Szrj 509*a9fa9459Szrj static int 510*a9fa9459Szrj process_file (const char *file_name) 511*a9fa9459Szrj { 512*a9fa9459Szrj FILE * file; 513*a9fa9459Szrj char armag[SARMAG]; 514*a9fa9459Szrj int ret; 515*a9fa9459Szrj 516*a9fa9459Szrj if (check_file (file_name, NULL)) 517*a9fa9459Szrj return 1; 518*a9fa9459Szrj 519*a9fa9459Szrj file = fopen (file_name, "r+b"); 520*a9fa9459Szrj if (file == NULL) 521*a9fa9459Szrj { 522*a9fa9459Szrj error (_("Input file '%s' is not readable\n"), file_name); 523*a9fa9459Szrj return 1; 524*a9fa9459Szrj } 525*a9fa9459Szrj 526*a9fa9459Szrj if (fread (armag, SARMAG, 1, file) != 1) 527*a9fa9459Szrj { 528*a9fa9459Szrj error (_("%s: Failed to read file's magic number\n"), 529*a9fa9459Szrj file_name); 530*a9fa9459Szrj fclose (file); 531*a9fa9459Szrj return 1; 532*a9fa9459Szrj } 533*a9fa9459Szrj 534*a9fa9459Szrj if (memcmp (armag, ARMAG, SARMAG) == 0) 535*a9fa9459Szrj ret = process_archive (file_name, file, FALSE); 536*a9fa9459Szrj else if (memcmp (armag, ARMAGT, SARMAG) == 0) 537*a9fa9459Szrj ret = process_archive (file_name, file, TRUE); 538*a9fa9459Szrj else 539*a9fa9459Szrj { 540*a9fa9459Szrj rewind (file); 541*a9fa9459Szrj archive_file_size = archive_file_offset = 0; 542*a9fa9459Szrj ret = process_object (file_name, file); 543*a9fa9459Szrj } 544*a9fa9459Szrj 545*a9fa9459Szrj fclose (file); 546*a9fa9459Szrj 547*a9fa9459Szrj return ret; 548*a9fa9459Szrj } 549*a9fa9459Szrj 550*a9fa9459Szrj static const struct 551*a9fa9459Szrj { 552*a9fa9459Szrj int osabi; 553*a9fa9459Szrj const char *name; 554*a9fa9459Szrj } 555*a9fa9459Szrj osabis[] = 556*a9fa9459Szrj { 557*a9fa9459Szrj { ELFOSABI_NONE, "none" }, 558*a9fa9459Szrj { ELFOSABI_HPUX, "HPUX" }, 559*a9fa9459Szrj { ELFOSABI_NETBSD, "NetBSD" }, 560*a9fa9459Szrj { ELFOSABI_GNU, "GNU" }, 561*a9fa9459Szrj { ELFOSABI_GNU, "Linux" }, 562*a9fa9459Szrj { ELFOSABI_SOLARIS, "Solaris" }, 563*a9fa9459Szrj { ELFOSABI_AIX, "AIX" }, 564*a9fa9459Szrj { ELFOSABI_IRIX, "Irix" }, 565*a9fa9459Szrj { ELFOSABI_FREEBSD, "FreeBSD" }, 566*a9fa9459Szrj { ELFOSABI_TRU64, "TRU64" }, 567*a9fa9459Szrj { ELFOSABI_MODESTO, "Modesto" }, 568*a9fa9459Szrj { ELFOSABI_OPENBSD, "OpenBSD" }, 569*a9fa9459Szrj { ELFOSABI_OPENVMS, "OpenVMS" }, 570*a9fa9459Szrj { ELFOSABI_NSK, "NSK" }, 571*a9fa9459Szrj { ELFOSABI_AROS, "AROS" }, 572*a9fa9459Szrj { ELFOSABI_FENIXOS, "FenixOS" } 573*a9fa9459Szrj }; 574*a9fa9459Szrj 575*a9fa9459Szrj /* Return ELFOSABI_XXX for an OSABI string, OSABI. */ 576*a9fa9459Szrj 577*a9fa9459Szrj static int 578*a9fa9459Szrj elf_osabi (const char *osabi) 579*a9fa9459Szrj { 580*a9fa9459Szrj unsigned int i; 581*a9fa9459Szrj 582*a9fa9459Szrj for (i = 0; i < ARRAY_SIZE (osabis); i++) 583*a9fa9459Szrj if (strcasecmp (osabi, osabis[i].name) == 0) 584*a9fa9459Szrj return osabis[i].osabi; 585*a9fa9459Szrj 586*a9fa9459Szrj error (_("Unknown OSABI: %s\n"), osabi); 587*a9fa9459Szrj 588*a9fa9459Szrj return -1; 589*a9fa9459Szrj } 590*a9fa9459Szrj 591*a9fa9459Szrj /* Return EM_XXX for a machine string, MACH. */ 592*a9fa9459Szrj 593*a9fa9459Szrj static int 594*a9fa9459Szrj elf_machine (const char *mach) 595*a9fa9459Szrj { 596*a9fa9459Szrj if (strcasecmp (mach, "i386") == 0) 597*a9fa9459Szrj return EM_386; 598*a9fa9459Szrj if (strcasecmp (mach, "iamcu") == 0) 599*a9fa9459Szrj return EM_IAMCU; 600*a9fa9459Szrj if (strcasecmp (mach, "l1om") == 0) 601*a9fa9459Szrj return EM_L1OM; 602*a9fa9459Szrj if (strcasecmp (mach, "k1om") == 0) 603*a9fa9459Szrj return EM_K1OM; 604*a9fa9459Szrj if (strcasecmp (mach, "x86_64") == 0) 605*a9fa9459Szrj return EM_X86_64; 606*a9fa9459Szrj if (strcasecmp (mach, "x86-64") == 0) 607*a9fa9459Szrj return EM_X86_64; 608*a9fa9459Szrj if (strcasecmp (mach, "none") == 0) 609*a9fa9459Szrj return EM_NONE; 610*a9fa9459Szrj 611*a9fa9459Szrj error (_("Unknown machine type: %s\n"), mach); 612*a9fa9459Szrj 613*a9fa9459Szrj return -1; 614*a9fa9459Szrj } 615*a9fa9459Szrj 616*a9fa9459Szrj /* Return ET_XXX for a type string, TYPE. */ 617*a9fa9459Szrj 618*a9fa9459Szrj static int 619*a9fa9459Szrj elf_type (const char *type) 620*a9fa9459Szrj { 621*a9fa9459Szrj if (strcasecmp (type, "rel") == 0) 622*a9fa9459Szrj return ET_REL; 623*a9fa9459Szrj if (strcasecmp (type, "exec") == 0) 624*a9fa9459Szrj return ET_EXEC; 625*a9fa9459Szrj if (strcasecmp (type, "dyn") == 0) 626*a9fa9459Szrj return ET_DYN; 627*a9fa9459Szrj if (strcasecmp (type, "none") == 0) 628*a9fa9459Szrj return ET_NONE; 629*a9fa9459Szrj 630*a9fa9459Szrj error (_("Unknown type: %s\n"), type); 631*a9fa9459Szrj 632*a9fa9459Szrj return -1; 633*a9fa9459Szrj } 634*a9fa9459Szrj 635*a9fa9459Szrj enum command_line_switch 636*a9fa9459Szrj { 637*a9fa9459Szrj OPTION_INPUT_MACH = 150, 638*a9fa9459Szrj OPTION_OUTPUT_MACH, 639*a9fa9459Szrj OPTION_INPUT_TYPE, 640*a9fa9459Szrj OPTION_OUTPUT_TYPE, 641*a9fa9459Szrj OPTION_INPUT_OSABI, 642*a9fa9459Szrj OPTION_OUTPUT_OSABI 643*a9fa9459Szrj }; 644*a9fa9459Szrj 645*a9fa9459Szrj static struct option options[] = 646*a9fa9459Szrj { 647*a9fa9459Szrj {"input-mach", required_argument, 0, OPTION_INPUT_MACH}, 648*a9fa9459Szrj {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH}, 649*a9fa9459Szrj {"input-type", required_argument, 0, OPTION_INPUT_TYPE}, 650*a9fa9459Szrj {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE}, 651*a9fa9459Szrj {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI}, 652*a9fa9459Szrj {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI}, 653*a9fa9459Szrj {"version", no_argument, 0, 'v'}, 654*a9fa9459Szrj {"help", no_argument, 0, 'h'}, 655*a9fa9459Szrj {0, no_argument, 0, 0} 656*a9fa9459Szrj }; 657*a9fa9459Szrj 658*a9fa9459Szrj static void 659*a9fa9459Szrj usage (FILE *stream, int exit_status) 660*a9fa9459Szrj { 661*a9fa9459Szrj fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"), 662*a9fa9459Szrj program_name); 663*a9fa9459Szrj fprintf (stream, _(" Update the ELF header of ELF files\n")); 664*a9fa9459Szrj fprintf (stream, _(" The options are:\n")); 665*a9fa9459Szrj fprintf (stream, _("\ 666*a9fa9459Szrj --input-mach <machine> Set input machine type to <machine>\n\ 667*a9fa9459Szrj --output-mach <machine> Set output machine type to <machine>\n\ 668*a9fa9459Szrj --input-type <type> Set input file type to <type>\n\ 669*a9fa9459Szrj --output-type <type> Set output file type to <type>\n\ 670*a9fa9459Szrj --input-osabi <osabi> Set input OSABI to <osabi>\n\ 671*a9fa9459Szrj --output-osabi <osabi> Set output OSABI to <osabi>\n\ 672*a9fa9459Szrj -h --help Display this information\n\ 673*a9fa9459Szrj -v --version Display the version number of %s\n\ 674*a9fa9459Szrj "), 675*a9fa9459Szrj program_name); 676*a9fa9459Szrj if (REPORT_BUGS_TO[0] && exit_status == 0) 677*a9fa9459Szrj fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 678*a9fa9459Szrj exit (exit_status); 679*a9fa9459Szrj } 680*a9fa9459Szrj 681*a9fa9459Szrj int 682*a9fa9459Szrj main (int argc, char ** argv) 683*a9fa9459Szrj { 684*a9fa9459Szrj int c, status; 685*a9fa9459Szrj 686*a9fa9459Szrj #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 687*a9fa9459Szrj setlocale (LC_MESSAGES, ""); 688*a9fa9459Szrj #endif 689*a9fa9459Szrj #if defined (HAVE_SETLOCALE) 690*a9fa9459Szrj setlocale (LC_CTYPE, ""); 691*a9fa9459Szrj #endif 692*a9fa9459Szrj bindtextdomain (PACKAGE, LOCALEDIR); 693*a9fa9459Szrj textdomain (PACKAGE); 694*a9fa9459Szrj 695*a9fa9459Szrj expandargv (&argc, &argv); 696*a9fa9459Szrj 697*a9fa9459Szrj while ((c = getopt_long (argc, argv, "hv", 698*a9fa9459Szrj options, (int *) 0)) != EOF) 699*a9fa9459Szrj { 700*a9fa9459Szrj switch (c) 701*a9fa9459Szrj { 702*a9fa9459Szrj case OPTION_INPUT_MACH: 703*a9fa9459Szrj input_elf_machine = elf_machine (optarg); 704*a9fa9459Szrj if (input_elf_machine < 0) 705*a9fa9459Szrj return 1; 706*a9fa9459Szrj input_elf_class = elf_class (input_elf_machine); 707*a9fa9459Szrj if (input_elf_class == ELF_CLASS_UNKNOWN) 708*a9fa9459Szrj return 1; 709*a9fa9459Szrj break; 710*a9fa9459Szrj 711*a9fa9459Szrj case OPTION_OUTPUT_MACH: 712*a9fa9459Szrj output_elf_machine = elf_machine (optarg); 713*a9fa9459Szrj if (output_elf_machine < 0) 714*a9fa9459Szrj return 1; 715*a9fa9459Szrj output_elf_class = elf_class (output_elf_machine); 716*a9fa9459Szrj if (output_elf_class == ELF_CLASS_UNKNOWN) 717*a9fa9459Szrj return 1; 718*a9fa9459Szrj break; 719*a9fa9459Szrj 720*a9fa9459Szrj case OPTION_INPUT_TYPE: 721*a9fa9459Szrj input_elf_type = elf_type (optarg); 722*a9fa9459Szrj if (input_elf_type < 0) 723*a9fa9459Szrj return 1; 724*a9fa9459Szrj break; 725*a9fa9459Szrj 726*a9fa9459Szrj case OPTION_OUTPUT_TYPE: 727*a9fa9459Szrj output_elf_type = elf_type (optarg); 728*a9fa9459Szrj if (output_elf_type < 0) 729*a9fa9459Szrj return 1; 730*a9fa9459Szrj break; 731*a9fa9459Szrj 732*a9fa9459Szrj case OPTION_INPUT_OSABI: 733*a9fa9459Szrj input_elf_osabi = elf_osabi (optarg); 734*a9fa9459Szrj if (input_elf_osabi < 0) 735*a9fa9459Szrj return 1; 736*a9fa9459Szrj break; 737*a9fa9459Szrj 738*a9fa9459Szrj case OPTION_OUTPUT_OSABI: 739*a9fa9459Szrj output_elf_osabi = elf_osabi (optarg); 740*a9fa9459Szrj if (output_elf_osabi < 0) 741*a9fa9459Szrj return 1; 742*a9fa9459Szrj break; 743*a9fa9459Szrj 744*a9fa9459Szrj case 'h': 745*a9fa9459Szrj usage (stdout, 0); 746*a9fa9459Szrj 747*a9fa9459Szrj case 'v': 748*a9fa9459Szrj print_version (program_name); 749*a9fa9459Szrj break; 750*a9fa9459Szrj 751*a9fa9459Szrj default: 752*a9fa9459Szrj usage (stderr, 1); 753*a9fa9459Szrj } 754*a9fa9459Szrj } 755*a9fa9459Szrj 756*a9fa9459Szrj if (optind == argc 757*a9fa9459Szrj || (output_elf_machine == -1 758*a9fa9459Szrj && output_elf_type == -1 759*a9fa9459Szrj && output_elf_osabi == -1)) 760*a9fa9459Szrj usage (stderr, 1); 761*a9fa9459Szrj 762*a9fa9459Szrj status = 0; 763*a9fa9459Szrj while (optind < argc) 764*a9fa9459Szrj status |= process_file (argv[optind++]); 765*a9fa9459Szrj 766*a9fa9459Szrj return status; 767*a9fa9459Szrj } 768