* copy.c (main): Even if is_strip, accept -d argument indicating alternate
[deliverable/binutils-gdb.git] / binutils / copy.c
CommitLineData
d8474a9b
PB
1/* copy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991 Free Software Foundation, Inc.
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
c074abee 20#include "bfd.h"
2a5f387b 21#include "sysdep.h"
5a77e916 22#include "bucomm.h"
fc5d6074 23
c074abee
DHW
24asymbol **sympp;
25char *input_target = NULL;
26char *output_target = NULL;
27char *input_filename = NULL;
28char *output_filename = NULL;
29
30
31static void setup_sections();
32static void copy_sections();
c074abee
DHW
33static boolean verbose;
34
782d7963
PB
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. */
38extern int is_strip;
39
c074abee
DHW
40/* IMPORTS */
41extern char *program_name;
5c670bc1 42extern char *program_version;
5a77e916 43
c074abee
DHW
44
45static
46void
47usage()
48{
49 fprintf(stderr,
a51d4b41 50 "Usage %s [-S][-s srcfmt] [-d dtfmt] [-b bothfmts] infile [outfile] [-vV]\n",
c074abee
DHW
51 program_name);
52 exit(1);
53}
54
a51d4b41
PB
55static
56void
57strip_usage()
58{
59 fprintf(stderr, "Usage %s [-vV] filename ...\n", program_name);
60 exit(1);
61}
62
c074abee
DHW
63
64/* Create a temp file in the same directory as supplied */
65static
66char *
67make_tempname(filename)
68char *filename;
69{
70 static char template[] = "stXXXXXX";
71 char *tmpname;
72 char * slash = strrchr( filename, '/' );
73 if (slash != (char *)NULL){
74 *slash = 0;
75 tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
76 strcpy(tmpname, filename);
77 strcat(tmpname, "/" );
78 strcat(tmpname, template);
79 mktemp(tmpname );
80 *slash = '/';
81 } else {
82 tmpname = xmalloc(sizeof(template));
83 strcpy(tmpname, template);
84 mktemp(tmpname);
85 }
86 return tmpname;
87}
88
89/*
90 All the symbols have been read in and point to their owning input section.
91 They have been relocated to that they are all relative to the base of
92 their owning section. On the way out, all the symbols will be relocated to
93 their new location in the output file, through some complex sums.
94
95*/
96static void
97mangle_sections(ibfd, obfd)
98 bfd *ibfd;
99 bfd *obfd;
100{
101 asection *current = ibfd->sections;
102 for (; current != NULL; current = current->next) {
103 current->output_section = bfd_get_section_by_name(obfd, current->name);
104 current->output_offset = 0;
105 }
106}
107
108static
109void
110copy_object(ibfd, obfd)
111bfd *ibfd;
112bfd *obfd;
113{
114
115 unsigned int symcount;
116
117
118 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
119 bfd_fatal(output_filename);
120
121
122 if (verbose)
123 printf("copy from %s(%s) to %s(%s)\n",
124 ibfd->filename, ibfd->xvec->name,
125 obfd->filename, obfd->xvec->name);
126
23565c68
SC
127 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
128 ||
c074abee 129 (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
23565c68
SC
130 (HAS_LINENO | HAS_DEBUG |
131 HAS_RELOC | HAS_SYMS | D_PAGED |
132 HAS_LOCALS))) == false)) {
133 bfd_fatal(bfd_get_filename(ibfd));
134 }
c074abee
DHW
135
136 /* Copy architecture of input file to output file */
21214e8e
SC
137 if (!bfd_set_arch_mach(obfd, bfd_get_arch(ibfd),
138 bfd_get_mach(ibfd))) {
c074abee 139 fprintf(stderr, "Output file cannot represent architecture %s\n",
21214e8e
SC
140 bfd_printable_arch_mach(bfd_get_arch(ibfd),
141 bfd_get_mach(ibfd)));
c074abee
DHW
142 }
143 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
144 {
145 bfd_fatal(ibfd->filename);
146 }
147
148 sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
149 symcount = bfd_canonicalize_symtab(ibfd, sympp);
150
782d7963 151 bfd_set_symtab(obfd, sympp, is_strip ? 0 : symcount);
c074abee
DHW
152
153 /*
154 bfd mandates that all output sections be created and sizes set before
155 any output is done. Thus, we traverse all sections twice.
156 */
157 bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
158 bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
159 mangle_sections(ibfd, obfd);
160}
161static
162char *
163cat(a,b,c)
164char *a;
165char *b;
166char *c;
167{
168 int size = strlen(a) + strlen(b) + strlen(c);
169 char *r = xmalloc(size+1);
170 strcpy(r,a);
171 strcat(r,b);
172 strcat(r,c);
173 return r;
174}
175
176static void
177copy_archive(ibfd, obfd)
178bfd *ibfd;
179bfd *obfd;
180{
1417a2cd 181 bfd **ptr = &obfd->archive_head;
c074abee
DHW
182 bfd *this_element;
183 /* Read each archive element in turn from the input, copy the
184 contents to a temp file, and keep the temp file handle */
ad19c0a2 185 char *dir = cat("./#",make_tempname(""),"cd");
c074abee
DHW
186
187 /* Make a temp directory to hold the contents */
188 mkdir(dir,0777);
189 obfd->has_armap = ibfd->has_armap;
190 this_element = bfd_openr_next_archived_file(ibfd, NULL);
ad19c0a2 191 ibfd->archive_head = this_element;
c074abee
DHW
192 while (this_element != (bfd *)NULL) {
193
194 /* Create an output file for this member */
195 char *output_name = cat(dir, "/",this_element->filename);
196 bfd *output_bfd = bfd_openw(output_name, output_target);
ad19c0a2 197
c074abee
DHW
198 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
199 bfd_fatal(output_filename);
200
201 if (output_bfd == (bfd *)NULL) {
202 bfd_fatal(output_name);
203 }
204 if (bfd_check_format(this_element, bfd_object) == true) {
205 copy_object(this_element, output_bfd);
206 }
207
208 bfd_close(output_bfd);
209 /* Now open the newly output file and attatch to our list */
210 output_bfd = bfd_openr(output_name, output_target);
211 /* Mark it for deletion */
212
213 *ptr = output_bfd;
214
1417a2cd 215 ptr = &output_bfd->next;
ad19c0a2
DHW
216 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
217 this_element = this_element->next;
c074abee
DHW
218
219 }
220 *ptr = (bfd *)NULL;
221
222 if (!bfd_close(obfd))
223 bfd_fatal(output_filename);
224
ad19c0a2
DHW
225 /* Now delete all the files that we opened.
226 Construct their names again, unfortunately, but so what;
227 we're about to exit anyway. */
c074abee
DHW
228 for (this_element = ibfd->archive_head;
229 this_element != (bfd *)NULL;
230 this_element = this_element->next)
231 {
232 unlink(cat(dir,"/",this_element->filename));
233 }
ad19c0a2 234 rmdir(dir);
c074abee
DHW
235 if (!bfd_close(ibfd))
236 bfd_fatal(input_filename);
237
238}
239
240static
617cd571 241void
c074abee
DHW
242copy_file(input_filename, output_filename)
243 char *input_filename;
244 char *output_filename;
245{
617cd571 246 bfd *ibfd;
c074abee 247
617cd571
SC
248 ibfd = bfd_openr(input_filename, input_target);
249 if (ibfd == NULL)
250 bfd_fatal(input_filename);
c074abee 251
617cd571
SC
252 if (bfd_check_format(ibfd, bfd_object)) {
253 bfd * obfd = bfd_openw(output_filename, output_target);
254 if (obfd == NULL)
255 bfd_fatal(output_filename);
c074abee 256
617cd571 257 copy_object(ibfd, obfd);
c074abee 258
782d7963
PB
259 if (ibfd->flags & EXEC_P)
260 obfd->flags |= EXEC_P;
617cd571
SC
261 if (!bfd_close(obfd))
262 bfd_fatal(output_filename);
c074abee 263
617cd571
SC
264 if (!bfd_close(ibfd))
265 bfd_fatal(input_filename);
266 }
267 else if (bfd_check_format(ibfd, bfd_archive)) {
268 bfd * obfd = bfd_openw(output_filename, output_target);
269 if (obfd == NULL)
270 bfd_fatal(output_filename);
271 copy_archive(ibfd, obfd);
272 }
c074abee
DHW
273}
274
275
276
277/** Actually do the work */
278static void
279setup_sections(ibfd, isection, obfd)
280 bfd *ibfd;
281 sec_ptr isection;
282 bfd *obfd;
283{
284 sec_ptr osection;
285 char *err;
782d7963
PB
286
287 osection = bfd_get_section_by_name(obfd, bfd_section_name(ibfd, isection));
c074abee 288 if (osection == NULL) {
782d7963
PB
289 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
290 if (osection == NULL) {
291 err = "making";
292 goto loser;
293 }
c074abee
DHW
294 }
295
296 if (!bfd_set_section_size(obfd,
297 osection,
298 bfd_section_size(ibfd, isection))) {
299 err = "size";
300 goto loser;
301 }
302
303 if (bfd_set_section_vma(obfd,
304 osection,
305 bfd_section_vma(ibfd, isection))
306 == false) {
307 err = "vma";
308 goto loser;
309 } /* on error */
310
311 if (bfd_set_section_alignment(obfd,
312 osection,
313 bfd_section_alignment(ibfd, isection))
314 == false) {
315 err = "alignment";
316 goto loser;
317 } /* on error */
318
319 if (!bfd_set_section_flags(obfd, osection,
320 bfd_get_section_flags(ibfd, isection))) {
321 err = "flags";
322 goto loser;
323 }
324
325 /* All went well */
326 return;
327
328loser:
329 fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
330 program_name,
331 bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
332 err, bfd_errmsg(bfd_error));
333 exit(1);
334} /* setup_sections() */
335
b473cf19
SC
336/*
337Copy all the section related data from an input section
338to an output section
339
340If stripping then don't copy any relocation info
341*/
c074abee
DHW
342static void
343copy_sections(ibfd, isection, obfd)
344 bfd *ibfd;
345 sec_ptr isection;
346 bfd *obfd;
347{
c074abee 348
b473cf19
SC
349 arelent **relpp;
350 int relcount;
351 sec_ptr osection;
fc5d6074 352 bfd_size_type size;
b473cf19
SC
353 osection = bfd_get_section_by_name(obfd,
354 bfd_section_name(ibfd, isection));
355
d20f480f 356 size = bfd_get_section_size_before_reloc(isection);
b473cf19
SC
357
358 if (size == 0)
359 return;
360
5a77e916 361 if (is_strip || bfd_get_reloc_upper_bound(ibfd, isection) == 0)
b473cf19
SC
362 {
363 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
364 }
365 else
366 {
5a77e916 367 relpp = (arelent **) xmalloc(bfd_get_reloc_upper_bound(ibfd, isection));
b473cf19
SC
368 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
369 bfd_set_reloc(obfd, osection, relpp, relcount);
370 }
c074abee 371
d20f480f
SC
372 isection->_cooked_size = isection->_raw_size;
373 isection->reloc_done =true;
374
c074abee 375
b473cf19
SC
376 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
377 {
fc5d6074 378 PTR memhunk = (PTR) xmalloc((unsigned)size);
c074abee 379
fc5d6074 380 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
b473cf19 381 bfd_fatal(bfd_get_filename(ibfd));
c074abee 382
fc5d6074 383 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
b473cf19
SC
384 bfd_fatal(bfd_get_filename(obfd));
385 free(memhunk);
c074abee 386 }
b473cf19
SC
387
388
c074abee
DHW
389}
390int
391main(argc, argv)
392 int argc;
393 char *argv[];
394{
617cd571 395 int i;
a51d4b41 396 int show_version = 0;
617cd571
SC
397 program_name = argv[0];
398
21214e8e
SC
399 bfd_init();
400
782d7963
PB
401 if (is_strip < 0) {
402 i = strlen (program_name);
403 is_strip = (i >= 5 && strcmp(program_name+i-5,"strip"));
617cd571
SC
404 }
405
a51d4b41
PB
406 if (is_strip)
407 {
408 for (i = 1; i < argc; i++)
409 {
410 if (argv[i][0] != '-')
411 break;
412 if (argv[i][1] == '-') {
413 i++;
414 break;
415 }
416 switch (argv[i][1]) {
417 case 'V':
418 show_version = true;
419 break;
420 case 'v':
421 verbose = true;
422 show_version = true;
423 break;
7c926404
KR
424
425 /* undocumented for now */
426 case 'd':
427 i++;
428 output_target = argv[i];
429 break;
a51d4b41
PB
430 default:
431 strip_usage();
432 }
433 }
434 if (show_version)
435 printf ("%s version %s\n", program_name, program_version);
436 for ( ; i < argc; i++) {
437 char *tmpname = make_tempname(argv[i]);
438 copy_file(argv[i], tmpname);
439 rename(tmpname, argv[i]);
440 }
441 return 0;
442 }
443
617cd571
SC
444 for (i = 1; i < argc; i++)
445 {
446 if (argv[i][0] == '-') {
447 switch (argv[i][1]) {
5c670bc1
RS
448 case 'V':
449 show_version = true;
450 break;
617cd571 451 case 'v':
a51d4b41 452 show_version = true;
617cd571
SC
453 verbose = true;
454 break;
455 case 'b':
456 i++;
457 input_target = output_target = argv[i];
458 break;
459 case 'S':
782d7963 460 is_strip = 1;
617cd571
SC
461 break;
462 case 's':
463 i++;
464 input_target = argv[i];
465 break;
466 case 'd':
467 i++;
468 output_target = argv[i];
469 break;
470 default:
471 usage();
c074abee 472 }
617cd571
SC
473 }
474 else {
475 if (input_filename) {
476 output_filename = argv[i];
c074abee 477 }
617cd571
SC
478 else {
479 input_filename = argv[i];
c074abee 480 }
617cd571
SC
481 }
482 }
483
5c670bc1
RS
484 if (show_version)
485 printf ("%s version %s\n", program_name, program_version);
486
617cd571
SC
487 if (input_filename == (char *) NULL)
488 usage();
489
490 if (output_target == (char *) NULL)
491 output_target = input_target;
c074abee 492
617cd571
SC
493 /* If there is no destination file then create a temp and rename
494 the result into the input */
c074abee 495
617cd571
SC
496 if (output_filename == (char *)NULL) {
497 char * tmpname = make_tempname(input_filename);
498 copy_file(input_filename, tmpname);
499 output_filename = input_filename;
500 rename(tmpname, input_filename);
501 }
502 else {
503 copy_file(input_filename, output_filename);
504 }
782d7963 505 return 0;
c074abee 506}
This page took 0.070456 seconds and 4 git commands to generate.