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