Oops.
[deliverable/binutils-gdb.git] / binutils / copy.c
CommitLineData
fc5d6074
SC
1/*** copy.c -- copy object file from input to output, optionally
2 massaging it */
7ed4093a 3#include <sysdep.h>
c074abee
DHW
4#include "bfd.h"
5
fc5d6074 6
c074abee
DHW
7asymbol **sympp;
8char *input_target = NULL;
9char *output_target = NULL;
10char *input_filename = NULL;
11char *output_filename = NULL;
12
13
14static void setup_sections();
15static void copy_sections();
16static boolean strip;
17static boolean verbose;
18
19/* IMPORTS */
20extern char *program_name;
21extern char *xmalloc();
22
23static
24void
25usage()
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 */
35static
36char *
37make_tempname(filename)
38char *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*/
66static void
67mangle_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
78static
79void
80copy_object(ibfd, obfd)
81bfd *ibfd;
82bfd *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
23565c68
SC
97 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
98 ||
c074abee 99 (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
23565c68
SC
100 (HAS_LINENO | HAS_DEBUG |
101 HAS_RELOC | HAS_SYMS | D_PAGED |
102 HAS_LOCALS))) == false)) {
103 bfd_fatal(bfd_get_filename(ibfd));
104 }
c074abee
DHW
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}
131static
132char *
133cat(a,b,c)
134char *a;
135char *b;
136char *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
146static void
147copy_archive(ibfd, obfd)
148bfd *ibfd;
149bfd *obfd;
150{
1417a2cd 151 bfd **ptr = &obfd->archive_head;
c074abee
DHW
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 */
ad19c0a2 155 char *dir = cat("./#",make_tempname(""),"cd");
c074abee
DHW
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);
ad19c0a2 161 ibfd->archive_head = this_element;
c074abee
DHW
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);
ad19c0a2 167
c074abee
DHW
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
1417a2cd 185 ptr = &output_bfd->next;
ad19c0a2
DHW
186 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
187 this_element = this_element->next;
c074abee
DHW
188
189 }
190 *ptr = (bfd *)NULL;
191
192 if (!bfd_close(obfd))
193 bfd_fatal(output_filename);
194
ad19c0a2
DHW
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. */
c074abee
DHW
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 }
ad19c0a2 204 rmdir(dir);
c074abee
DHW
205 if (!bfd_close(ibfd))
206 bfd_fatal(input_filename);
207
208}
209
210static
617cd571 211void
c074abee
DHW
212copy_file(input_filename, output_filename)
213 char *input_filename;
214 char *output_filename;
215{
617cd571 216 bfd *ibfd;
c074abee 217
617cd571
SC
218 ibfd = bfd_openr(input_filename, input_target);
219 if (ibfd == NULL)
220 bfd_fatal(input_filename);
c074abee 221
617cd571
SC
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);
c074abee 226
617cd571 227 copy_object(ibfd, obfd);
c074abee 228
617cd571
SC
229 if (!bfd_close(obfd))
230 bfd_fatal(output_filename);
c074abee 231
617cd571
SC
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 }
c074abee
DHW
241}
242
243
244
245/** Actually do the work */
246static void
247setup_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
292loser:
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
b473cf19
SC
300/*
301Copy all the section related data from an input section
302to an output section
303
304If stripping then don't copy any relocation info
305*/
c074abee
DHW
306static void
307copy_sections(ibfd, isection, obfd)
308 bfd *ibfd;
309 sec_ptr isection;
310 bfd *obfd;
311{
c074abee 312
b473cf19
SC
313 arelent **relpp;
314 int relcount;
315 sec_ptr osection;
fc5d6074 316 bfd_size_type size;
b473cf19
SC
317 osection = bfd_get_section_by_name(obfd,
318 bfd_section_name(ibfd, isection));
319
fc5d6074 320 size = isection->size;
b473cf19
SC
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 }
c074abee 335
c074abee 336
b473cf19
SC
337 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
338 {
fc5d6074 339 PTR memhunk = (PTR) xmalloc((unsigned)size);
c074abee 340
fc5d6074 341 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
b473cf19 342 bfd_fatal(bfd_get_filename(ibfd));
c074abee 343
fc5d6074 344 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
b473cf19
SC
345 bfd_fatal(bfd_get_filename(obfd));
346 free(memhunk);
c074abee 347 }
b473cf19
SC
348
349
c074abee
DHW
350}
351int
352main(argc, argv)
353 int argc;
354 char *argv[];
355{
617cd571
SC
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();
c074abee 388 }
617cd571
SC
389 }
390 else {
391 if (input_filename) {
392 output_filename = argv[i];
c074abee 393 }
617cd571
SC
394 else {
395 input_filename = argv[i];
c074abee 396 }
617cd571
SC
397 }
398 }
399
400 if (input_filename == (char *) NULL)
401 usage();
402
403 if (output_target == (char *) NULL)
404 output_target = input_target;
c074abee 405
617cd571
SC
406 /* If there is no destination file then create a temp and rename
407 the result into the input */
c074abee 408
617cd571
SC
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 }
c074abee
DHW
418 return 1;
419}
This page took 0.041912 seconds and 4 git commands to generate.