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