]> Git Repo - binutils.git/blame - binutils/copy.c
Restructure configuration scheme for bfd, binutils, ld.
[binutils.git] / binutils / copy.c
CommitLineData
fc5d6074
SC
1/*** copy.c -- copy object file from input to output, optionally
2 massaging it */
c074abee 3#include "bfd.h"
2a5f387b 4#include "sysdep.h"
fc5d6074 5
c074abee
DHW
6asymbol **sympp;
7char *input_target = NULL;
8char *output_target = NULL;
9char *input_filename = NULL;
10char *output_filename = NULL;
11
12
13static void setup_sections();
14static void copy_sections();
15static boolean strip;
16static boolean verbose;
17
18/* IMPORTS */
19extern char *program_name;
20extern char *xmalloc();
21
22static
23void
24usage()
25{
26 fprintf(stderr,
27 "Usage %s [-S][-s srcfmt] [-d dtfmt] [-b bothfmts] infile [outfile]\n",
28 program_name);
29 exit(1);
30}
31
32
33/* Create a temp file in the same directory as supplied */
34static
35char *
36make_tempname(filename)
37char *filename;
38{
39 static char template[] = "stXXXXXX";
40 char *tmpname;
41 char * slash = strrchr( filename, '/' );
42 if (slash != (char *)NULL){
43 *slash = 0;
44 tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
45 strcpy(tmpname, filename);
46 strcat(tmpname, "/" );
47 strcat(tmpname, template);
48 mktemp(tmpname );
49 *slash = '/';
50 } else {
51 tmpname = xmalloc(sizeof(template));
52 strcpy(tmpname, template);
53 mktemp(tmpname);
54 }
55 return tmpname;
56}
57
58/*
59 All the symbols have been read in and point to their owning input section.
60 They have been relocated to that they are all relative to the base of
61 their owning section. On the way out, all the symbols will be relocated to
62 their new location in the output file, through some complex sums.
63
64*/
65static void
66mangle_sections(ibfd, obfd)
67 bfd *ibfd;
68 bfd *obfd;
69{
70 asection *current = ibfd->sections;
71 for (; current != NULL; current = current->next) {
72 current->output_section = bfd_get_section_by_name(obfd, current->name);
73 current->output_offset = 0;
74 }
75}
76
77static
78void
79copy_object(ibfd, obfd)
80bfd *ibfd;
81bfd *obfd;
82{
83
84 unsigned int symcount;
85
86
87 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
88 bfd_fatal(output_filename);
89
90
91 if (verbose)
92 printf("copy from %s(%s) to %s(%s)\n",
93 ibfd->filename, ibfd->xvec->name,
94 obfd->filename, obfd->xvec->name);
95
23565c68
SC
96 if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
97 ||
c074abee 98 (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
23565c68
SC
99 (HAS_LINENO | HAS_DEBUG |
100 HAS_RELOC | HAS_SYMS | D_PAGED |
101 HAS_LOCALS))) == false)) {
102 bfd_fatal(bfd_get_filename(ibfd));
103 }
c074abee
DHW
104
105 /* Copy architecture of input file to output file */
21214e8e
SC
106 if (!bfd_set_arch_mach(obfd, bfd_get_arch(ibfd),
107 bfd_get_mach(ibfd))) {
c074abee 108 fprintf(stderr, "Output file cannot represent architecture %s\n",
21214e8e
SC
109 bfd_printable_arch_mach(bfd_get_arch(ibfd),
110 bfd_get_mach(ibfd)));
c074abee
DHW
111 }
112 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
113 {
114 bfd_fatal(ibfd->filename);
115 }
116
117 sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
118 symcount = bfd_canonicalize_symtab(ibfd, sympp);
119
120 bfd_set_symtab(obfd, sympp, strip == true ? 0 : symcount);
121
122 /*
123 bfd mandates that all output sections be created and sizes set before
124 any output is done. Thus, we traverse all sections twice.
125 */
126 bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
127 bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
128 mangle_sections(ibfd, obfd);
129}
130static
131char *
132cat(a,b,c)
133char *a;
134char *b;
135char *c;
136{
137 int size = strlen(a) + strlen(b) + strlen(c);
138 char *r = xmalloc(size+1);
139 strcpy(r,a);
140 strcat(r,b);
141 strcat(r,c);
142 return r;
143}
144
145static void
146copy_archive(ibfd, obfd)
147bfd *ibfd;
148bfd *obfd;
149{
1417a2cd 150 bfd **ptr = &obfd->archive_head;
c074abee
DHW
151 bfd *this_element;
152 /* Read each archive element in turn from the input, copy the
153 contents to a temp file, and keep the temp file handle */
ad19c0a2 154 char *dir = cat("./#",make_tempname(""),"cd");
c074abee
DHW
155
156 /* Make a temp directory to hold the contents */
157 mkdir(dir,0777);
158 obfd->has_armap = ibfd->has_armap;
159 this_element = bfd_openr_next_archived_file(ibfd, NULL);
ad19c0a2 160 ibfd->archive_head = this_element;
c074abee
DHW
161 while (this_element != (bfd *)NULL) {
162
163 /* Create an output file for this member */
164 char *output_name = cat(dir, "/",this_element->filename);
165 bfd *output_bfd = bfd_openw(output_name, output_target);
ad19c0a2 166
c074abee
DHW
167 if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
168 bfd_fatal(output_filename);
169
170 if (output_bfd == (bfd *)NULL) {
171 bfd_fatal(output_name);
172 }
173 if (bfd_check_format(this_element, bfd_object) == true) {
174 copy_object(this_element, output_bfd);
175 }
176
177 bfd_close(output_bfd);
178 /* Now open the newly output file and attatch to our list */
179 output_bfd = bfd_openr(output_name, output_target);
180 /* Mark it for deletion */
181
182 *ptr = output_bfd;
183
1417a2cd 184 ptr = &output_bfd->next;
ad19c0a2
DHW
185 this_element->next = bfd_openr_next_archived_file(ibfd, this_element);
186 this_element = this_element->next;
c074abee
DHW
187
188 }
189 *ptr = (bfd *)NULL;
190
191 if (!bfd_close(obfd))
192 bfd_fatal(output_filename);
193
ad19c0a2
DHW
194 /* Now delete all the files that we opened.
195 Construct their names again, unfortunately, but so what;
196 we're about to exit anyway. */
c074abee
DHW
197 for (this_element = ibfd->archive_head;
198 this_element != (bfd *)NULL;
199 this_element = this_element->next)
200 {
201 unlink(cat(dir,"/",this_element->filename));
202 }
ad19c0a2 203 rmdir(dir);
c074abee
DHW
204 if (!bfd_close(ibfd))
205 bfd_fatal(input_filename);
206
207}
208
209static
617cd571 210void
c074abee
DHW
211copy_file(input_filename, output_filename)
212 char *input_filename;
213 char *output_filename;
214{
617cd571 215 bfd *ibfd;
c074abee 216
617cd571
SC
217 ibfd = bfd_openr(input_filename, input_target);
218 if (ibfd == NULL)
219 bfd_fatal(input_filename);
c074abee 220
617cd571
SC
221 if (bfd_check_format(ibfd, bfd_object)) {
222 bfd * obfd = bfd_openw(output_filename, output_target);
223 if (obfd == NULL)
224 bfd_fatal(output_filename);
c074abee 225
617cd571 226 copy_object(ibfd, obfd);
c074abee 227
617cd571
SC
228 if (!bfd_close(obfd))
229 bfd_fatal(output_filename);
c074abee 230
617cd571
SC
231 if (!bfd_close(ibfd))
232 bfd_fatal(input_filename);
233 }
234 else if (bfd_check_format(ibfd, bfd_archive)) {
235 bfd * obfd = bfd_openw(output_filename, output_target);
236 if (obfd == NULL)
237 bfd_fatal(output_filename);
238 copy_archive(ibfd, obfd);
239 }
c074abee
DHW
240}
241
242
243
244/** Actually do the work */
245static void
246setup_sections(ibfd, isection, obfd)
247 bfd *ibfd;
248 sec_ptr isection;
249 bfd *obfd;
250{
251 sec_ptr osection;
252 char *err;
253 osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
254 if (osection == NULL) {
255 err = "making";
256 goto loser;
257 }
258
259 if (!bfd_set_section_size(obfd,
260 osection,
261 bfd_section_size(ibfd, isection))) {
262 err = "size";
263 goto loser;
264 }
265
266 if (bfd_set_section_vma(obfd,
267 osection,
268 bfd_section_vma(ibfd, isection))
269 == false) {
270 err = "vma";
271 goto loser;
272 } /* on error */
273
274 if (bfd_set_section_alignment(obfd,
275 osection,
276 bfd_section_alignment(ibfd, isection))
277 == false) {
278 err = "alignment";
279 goto loser;
280 } /* on error */
281
282 if (!bfd_set_section_flags(obfd, osection,
283 bfd_get_section_flags(ibfd, isection))) {
284 err = "flags";
285 goto loser;
286 }
287
288 /* All went well */
289 return;
290
291loser:
292 fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
293 program_name,
294 bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
295 err, bfd_errmsg(bfd_error));
296 exit(1);
297} /* setup_sections() */
298
b473cf19
SC
299/*
300Copy all the section related data from an input section
301to an output section
302
303If stripping then don't copy any relocation info
304*/
c074abee
DHW
305static void
306copy_sections(ibfd, isection, obfd)
307 bfd *ibfd;
308 sec_ptr isection;
309 bfd *obfd;
310{
c074abee 311
b473cf19
SC
312 arelent **relpp;
313 int relcount;
314 sec_ptr osection;
fc5d6074 315 bfd_size_type size;
b473cf19
SC
316 osection = bfd_get_section_by_name(obfd,
317 bfd_section_name(ibfd, isection));
318
fc5d6074 319 size = isection->size;
b473cf19
SC
320
321 if (size == 0)
322 return;
323
324 if (strip == true || get_reloc_upper_bound(ibfd, isection) == 0)
325 {
326 bfd_set_reloc(obfd, osection, (arelent **)NULL, 0);
327 }
328 else
329 {
330 relpp = (arelent **) xmalloc(get_reloc_upper_bound(ibfd, isection));
331 relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
332 bfd_set_reloc(obfd, osection, relpp, relcount);
333 }
c074abee 334
c074abee 335
b473cf19
SC
336 if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS)
337 {
fc5d6074 338 PTR memhunk = (PTR) xmalloc((unsigned)size);
c074abee 339
fc5d6074 340 if (!bfd_get_section_contents(ibfd, isection, memhunk, (file_ptr) 0, size))
b473cf19 341 bfd_fatal(bfd_get_filename(ibfd));
c074abee 342
fc5d6074 343 if (!bfd_set_section_contents(obfd, osection, memhunk, (file_ptr)0, size))
b473cf19
SC
344 bfd_fatal(bfd_get_filename(obfd));
345 free(memhunk);
c074abee 346 }
b473cf19
SC
347
348
c074abee
DHW
349}
350int
351main(argc, argv)
352 int argc;
353 char *argv[];
354{
617cd571
SC
355 int i;
356
357 program_name = argv[0];
358
21214e8e
SC
359 bfd_init();
360
617cd571
SC
361 if (strcmp(program_name,"strip") == 0) {
362 strip = true;
363 }
364
365 for (i = 1; i < argc; i++)
366 {
367 if (argv[i][0] == '-') {
368 switch (argv[i][1]) {
369 case 'v':
370 verbose = true;
371 break;
372 case 'b':
373 i++;
374 input_target = output_target = argv[i];
375 break;
376 case 'S':
377 strip = true;
378 break;
379 case 's':
380 i++;
381 input_target = argv[i];
382 break;
383 case 'd':
384 i++;
385 output_target = argv[i];
386 break;
387 default:
388 usage();
c074abee 389 }
617cd571
SC
390 }
391 else {
392 if (input_filename) {
393 output_filename = argv[i];
c074abee 394 }
617cd571
SC
395 else {
396 input_filename = argv[i];
c074abee 397 }
617cd571
SC
398 }
399 }
400
401 if (input_filename == (char *) NULL)
402 usage();
403
404 if (output_target == (char *) NULL)
405 output_target = input_target;
c074abee 406
617cd571
SC
407 /* If there is no destination file then create a temp and rename
408 the result into the input */
c074abee 409
617cd571
SC
410 if (output_filename == (char *)NULL) {
411 char * tmpname = make_tempname(input_filename);
412 copy_file(input_filename, tmpname);
413 output_filename = input_filename;
414 rename(tmpname, input_filename);
415 }
416 else {
417 copy_file(input_filename, output_filename);
418 }
c074abee
DHW
419 return 1;
420}
This page took 0.113247 seconds and 4 git commands to generate.