Support for accessing arbitrary MIPS stack frames in memory.
[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;
424 default:
425 strip_usage();
426 }
427 }
428 if (show_version)
429 printf ("%s version %s\n", program_name, program_version);
430 for ( ; i < argc; i++) {
431 char *tmpname = make_tempname(argv[i]);
432 copy_file(argv[i], tmpname);
433 rename(tmpname, argv[i]);
434 }
435 return 0;
436 }
437
617cd571
SC
438 for (i = 1; i < argc; i++)
439 {
440 if (argv[i][0] == '-') {
441 switch (argv[i][1]) {
5c670bc1
RS
442 case 'V':
443 show_version = true;
444 break;
617cd571 445 case 'v':
a51d4b41 446 show_version = true;
617cd571
SC
447 verbose = true;
448 break;
449 case 'b':
450 i++;
451 input_target = output_target = argv[i];
452 break;
453 case 'S':
782d7963 454 is_strip = 1;
617cd571
SC
455 break;
456 case 's':
457 i++;
458 input_target = argv[i];
459 break;
460 case 'd':
461 i++;
462 output_target = argv[i];
463 break;
464 default:
465 usage();
c074abee 466 }
617cd571
SC
467 }
468 else {
469 if (input_filename) {
470 output_filename = argv[i];
c074abee 471 }
617cd571
SC
472 else {
473 input_filename = argv[i];
c074abee 474 }
617cd571
SC
475 }
476 }
477
5c670bc1
RS
478 if (show_version)
479 printf ("%s version %s\n", program_name, program_version);
480
617cd571
SC
481 if (input_filename == (char *) NULL)
482 usage();
483
484 if (output_target == (char *) NULL)
485 output_target = input_target;
c074abee 486
617cd571
SC
487 /* If there is no destination file then create a temp and rename
488 the result into the input */
c074abee 489
617cd571
SC
490 if (output_filename == (char *)NULL) {
491 char * tmpname = make_tempname(input_filename);
492 copy_file(input_filename, tmpname);
493 output_filename = input_filename;
494 rename(tmpname, input_filename);
495 }
496 else {
497 copy_file(input_filename, output_filename);
498 }
782d7963 499 return 0;
c074abee 500}
This page took 0.069509 seconds and 4 git commands to generate.