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