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