]> Git Repo - binutils.git/blob - binutils/copy.c
Back from Intel with Steve
[binutils.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 boolean
207 copy_file(input_filename, output_filename)
208     char           *input_filename;
209     char           *output_filename;
210 {
211     bfd            *ibfd;
212
213
214     ibfd = bfd_openr(input_filename, input_target);
215     if (ibfd == NULL)
216         bfd_fatal(input_filename);
217
218     if (bfd_check_format(ibfd, bfd_object)) {
219         bfd * obfd = bfd_openw(output_filename, output_target);
220         if (obfd == NULL)
221             bfd_fatal(output_filename);
222
223         copy_object(ibfd, obfd);
224
225         if (!bfd_close(obfd))
226             bfd_fatal(output_filename);
227
228         if (!bfd_close(ibfd))
229             bfd_fatal(input_filename);
230     }
231     else     if (bfd_check_format(ibfd, bfd_archive)) {
232         bfd * obfd = bfd_openw(output_filename, output_target);
233         if (obfd == NULL)
234             bfd_fatal(output_filename);
235
236         copy_archive(ibfd, obfd);
237     }
238 }
239
240
241
242 /** Actually do the work */
243 static void
244 setup_sections(ibfd, isection, obfd)
245     bfd            *ibfd;
246     sec_ptr         isection;
247     bfd            *obfd;
248 {
249     sec_ptr         osection;
250     char           *err;
251     osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
252     if (osection == NULL) {
253         err = "making";
254         goto loser;
255     }
256
257     if (!bfd_set_section_size(obfd,
258                               osection,
259                               bfd_section_size(ibfd, isection))) {
260         err = "size";
261         goto loser;
262     }
263
264     if (bfd_set_section_vma(obfd,
265                             osection,
266                             bfd_section_vma(ibfd, isection))
267         == false) {
268         err = "vma";
269         goto loser;
270     }                           /* on error */
271
272     if (bfd_set_section_alignment(obfd,
273                                   osection,
274                                   bfd_section_alignment(ibfd, isection))
275         == false) {
276         err = "alignment";
277         goto loser;
278     }                           /* on error */
279
280     if (!bfd_set_section_flags(obfd, osection,
281                                bfd_get_section_flags(ibfd, isection))) {
282         err = "flags";
283         goto loser;
284     }
285
286     /* All went well */
287     return;
288
289 loser:
290     fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
291             program_name,
292             bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
293             err, bfd_errmsg(bfd_error));
294     exit(1);
295 }                               /* setup_sections() */
296
297 static void
298 copy_sections(ibfd, isection, obfd)
299     bfd            *ibfd;
300     sec_ptr         isection;
301     bfd            *obfd;
302 {
303     static unsigned char *memhunk = NULL;
304     arelent       **relpp;
305     int             relcount;
306     sec_ptr         osection;
307     unsigned long   size;
308     osection = bfd_get_section_by_name(obfd,
309                                        bfd_section_name(ibfd, isection));
310
311     size = bfd_section_size(ibfd, isection);
312
313     if (size == 0)
314         return;
315
316     if (get_reloc_upper_bound(ibfd, isection) != 0) {
317         relpp = (arelent **) xmalloc(get_reloc_upper_bound(ibfd, isection));
318
319         relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
320
321         bfd_set_reloc(obfd, osection, relpp, relcount);
322     }
323
324     if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS) {
325         memhunk = (unsigned char *) xmalloc(size);
326         /* now we have enough memory, just do it: */
327         if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size))
328             bfd_fatal(bfd_get_filename(ibfd));
329
330         if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
331             bfd_fatal(bfd_get_filename(obfd));
332     }                           /* only if the section has contents. */
333
334     free(memhunk);
335 }
336 int
337 main(argc, argv)
338     int             argc;
339     char           *argv[];
340 {
341     int             i;
342
343
344     program_name = argv[0];
345
346     if (strcmp(program_name,"strip") == 0) {
347         strip = true;
348     }
349
350     for (i = 1; i < argc; i++) 
351         {
352             if (argv[i][0] == '-') {
353                 switch (argv[i][1]) {
354             case 'v':
355                     verbose = true;
356                     break;
357             case 'b':
358                     i++;
359                     input_target = output_target = argv[i];
360                     break;
361             case 'S':
362                     strip = true;
363                     break;
364             case 's':
365                     i++;
366                     input_target = argv[i];
367                     break;
368             case 'd':
369                     i++;
370                     output_target = argv[i];
371                     break;
372             default:
373                     usage();
374                 }
375             }
376             else {
377                 if (input_filename) {
378                     output_filename = argv[i];
379                 }
380                 else {
381                     input_filename = argv[i];
382                 }
383             }
384         }
385
386     if (input_filename == (char *) NULL)
387         usage();
388
389     if (output_target == (char *) NULL)
390         output_target = input_target;
391
392     /* If there is no  destination file then create a temp and rename
393        the result into the input */
394
395     if (output_filename == (char *)NULL) {
396         char *  tmpname = make_tempname(input_filename);
397         if (copy_file(input_filename, tmpname)) {
398             output_filename = input_filename;
399             rename(tmpname, input_filename);
400             return 0;
401         }
402     }
403     else if (copy_file(input_filename, output_filename)) 
404         {
405             return 0;
406         }
407
408
409     return 1;
410 }
This page took 0.047449 seconds and 4 git commands to generate.