* remote.c, remote-mon.c, remote-utils.c, remote-utils.h,
[deliverable/binutils-gdb.git] / binutils / objcopy.c
CommitLineData
c0367ba5 1/* objcopy.c -- copy object file from input to output, optionally massaging it.
f7b839f7 2 Copyright (C) 1991, 92, 93, 94 Free Software Foundation, Inc.
c0367ba5 3
46050fe4
ILT
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19\f
c0367ba5
ILT
20#include "bfd.h"
21#include "sysdep.h"
22#include "bucomm.h"
23#include <getopt.h>
24
f7b839f7
DM
25static void setup_section ();
26static void copy_section ();
27static void mangle_section ();
c0367ba5 28
46050fe4 29#define nonfatal(s) {bfd_nonfatal(s); status = 1; return;}
c0367ba5 30
46050fe4
ILT
31static asymbol **isympp = NULL; /* Input symbols */
32static asymbol **osympp = NULL; /* Output symbols that survive stripping */
f7b839f7
DM
33
34/* If `copy_byte' >= 0, copy only that byte of every `interleave' bytes. */
35static int copy_byte = -1;
36static int interleave = 4;
37
46050fe4 38static boolean verbose; /* Print file and target names. */
f7b839f7 39static int status = 0; /* Exit status. */
c0367ba5
ILT
40
41enum strip_action
46050fe4
ILT
42 {
43 strip_undef,
44 strip_none, /* don't strip */
45 strip_debug, /* strip all debugger symbols */
46 strip_all /* strip all symbols */
47 };
c0367ba5
ILT
48
49/* Which symbols to remove. */
46050fe4 50static enum strip_action strip_symbols;
c0367ba5
ILT
51
52enum locals_action
46050fe4
ILT
53 {
54 locals_undef,
55 locals_start_L, /* discard locals starting with L */
56 locals_all /* discard all locals */
57 };
58
59/* Which local symbols to remove. Overrides strip_all. */
60static enum locals_action discard_locals;
61
62/* Options to handle if running as "strip". */
63
64static struct option strip_options[] =
c0367ba5 65{
46050fe4
ILT
66 {"discard-all", no_argument, 0, 'x'},
67 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 68 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 69 {"help", no_argument, 0, 'h'},
46050fe4 70 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7 71 {"input-target", required_argument, 0, 'I'},
46050fe4 72 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7
DM
73 {"output-target", required_argument, 0, 'O'},
74 {"strip-all", no_argument, 0, 's'},
75 {"strip-debug", no_argument, 0, 'S'},
46050fe4 76 {"target", required_argument, 0, 'F'},
46050fe4 77 {"verbose", no_argument, 0, 'v'},
f7b839f7 78 {"version", no_argument, 0, 'V'},
46050fe4 79 {0, no_argument, 0, 0}
c0367ba5
ILT
80};
81
46050fe4 82/* Options to handle if running as "objcopy". */
c0367ba5 83
46050fe4
ILT
84static struct option copy_options[] =
85{
f7b839f7 86 {"byte", required_argument, 0, 'b'},
46050fe4
ILT
87 {"discard-all", no_argument, 0, 'x'},
88 {"discard-locals", no_argument, 0, 'X'},
f7b839f7 89 {"format", required_argument, 0, 'F'}, /* Obsolete */
46050fe4 90 {"help", no_argument, 0, 'h'},
46050fe4 91 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
f7b839f7
DM
92 {"input-target", required_argument, 0, 'I'},
93 {"interleave", required_argument, 0, 'i'},
46050fe4 94 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
f7b839f7
DM
95 {"output-target", required_argument, 0, 'O'},
96 {"strip-all", no_argument, 0, 'S'},
97 {"strip-debug", no_argument, 0, 'g'},
46050fe4 98 {"target", required_argument, 0, 'F'},
46050fe4 99 {"verbose", no_argument, 0, 'v'},
f7b839f7 100 {"version", no_argument, 0, 'V'},
46050fe4 101 {0, no_argument, 0, 0}
c0367ba5
ILT
102};
103
104/* IMPORTS */
46050fe4
ILT
105extern char *program_name;
106extern char *program_version;
107
108/* This flag distinguishes between strip and objcopy:
109 1 means this is 'strip'; 0 means this is 'objcopy'.
110 -1 means if we should use argv[0] to decide. */
111extern int is_strip;
c0367ba5
ILT
112
113
46050fe4
ILT
114static void
115copy_usage (stream, status)
c0367ba5
ILT
116 FILE *stream;
117 int status;
118{
46050fe4 119 fprintf (stream, "\
f7b839f7
DM
120Usage: %s [-vVSgxX] [-I bfdname] [-O bfdname] [-F bfdname] [-b byte]\n\
121 [-i interleave] [--interleave=interleave] [--byte=byte]\n\
46050fe4
ILT
122 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
123 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
f7b839f7
DM
124 [--verbose] [--version] [--help] in-file [out-file]\n",
125 program_name);
46050fe4 126 exit (status);
c0367ba5
ILT
127}
128
46050fe4
ILT
129static void
130strip_usage (stream, status)
c0367ba5
ILT
131 FILE *stream;
132 int status;
133{
46050fe4
ILT
134 fprintf (stream, "\
135Usage: %s [-vVsSgxX] [-I bfdname] [-O bfdname] [-F bfdname]\n\
136 [--input-target=bfdname] [--output-target=bfdname] [--target=bfdname]\n\
137 [--strip-all] [--strip-debug] [--discard-all] [--discard-locals]\n\
138 [--verbose] [--version] [--help] file...\n",
139 program_name);
140 exit (status);
c0367ba5
ILT
141}
142
143
46050fe4 144/* Return the name of a temporary file in the same directory as FILENAME. */
c0367ba5 145
46050fe4
ILT
146static char *
147make_tempname (filename)
148 char *filename;
c0367ba5 149{
46050fe4
ILT
150 static char template[] = "stXXXXXX";
151 char *tmpname;
152 char *slash = strrchr (filename, '/');
153
154 if (slash != (char *) NULL)
155 {
156 *slash = 0;
157 tmpname = xmalloc (strlen (filename) + sizeof (template) + 1);
158 strcpy (tmpname, filename);
159 strcat (tmpname, "/");
160 strcat (tmpname, template);
161 mktemp (tmpname);
162 *slash = '/';
163 }
164 else
165 {
166 tmpname = xmalloc (sizeof (template));
167 strcpy (tmpname, template);
168 mktemp (tmpname);
c0367ba5 169 }
46050fe4 170 return tmpname;
c0367ba5
ILT
171}
172
46050fe4 173/* Choose which symbol entries to copy; put the result in OSYMS.
c0367ba5 174 We don't copy in place, because that confuses the relocs.
46050fe4
ILT
175 Return the number of symbols to print. */
176
c0367ba5
ILT
177static unsigned int
178filter_symbols (abfd, osyms, isyms, symcount)
179 bfd *abfd;
180 asymbol **osyms, **isyms;
181 unsigned long symcount;
182{
183 register asymbol **from = isyms, **to = osyms;
46050fe4
ILT
184 char locals_prefix = bfd_get_symbol_leading_char (abfd) == '_' ? 'L' : '.';
185 unsigned int src_count = 0, dst_count = 0;
c0367ba5 186
46050fe4
ILT
187 for (; src_count < symcount; src_count++)
188 {
189 asymbol *sym = from[src_count];
190 flagword flags = sym->flags;
191 int keep;
c0367ba5 192
46050fe4
ILT
193 if ((flags & BSF_GLOBAL) /* Keep if external. */
194 || bfd_get_section (sym) == &bfd_und_section
195 || bfd_is_com_section (bfd_get_section (sym)))
196 keep = 1;
197 else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */
198 keep = strip_symbols != strip_debug;
199 else /* Local symbol. */
200 keep = discard_locals != locals_all
201 && (discard_locals != locals_start_L ||
202 bfd_asymbol_name (sym)[0] != locals_prefix);
203 if (keep)
204 to[dst_count++] = sym;
c0367ba5 205 }
c0367ba5
ILT
206
207 return dst_count;
208}
209
f7b839f7
DM
210/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
211 Adjust *SIZE. */
212
213void
214filter_bytes (memhunk, size)
5d2f7e30 215 char *memhunk;
f7b839f7
DM
216 bfd_size_type *size;
217{
218 char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size;
219
220 for (; from < end; from += interleave)
221 *to++ = *from;
222 *size /= interleave;
223}
224
46050fe4
ILT
225/* Copy object file IBFD onto OBFD. */
226
c0367ba5 227static void
46050fe4
ILT
228copy_object (ibfd, obfd)
229 bfd *ibfd;
230 bfd *obfd;
c0367ba5 231{
46050fe4 232 unsigned int symcount;
c0367ba5 233
46050fe4
ILT
234 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
235 {
236 nonfatal (bfd_get_filename (obfd));
237 }
c0367ba5 238
46050fe4
ILT
239 if (verbose)
240 printf ("copy from %s(%s) to %s(%s)\n",
241 bfd_get_filename(ibfd), bfd_get_target(ibfd),
242 bfd_get_filename(obfd), bfd_get_target(obfd));
c0367ba5 243
46050fe4
ILT
244 if (!bfd_set_start_address (obfd, bfd_get_start_address (ibfd))
245 || !bfd_set_file_flags (obfd,
246 (bfd_get_file_flags (ibfd)
247 & bfd_applicable_file_flags (obfd))))
248 {
249 nonfatal (bfd_get_filename (ibfd));
250 }
c0367ba5 251
46050fe4
ILT
252 /* Copy architecture of input file to output file */
253 if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
254 bfd_get_mach (ibfd)))
255 {
256 fprintf (stderr, "Output file cannot represent architecture %s\n",
257 bfd_printable_arch_mach (bfd_get_arch (ibfd),
258 bfd_get_mach (ibfd)));
259 }
260 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
261 {
262 nonfatal (bfd_get_filename(ibfd));
263 }
c0367ba5 264
46050fe4
ILT
265 if (isympp)
266 free (isympp);
267 if (osympp != isympp)
268 free (osympp);
c0367ba5 269
46050fe4
ILT
270 if (strip_symbols == strip_all && discard_locals == locals_undef)
271 {
272 osympp = isympp = NULL;
273 symcount = 0;
c0367ba5 274 }
46050fe4
ILT
275 else
276 {
277 osympp = isympp = (asymbol **) xmalloc (get_symtab_upper_bound (ibfd));
278 symcount = bfd_canonicalize_symtab (ibfd, isympp);
279
280 if (strip_symbols == strip_debug || discard_locals != locals_undef)
c0367ba5 281 {
46050fe4
ILT
282 osympp = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
283 symcount = filter_symbols (ibfd, osympp, isympp, symcount);
c0367ba5 284 }
46050fe4
ILT
285 }
286
287 bfd_set_symtab (obfd, osympp, symcount);
c0367ba5 288
46050fe4
ILT
289 /* bfd mandates that all output sections be created and sizes set before
290 any output is done. Thus, we traverse all sections multiple times. */
f7b839f7
DM
291 bfd_map_over_sections (ibfd, setup_section, (void *) obfd);
292 bfd_map_over_sections (ibfd, copy_section, (void *) obfd);
293 bfd_map_over_sections (ibfd, mangle_section, (void *) obfd);
c0367ba5 294}
46050fe4
ILT
295
296static char *
297cat (a, b, c)
298 char *a;
299 char *b;
300 char *c;
c0367ba5 301{
46050fe4
ILT
302 size_t size = strlen (a) + strlen (b) + strlen (c);
303 char *r = xmalloc (size + 1);
304
305 strcpy (r, a);
306 strcat (r, b);
307 strcat (r, c);
308 return r;
c0367ba5
ILT
309}
310
46050fe4
ILT
311/* Read each archive element in turn from IBFD, copy the
312 contents to temp file, and keep the temp file handle. */
313
314static void
315copy_archive (ibfd, obfd, output_target)
316 bfd *ibfd;
317 bfd *obfd;
318 char *output_target;
c0367ba5 319{
46050fe4
ILT
320 bfd **ptr = &obfd->archive_head;
321 bfd *this_element;
322 char *dir = cat ("./#", make_tempname (""), "cd");
323
324 /* Make a temp directory to hold the contents. */
325 mkdir (dir, 0777);
326 obfd->has_armap = ibfd->has_armap;
327
328 this_element = bfd_openr_next_archived_file (ibfd, NULL);
329 ibfd->archive_head = this_element;
330 while (this_element != (bfd *) NULL)
331 {
332 /* Create an output file for this member. */
333 char *output_name = cat (dir, "/", bfd_get_filename(this_element));
334 bfd *output_bfd = bfd_openw (output_name, output_target);
335
336 if (output_bfd == (bfd *) NULL)
337 {
338 nonfatal (output_name);
c0367ba5 339 }
46050fe4
ILT
340 if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
341 {
342 nonfatal (bfd_get_filename (obfd));
c0367ba5
ILT
343 }
344
46050fe4
ILT
345 if (bfd_check_format (this_element, bfd_object) == true)
346 {
347 copy_object (this_element, output_bfd);
348 }
c0367ba5 349
46050fe4
ILT
350 bfd_close (output_bfd);
351 /* Open the newly output file and attatch to our list. */
352 output_bfd = bfd_openr (output_name, output_target);
c0367ba5 353
46050fe4
ILT
354 /* Mark it for deletion. */
355 *ptr = output_bfd;
356 ptr = &output_bfd->next;
357 this_element->next = bfd_openr_next_archived_file (ibfd, this_element);
358 this_element = this_element->next;
c0367ba5 359 }
46050fe4 360 *ptr = (bfd *) NULL;
c0367ba5 361
46050fe4
ILT
362 if (!bfd_close (obfd))
363 {
364 nonfatal (bfd_get_filename (obfd));
c0367ba5 365 }
c0367ba5 366
46050fe4
ILT
367 /* Delete all the files that we opened.
368 Construct their names again, unfortunately, but
369 we're about to exit anyway. */
370 for (this_element = ibfd->archive_head;
371 this_element != (bfd *) NULL;
372 this_element = this_element->next)
373 {
374 unlink (cat (dir, "/", bfd_get_filename (this_element)));
375 }
376 rmdir (dir);
377 if (!bfd_close (ibfd))
378 {
379 nonfatal (bfd_get_filename (ibfd));
380 }
c0367ba5
ILT
381}
382
46050fe4
ILT
383/* The top-level control. */
384
385static void
386copy_file (input_filename, output_filename, input_target, output_target)
387 char *input_filename;
388 char *output_filename;
389 char *input_target;
390 char *output_target;
c0367ba5 391{
46050fe4 392 bfd *ibfd;
cef35d48 393 char **matching;
c0367ba5
ILT
394
395 /* To allow us to do "strip *" without dying on the first
396 non-object file, failures are nonfatal. */
397
46050fe4 398 ibfd = bfd_openr (input_filename, input_target);
c0367ba5
ILT
399 if (ibfd == NULL)
400 {
46050fe4 401 nonfatal (input_filename);
c0367ba5
ILT
402 }
403
cef35d48
DM
404 if (bfd_check_format (ibfd, bfd_archive))
405 {
406 bfd *obfd = bfd_openw (output_filename, output_target);
407 if (obfd == NULL)
408 {
409 nonfatal (output_filename);
410 }
411 copy_archive (ibfd, obfd, output_target);
412 }
413 else if (bfd_check_format_matches (ibfd, bfd_object, &matching))
46050fe4
ILT
414 {
415 bfd *obfd = bfd_openw (output_filename, output_target);
416 if (obfd == NULL)
417 {
418 nonfatal (output_filename);
419 }
c0367ba5 420
46050fe4 421 copy_object (ibfd, obfd);
c0367ba5 422
46050fe4
ILT
423 if (!bfd_close (obfd))
424 {
425 nonfatal (output_filename);
426 }
427
428 if (!bfd_close (ibfd))
429 {
430 nonfatal (input_filename);
431 }
432 }
cef35d48 433 else
46050fe4 434 {
cef35d48
DM
435 bfd_nonfatal (input_filename);
436 if (bfd_error == file_ambiguously_recognized)
46050fe4 437 {
cef35d48
DM
438 list_matching_formats (matching);
439 free (matching);
46050fe4 440 }
cef35d48 441 status = 1;
46050fe4
ILT
442 }
443}
444
445/* Create a section in OBFD with the same name and attributes
446 as ISECTION in IBFD. */
c0367ba5 447
c0367ba5 448static void
f7b839f7 449setup_section (ibfd, isection, obfd)
46050fe4
ILT
450 bfd *ibfd;
451 sec_ptr isection;
452 bfd *obfd;
c0367ba5 453{
46050fe4
ILT
454 sec_ptr osection;
455 char *err;
456
457 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
458 && (strip_symbols == strip_debug
459 || strip_symbols == strip_all
460 || discard_locals == locals_all))
461 return;
462
463 osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
464 if (osection == NULL)
465 {
466 osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
467 if (osection == NULL)
468 {
469 err = "making";
470 goto loser;
c0367ba5
ILT
471 }
472 }
473
46050fe4
ILT
474 if (!bfd_set_section_size (obfd,
475 osection,
476 bfd_section_size (ibfd, isection)))
477 {
478 err = "size";
479 goto loser;
c0367ba5
ILT
480 }
481
46050fe4
ILT
482 if (bfd_set_section_vma (obfd,
483 osection,
484 bfd_section_vma (ibfd, isection))
485 == false)
486 {
487 err = "vma";
488 goto loser;
489 }
c0367ba5 490
46050fe4
ILT
491 if (bfd_set_section_alignment (obfd,
492 osection,
493 bfd_section_alignment (ibfd, isection))
494 == false)
495 {
496 err = "alignment";
497 goto loser;
498 }
c0367ba5 499
46050fe4
ILT
500 if (!bfd_set_section_flags (obfd, osection,
501 bfd_get_section_flags (ibfd, isection)))
502 {
503 err = "flags";
504 goto loser;
c0367ba5
ILT
505 }
506
46050fe4
ILT
507 /* All went well */
508 return;
c0367ba5
ILT
509
510loser:
46050fe4
ILT
511 fprintf (stderr, "%s: %s: section `%s': error in %s: %s\n",
512 program_name,
513 bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
514 err, bfd_errmsg (bfd_error));
515 status = 1;
516}
517
518/* Copy the data of input section ISECTION of IBFD
519 to an output section with the same name in OBFD.
520 If stripping then don't copy any relocation info. */
521
c0367ba5 522static void
f7b839f7 523copy_section (ibfd, isection, obfd)
46050fe4
ILT
524 bfd *ibfd;
525 sec_ptr isection;
526 bfd *obfd;
c0367ba5 527{
46050fe4
ILT
528 arelent **relpp;
529 int relcount;
530 sec_ptr osection;
531 bfd_size_type size;
532
533 if ((bfd_get_section_flags (ibfd, isection) & SEC_DEBUGGING) != 0
534 && (strip_symbols == strip_debug
535 || strip_symbols == strip_all
536 || discard_locals == locals_all))
537 {
538 return;
539 }
c0367ba5 540
46050fe4
ILT
541 osection = bfd_get_section_by_name (obfd,
542 bfd_section_name (ibfd, isection));
c0367ba5 543
46050fe4 544 size = bfd_get_section_size_before_reloc (isection);
c0367ba5
ILT
545
546 if (size == 0)
547 return;
548
549 if (strip_symbols == strip_all
46050fe4 550 || bfd_get_reloc_upper_bound (ibfd, isection) == 0)
c0367ba5 551 {
46050fe4
ILT
552 bfd_set_reloc (obfd, osection, (arelent **) NULL, 0);
553 }
554 else
c0367ba5 555 {
46050fe4
ILT
556 relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (ibfd, isection));
557 relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
558 bfd_set_reloc (obfd, osection, relpp, relcount);
c0367ba5
ILT
559 }
560
561 isection->_cooked_size = isection->_raw_size;
46050fe4 562 isection->reloc_done = true;
c0367ba5 563
46050fe4 564 if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS)
c0367ba5 565 {
46050fe4 566 PTR memhunk = (PTR) xmalloc ((unsigned) size);
c0367ba5 567
46050fe4
ILT
568 if (!bfd_get_section_contents (ibfd, isection, memhunk, (file_ptr) 0,
569 size))
570 {
571 nonfatal (bfd_get_filename (ibfd));
572 }
c0367ba5 573
f7b839f7
DM
574 if (copy_byte >= 0)
575 filter_bytes (memhunk, &size);
576
46050fe4
ILT
577 if (!bfd_set_section_contents (obfd, osection, memhunk, (file_ptr) 0,
578 size))
579 {
580 nonfatal (bfd_get_filename (obfd));
581 }
582 free (memhunk);
c0367ba5 583 }
46050fe4 584}
c0367ba5 585
46050fe4
ILT
586/* All the symbols have been read in and point to their owning input section.
587 They have been relocated so that they are all relative to the base of
588 their owning section. On the way out, all the symbols will be relocated to
589 their new location in the output file, through some complex sums. */
c0367ba5 590
46050fe4 591static void
f7b839f7 592mangle_section (ibfd, p, obfd)
46050fe4
ILT
593 bfd *ibfd;
594 asection *p;
595 bfd *obfd;
596{
597 p->output_section = bfd_get_section_by_name (obfd, p->name);
598 p->output_offset = 0;
c0367ba5 599}
46050fe4
ILT
600
601/* The number of bytes to copy at once. */
602#define COPY_BUF 8192
603
604/* Copy file FROM to file TO, performing no translations.
605 Return 0 if ok, -1 if error. */
606
607static int
608simple_copy (from, to)
609 char *from, *to;
c0367ba5 610{
46050fe4
ILT
611 int fromfd, tofd, nread;
612 char buf[COPY_BUF];
613
614 fromfd = open (from, O_RDONLY);
615 if (fromfd < 0)
616 return -1;
617 tofd = open (to, O_WRONLY | O_CREAT | O_TRUNC);
618 if (tofd < 0)
619 {
620 close (fromfd);
621 return -1;
622 }
623 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
624 {
625 if (write (tofd, buf, nread) != nread)
626 {
627 close (fromfd);
628 close (tofd);
629 return -1;
630 }
631 }
632 close (fromfd);
633 close (tofd);
634 if (nread < 0)
635 return -1;
636 return 0;
637}
c0367ba5 638
46050fe4
ILT
639#ifndef S_ISLNK
640#ifdef S_IFLNK
641#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
642#else
643#define S_ISLNK(m) 0
644#define lstat stat
645#endif
646#endif
647
648/* Rename FROM to TO, copying if TO is a link.
649 Assumes that TO already exists, because FROM is a temp file.
650 Return 0 if ok, -1 if error. */
651
652static int
653smart_rename (from, to)
654 char *from, *to;
655{
656 struct stat s;
657 int ret = 0;
c0367ba5 658
46050fe4
ILT
659 if (lstat (to, &s))
660 return -1;
c0367ba5 661
46050fe4
ILT
662 /* Use rename only if TO is not a symbolic link and has
663 only one hard link. */
664 if (!S_ISLNK (s.st_mode) && s.st_nlink == 1)
665 {
666 ret = rename (from, to);
667 if (ret == 0)
668 {
669 /* Try to preserve the permission bits and ownership of TO. */
670 chmod (to, s.st_mode & 07777);
671 chown (to, s.st_uid, s.st_gid);
672 }
673 }
674 else
675 {
676 ret = simple_copy (from, to);
677 if (ret == 0)
678 unlink (from);
679 }
680 return ret;
681}
682
683static int
684strip_main (argc, argv)
685 int argc;
686 char *argv[];
687{
688 char *input_target = NULL, *output_target = NULL;
689 boolean show_version = false;
690 int c, i;
691
692 while ((c = getopt_long (argc, argv, "I:O:F:sSgxXVv",
693 strip_options, (int *) 0)) != EOF)
694 {
695 switch (c)
696 {
697 case 'I':
698 input_target = optarg;
704bbd0d 699 break;
46050fe4
ILT
700 case 'O':
701 output_target = optarg;
702 break;
703 case 'F':
704 input_target = output_target = optarg;
705 break;
706 case 's':
c0367ba5 707 strip_symbols = strip_all;
46050fe4
ILT
708 break;
709 case 'S':
710 case 'g':
711 strip_symbols = strip_debug;
712 break;
713 case 'x':
714 discard_locals = locals_all;
715 break;
716 case 'X':
717 discard_locals = locals_start_L;
718 break;
719 case 'v':
720 verbose = true;
721 break;
722 case 'V':
723 show_version = true;
724 break;
725 case 0:
726 break; /* we've been given a long option */
727 case 'h':
728 strip_usage (stdout, 0);
729 default:
730 strip_usage (stderr, 1);
731 }
732 }
733
734 if (show_version)
735 {
736 printf ("GNU %s version %s\n", program_name, program_version);
737 exit (0);
738 }
c0367ba5 739
46050fe4
ILT
740 /* Default is to strip all symbols. */
741 if (strip_symbols == strip_undef && discard_locals == locals_undef)
742 strip_symbols = strip_all;
743
744 if (output_target == (char *) NULL)
745 output_target = input_target;
746
747 i = optind;
748 if (i == argc)
749 strip_usage (stderr, 1);
750
751 for (; i < argc; i++)
752 {
753 int hold_status = status;
c0367ba5 754
46050fe4
ILT
755 char *tmpname = make_tempname (argv[i]);
756 status = 0;
757 copy_file (argv[i], tmpname, input_target, output_target);
758 if (status == 0)
759 {
760 smart_rename (tmpname, argv[i]);
761 status = hold_status;
c0367ba5 762 }
46050fe4
ILT
763 else
764 unlink (tmpname);
765 free (tmpname);
766 }
767
768 return 0;
769}
770
771static int
772copy_main (argc, argv)
773 int argc;
774 char *argv[];
775{
776 char *input_filename, *output_filename;
777 char *input_target = NULL, *output_target = NULL;
778 boolean show_version = false;
779 int c;
780
f7b839f7 781 while ((c = getopt_long (argc, argv, "b:i:I:s:O:d:F:SgxXVv",
46050fe4
ILT
782 copy_options, (int *) 0)) != EOF)
783 {
784 switch (c)
785 {
f7b839f7
DM
786 case 'b':
787 copy_byte = atoi(optarg);
788 if (copy_byte < 0)
789 {
790 fprintf (stderr, "%s: byte number must be non-negative\n",
791 program_name);
792 exit (1);
793 }
794 break;
795 case 'i':
796 interleave = atoi(optarg);
797 if (interleave < 1)
798 {
799 fprintf(stderr, "%s: interleave must be positive\n",
800 program_name);
801 exit (1);
802 }
803 break;
c0367ba5 804 case 'I':
46050fe4 805 case 's': /* "source" - 'I' is preferred */
c0367ba5 806 input_target = optarg;
704bbd0d 807 break;
c0367ba5 808 case 'O':
46050fe4 809 case 'd': /* "destination" - 'O' is preferred */
c0367ba5
ILT
810 output_target = optarg;
811 break;
812 case 'F':
c0367ba5
ILT
813 input_target = output_target = optarg;
814 break;
c0367ba5
ILT
815 case 'S':
816 strip_symbols = strip_all;
817 break;
818 case 'g':
819 strip_symbols = strip_debug;
820 break;
821 case 'x':
822 discard_locals = locals_all;
823 break;
824 case 'X':
825 discard_locals = locals_start_L;
826 break;
827 case 'v':
828 verbose = true;
829 break;
830 case 'V':
831 show_version = true;
832 break;
46050fe4 833 case 0:
c0367ba5
ILT
834 break; /* we've been given a long option */
835 case 'h':
836 copy_usage (stdout, 0);
837 default:
838 copy_usage (stderr, 1);
46050fe4
ILT
839 }
840 }
841
842 if (show_version)
843 {
844 printf ("GNU %s version %s\n", program_name, program_version);
845 exit (0);
846 }
c0367ba5 847
f7b839f7
DM
848 if (copy_byte >= interleave)
849 {
850 fprintf (stderr, "%s: byte number must be less than interleave\n",
851 program_name);
852 exit (1);
853 }
854
46050fe4
ILT
855 if (optind == argc || optind + 2 < argc)
856 copy_usage (stderr, 1);
c0367ba5
ILT
857
858 input_filename = argv[optind];
859 if (optind + 1 < argc)
46050fe4 860 output_filename = argv[optind + 1];
c0367ba5
ILT
861
862 /* Default is to strip no symbols. */
863 if (strip_symbols == strip_undef && discard_locals == locals_undef)
46050fe4 864 strip_symbols = strip_none;
c0367ba5
ILT
865
866 if (output_target == (char *) NULL)
867 output_target = input_target;
868
46050fe4
ILT
869 /* If there is no destination file then create a temp and rename
870 the result into the input. */
871
872 if (output_filename == (char *) NULL)
873 {
874 char *tmpname = make_tempname (input_filename);
875 copy_file (input_filename, tmpname, input_target, output_target);
876 if (status == 0)
877 smart_rename (tmpname, input_filename);
878 else
879 unlink (tmpname);
880 }
881 else
882 {
883 copy_file (input_filename, output_filename, input_target, output_target);
884 }
885
c0367ba5
ILT
886 return 0;
887}
46050fe4
ILT
888
889int
890main (argc, argv)
891 int argc;
892 char *argv[];
893{
894 program_name = argv[0];
704bbd0d 895 xmalloc_set_program_name (program_name);
46050fe4
ILT
896 strip_symbols = strip_undef;
897 discard_locals = locals_undef;
898
899 bfd_init ();
900
901 if (is_strip < 0)
902 {
903 int i = strlen (program_name);
904 is_strip = (i >= 5 && strcmp (program_name + i - 5, "strip"));
905 }
906
907 if (is_strip)
908 strip_main (argc, argv);
909 else
910 copy_main (argc, argv);
911
912 return status;
913}
This page took 0.086338 seconds and 4 git commands to generate.