* m68k-pinsn.c (print_insn_arg): fixed so that -ve branch
[deliverable/binutils-gdb.git] / binutils / copy.c
1 /* copy.c -- copy object file from input to output, optionally massaging it.
2 Copyright (C) 1991 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
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.
10
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.
15
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. */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "bucomm.h"
23
24 asymbol **sympp;
25 char *input_target = NULL;
26 char *output_target = NULL;
27 char *input_filename = NULL;
28 char *output_filename = NULL;
29
30
31 static void setup_sections();
32 static void copy_sections();
33 static boolean verbose;
34
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. */
38 extern int is_strip;
39
40 /* IMPORTS */
41 extern char *program_name;
42
43
44 static
45 void
46 usage()
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 */
56 static
57 char *
58 make_tempname(filename)
59 char *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 */
87 static void
88 mangle_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
99 static
100 void
101 copy_object(ibfd, obfd)
102 bfd *ibfd;
103 bfd *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
118 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
119 ||
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));
125 }
126
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)));
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
142 bfd_set_symtab(obfd, sympp, is_strip ? 0 : symcount);
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 }
152 static
153 char *
154 cat(a,b,c)
155 char *a;
156 char *b;
157 char *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
167 static void
168 copy_archive(ibfd, obfd)
169 bfd *ibfd;
170 bfd *obfd;
171 {
172 bfd **ptr = &obfd->archive_head;
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 */
176 char *dir = cat("./#",make_tempname(""),"cd");
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);
182 ibfd->archive_head = this_element;
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);
188
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
206 ptr = &output_bfd->next;
207 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
208 this_element = this_element->next;
209
210 }
211 *ptr = (bfd *)NULL;
212
213 if (!bfd_close(obfd))
214 bfd_fatal(output_filename);
215
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)
222 {
223 unlink(cat(dir,"/",this_element->filename));
224 }
225 rmdir(dir);
226 if (!bfd_close(ibfd))
227 bfd_fatal(input_filename);
228
229 }
230
231 static
232 void
233 copy_file(input_filename, output_filename)
234 char *input_filename;
235 char *output_filename;
236 {
237 bfd *ibfd;
238
239 ibfd = bfd_openr(input_filename, input_target);
240 if (ibfd == NULL)
241 bfd_fatal(input_filename);
242
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);
247
248 copy_object(ibfd, obfd);
249
250 if (ibfd->flags & EXEC_P)
251 obfd->flags |= EXEC_P;
252 if (!bfd_close(obfd))
253 bfd_fatal(output_filename);
254
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 }
264 }
265
266
267
268 /** Actually do the work */
269 static void
270 setup_sections(ibfd, isection, obfd)
271 bfd *ibfd;
272 sec_ptr isection;
273 bfd *obfd;
274 {
275 sec_ptr osection;
276 char *err;
277
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) {
282 err = "making";
283 goto loser;
284 }
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
319 loser:
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
327 /*
328 Copy all the section related data from an input section
329 to an output section
330
331 If stripping then don't copy any relocation info
332 */
333 static void
334 copy_sections(ibfd, isection, obfd)
335 bfd *ibfd;
336 sec_ptr isection;
337 bfd *obfd;
338 {
339
340 arelent **relpp;
341 int relcount;
342 sec_ptr osection;
343 bfd_size_type size;
344 osection = bfd_get_section_by_name(obfd,
345 bfd_section_name(ibfd, isection));
346
347 size = bfd_get_section_size_before_reloc(isection);
348
349 if (size == 0)
350 return;
351
352 if (is_strip || bfd_get_reloc_upper_bound(ibfd, isection) == 0)
353 {
354 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
355 }
356 else
357 {
358 relpp = (arelent **) xmalloc(bfd_get_reloc_upper_bound(ibfd, isection));
359 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
360 bfd_set_reloc(obfd, osection, relpp, relcount);
361 }
362
363 isection->_cooked_size = isection->_raw_size;
364 isection->reloc_done =true;
365
366
367 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
368 {
369 PTR memhunk = (PTR) xmalloc((unsigned)size);
370
371 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
372 bfd_fatal(bfd_get_filename(ibfd));
373
374 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
375 bfd_fatal(bfd_get_filename(obfd));
376 free(memhunk);
377 }
378
379
380 }
381 int
382 main(argc, argv)
383 int argc;
384 char *argv[];
385 {
386 int i;
387
388 program_name = argv[0];
389
390 bfd_init();
391
392 if (is_strip < 0) {
393 i = strlen (program_name);
394 is_strip = (i >= 5 && strcmp(program_name+i-5,"strip"));
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':
409 is_strip = 1;
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();
421 }
422 }
423 else {
424 if (input_filename) {
425 output_filename = argv[i];
426 }
427 else {
428 input_filename = argv[i];
429 }
430 }
431 }
432
433 if (input_filename == (char *) NULL)
434 usage();
435
436 if (output_target == (char *) NULL)
437 output_target = input_target;
438
439 /* If there is no destination file then create a temp and rename
440 the result into the input */
441
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 }
451 return 0;
452 }
This page took 0.057735 seconds and 4 git commands to generate.