1 /* copy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
24 char *input_target = NULL;
25 char *output_target = NULL;
26 char *input_filename = NULL;
27 char *output_filename = NULL;
30 static void setup_sections();
31 static void copy_sections();
33 static boolean verbose;
35 /* This flag distinguishes between strip and copy:
36 1 means this is 'strip'; 0 means this is 'copy'.
37 -1 means if we should use argv[0] to decide. */
41 extern char *program_name;
42 extern char *xmalloc();
49 "Usage %s [-S][-s srcfmt] [-d dtfmt] [-b bothfmts] infile [outfile]\n",
55 /* Create a temp file in the same directory as supplied */
58 make_tempname(filename)
61 static char template[] = "stXXXXXX";
63 char * slash = strrchr( filename, '/' );
64 if (slash != (char *)NULL){
66 tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
67 strcpy(tmpname, filename);
68 strcat(tmpname, "/" );
69 strcat(tmpname, template);
73 tmpname = xmalloc(sizeof(template));
74 strcpy(tmpname, template);
81 All the symbols have been read in and point to their owning input section.
82 They have been relocated to that they are all relative to the base of
83 their owning section. On the way out, all the symbols will be relocated to
84 their new location in the output file, through some complex sums.
88 mangle_sections(ibfd, obfd)
92 asection *current = ibfd->sections;
93 for (; current != NULL; current = current->next) {
94 current->output_section = bfd_get_section_by_name(obfd, current->name);
95 current->output_offset = 0;
101 copy_object(ibfd, obfd)
106 unsigned int symcount;
109 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
110 bfd_fatal(output_filename);
114 printf("copy from %s(%s) to %s(%s)\n",
115 ibfd->filename, ibfd->xvec->name,
116 obfd->filename, obfd->xvec->name);
118 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
120 (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
121 (HAS_LINENO | HAS_DEBUG |
122 HAS_RELOC | HAS_SYMS | D_PAGED |
123 HAS_LOCALS))) == false)) {
124 bfd_fatal(bfd_get_filename(ibfd));
127 /* Copy architecture of input file to output file */
128 if (!bfd_set_arch_mach(obfd, bfd_get_arch(ibfd),
129 bfd_get_mach(ibfd))) {
130 fprintf(stderr, "Output file cannot represent architecture %s\n",
131 bfd_printable_arch_mach(bfd_get_arch(ibfd),
132 bfd_get_mach(ibfd)));
134 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
136 bfd_fatal(ibfd->filename);
139 sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
140 symcount = bfd_canonicalize_symtab(ibfd, sympp);
142 bfd_set_symtab(obfd, sympp, is_strip ? 0 : symcount);
145 bfd mandates that all output sections be created and sizes set before
146 any output is done. Thus, we traverse all sections twice.
148 bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
149 bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
150 mangle_sections(ibfd, obfd);
159 int size = strlen(a) + strlen(b) + strlen(c);
160 char *r = xmalloc(size+1);
168 copy_archive(ibfd, obfd)
172 bfd **ptr = &obfd->archive_head;
174 /* Read each archive element in turn from the input, copy the
175 contents to a temp file, and keep the temp file handle */
176 char *dir = cat("./#",make_tempname(""),"cd");
178 /* Make a temp directory to hold the contents */
180 obfd->has_armap = ibfd->has_armap;
181 this_element = bfd_openr_next_archived_file(ibfd, NULL);
182 ibfd->archive_head = this_element;
183 while (this_element != (bfd *)NULL) {
185 /* Create an output file for this member */
186 char *output_name = cat(dir, "/",this_element->filename);
187 bfd *output_bfd = bfd_openw(output_name, output_target);
189 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
190 bfd_fatal(output_filename);
192 if (output_bfd == (bfd *)NULL) {
193 bfd_fatal(output_name);
195 if (bfd_check_format(this_element, bfd_object) == true) {
196 copy_object(this_element, output_bfd);
199 bfd_close(output_bfd);
200 /* Now open the newly output file and attatch to our list */
201 output_bfd = bfd_openr(output_name, output_target);
202 /* Mark it for deletion */
206 ptr = &output_bfd->next;
207 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
208 this_element = this_element->next;
213 if (!bfd_close(obfd))
214 bfd_fatal(output_filename);
216 /* Now delete all the files that we opened.
217 Construct their names again, unfortunately, but so what;
218 we're about to exit anyway. */
219 for (this_element = ibfd->archive_head;
220 this_element != (bfd *)NULL;
221 this_element = this_element->next)
223 unlink(cat(dir,"/",this_element->filename));
226 if (!bfd_close(ibfd))
227 bfd_fatal(input_filename);
233 copy_file(input_filename, output_filename)
234 char *input_filename;
235 char *output_filename;
239 ibfd = bfd_openr(input_filename, input_target);
241 bfd_fatal(input_filename);
243 if (bfd_check_format(ibfd, bfd_object)) {
244 bfd * obfd = bfd_openw(output_filename, output_target);
246 bfd_fatal(output_filename);
248 copy_object(ibfd, obfd);
250 if (ibfd->flags & EXEC_P)
251 obfd->flags |= EXEC_P;
252 if (!bfd_close(obfd))
253 bfd_fatal(output_filename);
255 if (!bfd_close(ibfd))
256 bfd_fatal(input_filename);
258 else if (bfd_check_format(ibfd, bfd_archive)) {
259 bfd * obfd = bfd_openw(output_filename, output_target);
261 bfd_fatal(output_filename);
262 copy_archive(ibfd, obfd);
268 /** Actually do the work */
270 setup_sections(ibfd, isection, obfd)
278 osection = bfd_get_section_by_name(obfd, bfd_section_name(ibfd, isection));
279 if (osection == NULL) {
280 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
281 if (osection == NULL) {
287 if (!bfd_set_section_size(obfd,
289 bfd_section_size(ibfd, isection))) {
294 if (bfd_set_section_vma(obfd,
296 bfd_section_vma(ibfd, isection))
302 if (bfd_set_section_alignment(obfd,
304 bfd_section_alignment(ibfd, isection))
310 if (!bfd_set_section_flags(obfd, osection,
311 bfd_get_section_flags(ibfd, isection))) {
320 fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
322 bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
323 err, bfd_errmsg(bfd_error));
325 } /* setup_sections() */
328 Copy all the section related data from an input section
331 If stripping then don't copy any relocation info
334 copy_sections(ibfd, isection, obfd)
344 osection = bfd_get_section_by_name(obfd,
345 bfd_section_name(ibfd, isection));
347 size = isection->size;
352 if (is_strip || get_reloc_upper_bound(ibfd, isection) == 0)
354 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
358 relpp = (arelent **) xmalloc(get_reloc_upper_bound(ibfd, isection));
359 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
360 bfd_set_reloc(obfd, osection, relpp, relcount);
364 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
366 PTR memhunk = (PTR) xmalloc((unsigned)size);
368 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
369 bfd_fatal(bfd_get_filename(ibfd));
371 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
372 bfd_fatal(bfd_get_filename(obfd));
385 program_name = argv[0];
390 i = strlen (program_name);
391 is_strip = (i >= 5 && strcmp(program_name+i-5,"strip"));
394 for (i = 1; i < argc; i++)
396 if (argv[i][0] == '-') {
397 switch (argv[i][1]) {
403 input_target = output_target = argv[i];
410 input_target = argv[i];
414 output_target = argv[i];
421 if (input_filename) {
422 output_filename = argv[i];
425 input_filename = argv[i];
430 if (input_filename == (char *) NULL)
433 if (output_target == (char *) NULL)
434 output_target = input_target;
436 /* If there is no destination file then create a temp and rename
437 the result into the input */
439 if (output_filename == (char *)NULL) {
440 char * tmpname = make_tempname(input_filename);
441 copy_file(input_filename, tmpname);
442 output_filename = input_filename;
443 rename(tmpname, input_filename);
446 copy_file(input_filename, output_filename);