*** empty log message ***
[deliverable/binutils-gdb.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.036933 seconds and 4 git commands to generate.