]> Git Repo - binutils.git/blame - binutils/copy.c
*** empty log message ***
[binutils.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
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}
127static
128char *
129cat(a,b,c)
130char *a;
131char *b;
132char *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
142static void
143copy_archive(ibfd, obfd)
144bfd *ibfd;
145bfd *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 */
b6fc45ca 151 char *dir = cat("./",make_tempname(""),"copy-dir");
c074abee
DHW
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
205static
617cd571 206void
c074abee
DHW
207copy_file(input_filename, output_filename)
208 char *input_filename;
209 char *output_filename;
210{
617cd571 211 bfd *ibfd;
c074abee 212
617cd571
SC
213 ibfd = bfd_openr(input_filename, input_target);
214 if (ibfd == NULL)
215 bfd_fatal(input_filename);
c074abee 216
617cd571
SC
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);
c074abee 221
617cd571 222 copy_object(ibfd, obfd);
c074abee 223
617cd571
SC
224 if (!bfd_close(obfd))
225 bfd_fatal(output_filename);
c074abee 226
617cd571
SC
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 }
c074abee
DHW
236}
237
238
239
240/** Actually do the work */
241static void
242setup_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
287loser:
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
b473cf19
SC
295/*
296Copy all the section related data from an input section
297to an output section
298
299If stripping then don't copy any relocation info
300*/
c074abee
DHW
301static void
302copy_sections(ibfd, isection, obfd)
303 bfd *ibfd;
304 sec_ptr isection;
305 bfd *obfd;
306{
c074abee 307
b473cf19
SC
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 }
c074abee 330
c074abee 331
b473cf19
SC
332 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
333 {
334 unsigned char *memhunk = (unsigned char *) xmalloc(size);
c074abee 335
b473cf19
SC
336 if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size))
337 bfd_fatal(bfd_get_filename(ibfd));
c074abee 338
b473cf19
SC
339 if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
340 bfd_fatal(bfd_get_filename(obfd));
341 free(memhunk);
c074abee 342 }
b473cf19
SC
343
344
c074abee
DHW
345}
346int
347main(argc, argv)
348 int argc;
349 char *argv[];
350{
617cd571
SC
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();
c074abee 383 }
617cd571
SC
384 }
385 else {
386 if (input_filename) {
387 output_filename = argv[i];
c074abee 388 }
617cd571
SC
389 else {
390 input_filename = argv[i];
c074abee 391 }
617cd571
SC
392 }
393 }
394
395 if (input_filename == (char *) NULL)
396 usage();
397
398 if (output_target == (char *) NULL)
399 output_target = input_target;
c074abee 400
617cd571
SC
401 /* If there is no destination file then create a temp and rename
402 the result into the input */
c074abee 403
617cd571
SC
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 }
c074abee
DHW
413 return 1;
414}
This page took 0.064494 seconds and 4 git commands to generate.