1 /* elfedit.c -- Update the ELF header of an ELF format file
3 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
28 /* Define BFD64 here, even if our default architecture is 32 bit ELF
29 as this will allow us to read in and parse 64bit and 32bit ELF files.
30 Only do this if we believe that the compiler can support a 64 bit
31 data type. For now we only rely on GCC being able to do this. */
38 #include "elf/common.h"
39 #include "elf/external.h"
40 #include "elf/internal.h"
46 #include "libiberty.h"
47 #include "safe-ctype.h"
48 #include "filenames.h"
50 char * program_name
= "elfedit";
51 static long archive_file_offset
;
52 static unsigned long archive_file_size
;
53 static Elf_Internal_Ehdr elf_header
;
54 static Elf32_External_Ehdr ehdr32
;
55 static Elf64_External_Ehdr ehdr64
;
56 static int input_elf_machine
= -1;
57 static int output_elf_machine
= -1;
58 static int input_elf_type
= -1;
59 static int output_elf_type
= -1;
60 static int input_elf_osabi
= -1;
61 static int output_elf_osabi
= -1;
62 static int input_elf_class
= -1;
64 #define streq(a,b) (strcmp ((a), (b)) == 0)
65 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
66 #define const_strneq(a,b) (strncmp ((a), (b), sizeof (b) - 1) == 0)
69 non_fatal (const char *message
, ...)
73 va_start (args
, message
);
74 fprintf (stderr
, _("%s: Error: "), program_name
);
75 vfprintf (stderr
, message
, args
);
79 #define BYTE_GET(field) byte_get (field, sizeof (field))
80 #define BYTE_PUT(field, val) byte_put (field, val, sizeof (field))
82 static bfd_vma (*byte_get
) (unsigned char *, int);
83 static void (*byte_put
) (unsigned char *, bfd_vma
, int);
86 byte_get_little_endian (unsigned char *field
, int size
)
94 return ((unsigned int) (field
[0]))
95 | (((unsigned int) (field
[1])) << 8);
98 return ((unsigned long) (field
[0]))
99 | (((unsigned long) (field
[1])) << 8)
100 | (((unsigned long) (field
[2])) << 16)
101 | (((unsigned long) (field
[3])) << 24);
104 if (sizeof (bfd_vma
) == 8)
105 return ((bfd_vma
) (field
[0]))
106 | (((bfd_vma
) (field
[1])) << 8)
107 | (((bfd_vma
) (field
[2])) << 16)
108 | (((bfd_vma
) (field
[3])) << 24)
109 | (((bfd_vma
) (field
[4])) << 32)
110 | (((bfd_vma
) (field
[5])) << 40)
111 | (((bfd_vma
) (field
[6])) << 48)
112 | (((bfd_vma
) (field
[7])) << 56);
113 else if (sizeof (bfd_vma
) == 4)
114 /* We want to extract data from an 8 byte wide field and
115 place it into a 4 byte wide field. Since this is a little
116 endian source we can just use the 4 byte extraction code. */
117 return ((unsigned long) (field
[0]))
118 | (((unsigned long) (field
[1])) << 8)
119 | (((unsigned long) (field
[2])) << 16)
120 | (((unsigned long) (field
[3])) << 24);
123 non_fatal (_("Unhandled data length: %d\n"), size
);
129 byte_get_big_endian (unsigned char *field
, int size
)
137 return ((unsigned int) (field
[1])) | (((int) (field
[0])) << 8);
140 return ((unsigned long) (field
[3]))
141 | (((unsigned long) (field
[2])) << 8)
142 | (((unsigned long) (field
[1])) << 16)
143 | (((unsigned long) (field
[0])) << 24);
146 if (sizeof (bfd_vma
) == 8)
147 return ((bfd_vma
) (field
[7]))
148 | (((bfd_vma
) (field
[6])) << 8)
149 | (((bfd_vma
) (field
[5])) << 16)
150 | (((bfd_vma
) (field
[4])) << 24)
151 | (((bfd_vma
) (field
[3])) << 32)
152 | (((bfd_vma
) (field
[2])) << 40)
153 | (((bfd_vma
) (field
[1])) << 48)
154 | (((bfd_vma
) (field
[0])) << 56);
155 else if (sizeof (bfd_vma
) == 4)
157 /* Although we are extracing data from an 8 byte wide field,
158 we are returning only 4 bytes of data. */
160 return ((unsigned long) (field
[3]))
161 | (((unsigned long) (field
[2])) << 8)
162 | (((unsigned long) (field
[1])) << 16)
163 | (((unsigned long) (field
[0])) << 24);
167 non_fatal (_("Unhandled data length: %d\n"), size
);
173 byte_put_little_endian (unsigned char * field
, bfd_vma value
, int size
)
178 field
[7] = (((value
>> 24) >> 24) >> 8) & 0xff;
179 field
[6] = ((value
>> 24) >> 24) & 0xff;
180 field
[5] = ((value
>> 24) >> 16) & 0xff;
181 field
[4] = ((value
>> 24) >> 8) & 0xff;
184 field
[3] = (value
>> 24) & 0xff;
185 field
[2] = (value
>> 16) & 0xff;
188 field
[1] = (value
>> 8) & 0xff;
191 field
[0] = value
& 0xff;
195 non_fatal (_("Unhandled data length: %d\n"), size
);
201 byte_put_big_endian (unsigned char * field
, bfd_vma value
, int size
)
206 field
[7] = value
& 0xff;
207 field
[6] = (value
>> 8) & 0xff;
208 field
[5] = (value
>> 16) & 0xff;
209 field
[4] = (value
>> 24) & 0xff;
214 field
[3] = value
& 0xff;
215 field
[2] = (value
>> 8) & 0xff;
219 field
[1] = value
& 0xff;
223 field
[0] = value
& 0xff;
227 non_fatal (_("Unhandled data length: %d\n"), size
);
233 update_elf_header (const char *file_name
, FILE *file
)
235 int class, machine
, type
, status
, osabi
;
237 if (elf_header
.e_ident
[EI_MAG0
] != ELFMAG0
238 || elf_header
.e_ident
[EI_MAG1
] != ELFMAG1
239 || elf_header
.e_ident
[EI_MAG2
] != ELFMAG2
240 || elf_header
.e_ident
[EI_MAG3
] != ELFMAG3
)
243 (_("%s: Not an ELF file - wrong magic bytes at the start\n"),
248 if (elf_header
.e_ident
[EI_VERSION
] != EV_CURRENT
)
251 (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
252 file_name
, elf_header
.e_ident
[EI_VERSION
],
257 /* Return if e_machine is the same as output_elf_machine. */
258 if (output_elf_machine
== elf_header
.e_machine
)
261 class = elf_header
.e_ident
[EI_CLASS
];
263 /* Skip if class doesn't match. */
264 if (input_elf_class
!= -1 && class != input_elf_class
)
267 (_("%s: Unmatched EI_CLASS: %d is not %d\n"),
268 file_name
, class, input_elf_class
);
272 machine
= elf_header
.e_machine
;
274 /* Skip if e_machine doesn't match. */
275 if (input_elf_machine
!= -1 && machine
!= input_elf_machine
)
278 (_("%s: Unmatched e_machine: %d is not %d\n"),
279 file_name
, machine
, input_elf_machine
);
283 type
= elf_header
.e_type
;
285 /* Skip if e_type doesn't match. */
286 if (input_elf_type
!= -1 && type
!= input_elf_type
)
289 (_("%s: Unmatched e_type: %d is not %d\n"),
290 file_name
, type
, input_elf_type
);
294 osabi
= elf_header
.e_ident
[EI_OSABI
];
296 /* Skip if OSABI doesn't match. */
297 if (input_elf_osabi
!= -1 && osabi
!= input_elf_osabi
)
300 (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
301 file_name
, osabi
, input_elf_osabi
);
305 /* Update e_machine, e_type and EI_OSABI. */
309 /* We should never get here. */
313 if (output_elf_machine
!= -1)
314 BYTE_PUT (ehdr32
.e_machine
, output_elf_machine
);
315 if (output_elf_type
!= -1)
316 BYTE_PUT (ehdr32
.e_type
, output_elf_type
);
317 if (output_elf_osabi
!= -1)
318 ehdr32
.e_ident
[EI_OSABI
] = output_elf_osabi
;
319 status
= fwrite (&ehdr32
, sizeof (ehdr32
), 1, file
) == 1;
322 if (output_elf_machine
!= -1)
323 BYTE_PUT (ehdr64
.e_machine
, output_elf_machine
);
324 if (output_elf_type
!= -1)
325 BYTE_PUT (ehdr64
.e_type
, output_elf_type
);
326 if (output_elf_osabi
!= -1)
327 ehdr64
.e_ident
[EI_OSABI
] = output_elf_osabi
;
328 status
= fwrite (&ehdr64
, sizeof (ehdr64
), 1, file
) == 1;
333 non_fatal (_("%s: Failed to update ELF header: %s\n"),
334 file_name
, strerror (errno
));
340 get_file_header (FILE * file
)
342 /* Read in the identity array. */
343 if (fread (elf_header
.e_ident
, EI_NIDENT
, 1, file
) != 1)
346 /* Determine how to read the rest of the header. */
347 switch (elf_header
.e_ident
[EI_DATA
])
349 default: /* fall through */
350 case ELFDATANONE
: /* fall through */
352 byte_get
= byte_get_little_endian
;
353 byte_put
= byte_put_little_endian
;
356 byte_get
= byte_get_big_endian
;
357 byte_put
= byte_put_big_endian
;
361 /* Read in the rest of the header. For now we only support 32 bit
362 and 64 bit ELF files. */
363 switch (elf_header
.e_ident
[EI_CLASS
])
366 non_fatal (_("Unsupported EI_CLASS: %d\n"),
367 elf_header
.e_ident
[EI_CLASS
]);
371 if (fread (ehdr32
.e_type
, sizeof (ehdr32
) - EI_NIDENT
,
375 elf_header
.e_type
= BYTE_GET (ehdr32
.e_type
);
376 elf_header
.e_machine
= BYTE_GET (ehdr32
.e_machine
);
377 elf_header
.e_version
= BYTE_GET (ehdr32
.e_version
);
378 elf_header
.e_entry
= BYTE_GET (ehdr32
.e_entry
);
379 elf_header
.e_phoff
= BYTE_GET (ehdr32
.e_phoff
);
380 elf_header
.e_shoff
= BYTE_GET (ehdr32
.e_shoff
);
381 elf_header
.e_flags
= BYTE_GET (ehdr32
.e_flags
);
382 elf_header
.e_ehsize
= BYTE_GET (ehdr32
.e_ehsize
);
383 elf_header
.e_phentsize
= BYTE_GET (ehdr32
.e_phentsize
);
384 elf_header
.e_phnum
= BYTE_GET (ehdr32
.e_phnum
);
385 elf_header
.e_shentsize
= BYTE_GET (ehdr32
.e_shentsize
);
386 elf_header
.e_shnum
= BYTE_GET (ehdr32
.e_shnum
);
387 elf_header
.e_shstrndx
= BYTE_GET (ehdr32
.e_shstrndx
);
389 memcpy (&ehdr32
, &elf_header
, EI_NIDENT
);
393 /* If we have been compiled with sizeof (bfd_vma) == 4, then
394 we will not be able to cope with the 64bit data found in
395 64 ELF files. Detect this now and abort before we start
396 overwriting things. */
397 if (sizeof (bfd_vma
) < 8)
399 non_fatal (_("This executable has been built without support for a\n\
400 64 bit data type and so it cannot process 64 bit ELF files.\n"));
404 if (fread (ehdr64
.e_type
, sizeof (ehdr64
) - EI_NIDENT
,
408 elf_header
.e_type
= BYTE_GET (ehdr64
.e_type
);
409 elf_header
.e_machine
= BYTE_GET (ehdr64
.e_machine
);
410 elf_header
.e_version
= BYTE_GET (ehdr64
.e_version
);
411 elf_header
.e_entry
= BYTE_GET (ehdr64
.e_entry
);
412 elf_header
.e_phoff
= BYTE_GET (ehdr64
.e_phoff
);
413 elf_header
.e_shoff
= BYTE_GET (ehdr64
.e_shoff
);
414 elf_header
.e_flags
= BYTE_GET (ehdr64
.e_flags
);
415 elf_header
.e_ehsize
= BYTE_GET (ehdr64
.e_ehsize
);
416 elf_header
.e_phentsize
= BYTE_GET (ehdr64
.e_phentsize
);
417 elf_header
.e_phnum
= BYTE_GET (ehdr64
.e_phnum
);
418 elf_header
.e_shentsize
= BYTE_GET (ehdr64
.e_shentsize
);
419 elf_header
.e_shnum
= BYTE_GET (ehdr64
.e_shnum
);
420 elf_header
.e_shstrndx
= BYTE_GET (ehdr64
.e_shstrndx
);
422 memcpy (&ehdr64
, &elf_header
, EI_NIDENT
);
428 /* Process one ELF object file according to the command line options.
429 This file may actually be stored in an archive. The file is
430 positioned at the start of the ELF object. */
433 process_object (const char *file_name
, FILE *file
)
435 /* Rememeber where we are. */
436 long offset
= ftell (file
);
438 if (! get_file_header (file
))
440 non_fatal (_("%s: Failed to read ELF header\n"), file_name
);
444 /* Go to the position of the ELF header. */
445 if (fseek (file
, offset
, SEEK_SET
) != 0)
447 non_fatal (_("%s: Failed to seek to ELF header\n"), file_name
);
450 if (! update_elf_header (file_name
, file
))
456 /* Return the path name for a proxy entry in a thin archive, adjusted relative
457 to the path name of the thin archive itself if necessary. Always returns
458 a pointer to malloc'ed memory. */
461 adjust_relative_path (const char *file_name
, char * name
, int name_len
)
463 char * member_file_name
;
464 const char * base_name
= lbasename (file_name
);
466 /* This is a proxy entry for a thin archive member.
467 If the extended name table contains an absolute path
468 name, or if the archive is in the current directory,
469 use the path name as given. Otherwise, we need to
470 find the member relative to the directory where the
471 archive is located. */
472 if (IS_ABSOLUTE_PATH (name
) || base_name
== file_name
)
474 member_file_name
= malloc (name_len
+ 1);
475 if (member_file_name
== NULL
)
477 non_fatal (_("Out of memory\n"));
480 memcpy (member_file_name
, name
, name_len
);
481 member_file_name
[name_len
] = '\0';
485 /* Concatenate the path components of the archive file name
486 to the relative path name from the extended name table. */
487 size_t prefix_len
= base_name
- file_name
;
488 member_file_name
= malloc (prefix_len
+ name_len
+ 1);
489 if (member_file_name
== NULL
)
491 non_fatal (_("Out of memory\n"));
494 memcpy (member_file_name
, file_name
, prefix_len
);
495 memcpy (member_file_name
+ prefix_len
, name
, name_len
);
496 member_file_name
[prefix_len
+ name_len
] = '\0';
498 return member_file_name
;
501 /* Structure to hold information about an archive file. */
505 char * file_name
; /* Archive file name. */
506 FILE * file
; /* Open file descriptor. */
507 unsigned long index_num
; /* Number of symbols in table. */
508 unsigned long * index_array
; /* The array of member offsets. */
509 char * sym_table
; /* The symbol table. */
510 unsigned long sym_size
; /* Size of the symbol table. */
511 char * longnames
; /* The long file names table. */
512 unsigned long longnames_size
; /* Size of the long file names table. */
513 unsigned long nested_member_origin
; /* Origin in the nested archive of the current member. */
514 unsigned long next_arhdr_offset
; /* Offset of the next archive header. */
515 bfd_boolean is_thin_archive
; /* TRUE if this is a thin archive. */
516 struct ar_hdr arhdr
; /* Current archive header. */
519 /* Read the symbol table and long-name table from an archive. */
522 setup_archive (struct archive_info
* arch
, const char * file_name
,
523 FILE * file
, bfd_boolean is_thin_archive
)
528 arch
->file_name
= strdup (file_name
);
531 arch
->index_array
= NULL
;
532 arch
->sym_table
= NULL
;
534 arch
->longnames
= NULL
;
535 arch
->longnames_size
= 0;
536 arch
->nested_member_origin
= 0;
537 arch
->is_thin_archive
= is_thin_archive
;
538 arch
->next_arhdr_offset
= SARMAG
;
540 /* Read the first archive member header. */
541 if (fseek (file
, SARMAG
, SEEK_SET
) != 0)
543 non_fatal (_("%s: failed to seek to first archive header\n"),
547 got
= fread (&arch
->arhdr
, 1, sizeof arch
->arhdr
, file
);
548 if (got
!= sizeof arch
->arhdr
)
553 non_fatal (_("%s: failed to read archive header\n"), file_name
);
557 /* See if this is the archive symbol table. */
558 if (const_strneq (arch
->arhdr
.ar_name
, "/ ")
559 || const_strneq (arch
->arhdr
.ar_name
, "/SYM64/ "))
561 size
= strtoul (arch
->arhdr
.ar_size
, NULL
, 10);
562 size
= size
+ (size
& 1);
564 arch
->next_arhdr_offset
+= sizeof arch
->arhdr
+ size
;
566 if (fseek (file
, size
, SEEK_CUR
) != 0)
568 non_fatal (_("%s: failed to skip archive symbol table\n"),
573 /* Read the next archive header. */
574 got
= fread (&arch
->arhdr
, 1, sizeof arch
->arhdr
, file
);
575 if (got
!= sizeof arch
->arhdr
)
579 non_fatal (_("%s: failed to read archive header following archive index\n"),
585 if (const_strneq (arch
->arhdr
.ar_name
, "// "))
587 /* This is the archive string table holding long member names. */
588 arch
->longnames_size
= strtoul (arch
->arhdr
.ar_size
, NULL
, 10);
589 arch
->next_arhdr_offset
+= sizeof arch
->arhdr
+ arch
->longnames_size
;
591 arch
->longnames
= malloc (arch
->longnames_size
);
592 if (arch
->longnames
== NULL
)
594 non_fatal (_("Out of memory reading long symbol names in archive\n"));
598 if (fread (arch
->longnames
, arch
->longnames_size
, 1, file
) != 1)
600 free (arch
->longnames
);
601 arch
->longnames
= NULL
;
602 non_fatal (_("%s: failed to read long symbol name string table\n")
607 if ((arch
->longnames_size
& 1) != 0)
614 /* Release the memory used for the archive information. */
617 release_archive (struct archive_info
* arch
)
619 if (arch
->file_name
!= NULL
)
620 free (arch
->file_name
);
621 if (arch
->index_array
!= NULL
)
622 free (arch
->index_array
);
623 if (arch
->sym_table
!= NULL
)
624 free (arch
->sym_table
);
625 if (arch
->longnames
!= NULL
)
626 free (arch
->longnames
);
629 /* Open and setup a nested archive, if not already open. */
632 setup_nested_archive (struct archive_info
* nested_arch
, char * member_file_name
)
636 /* Have we already setup this archive? */
637 if (nested_arch
->file_name
!= NULL
638 && streq (nested_arch
->file_name
, member_file_name
))
641 /* Close previous file and discard cached information. */
642 if (nested_arch
->file
!= NULL
)
643 fclose (nested_arch
->file
);
644 release_archive (nested_arch
);
646 member_file
= fopen (member_file_name
, "r+b");
647 if (member_file
== NULL
)
649 return setup_archive (nested_arch
, member_file_name
, member_file
,
654 get_archive_member_name_at (struct archive_info
* arch
,
655 unsigned long offset
,
656 struct archive_info
* nested_arch
);
658 /* Get the name of an archive member from the current archive header.
659 For simple names, this will modify the ar_name field of the current
660 archive header. For long names, it will return a pointer to the
661 longnames table. For nested archives, it will open the nested archive
662 and get the name recursively. NESTED_ARCH is a single-entry cache so
663 we don't keep rereading the same information from a nested archive. */
666 get_archive_member_name (struct archive_info
* arch
,
667 struct archive_info
* nested_arch
)
671 if (arch
->arhdr
.ar_name
[0] == '/')
673 /* We have a long name. */
675 char * member_file_name
;
678 arch
->nested_member_origin
= 0;
679 k
= j
= strtoul (arch
->arhdr
.ar_name
+ 1, &endp
, 10);
680 if (arch
->is_thin_archive
&& endp
!= NULL
&& * endp
== ':')
681 arch
->nested_member_origin
= strtoul (endp
+ 1, NULL
, 10);
683 while ((j
< arch
->longnames_size
)
684 && (arch
->longnames
[j
] != '\n')
685 && (arch
->longnames
[j
] != '\0'))
687 if (arch
->longnames
[j
-1] == '/')
689 arch
->longnames
[j
] = '\0';
691 if (!arch
->is_thin_archive
|| arch
->nested_member_origin
== 0)
692 return arch
->longnames
+ k
;
694 /* This is a proxy for a member of a nested archive.
695 Find the name of the member in that archive. */
696 member_file_name
= adjust_relative_path (arch
->file_name
,
699 if (member_file_name
!= NULL
700 && setup_nested_archive (nested_arch
, member_file_name
) == 0
701 && (member_name
= get_archive_member_name_at (nested_arch
,
702 arch
->nested_member_origin
,
705 free (member_file_name
);
708 free (member_file_name
);
710 /* Last resort: just return the name of the nested archive. */
711 return arch
->longnames
+ k
;
714 /* We have a normal (short) name. */
716 while ((arch
->arhdr
.ar_name
[j
] != '/') && (j
< 16))
718 arch
->arhdr
.ar_name
[j
] = '\0';
719 return arch
->arhdr
.ar_name
;
722 /* Get the name of an archive member at a given OFFSET within an
726 get_archive_member_name_at (struct archive_info
* arch
,
727 unsigned long offset
,
728 struct archive_info
* nested_arch
)
732 if (fseek (arch
->file
, offset
, SEEK_SET
) != 0)
734 non_fatal (_("%s: failed to seek to next file name\n"),
738 got
= fread (&arch
->arhdr
, 1, sizeof arch
->arhdr
, arch
->file
);
739 if (got
!= sizeof arch
->arhdr
)
741 non_fatal (_("%s: failed to read archive header\n"),
745 if (memcmp (arch
->arhdr
.ar_fmag
, ARFMAG
, 2) != 0)
747 non_fatal (_("%s: did not find a valid archive header\n"),
752 return get_archive_member_name (arch
, nested_arch
);
755 /* Construct a string showing the name of the archive member, qualified
756 with the name of the containing archive file. For thin archives, we
757 use square brackets to denote the indirection. For nested archives,
758 we show the qualified name of the external member inside the square
759 brackets (e.g., "thin.a[normal.a(foo.o)]"). */
762 make_qualified_name (struct archive_info
* arch
,
763 struct archive_info
* nested_arch
,
769 len
= strlen (arch
->file_name
) + strlen (member_name
) + 3;
770 if (arch
->is_thin_archive
&& arch
->nested_member_origin
!= 0)
771 len
+= strlen (nested_arch
->file_name
) + 2;
776 non_fatal (_("Out of memory\n"));
780 if (arch
->is_thin_archive
&& arch
->nested_member_origin
!= 0)
781 snprintf (name
, len
, "%s[%s(%s)]", arch
->file_name
,
782 nested_arch
->file_name
, member_name
);
783 else if (arch
->is_thin_archive
)
784 snprintf (name
, len
, "%s[%s]", arch
->file_name
, member_name
);
786 snprintf (name
, len
, "%s(%s)", arch
->file_name
, member_name
);
791 /* Process an ELF archive.
792 On entry the file is positioned just after the ARMAG string. */
795 process_archive (const char * file_name
, FILE * file
,
796 bfd_boolean is_thin_archive
)
798 struct archive_info arch
;
799 struct archive_info nested_arch
;
803 /* The ARCH structure is used to hold information about this archive. */
804 arch
.file_name
= NULL
;
806 arch
.index_array
= NULL
;
807 arch
.sym_table
= NULL
;
808 arch
.longnames
= NULL
;
810 /* The NESTED_ARCH structure is used as a single-item cache of information
811 about a nested archive (when members of a thin archive reside within
812 another regular archive file). */
813 nested_arch
.file_name
= NULL
;
814 nested_arch
.file
= NULL
;
815 nested_arch
.index_array
= NULL
;
816 nested_arch
.sym_table
= NULL
;
817 nested_arch
.longnames
= NULL
;
819 if (setup_archive (&arch
, file_name
, file
, is_thin_archive
) != 0)
831 char * qualified_name
;
833 /* Read the next archive header. */
834 if (fseek (file
, arch
.next_arhdr_offset
, SEEK_SET
) != 0)
836 non_fatal (_("%s: failed to seek to next archive header\n"),
840 got
= fread (&arch
.arhdr
, 1, sizeof arch
.arhdr
, file
);
841 if (got
!= sizeof arch
.arhdr
)
845 non_fatal (_("%s: failed to read archive header\n"),
850 if (memcmp (arch
.arhdr
.ar_fmag
, ARFMAG
, 2) != 0)
852 non_fatal (_("%s: did not find a valid archive header\n"),
858 arch
.next_arhdr_offset
+= sizeof arch
.arhdr
;
860 archive_file_size
= strtoul (arch
.arhdr
.ar_size
, NULL
, 10);
861 if (archive_file_size
& 01)
864 name
= get_archive_member_name (&arch
, &nested_arch
);
867 non_fatal (_("%s: bad archive file name\n"), file_name
);
871 namelen
= strlen (name
);
873 qualified_name
= make_qualified_name (&arch
, &nested_arch
, name
);
874 if (qualified_name
== NULL
)
876 non_fatal (_("%s: bad archive file name\n"), file_name
);
881 if (is_thin_archive
&& arch
.nested_member_origin
== 0)
883 /* This is a proxy for an external member of a thin archive. */
885 char *member_file_name
= adjust_relative_path (file_name
,
887 if (member_file_name
== NULL
)
893 member_file
= fopen (member_file_name
, "r+b");
894 if (member_file
== NULL
)
896 non_fatal (_("Input file '%s' is not readable\n"),
898 free (member_file_name
);
903 archive_file_offset
= arch
.nested_member_origin
;
905 ret
|= process_object (qualified_name
, member_file
);
907 fclose (member_file
);
908 free (member_file_name
);
910 else if (is_thin_archive
)
912 /* This is a proxy for a member of a nested archive. */
913 archive_file_offset
= arch
.nested_member_origin
+ sizeof arch
.arhdr
;
915 /* The nested archive file will have been opened and setup by
916 get_archive_member_name. */
917 if (fseek (nested_arch
.file
, archive_file_offset
,
920 non_fatal (_("%s: failed to seek to archive member\n"),
921 nested_arch
.file_name
);
926 ret
|= process_object (qualified_name
, nested_arch
.file
);
930 archive_file_offset
= arch
.next_arhdr_offset
;
931 arch
.next_arhdr_offset
+= archive_file_size
;
933 ret
|= process_object (qualified_name
, file
);
936 free (qualified_name
);
940 if (nested_arch
.file
!= NULL
)
941 fclose (nested_arch
.file
);
942 release_archive (&nested_arch
);
943 release_archive (&arch
);
949 check_file (const char *file_name
, struct stat
*statbuf_p
)
953 if (statbuf_p
== NULL
)
954 statbuf_p
= &statbuf
;
956 if (stat (file_name
, statbuf_p
) < 0)
959 non_fatal (_("'%s': No such file\n"), file_name
);
961 non_fatal (_("Could not locate '%s'. System error message: %s\n"),
962 file_name
, strerror (errno
));
966 if (! S_ISREG (statbuf_p
->st_mode
))
968 non_fatal (_("'%s' is not an ordinary file\n"), file_name
);
976 process_file (const char *file_name
)
982 if (check_file (file_name
, NULL
))
985 file
= fopen (file_name
, "r+b");
988 non_fatal (_("Input file '%s' is not readable\n"), file_name
);
992 if (fread (armag
, SARMAG
, 1, file
) != 1)
994 non_fatal (_("%s: Failed to read file's magic number\n"),
1000 if (memcmp (armag
, ARMAG
, SARMAG
) == 0)
1001 ret
= process_archive (file_name
, file
, FALSE
);
1002 else if (memcmp (armag
, ARMAGT
, SARMAG
) == 0)
1003 ret
= process_archive (file_name
, file
, TRUE
);
1007 archive_file_size
= archive_file_offset
= 0;
1008 ret
= process_object (file_name
, file
);
1023 { ELFOSABI_NONE
, "none" },
1024 { ELFOSABI_HPUX
, "HPUX" },
1025 { ELFOSABI_NETBSD
, "NetBSD" },
1026 { ELFOSABI_LINUX
, "Linux" },
1027 { ELFOSABI_HURD
, "Hurd" },
1028 { ELFOSABI_SOLARIS
, "Solaris" },
1029 { ELFOSABI_AIX
, "AIX" },
1030 { ELFOSABI_IRIX
, "Irix" },
1031 { ELFOSABI_FREEBSD
, "FreeBSD" },
1032 { ELFOSABI_TRU64
, "TRU64" },
1033 { ELFOSABI_MODESTO
, "Modesto" },
1034 { ELFOSABI_OPENBSD
, "OpenBSD" },
1035 { ELFOSABI_OPENVMS
, "OpenVMS" },
1036 { ELFOSABI_NSK
, "NSK" },
1037 { ELFOSABI_AROS
, "AROS" },
1038 { ELFOSABI_FENIXOS
, "FenixOS" }
1041 /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
1044 elf_osabi (const char *osabi
)
1048 for (i
= 0; i
< ARRAY_SIZE (osabis
); i
++)
1049 if (strcasecmp (osabi
, osabis
[i
].name
) == 0)
1050 return osabis
[i
].osabi
;
1052 non_fatal (_("Unknown OSABI: %s\n"), osabi
);
1057 /* Return EM_XXX for a machine string, MACH. */
1060 elf_machine (const char *mach
)
1062 if (strcasecmp (mach
, "l1om") == 0)
1064 if (strcasecmp (mach
, "x86_64") == 0)
1066 if (strcasecmp (mach
, "x86-64") == 0)
1068 if (strcasecmp (mach
, "none") == 0)
1071 non_fatal (_("Unknown machine type: %s\n"), mach
);
1076 /* Return ELF class for a machine type, MACH. */
1079 elf_class (int mach
)
1087 return ELFCLASSNONE
;
1089 non_fatal (_("Unknown machine type: %d\n"), mach
);
1094 /* Return ET_XXX for a type string, TYPE. */
1097 elf_type (const char *type
)
1099 if (strcasecmp (type
, "rel") == 0)
1101 if (strcasecmp (type
, "exec") == 0)
1103 if (strcasecmp (type
, "dyn") == 0)
1105 if (strcasecmp (type
, "none") == 0)
1108 non_fatal (_("Unknown type: %s\n"), type
);
1113 enum command_line_switch
1115 OPTION_INPUT_MACH
= 150,
1123 static struct option options
[] =
1125 {"input-mach", required_argument
, 0, OPTION_INPUT_MACH
},
1126 {"output-mach", required_argument
, 0, OPTION_OUTPUT_MACH
},
1127 {"input-type", required_argument
, 0, OPTION_INPUT_TYPE
},
1128 {"output-type", required_argument
, 0, OPTION_OUTPUT_TYPE
},
1129 {"input-osabi", required_argument
, 0, OPTION_INPUT_OSABI
},
1130 {"output-osabi", required_argument
, 0, OPTION_OUTPUT_OSABI
},
1131 {"version", no_argument
, 0, 'v'},
1132 {"help", no_argument
, 0, 'h'},
1133 {0, no_argument
, 0, 0}
1137 usage (FILE *stream
, int exit_status
)
1139 fprintf (stream
, _("Usage: %s <option(s)> elffile(s)\n"),
1141 fprintf (stream
, _(" Update the ELF header of ELF files\n"));
1142 fprintf (stream
, _(" The options are:\n"));
1143 fprintf (stream
, _("\
1144 --input-mach <machine> Set input machine type to <machine>\n\
1145 --output-mach <machine> Set output machine type to <machine>\n\
1146 --input-type <type> Set input file type to <type>\n\
1147 --output-type <type> Set output file type to <type>\n\
1148 --input-osabi <osabi> Set input OSABI to <osabi>\n\
1149 --output-osabi <osabi> Set output OSABI to <osabi>\n\
1150 -h --help Display this information\n\
1151 -v --version Display the version number of %s\n\
1154 if (REPORT_BUGS_TO
[0] && exit_status
== 0)
1155 fprintf (stream
, _("Report bugs to %s\n"), REPORT_BUGS_TO
);
1160 main (int argc
, char ** argv
)
1164 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
1165 setlocale (LC_MESSAGES
, "");
1167 #if defined (HAVE_SETLOCALE)
1168 setlocale (LC_CTYPE
, "");
1170 bindtextdomain (PACKAGE
, LOCALEDIR
);
1171 textdomain (PACKAGE
);
1173 expandargv (&argc
, &argv
);
1175 while ((c
= getopt_long (argc
, argv
, "hv",
1176 options
, (int *) 0)) != EOF
)
1180 case OPTION_INPUT_MACH
:
1181 input_elf_machine
= elf_machine (optarg
);
1182 if (input_elf_machine
< 0)
1184 input_elf_class
= elf_class (input_elf_machine
);
1185 if (input_elf_class
< 0)
1189 case OPTION_OUTPUT_MACH
:
1190 output_elf_machine
= elf_machine (optarg
);
1191 if (output_elf_machine
< 0)
1195 case OPTION_INPUT_TYPE
:
1196 input_elf_type
= elf_type (optarg
);
1197 if (input_elf_type
< 0)
1201 case OPTION_OUTPUT_TYPE
:
1202 output_elf_type
= elf_type (optarg
);
1203 if (output_elf_type
< 0)
1207 case OPTION_INPUT_OSABI
:
1208 input_elf_osabi
= elf_osabi (optarg
);
1209 if (input_elf_osabi
< 0)
1213 case OPTION_OUTPUT_OSABI
:
1214 output_elf_osabi
= elf_osabi (optarg
);
1215 if (output_elf_osabi
< 0)
1223 print_version (program_name
);
1232 || (output_elf_machine
== -1
1233 && output_elf_type
== -1
1234 && output_elf_osabi
== -1))
1238 while (optind
< argc
)
1239 status
|= process_file (argv
[optind
++]);