]> Git Repo - binutils.git/blob - binutils/copy.c
Use the new architecture functions
[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_arch(ibfd),
108                            bfd_get_mach(ibfd))) {
109         fprintf(stderr, "Output file cannot represent architecture %s\n",
110                 bfd_printable_arch_mach(bfd_get_arch(ibfd),
111                                         bfd_get_mach(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   bfd_init();
361
362   if (strcmp(program_name,"strip") == 0) {
363     strip = true;
364   }
365
366   for (i = 1; i < argc; i++) 
367     {
368       if (argv[i][0] == '-') {
369         switch (argv[i][1]) {
370         case 'v':
371           verbose = true;
372           break;
373         case 'b':
374           i++;
375           input_target = output_target = argv[i];
376           break;
377         case 'S':
378           strip = true;
379           break;
380         case 's':
381           i++;
382           input_target = argv[i];
383           break;
384         case 'd':
385           i++;
386           output_target = argv[i];
387           break;
388         default:
389           usage();
390         }
391       }
392       else {
393         if (input_filename) {
394           output_filename = argv[i];
395         }
396         else {
397           input_filename = argv[i];
398         }
399       }
400     }
401
402   if (input_filename == (char *) NULL)
403     usage();
404
405   if (output_target == (char *) NULL)
406     output_target = input_target;
407
408   /* If there is no  destination file then create a temp and rename
409      the result into the input */
410
411   if (output_filename == (char *)NULL) {
412     char *      tmpname = make_tempname(input_filename);
413     copy_file(input_filename, tmpname);
414     output_filename = input_filename;
415     rename(tmpname, input_filename);
416   }
417   else {
418     copy_file(input_filename, output_filename);
419   }
420     return 1;
421 }
This page took 0.053562 seconds and 4 git commands to generate.