]> Git Repo - binutils.git/blob - binutils/copy.c
Fix =&'s in copy.c
[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(""),"cd");
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     ibfd->archive_head = this_element;
158     while (this_element != (bfd *)NULL) {
159
160         /* Create an output file for this member */
161         char *output_name = cat(dir, "/",this_element->filename);
162         bfd *output_bfd = bfd_openw(output_name, output_target);
163
164         if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
165             bfd_fatal(output_filename);
166
167         if (output_bfd == (bfd *)NULL) {
168             bfd_fatal(output_name);
169         }
170         if (bfd_check_format(this_element, bfd_object) == true) {
171             copy_object(this_element, output_bfd);
172         }
173
174         bfd_close(output_bfd);
175         /* Now open the newly output file and attatch to our list */
176         output_bfd = bfd_openr(output_name, output_target);
177         /* Mark it for deletion */
178
179         *ptr = output_bfd;
180
181         ptr = &output_bfd->next;
182         this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
183         this_element = this_element->next;
184
185     }
186     *ptr = (bfd *)NULL;
187
188     if (!bfd_close(obfd))
189         bfd_fatal(output_filename);
190
191     /* Now delete all the files that we opened.
192        Construct their names again, unfortunately, but so what;
193        we're about to exit anyway. */
194     for (this_element = ibfd->archive_head;
195          this_element != (bfd *)NULL;
196          this_element = this_element->next) 
197         {
198         unlink(cat(dir,"/",this_element->filename));
199     }
200     rmdir(dir);
201     if (!bfd_close(ibfd))
202         bfd_fatal(input_filename);
203
204 }
205
206 static
207 void
208 copy_file(input_filename, output_filename)
209     char           *input_filename;
210     char           *output_filename;
211 {
212   bfd            *ibfd;
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     copy_archive(ibfd, obfd);
236   }
237 }
238
239
240
241 /** Actually do the work */
242 static void
243 setup_sections(ibfd, isection, obfd)
244     bfd            *ibfd;
245     sec_ptr         isection;
246     bfd            *obfd;
247 {
248     sec_ptr         osection;
249     char           *err;
250     osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
251     if (osection == NULL) {
252         err = "making";
253         goto loser;
254     }
255
256     if (!bfd_set_section_size(obfd,
257                               osection,
258                               bfd_section_size(ibfd, isection))) {
259         err = "size";
260         goto loser;
261     }
262
263     if (bfd_set_section_vma(obfd,
264                             osection,
265                             bfd_section_vma(ibfd, isection))
266         == false) {
267         err = "vma";
268         goto loser;
269     }                           /* on error */
270
271     if (bfd_set_section_alignment(obfd,
272                                   osection,
273                                   bfd_section_alignment(ibfd, isection))
274         == false) {
275         err = "alignment";
276         goto loser;
277     }                           /* on error */
278
279     if (!bfd_set_section_flags(obfd, osection,
280                                bfd_get_section_flags(ibfd, isection))) {
281         err = "flags";
282         goto loser;
283     }
284
285     /* All went well */
286     return;
287
288 loser:
289     fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
290             program_name,
291             bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
292             err, bfd_errmsg(bfd_error));
293     exit(1);
294 }                               /* setup_sections() */
295
296 /*
297 Copy all the section related data from an input section
298 to an output section
299
300 If stripping then don't copy any relocation info
301 */
302 static void
303 copy_sections(ibfd, isection, obfd)
304     bfd            *ibfd;
305     sec_ptr         isection;
306     bfd            *obfd;
307 {
308
309   arelent       **relpp;
310   int             relcount;
311   sec_ptr         osection;
312   unsigned long   size;
313   osection = bfd_get_section_by_name(obfd,
314                                      bfd_section_name(ibfd, isection));
315
316   size = bfd_section_size(ibfd, isection);
317
318   if (size == 0)
319     return;
320
321   if (strip == true || get_reloc_upper_bound(ibfd, isection) == 0) 
322     {
323       bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
324     } 
325   else 
326     {
327       relpp = (arelent **) xmalloc(get_reloc_upper_bound(ibfd, isection));
328       relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
329       bfd_set_reloc(obfd, osection, relpp, relcount);
330     }
331
332
333   if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS) 
334     {
335       unsigned char *memhunk = (unsigned char *) xmalloc(size);
336
337       if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size))
338         bfd_fatal(bfd_get_filename(ibfd));
339
340       if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
341         bfd_fatal(bfd_get_filename(obfd));
342       free(memhunk);
343     }
344
345
346 }
347 int
348 main(argc, argv)
349     int             argc;
350     char           *argv[];
351 {
352   int             i;
353
354   program_name = argv[0];
355
356   if (strcmp(program_name,"strip") == 0) {
357     strip = true;
358   }
359
360   for (i = 1; i < argc; i++) 
361     {
362       if (argv[i][0] == '-') {
363         switch (argv[i][1]) {
364         case 'v':
365           verbose = true;
366           break;
367         case 'b':
368           i++;
369           input_target = output_target = argv[i];
370           break;
371         case 'S':
372           strip = true;
373           break;
374         case 's':
375           i++;
376           input_target = argv[i];
377           break;
378         case 'd':
379           i++;
380           output_target = argv[i];
381           break;
382         default:
383           usage();
384         }
385       }
386       else {
387         if (input_filename) {
388           output_filename = argv[i];
389         }
390         else {
391           input_filename = argv[i];
392         }
393       }
394     }
395
396   if (input_filename == (char *) NULL)
397     usage();
398
399   if (output_target == (char *) NULL)
400     output_target = input_target;
401
402   /* If there is no  destination file then create a temp and rename
403      the result into the input */
404
405   if (output_filename == (char *)NULL) {
406     char *      tmpname = make_tempname(input_filename);
407     copy_file(input_filename, tmpname);
408     output_filename = input_filename;
409     rename(tmpname, input_filename);
410   }
411   else {
412     copy_file(input_filename, output_filename);
413   }
414     return 1;
415 }
This page took 0.044117 seconds and 4 git commands to generate.