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