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