1*a9fa9459Szrj /* objcopy.c -- copy object file from input to output, optionally massaging it.
2*a9fa9459Szrj    Copyright (C) 1991-2016 Free Software Foundation, Inc.
3*a9fa9459Szrj 
4*a9fa9459Szrj    This file is part of GNU Binutils.
5*a9fa9459Szrj 
6*a9fa9459Szrj    This program is free software; you can redistribute it and/or modify
7*a9fa9459Szrj    it under the terms of the GNU General Public License as published by
8*a9fa9459Szrj    the Free Software Foundation; either version 3 of the License, or
9*a9fa9459Szrj    (at your option) any later version.
10*a9fa9459Szrj 
11*a9fa9459Szrj    This program is distributed in the hope that it will be useful,
12*a9fa9459Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*a9fa9459Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*a9fa9459Szrj    GNU General Public License for more details.
15*a9fa9459Szrj 
16*a9fa9459Szrj    You should have received a copy of the GNU General Public License
17*a9fa9459Szrj    along with this program; if not, write to the Free Software
18*a9fa9459Szrj    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19*a9fa9459Szrj    02110-1301, USA.  */
20*a9fa9459Szrj 
21*a9fa9459Szrj #include "sysdep.h"
22*a9fa9459Szrj #include "bfd.h"
23*a9fa9459Szrj #include "progress.h"
24*a9fa9459Szrj #include "getopt.h"
25*a9fa9459Szrj #include "libiberty.h"
26*a9fa9459Szrj #include "bucomm.h"
27*a9fa9459Szrj #include "budbg.h"
28*a9fa9459Szrj #include "filenames.h"
29*a9fa9459Szrj #include "fnmatch.h"
30*a9fa9459Szrj #include "elf-bfd.h"
31*a9fa9459Szrj #include "libbfd.h"
32*a9fa9459Szrj #include "coff/internal.h"
33*a9fa9459Szrj #include "libcoff.h"
34*a9fa9459Szrj 
35*a9fa9459Szrj /* FIXME: See bfd/peXXigen.c for why we include an architecture specific
36*a9fa9459Szrj    header in generic PE code.  */
37*a9fa9459Szrj #include "coff/i386.h"
38*a9fa9459Szrj #include "coff/pe.h"
39*a9fa9459Szrj 
40*a9fa9459Szrj static bfd_vma pe_file_alignment = (bfd_vma) -1;
41*a9fa9459Szrj static bfd_vma pe_heap_commit = (bfd_vma) -1;
42*a9fa9459Szrj static bfd_vma pe_heap_reserve = (bfd_vma) -1;
43*a9fa9459Szrj static bfd_vma pe_image_base = (bfd_vma) -1;
44*a9fa9459Szrj static bfd_vma pe_section_alignment = (bfd_vma) -1;
45*a9fa9459Szrj static bfd_vma pe_stack_commit = (bfd_vma) -1;
46*a9fa9459Szrj static bfd_vma pe_stack_reserve = (bfd_vma) -1;
47*a9fa9459Szrj static short pe_subsystem = -1;
48*a9fa9459Szrj static short pe_major_subsystem_version = -1;
49*a9fa9459Szrj static short pe_minor_subsystem_version = -1;
50*a9fa9459Szrj 
51*a9fa9459Szrj struct is_specified_symbol_predicate_data
52*a9fa9459Szrj {
53*a9fa9459Szrj   const char *  name;
54*a9fa9459Szrj   bfd_boolean	found;
55*a9fa9459Szrj };
56*a9fa9459Szrj 
57*a9fa9459Szrj /* A list to support redefine_sym.  */
58*a9fa9459Szrj struct redefine_node
59*a9fa9459Szrj {
60*a9fa9459Szrj   char *source;
61*a9fa9459Szrj   char *target;
62*a9fa9459Szrj   struct redefine_node *next;
63*a9fa9459Szrj };
64*a9fa9459Szrj 
65*a9fa9459Szrj struct addsym_node
66*a9fa9459Szrj {
67*a9fa9459Szrj   struct addsym_node *next;
68*a9fa9459Szrj   char *    symdef;
69*a9fa9459Szrj   long      symval;
70*a9fa9459Szrj   flagword  flags;
71*a9fa9459Szrj   char *    section;
72*a9fa9459Szrj   char *    othersym;
73*a9fa9459Szrj };
74*a9fa9459Szrj 
75*a9fa9459Szrj typedef struct section_rename
76*a9fa9459Szrj {
77*a9fa9459Szrj   const char *            old_name;
78*a9fa9459Szrj   const char *            new_name;
79*a9fa9459Szrj   flagword                flags;
80*a9fa9459Szrj   struct section_rename * next;
81*a9fa9459Szrj }
82*a9fa9459Szrj section_rename;
83*a9fa9459Szrj 
84*a9fa9459Szrj /* List of sections to be renamed.  */
85*a9fa9459Szrj static section_rename *section_rename_list;
86*a9fa9459Szrj 
87*a9fa9459Szrj static asymbol **isympp = NULL;	/* Input symbols.  */
88*a9fa9459Szrj static asymbol **osympp = NULL;	/* Output symbols that survive stripping.  */
89*a9fa9459Szrj 
90*a9fa9459Szrj /* If `copy_byte' >= 0, copy 'copy_width' byte(s) of every `interleave' bytes.  */
91*a9fa9459Szrj static int copy_byte = -1;
92*a9fa9459Szrj static int interleave = 0; /* Initialised to 4 in copy_main().  */
93*a9fa9459Szrj static int copy_width = 1;
94*a9fa9459Szrj 
95*a9fa9459Szrj static bfd_boolean verbose;		/* Print file and target names.  */
96*a9fa9459Szrj static bfd_boolean preserve_dates;	/* Preserve input file timestamp.  */
97*a9fa9459Szrj static int deterministic = -1;		/* Enable deterministic archives.  */
98*a9fa9459Szrj static int status = 0;		/* Exit status.  */
99*a9fa9459Szrj 
100*a9fa9459Szrj enum strip_action
101*a9fa9459Szrj {
102*a9fa9459Szrj   STRIP_UNDEF,
103*a9fa9459Szrj   STRIP_NONE,		/* Don't strip.  */
104*a9fa9459Szrj   STRIP_DEBUG,		/* Strip all debugger symbols.  */
105*a9fa9459Szrj   STRIP_UNNEEDED,	/* Strip unnecessary symbols.  */
106*a9fa9459Szrj   STRIP_NONDEBUG,	/* Strip everything but debug info.  */
107*a9fa9459Szrj   STRIP_DWO,		/* Strip all DWO info.  */
108*a9fa9459Szrj   STRIP_NONDWO,		/* Strip everything but DWO info.  */
109*a9fa9459Szrj   STRIP_ALL		/* Strip all symbols.  */
110*a9fa9459Szrj };
111*a9fa9459Szrj 
112*a9fa9459Szrj /* Which symbols to remove.  */
113*a9fa9459Szrj static enum strip_action strip_symbols = STRIP_UNDEF;
114*a9fa9459Szrj 
115*a9fa9459Szrj enum locals_action
116*a9fa9459Szrj {
117*a9fa9459Szrj   LOCALS_UNDEF,
118*a9fa9459Szrj   LOCALS_START_L,	/* Discard locals starting with L.  */
119*a9fa9459Szrj   LOCALS_ALL		/* Discard all locals.  */
120*a9fa9459Szrj };
121*a9fa9459Szrj 
122*a9fa9459Szrj /* Which local symbols to remove.  Overrides STRIP_ALL.  */
123*a9fa9459Szrj static enum locals_action discard_locals;
124*a9fa9459Szrj 
125*a9fa9459Szrj /* Structure used to hold lists of sections and actions to take.  */
126*a9fa9459Szrj struct section_list
127*a9fa9459Szrj {
128*a9fa9459Szrj   struct section_list * next;	   /* Next section to change.  */
129*a9fa9459Szrj   const char *		pattern;   /* Section name pattern.  */
130*a9fa9459Szrj   bfd_boolean		used;	   /* Whether this entry was used.  */
131*a9fa9459Szrj 
132*a9fa9459Szrj   unsigned int          context;   /* What to do with matching sections.  */
133*a9fa9459Szrj   /* Flag bits used in the context field.
134*a9fa9459Szrj      COPY and REMOVE are mutually exlusive.  SET and ALTER are mutually exclusive.  */
135*a9fa9459Szrj #define SECTION_CONTEXT_REMOVE    (1 << 0) /* Remove this section.  */
136*a9fa9459Szrj #define SECTION_CONTEXT_COPY      (1 << 1) /* Copy this section, delete all non-copied section.  */
137*a9fa9459Szrj #define SECTION_CONTEXT_SET_VMA   (1 << 2) /* Set the sections' VMA address.  */
138*a9fa9459Szrj #define SECTION_CONTEXT_ALTER_VMA (1 << 3) /* Increment or decrement the section's VMA address.  */
139*a9fa9459Szrj #define SECTION_CONTEXT_SET_LMA   (1 << 4) /* Set the sections' LMA address.  */
140*a9fa9459Szrj #define SECTION_CONTEXT_ALTER_LMA (1 << 5) /* Increment or decrement the section's LMA address.  */
141*a9fa9459Szrj #define SECTION_CONTEXT_SET_FLAGS (1 << 6) /* Set the section's flags.  */
142*a9fa9459Szrj 
143*a9fa9459Szrj   bfd_vma		vma_val;   /* Amount to change by or set to.  */
144*a9fa9459Szrj   bfd_vma		lma_val;   /* Amount to change by or set to.  */
145*a9fa9459Szrj   flagword		flags;	   /* What to set the section flags to.	 */
146*a9fa9459Szrj };
147*a9fa9459Szrj 
148*a9fa9459Szrj static struct section_list *change_sections;
149*a9fa9459Szrj 
150*a9fa9459Szrj /* TRUE if some sections are to be removed.  */
151*a9fa9459Szrj static bfd_boolean sections_removed;
152*a9fa9459Szrj 
153*a9fa9459Szrj /* TRUE if only some sections are to be copied.  */
154*a9fa9459Szrj static bfd_boolean sections_copied;
155*a9fa9459Szrj 
156*a9fa9459Szrj /* Changes to the start address.  */
157*a9fa9459Szrj static bfd_vma change_start = 0;
158*a9fa9459Szrj static bfd_boolean set_start_set = FALSE;
159*a9fa9459Szrj static bfd_vma set_start;
160*a9fa9459Szrj 
161*a9fa9459Szrj /* Changes to section addresses.  */
162*a9fa9459Szrj static bfd_vma change_section_address = 0;
163*a9fa9459Szrj 
164*a9fa9459Szrj /* Filling gaps between sections.  */
165*a9fa9459Szrj static bfd_boolean gap_fill_set = FALSE;
166*a9fa9459Szrj static bfd_byte gap_fill = 0;
167*a9fa9459Szrj 
168*a9fa9459Szrj /* Pad to a given address.  */
169*a9fa9459Szrj static bfd_boolean pad_to_set = FALSE;
170*a9fa9459Szrj static bfd_vma pad_to;
171*a9fa9459Szrj 
172*a9fa9459Szrj /* Use alternative machine code?  */
173*a9fa9459Szrj static unsigned long use_alt_mach_code = 0;
174*a9fa9459Szrj 
175*a9fa9459Szrj /* Output BFD flags user wants to set or clear */
176*a9fa9459Szrj static flagword bfd_flags_to_set;
177*a9fa9459Szrj static flagword bfd_flags_to_clear;
178*a9fa9459Szrj 
179*a9fa9459Szrj /* List of sections to add.  */
180*a9fa9459Szrj struct section_add
181*a9fa9459Szrj {
182*a9fa9459Szrj   /* Next section to add.  */
183*a9fa9459Szrj   struct section_add *next;
184*a9fa9459Szrj   /* Name of section to add.  */
185*a9fa9459Szrj   const char *name;
186*a9fa9459Szrj   /* Name of file holding section contents.  */
187*a9fa9459Szrj   const char *filename;
188*a9fa9459Szrj   /* Size of file.  */
189*a9fa9459Szrj   size_t size;
190*a9fa9459Szrj   /* Contents of file.  */
191*a9fa9459Szrj   bfd_byte *contents;
192*a9fa9459Szrj   /* BFD section, after it has been added.  */
193*a9fa9459Szrj   asection *section;
194*a9fa9459Szrj };
195*a9fa9459Szrj 
196*a9fa9459Szrj /* List of sections to add to the output BFD.  */
197*a9fa9459Szrj static struct section_add *add_sections;
198*a9fa9459Szrj 
199*a9fa9459Szrj /* List of sections to update in the output BFD.  */
200*a9fa9459Szrj static struct section_add *update_sections;
201*a9fa9459Szrj 
202*a9fa9459Szrj /* List of sections to dump from the output BFD.  */
203*a9fa9459Szrj static struct section_add *dump_sections;
204*a9fa9459Szrj 
205*a9fa9459Szrj /* If non-NULL the argument to --add-gnu-debuglink.
206*a9fa9459Szrj    This should be the filename to store in the .gnu_debuglink section.  */
207*a9fa9459Szrj static const char * gnu_debuglink_filename = NULL;
208*a9fa9459Szrj 
209*a9fa9459Szrj /* Whether to convert debugging information.  */
210*a9fa9459Szrj static bfd_boolean convert_debugging = FALSE;
211*a9fa9459Szrj 
212*a9fa9459Szrj /* Whether to compress/decompress DWARF debug sections.  */
213*a9fa9459Szrj static enum
214*a9fa9459Szrj {
215*a9fa9459Szrj   nothing = 0,
216*a9fa9459Szrj   compress = 1 << 0,
217*a9fa9459Szrj   compress_zlib = compress | 1 << 1,
218*a9fa9459Szrj   compress_gnu_zlib = compress | 1 << 2,
219*a9fa9459Szrj   compress_gabi_zlib = compress | 1 << 3,
220*a9fa9459Szrj   decompress = 1 << 4
221*a9fa9459Szrj } do_debug_sections = nothing;
222*a9fa9459Szrj 
223*a9fa9459Szrj /* Whether to generate ELF common symbols with the STT_COMMON type.  */
224*a9fa9459Szrj static enum bfd_link_elf_stt_common do_elf_stt_common = unchanged;
225*a9fa9459Szrj 
226*a9fa9459Szrj /* Whether to change the leading character in symbol names.  */
227*a9fa9459Szrj static bfd_boolean change_leading_char = FALSE;
228*a9fa9459Szrj 
229*a9fa9459Szrj /* Whether to remove the leading character from global symbol names.  */
230*a9fa9459Szrj static bfd_boolean remove_leading_char = FALSE;
231*a9fa9459Szrj 
232*a9fa9459Szrj /* Whether to permit wildcard in symbol comparison.  */
233*a9fa9459Szrj static bfd_boolean wildcard = FALSE;
234*a9fa9459Szrj 
235*a9fa9459Szrj /* True if --localize-hidden is in effect.  */
236*a9fa9459Szrj static bfd_boolean localize_hidden = FALSE;
237*a9fa9459Szrj 
238*a9fa9459Szrj /* List of symbols to strip, keep, localize, keep-global, weaken,
239*a9fa9459Szrj    or redefine.  */
240*a9fa9459Szrj static htab_t strip_specific_htab = NULL;
241*a9fa9459Szrj static htab_t strip_unneeded_htab = NULL;
242*a9fa9459Szrj static htab_t keep_specific_htab = NULL;
243*a9fa9459Szrj static htab_t localize_specific_htab = NULL;
244*a9fa9459Szrj static htab_t globalize_specific_htab = NULL;
245*a9fa9459Szrj static htab_t keepglobal_specific_htab = NULL;
246*a9fa9459Szrj static htab_t weaken_specific_htab = NULL;
247*a9fa9459Szrj static struct redefine_node *redefine_sym_list = NULL;
248*a9fa9459Szrj static struct addsym_node *add_sym_list = NULL, **add_sym_tail = &add_sym_list;
249*a9fa9459Szrj static int add_symbols = 0;
250*a9fa9459Szrj 
251*a9fa9459Szrj /* If this is TRUE, we weaken global symbols (set BSF_WEAK).  */
252*a9fa9459Szrj static bfd_boolean weaken = FALSE;
253*a9fa9459Szrj 
254*a9fa9459Szrj /* If this is TRUE, we retain BSF_FILE symbols.  */
255*a9fa9459Szrj static bfd_boolean keep_file_symbols = FALSE;
256*a9fa9459Szrj 
257*a9fa9459Szrj /* Prefix symbols/sections.  */
258*a9fa9459Szrj static char *prefix_symbols_string = 0;
259*a9fa9459Szrj static char *prefix_sections_string = 0;
260*a9fa9459Szrj static char *prefix_alloc_sections_string = 0;
261*a9fa9459Szrj 
262*a9fa9459Szrj /* True if --extract-symbol was passed on the command line.  */
263*a9fa9459Szrj static bfd_boolean extract_symbol = FALSE;
264*a9fa9459Szrj 
265*a9fa9459Szrj /* If `reverse_bytes' is nonzero, then reverse the order of every chunk
266*a9fa9459Szrj    of <reverse_bytes> bytes within each output section.  */
267*a9fa9459Szrj static int reverse_bytes = 0;
268*a9fa9459Szrj 
269*a9fa9459Szrj /* For Coff objects, we may want to allow or disallow long section names,
270*a9fa9459Szrj    or preserve them where found in the inputs.  Debug info relies on them.  */
271*a9fa9459Szrj enum long_section_name_handling
272*a9fa9459Szrj {
273*a9fa9459Szrj   DISABLE,
274*a9fa9459Szrj   ENABLE,
275*a9fa9459Szrj   KEEP
276*a9fa9459Szrj };
277*a9fa9459Szrj 
278*a9fa9459Szrj /* The default long section handling mode is to preserve them.
279*a9fa9459Szrj    This is also the only behaviour for 'strip'.  */
280*a9fa9459Szrj static enum long_section_name_handling long_section_names = KEEP;
281*a9fa9459Szrj 
282*a9fa9459Szrj /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
283*a9fa9459Szrj enum command_line_switch
284*a9fa9459Szrj {
285*a9fa9459Szrj   OPTION_ADD_SECTION=150,
286*a9fa9459Szrj   OPTION_ADD_GNU_DEBUGLINK,
287*a9fa9459Szrj   OPTION_ADD_SYMBOL,
288*a9fa9459Szrj   OPTION_ALT_MACH_CODE,
289*a9fa9459Szrj   OPTION_CHANGE_ADDRESSES,
290*a9fa9459Szrj   OPTION_CHANGE_LEADING_CHAR,
291*a9fa9459Szrj   OPTION_CHANGE_SECTION_ADDRESS,
292*a9fa9459Szrj   OPTION_CHANGE_SECTION_LMA,
293*a9fa9459Szrj   OPTION_CHANGE_SECTION_VMA,
294*a9fa9459Szrj   OPTION_CHANGE_START,
295*a9fa9459Szrj   OPTION_CHANGE_WARNINGS,
296*a9fa9459Szrj   OPTION_COMPRESS_DEBUG_SECTIONS,
297*a9fa9459Szrj   OPTION_DEBUGGING,
298*a9fa9459Szrj   OPTION_DECOMPRESS_DEBUG_SECTIONS,
299*a9fa9459Szrj   OPTION_DUMP_SECTION,
300*a9fa9459Szrj   OPTION_ELF_STT_COMMON,
301*a9fa9459Szrj   OPTION_EXTRACT_DWO,
302*a9fa9459Szrj   OPTION_EXTRACT_SYMBOL,
303*a9fa9459Szrj   OPTION_FILE_ALIGNMENT,
304*a9fa9459Szrj   OPTION_FORMATS_INFO,
305*a9fa9459Szrj   OPTION_GAP_FILL,
306*a9fa9459Szrj   OPTION_GLOBALIZE_SYMBOL,
307*a9fa9459Szrj   OPTION_GLOBALIZE_SYMBOLS,
308*a9fa9459Szrj   OPTION_HEAP,
309*a9fa9459Szrj   OPTION_IMAGE_BASE,
310*a9fa9459Szrj   OPTION_IMPURE,
311*a9fa9459Szrj   OPTION_INTERLEAVE_WIDTH,
312*a9fa9459Szrj   OPTION_KEEPGLOBAL_SYMBOLS,
313*a9fa9459Szrj   OPTION_KEEP_FILE_SYMBOLS,
314*a9fa9459Szrj   OPTION_KEEP_SYMBOLS,
315*a9fa9459Szrj   OPTION_LOCALIZE_HIDDEN,
316*a9fa9459Szrj   OPTION_LOCALIZE_SYMBOLS,
317*a9fa9459Szrj   OPTION_LONG_SECTION_NAMES,
318*a9fa9459Szrj   OPTION_NO_CHANGE_WARNINGS,
319*a9fa9459Szrj   OPTION_ONLY_KEEP_DEBUG,
320*a9fa9459Szrj   OPTION_PAD_TO,
321*a9fa9459Szrj   OPTION_PREFIX_ALLOC_SECTIONS,
322*a9fa9459Szrj   OPTION_PREFIX_SECTIONS,
323*a9fa9459Szrj   OPTION_PREFIX_SYMBOLS,
324*a9fa9459Szrj   OPTION_PURE,
325*a9fa9459Szrj   OPTION_READONLY_TEXT,
326*a9fa9459Szrj   OPTION_REDEFINE_SYM,
327*a9fa9459Szrj   OPTION_REDEFINE_SYMS,
328*a9fa9459Szrj   OPTION_REMOVE_LEADING_CHAR,
329*a9fa9459Szrj   OPTION_RENAME_SECTION,
330*a9fa9459Szrj   OPTION_REVERSE_BYTES,
331*a9fa9459Szrj   OPTION_SECTION_ALIGNMENT,
332*a9fa9459Szrj   OPTION_SET_SECTION_FLAGS,
333*a9fa9459Szrj   OPTION_SET_START,
334*a9fa9459Szrj   OPTION_SREC_FORCES3,
335*a9fa9459Szrj   OPTION_SREC_LEN,
336*a9fa9459Szrj   OPTION_STACK,
337*a9fa9459Szrj   OPTION_STRIP_DWO,
338*a9fa9459Szrj   OPTION_STRIP_SYMBOLS,
339*a9fa9459Szrj   OPTION_STRIP_UNNEEDED,
340*a9fa9459Szrj   OPTION_STRIP_UNNEEDED_SYMBOL,
341*a9fa9459Szrj   OPTION_STRIP_UNNEEDED_SYMBOLS,
342*a9fa9459Szrj   OPTION_SUBSYSTEM,
343*a9fa9459Szrj   OPTION_UPDATE_SECTION,
344*a9fa9459Szrj   OPTION_WEAKEN,
345*a9fa9459Szrj   OPTION_WEAKEN_SYMBOLS,
346*a9fa9459Szrj   OPTION_WRITABLE_TEXT
347*a9fa9459Szrj };
348*a9fa9459Szrj 
349*a9fa9459Szrj /* Options to handle if running as "strip".  */
350*a9fa9459Szrj 
351*a9fa9459Szrj static struct option strip_options[] =
352*a9fa9459Szrj {
353*a9fa9459Szrj   {"disable-deterministic-archives", no_argument, 0, 'U'},
354*a9fa9459Szrj   {"discard-all", no_argument, 0, 'x'},
355*a9fa9459Szrj   {"discard-locals", no_argument, 0, 'X'},
356*a9fa9459Szrj   {"enable-deterministic-archives", no_argument, 0, 'D'},
357*a9fa9459Szrj   {"format", required_argument, 0, 'F'}, /* Obsolete */
358*a9fa9459Szrj   {"help", no_argument, 0, 'h'},
359*a9fa9459Szrj   {"info", no_argument, 0, OPTION_FORMATS_INFO},
360*a9fa9459Szrj   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
361*a9fa9459Szrj   {"input-target", required_argument, 0, 'I'},
362*a9fa9459Szrj   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
363*a9fa9459Szrj   {"keep-symbol", required_argument, 0, 'K'},
364*a9fa9459Szrj   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
365*a9fa9459Szrj   {"output-file", required_argument, 0, 'o'},
366*a9fa9459Szrj   {"output-format", required_argument, 0, 'O'},	/* Obsolete */
367*a9fa9459Szrj   {"output-target", required_argument, 0, 'O'},
368*a9fa9459Szrj   {"preserve-dates", no_argument, 0, 'p'},
369*a9fa9459Szrj   {"remove-section", required_argument, 0, 'R'},
370*a9fa9459Szrj   {"strip-all", no_argument, 0, 's'},
371*a9fa9459Szrj   {"strip-debug", no_argument, 0, 'S'},
372*a9fa9459Szrj   {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
373*a9fa9459Szrj   {"strip-symbol", required_argument, 0, 'N'},
374*a9fa9459Szrj   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
375*a9fa9459Szrj   {"target", required_argument, 0, 'F'},
376*a9fa9459Szrj   {"verbose", no_argument, 0, 'v'},
377*a9fa9459Szrj   {"version", no_argument, 0, 'V'},
378*a9fa9459Szrj   {"wildcard", no_argument, 0, 'w'},
379*a9fa9459Szrj   {0, no_argument, 0, 0}
380*a9fa9459Szrj };
381*a9fa9459Szrj 
382*a9fa9459Szrj /* Options to handle if running as "objcopy".  */
383*a9fa9459Szrj 
384*a9fa9459Szrj static struct option copy_options[] =
385*a9fa9459Szrj {
386*a9fa9459Szrj   {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
387*a9fa9459Szrj   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
388*a9fa9459Szrj   {"add-symbol", required_argument, 0, OPTION_ADD_SYMBOL},
389*a9fa9459Szrj   {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
390*a9fa9459Szrj   {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
391*a9fa9459Szrj   {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
392*a9fa9459Szrj   {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
393*a9fa9459Szrj   {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
394*a9fa9459Szrj   {"binary-architecture", required_argument, 0, 'B'},
395*a9fa9459Szrj   {"byte", required_argument, 0, 'b'},
396*a9fa9459Szrj   {"change-addresses", required_argument, 0, OPTION_CHANGE_ADDRESSES},
397*a9fa9459Szrj   {"change-leading-char", no_argument, 0, OPTION_CHANGE_LEADING_CHAR},
398*a9fa9459Szrj   {"change-section-address", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
399*a9fa9459Szrj   {"change-section-lma", required_argument, 0, OPTION_CHANGE_SECTION_LMA},
400*a9fa9459Szrj   {"change-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_VMA},
401*a9fa9459Szrj   {"change-start", required_argument, 0, OPTION_CHANGE_START},
402*a9fa9459Szrj   {"change-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
403*a9fa9459Szrj   {"compress-debug-sections", optional_argument, 0, OPTION_COMPRESS_DEBUG_SECTIONS},
404*a9fa9459Szrj   {"debugging", no_argument, 0, OPTION_DEBUGGING},
405*a9fa9459Szrj   {"decompress-debug-sections", no_argument, 0, OPTION_DECOMPRESS_DEBUG_SECTIONS},
406*a9fa9459Szrj   {"disable-deterministic-archives", no_argument, 0, 'U'},
407*a9fa9459Szrj   {"discard-all", no_argument, 0, 'x'},
408*a9fa9459Szrj   {"discard-locals", no_argument, 0, 'X'},
409*a9fa9459Szrj   {"dump-section", required_argument, 0, OPTION_DUMP_SECTION},
410*a9fa9459Szrj   {"elf-stt-common", required_argument, 0, OPTION_ELF_STT_COMMON},
411*a9fa9459Szrj   {"enable-deterministic-archives", no_argument, 0, 'D'},
412*a9fa9459Szrj   {"extract-dwo", no_argument, 0, OPTION_EXTRACT_DWO},
413*a9fa9459Szrj   {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
414*a9fa9459Szrj   {"file-alignment", required_argument, 0, OPTION_FILE_ALIGNMENT},
415*a9fa9459Szrj   {"format", required_argument, 0, 'F'}, /* Obsolete */
416*a9fa9459Szrj   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
417*a9fa9459Szrj   {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
418*a9fa9459Szrj   {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
419*a9fa9459Szrj   {"heap", required_argument, 0, OPTION_HEAP},
420*a9fa9459Szrj   {"help", no_argument, 0, 'h'},
421*a9fa9459Szrj   {"image-base", required_argument, 0 , OPTION_IMAGE_BASE},
422*a9fa9459Szrj   {"impure", no_argument, 0, OPTION_IMPURE},
423*a9fa9459Szrj   {"info", no_argument, 0, OPTION_FORMATS_INFO},
424*a9fa9459Szrj   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
425*a9fa9459Szrj   {"input-target", required_argument, 0, 'I'},
426*a9fa9459Szrj   {"interleave", optional_argument, 0, 'i'},
427*a9fa9459Szrj   {"interleave-width", required_argument, 0, OPTION_INTERLEAVE_WIDTH},
428*a9fa9459Szrj   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
429*a9fa9459Szrj   {"keep-global-symbol", required_argument, 0, 'G'},
430*a9fa9459Szrj   {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS},
431*a9fa9459Szrj   {"keep-symbol", required_argument, 0, 'K'},
432*a9fa9459Szrj   {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS},
433*a9fa9459Szrj   {"localize-hidden", no_argument, 0, OPTION_LOCALIZE_HIDDEN},
434*a9fa9459Szrj   {"localize-symbol", required_argument, 0, 'L'},
435*a9fa9459Szrj   {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS},
436*a9fa9459Szrj   {"long-section-names", required_argument, 0, OPTION_LONG_SECTION_NAMES},
437*a9fa9459Szrj   {"no-adjust-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
438*a9fa9459Szrj   {"no-change-warnings", no_argument, 0, OPTION_NO_CHANGE_WARNINGS},
439*a9fa9459Szrj   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
440*a9fa9459Szrj   {"only-section", required_argument, 0, 'j'},
441*a9fa9459Szrj   {"output-format", required_argument, 0, 'O'},	/* Obsolete */
442*a9fa9459Szrj   {"output-target", required_argument, 0, 'O'},
443*a9fa9459Szrj   {"pad-to", required_argument, 0, OPTION_PAD_TO},
444*a9fa9459Szrj   {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
445*a9fa9459Szrj   {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
446*a9fa9459Szrj   {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
447*a9fa9459Szrj   {"preserve-dates", no_argument, 0, 'p'},
448*a9fa9459Szrj   {"pure", no_argument, 0, OPTION_PURE},
449*a9fa9459Szrj   {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
450*a9fa9459Szrj   {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM},
451*a9fa9459Szrj   {"redefine-syms", required_argument, 0, OPTION_REDEFINE_SYMS},
452*a9fa9459Szrj   {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR},
453*a9fa9459Szrj   {"remove-section", required_argument, 0, 'R'},
454*a9fa9459Szrj   {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
455*a9fa9459Szrj   {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
456*a9fa9459Szrj   {"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
457*a9fa9459Szrj   {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
458*a9fa9459Szrj   {"set-start", required_argument, 0, OPTION_SET_START},
459*a9fa9459Szrj   {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
460*a9fa9459Szrj   {"srec-len", required_argument, 0, OPTION_SREC_LEN},
461*a9fa9459Szrj   {"stack", required_argument, 0, OPTION_STACK},
462*a9fa9459Szrj   {"strip-all", no_argument, 0, 'S'},
463*a9fa9459Szrj   {"strip-debug", no_argument, 0, 'g'},
464*a9fa9459Szrj   {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
465*a9fa9459Szrj   {"strip-symbol", required_argument, 0, 'N'},
466*a9fa9459Szrj   {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
467*a9fa9459Szrj   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
468*a9fa9459Szrj   {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
469*a9fa9459Szrj   {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
470*a9fa9459Szrj   {"subsystem", required_argument, 0, OPTION_SUBSYSTEM},
471*a9fa9459Szrj   {"target", required_argument, 0, 'F'},
472*a9fa9459Szrj   {"update-section", required_argument, 0, OPTION_UPDATE_SECTION},
473*a9fa9459Szrj   {"verbose", no_argument, 0, 'v'},
474*a9fa9459Szrj   {"version", no_argument, 0, 'V'},
475*a9fa9459Szrj   {"weaken", no_argument, 0, OPTION_WEAKEN},
476*a9fa9459Szrj   {"weaken-symbol", required_argument, 0, 'W'},
477*a9fa9459Szrj   {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
478*a9fa9459Szrj   {"wildcard", no_argument, 0, 'w'},
479*a9fa9459Szrj   {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
480*a9fa9459Szrj   {0, no_argument, 0, 0}
481*a9fa9459Szrj };
482*a9fa9459Szrj 
483*a9fa9459Szrj /* IMPORTS */
484*a9fa9459Szrj extern char *program_name;
485*a9fa9459Szrj 
486*a9fa9459Szrj /* This flag distinguishes between strip and objcopy:
487*a9fa9459Szrj    1 means this is 'strip'; 0 means this is 'objcopy'.
488*a9fa9459Szrj    -1 means if we should use argv[0] to decide.  */
489*a9fa9459Szrj extern int is_strip;
490*a9fa9459Szrj 
491*a9fa9459Szrj /* The maximum length of an S record.  This variable is declared in srec.c
492*a9fa9459Szrj    and can be modified by the --srec-len parameter.  */
493*a9fa9459Szrj extern unsigned int Chunk;
494*a9fa9459Szrj 
495*a9fa9459Szrj /* Restrict the generation of Srecords to type S3 only.
496*a9fa9459Szrj    This variable is declare in bfd/srec.c and can be toggled
497*a9fa9459Szrj    on by the --srec-forceS3 command line switch.  */
498*a9fa9459Szrj extern bfd_boolean S3Forced;
499*a9fa9459Szrj 
500*a9fa9459Szrj /* Forward declarations.  */
501*a9fa9459Szrj static void setup_section (bfd *, asection *, void *);
502*a9fa9459Szrj static void setup_bfd_headers (bfd *, bfd *);
503*a9fa9459Szrj static void copy_relocations_in_section (bfd *, asection *, void *);
504*a9fa9459Szrj static void copy_section (bfd *, asection *, void *);
505*a9fa9459Szrj static void get_sections (bfd *, asection *, void *);
506*a9fa9459Szrj static int compare_section_lma (const void *, const void *);
507*a9fa9459Szrj static void mark_symbols_used_in_relocations (bfd *, asection *, void *);
508*a9fa9459Szrj static bfd_boolean write_debugging_info (bfd *, void *, long *, asymbol ***);
509*a9fa9459Szrj static const char *lookup_sym_redefinition (const char *);
510*a9fa9459Szrj static const char *find_section_rename (const char *, flagword *);
511*a9fa9459Szrj 
512*a9fa9459Szrj static void
copy_usage(FILE * stream,int exit_status)513*a9fa9459Szrj copy_usage (FILE *stream, int exit_status)
514*a9fa9459Szrj {
515*a9fa9459Szrj   fprintf (stream, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name);
516*a9fa9459Szrj   fprintf (stream, _(" Copies a binary file, possibly transforming it in the process\n"));
517*a9fa9459Szrj   fprintf (stream, _(" The options are:\n"));
518*a9fa9459Szrj   fprintf (stream, _("\
519*a9fa9459Szrj   -I --input-target <bfdname>      Assume input file is in format <bfdname>\n\
520*a9fa9459Szrj   -O --output-target <bfdname>     Create an output file in format <bfdname>\n\
521*a9fa9459Szrj   -B --binary-architecture <arch>  Set output arch, when input is arch-less\n\
522*a9fa9459Szrj   -F --target <bfdname>            Set both input and output format to <bfdname>\n\
523*a9fa9459Szrj      --debugging                   Convert debugging information, if possible\n\
524*a9fa9459Szrj   -p --preserve-dates              Copy modified/access timestamps to the output\n"));
525*a9fa9459Szrj   if (DEFAULT_AR_DETERMINISTIC)
526*a9fa9459Szrj     fprintf (stream, _("\
527*a9fa9459Szrj   -D --enable-deterministic-archives\n\
528*a9fa9459Szrj                                    Produce deterministic output when stripping archives (default)\n\
529*a9fa9459Szrj   -U --disable-deterministic-archives\n\
530*a9fa9459Szrj                                    Disable -D behavior\n"));
531*a9fa9459Szrj   else
532*a9fa9459Szrj     fprintf (stream, _("\
533*a9fa9459Szrj   -D --enable-deterministic-archives\n\
534*a9fa9459Szrj                                    Produce deterministic output when stripping archives\n\
535*a9fa9459Szrj   -U --disable-deterministic-archives\n\
536*a9fa9459Szrj                                    Disable -D behavior (default)\n"));
537*a9fa9459Szrj   fprintf (stream, _("\
538*a9fa9459Szrj   -j --only-section <name>         Only copy section <name> into the output\n\
539*a9fa9459Szrj      --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>\n\
540*a9fa9459Szrj   -R --remove-section <name>       Remove section <name> from the output\n\
541*a9fa9459Szrj   -S --strip-all                   Remove all symbol and relocation information\n\
542*a9fa9459Szrj   -g --strip-debug                 Remove all debugging symbols & sections\n\
543*a9fa9459Szrj      --strip-dwo                   Remove all DWO sections\n\
544*a9fa9459Szrj      --strip-unneeded              Remove all symbols not needed by relocations\n\
545*a9fa9459Szrj   -N --strip-symbol <name>         Do not copy symbol <name>\n\
546*a9fa9459Szrj      --strip-unneeded-symbol <name>\n\
547*a9fa9459Szrj                                    Do not copy symbol <name> unless needed by\n\
548*a9fa9459Szrj                                      relocations\n\
549*a9fa9459Szrj      --only-keep-debug             Strip everything but the debug information\n\
550*a9fa9459Szrj      --extract-dwo                 Copy only DWO sections\n\
551*a9fa9459Szrj      --extract-symbol              Remove section contents but keep symbols\n\
552*a9fa9459Szrj   -K --keep-symbol <name>          Do not strip symbol <name>\n\
553*a9fa9459Szrj      --keep-file-symbols           Do not strip file symbol(s)\n\
554*a9fa9459Szrj      --localize-hidden             Turn all ELF hidden symbols into locals\n\
555*a9fa9459Szrj   -L --localize-symbol <name>      Force symbol <name> to be marked as a local\n\
556*a9fa9459Szrj      --globalize-symbol <name>     Force symbol <name> to be marked as a global\n\
557*a9fa9459Szrj   -G --keep-global-symbol <name>   Localize all symbols except <name>\n\
558*a9fa9459Szrj   -W --weaken-symbol <name>        Force symbol <name> to be marked as a weak\n\
559*a9fa9459Szrj      --weaken                      Force all global symbols to be marked as weak\n\
560*a9fa9459Szrj   -w --wildcard                    Permit wildcard in symbol comparison\n\
561*a9fa9459Szrj   -x --discard-all                 Remove all non-global symbols\n\
562*a9fa9459Szrj   -X --discard-locals              Remove any compiler-generated symbols\n\
563*a9fa9459Szrj   -i --interleave[=<number>]       Only copy N out of every <number> bytes\n\
564*a9fa9459Szrj      --interleave-width <number>   Set N for --interleave\n\
565*a9fa9459Szrj   -b --byte <num>                  Select byte <num> in every interleaved block\n\
566*a9fa9459Szrj      --gap-fill <val>              Fill gaps between sections with <val>\n\
567*a9fa9459Szrj      --pad-to <addr>               Pad the last section up to address <addr>\n\
568*a9fa9459Szrj      --set-start <addr>            Set the start address to <addr>\n\
569*a9fa9459Szrj     {--change-start|--adjust-start} <incr>\n\
570*a9fa9459Szrj                                    Add <incr> to the start address\n\
571*a9fa9459Szrj     {--change-addresses|--adjust-vma} <incr>\n\
572*a9fa9459Szrj                                    Add <incr> to LMA, VMA and start addresses\n\
573*a9fa9459Szrj     {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>\n\
574*a9fa9459Szrj                                    Change LMA and VMA of section <name> by <val>\n\
575*a9fa9459Szrj      --change-section-lma <name>{=|+|-}<val>\n\
576*a9fa9459Szrj                                    Change the LMA of section <name> by <val>\n\
577*a9fa9459Szrj      --change-section-vma <name>{=|+|-}<val>\n\
578*a9fa9459Szrj                                    Change the VMA of section <name> by <val>\n\
579*a9fa9459Szrj     {--[no-]change-warnings|--[no-]adjust-warnings}\n\
580*a9fa9459Szrj                                    Warn if a named section does not exist\n\
581*a9fa9459Szrj      --set-section-flags <name>=<flags>\n\
582*a9fa9459Szrj                                    Set section <name>'s properties to <flags>\n\
583*a9fa9459Szrj      --add-section <name>=<file>   Add section <name> found in <file> to output\n\
584*a9fa9459Szrj      --update-section <name>=<file>\n\
585*a9fa9459Szrj                                    Update contents of section <name> with\n\
586*a9fa9459Szrj                                    contents found in <file>\n\
587*a9fa9459Szrj      --dump-section <name>=<file>  Dump the contents of section <name> into <file>\n\
588*a9fa9459Szrj      --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
589*a9fa9459Szrj      --long-section-names {enable|disable|keep}\n\
590*a9fa9459Szrj                                    Handle long section names in Coff objects.\n\
591*a9fa9459Szrj      --change-leading-char         Force output format's leading character style\n\
592*a9fa9459Szrj      --remove-leading-char         Remove leading character from global symbols\n\
593*a9fa9459Szrj      --reverse-bytes=<num>         Reverse <num> bytes at a time, in output sections with content\n\
594*a9fa9459Szrj      --redefine-sym <old>=<new>    Redefine symbol name <old> to <new>\n\
595*a9fa9459Szrj      --redefine-syms <file>        --redefine-sym for all symbol pairs \n\
596*a9fa9459Szrj                                      listed in <file>\n\
597*a9fa9459Szrj      --srec-len <number>           Restrict the length of generated Srecords\n\
598*a9fa9459Szrj      --srec-forceS3                Restrict the type of generated Srecords to S3\n\
599*a9fa9459Szrj      --strip-symbols <file>        -N for all symbols listed in <file>\n\
600*a9fa9459Szrj      --strip-unneeded-symbols <file>\n\
601*a9fa9459Szrj                                    --strip-unneeded-symbol for all symbols listed\n\
602*a9fa9459Szrj                                      in <file>\n\
603*a9fa9459Szrj      --keep-symbols <file>         -K for all symbols listed in <file>\n\
604*a9fa9459Szrj      --localize-symbols <file>     -L for all symbols listed in <file>\n\
605*a9fa9459Szrj      --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
606*a9fa9459Szrj      --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
607*a9fa9459Szrj      --weaken-symbols <file>       -W for all symbols listed in <file>\n\
608*a9fa9459Szrj      --add-symbol <name>=[<section>:]<value>[,<flags>]  Add a symbol\n\
609*a9fa9459Szrj      --alt-machine-code <index>    Use the target's <index>'th alternative machine\n\
610*a9fa9459Szrj      --writable-text               Mark the output text as writable\n\
611*a9fa9459Szrj      --readonly-text               Make the output text write protected\n\
612*a9fa9459Szrj      --pure                        Mark the output file as demand paged\n\
613*a9fa9459Szrj      --impure                      Mark the output file as impure\n\
614*a9fa9459Szrj      --prefix-symbols <prefix>     Add <prefix> to start of every symbol name\n\
615*a9fa9459Szrj      --prefix-sections <prefix>    Add <prefix> to start of every section name\n\
616*a9fa9459Szrj      --prefix-alloc-sections <prefix>\n\
617*a9fa9459Szrj                                    Add <prefix> to start of every allocatable\n\
618*a9fa9459Szrj                                      section name\n\
619*a9fa9459Szrj      --file-alignment <num>        Set PE file alignment to <num>\n\
620*a9fa9459Szrj      --heap <reserve>[,<commit>]   Set PE reserve/commit heap to <reserve>/\n\
621*a9fa9459Szrj                                    <commit>\n\
622*a9fa9459Szrj      --image-base <address>        Set PE image base to <address>\n\
623*a9fa9459Szrj      --section-alignment <num>     Set PE section alignment to <num>\n\
624*a9fa9459Szrj      --stack <reserve>[,<commit>]  Set PE reserve/commit stack to <reserve>/\n\
625*a9fa9459Szrj                                    <commit>\n\
626*a9fa9459Szrj      --subsystem <name>[:<version>]\n\
627*a9fa9459Szrj                                    Set PE subsystem to <name> [& <version>]\n\
628*a9fa9459Szrj      --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
629*a9fa9459Szrj                                    Compress DWARF debug sections using zlib\n\
630*a9fa9459Szrj      --decompress-debug-sections   Decompress DWARF debug sections using zlib\n\
631*a9fa9459Szrj      --elf-stt-common=[yes|no]     Generate ELF common symbols with STT_COMMON\n\
632*a9fa9459Szrj                                      type\n\
633*a9fa9459Szrj   -v --verbose                     List all object files modified\n\
634*a9fa9459Szrj   @<file>                          Read options from <file>\n\
635*a9fa9459Szrj   -V --version                     Display this program's version number\n\
636*a9fa9459Szrj   -h --help                        Display this output\n\
637*a9fa9459Szrj      --info                        List object formats & architectures supported\n\
638*a9fa9459Szrj "));
639*a9fa9459Szrj   list_supported_targets (program_name, stream);
640*a9fa9459Szrj   if (REPORT_BUGS_TO[0] && exit_status == 0)
641*a9fa9459Szrj     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
642*a9fa9459Szrj   exit (exit_status);
643*a9fa9459Szrj }
644*a9fa9459Szrj 
645*a9fa9459Szrj static void
strip_usage(FILE * stream,int exit_status)646*a9fa9459Szrj strip_usage (FILE *stream, int exit_status)
647*a9fa9459Szrj {
648*a9fa9459Szrj   fprintf (stream, _("Usage: %s <option(s)> in-file(s)\n"), program_name);
649*a9fa9459Szrj   fprintf (stream, _(" Removes symbols and sections from files\n"));
650*a9fa9459Szrj   fprintf (stream, _(" The options are:\n"));
651*a9fa9459Szrj   fprintf (stream, _("\
652*a9fa9459Szrj   -I --input-target=<bfdname>      Assume input file is in format <bfdname>\n\
653*a9fa9459Szrj   -O --output-target=<bfdname>     Create an output file in format <bfdname>\n\
654*a9fa9459Szrj   -F --target=<bfdname>            Set both input and output format to <bfdname>\n\
655*a9fa9459Szrj   -p --preserve-dates              Copy modified/access timestamps to the output\n\
656*a9fa9459Szrj "));
657*a9fa9459Szrj   if (DEFAULT_AR_DETERMINISTIC)
658*a9fa9459Szrj     fprintf (stream, _("\
659*a9fa9459Szrj   -D --enable-deterministic-archives\n\
660*a9fa9459Szrj                                    Produce deterministic output when stripping archives (default)\n\
661*a9fa9459Szrj   -U --disable-deterministic-archives\n\
662*a9fa9459Szrj                                    Disable -D behavior\n"));
663*a9fa9459Szrj   else
664*a9fa9459Szrj     fprintf (stream, _("\
665*a9fa9459Szrj   -D --enable-deterministic-archives\n\
666*a9fa9459Szrj                                    Produce deterministic output when stripping archives\n\
667*a9fa9459Szrj   -U --disable-deterministic-archives\n\
668*a9fa9459Szrj                                    Disable -D behavior (default)\n"));
669*a9fa9459Szrj   fprintf (stream, _("\
670*a9fa9459Szrj   -R --remove-section=<name>       Also remove section <name> from the output\n\
671*a9fa9459Szrj   -s --strip-all                   Remove all symbol and relocation information\n\
672*a9fa9459Szrj   -g -S -d --strip-debug           Remove all debugging symbols & sections\n\
673*a9fa9459Szrj      --strip-dwo                   Remove all DWO sections\n\
674*a9fa9459Szrj      --strip-unneeded              Remove all symbols not needed by relocations\n\
675*a9fa9459Szrj      --only-keep-debug             Strip everything but the debug information\n\
676*a9fa9459Szrj   -N --strip-symbol=<name>         Do not copy symbol <name>\n\
677*a9fa9459Szrj   -K --keep-symbol=<name>          Do not strip symbol <name>\n\
678*a9fa9459Szrj      --keep-file-symbols           Do not strip file symbol(s)\n\
679*a9fa9459Szrj   -w --wildcard                    Permit wildcard in symbol comparison\n\
680*a9fa9459Szrj   -x --discard-all                 Remove all non-global symbols\n\
681*a9fa9459Szrj   -X --discard-locals              Remove any compiler-generated symbols\n\
682*a9fa9459Szrj   -v --verbose                     List all object files modified\n\
683*a9fa9459Szrj   -V --version                     Display this program's version number\n\
684*a9fa9459Szrj   -h --help                        Display this output\n\
685*a9fa9459Szrj      --info                        List object formats & architectures supported\n\
686*a9fa9459Szrj   -o <file>                        Place stripped output into <file>\n\
687*a9fa9459Szrj "));
688*a9fa9459Szrj 
689*a9fa9459Szrj   list_supported_targets (program_name, stream);
690*a9fa9459Szrj   if (REPORT_BUGS_TO[0] && exit_status == 0)
691*a9fa9459Szrj     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
692*a9fa9459Szrj   exit (exit_status);
693*a9fa9459Szrj }
694*a9fa9459Szrj 
695*a9fa9459Szrj /* Parse section flags into a flagword, with a fatal error if the
696*a9fa9459Szrj    string can't be parsed.  */
697*a9fa9459Szrj 
698*a9fa9459Szrj static flagword
parse_flags(const char * s)699*a9fa9459Szrj parse_flags (const char *s)
700*a9fa9459Szrj {
701*a9fa9459Szrj   flagword ret;
702*a9fa9459Szrj   const char *snext;
703*a9fa9459Szrj   int len;
704*a9fa9459Szrj 
705*a9fa9459Szrj   ret = SEC_NO_FLAGS;
706*a9fa9459Szrj 
707*a9fa9459Szrj   do
708*a9fa9459Szrj     {
709*a9fa9459Szrj       snext = strchr (s, ',');
710*a9fa9459Szrj       if (snext == NULL)
711*a9fa9459Szrj 	len = strlen (s);
712*a9fa9459Szrj       else
713*a9fa9459Szrj 	{
714*a9fa9459Szrj 	  len = snext - s;
715*a9fa9459Szrj 	  ++snext;
716*a9fa9459Szrj 	}
717*a9fa9459Szrj 
718*a9fa9459Szrj       if (0) ;
719*a9fa9459Szrj #define PARSE_FLAG(fname,fval)					\
720*a9fa9459Szrj       else if (strncasecmp (fname, s, len) == 0) ret |= fval
721*a9fa9459Szrj       PARSE_FLAG ("alloc", SEC_ALLOC);
722*a9fa9459Szrj       PARSE_FLAG ("load", SEC_LOAD);
723*a9fa9459Szrj       PARSE_FLAG ("noload", SEC_NEVER_LOAD);
724*a9fa9459Szrj       PARSE_FLAG ("readonly", SEC_READONLY);
725*a9fa9459Szrj       PARSE_FLAG ("debug", SEC_DEBUGGING);
726*a9fa9459Szrj       PARSE_FLAG ("code", SEC_CODE);
727*a9fa9459Szrj       PARSE_FLAG ("data", SEC_DATA);
728*a9fa9459Szrj       PARSE_FLAG ("rom", SEC_ROM);
729*a9fa9459Szrj       PARSE_FLAG ("share", SEC_COFF_SHARED);
730*a9fa9459Szrj       PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
731*a9fa9459Szrj       PARSE_FLAG ("merge", SEC_MERGE);
732*a9fa9459Szrj       PARSE_FLAG ("strings", SEC_STRINGS);
733*a9fa9459Szrj #undef PARSE_FLAG
734*a9fa9459Szrj       else
735*a9fa9459Szrj 	{
736*a9fa9459Szrj 	  char *copy;
737*a9fa9459Szrj 
738*a9fa9459Szrj 	  copy = (char *) xmalloc (len + 1);
739*a9fa9459Szrj 	  strncpy (copy, s, len);
740*a9fa9459Szrj 	  copy[len] = '\0';
741*a9fa9459Szrj 	  non_fatal (_("unrecognized section flag `%s'"), copy);
742*a9fa9459Szrj 	  fatal (_("supported flags: %s"),
743*a9fa9459Szrj 		 "alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings");
744*a9fa9459Szrj 	}
745*a9fa9459Szrj 
746*a9fa9459Szrj       s = snext;
747*a9fa9459Szrj     }
748*a9fa9459Szrj   while (s != NULL);
749*a9fa9459Szrj 
750*a9fa9459Szrj   return ret;
751*a9fa9459Szrj }
752*a9fa9459Szrj 
753*a9fa9459Szrj /* Parse symbol flags into a flagword, with a fatal error if the
754*a9fa9459Szrj    string can't be parsed.  */
755*a9fa9459Szrj 
756*a9fa9459Szrj static flagword
parse_symflags(const char * s,char ** other)757*a9fa9459Szrj parse_symflags (const char *s, char **other)
758*a9fa9459Szrj {
759*a9fa9459Szrj   flagword ret;
760*a9fa9459Szrj   const char *snext;
761*a9fa9459Szrj   size_t len;
762*a9fa9459Szrj 
763*a9fa9459Szrj   ret = BSF_NO_FLAGS;
764*a9fa9459Szrj 
765*a9fa9459Szrj   do
766*a9fa9459Szrj     {
767*a9fa9459Szrj       snext = strchr (s, ',');
768*a9fa9459Szrj       if (snext == NULL)
769*a9fa9459Szrj 	len = strlen (s);
770*a9fa9459Szrj       else
771*a9fa9459Szrj 	{
772*a9fa9459Szrj 	  len = snext - s;
773*a9fa9459Szrj 	  ++snext;
774*a9fa9459Szrj 	}
775*a9fa9459Szrj 
776*a9fa9459Szrj #define PARSE_FLAG(fname, fval)						\
777*a9fa9459Szrj       else if (len == sizeof fname - 1					\
778*a9fa9459Szrj 	       && strncasecmp (fname, s, len) == 0)			\
779*a9fa9459Szrj 	ret |= fval
780*a9fa9459Szrj 
781*a9fa9459Szrj #define PARSE_OTHER(fname, fval)					\
782*a9fa9459Szrj       else if (len >= sizeof fname					\
783*a9fa9459Szrj 	       && strncasecmp (fname, s, sizeof fname - 1) == 0)	\
784*a9fa9459Szrj 	fval = xstrndup (s + sizeof fname - 1, len - sizeof fname + 1)
785*a9fa9459Szrj 
786*a9fa9459Szrj       if (0) ;
787*a9fa9459Szrj       PARSE_FLAG ("local", BSF_LOCAL);
788*a9fa9459Szrj       PARSE_FLAG ("global", BSF_GLOBAL);
789*a9fa9459Szrj       PARSE_FLAG ("export", BSF_EXPORT);
790*a9fa9459Szrj       PARSE_FLAG ("debug", BSF_DEBUGGING);
791*a9fa9459Szrj       PARSE_FLAG ("function", BSF_FUNCTION);
792*a9fa9459Szrj       PARSE_FLAG ("weak", BSF_WEAK);
793*a9fa9459Szrj       PARSE_FLAG ("section", BSF_SECTION_SYM);
794*a9fa9459Szrj       PARSE_FLAG ("constructor", BSF_CONSTRUCTOR);
795*a9fa9459Szrj       PARSE_FLAG ("warning", BSF_WARNING);
796*a9fa9459Szrj       PARSE_FLAG ("indirect", BSF_INDIRECT);
797*a9fa9459Szrj       PARSE_FLAG ("file", BSF_FILE);
798*a9fa9459Szrj       PARSE_FLAG ("object", BSF_OBJECT);
799*a9fa9459Szrj       PARSE_FLAG ("synthetic", BSF_SYNTHETIC);
800*a9fa9459Szrj       PARSE_FLAG ("indirect-function", BSF_GNU_INDIRECT_FUNCTION | BSF_FUNCTION);
801*a9fa9459Szrj       PARSE_FLAG ("unique-object", BSF_GNU_UNIQUE | BSF_OBJECT);
802*a9fa9459Szrj       PARSE_OTHER ("before=", *other);
803*a9fa9459Szrj 
804*a9fa9459Szrj #undef PARSE_FLAG
805*a9fa9459Szrj #undef PARSE_OTHER
806*a9fa9459Szrj       else
807*a9fa9459Szrj 	{
808*a9fa9459Szrj 	  char *copy;
809*a9fa9459Szrj 
810*a9fa9459Szrj 	  copy = (char *) xmalloc (len + 1);
811*a9fa9459Szrj 	  strncpy (copy, s, len);
812*a9fa9459Szrj 	  copy[len] = '\0';
813*a9fa9459Szrj 	  non_fatal (_("unrecognized symbol flag `%s'"), copy);
814*a9fa9459Szrj 	  fatal (_("supported flags: %s"),
815*a9fa9459Szrj 		 "local, global, export, debug, function, weak, section, "
816*a9fa9459Szrj 		 "constructor, warning, indirect, file, object, synthetic, "
817*a9fa9459Szrj 		 "indirect-function, unique-object, before=<othersym>");
818*a9fa9459Szrj 	}
819*a9fa9459Szrj 
820*a9fa9459Szrj       s = snext;
821*a9fa9459Szrj     }
822*a9fa9459Szrj   while (s != NULL);
823*a9fa9459Szrj 
824*a9fa9459Szrj   return ret;
825*a9fa9459Szrj }
826*a9fa9459Szrj 
827*a9fa9459Szrj /* Find and optionally add an entry in the change_sections list.
828*a9fa9459Szrj 
829*a9fa9459Szrj    We need to be careful in how we match section names because of the support
830*a9fa9459Szrj    for wildcard characters.  For example suppose that the user has invoked
831*a9fa9459Szrj    objcopy like this:
832*a9fa9459Szrj 
833*a9fa9459Szrj        --set-section-flags .debug_*=debug
834*a9fa9459Szrj        --set-section-flags .debug_str=readonly,debug
835*a9fa9459Szrj        --change-section-address .debug_*ranges=0x1000
836*a9fa9459Szrj 
837*a9fa9459Szrj    With the idea that all debug sections will receive the DEBUG flag, the
838*a9fa9459Szrj    .debug_str section will also receive the READONLY flag and the
839*a9fa9459Szrj    .debug_ranges and .debug_aranges sections will have their address set to
840*a9fa9459Szrj    0x1000.  (This may not make much sense, but it is just an example).
841*a9fa9459Szrj 
842*a9fa9459Szrj    When adding the section name patterns to the section list we need to make
843*a9fa9459Szrj    sure that previous entries do not match with the new entry, unless the
844*a9fa9459Szrj    match is exact.  (In which case we assume that the user is overriding
845*a9fa9459Szrj    the previous entry with the new context).
846*a9fa9459Szrj 
847*a9fa9459Szrj    When matching real section names to the section list we make use of the
848*a9fa9459Szrj    wildcard characters, but we must do so in context.  Eg if we are setting
849*a9fa9459Szrj    section addresses then we match for .debug_ranges but not for .debug_info.
850*a9fa9459Szrj 
851*a9fa9459Szrj    Finally, if ADD is false and we do find a match, we mark the section list
852*a9fa9459Szrj    entry as used.  */
853*a9fa9459Szrj 
854*a9fa9459Szrj static struct section_list *
find_section_list(const char * name,bfd_boolean add,unsigned int context)855*a9fa9459Szrj find_section_list (const char *name, bfd_boolean add, unsigned int context)
856*a9fa9459Szrj {
857*a9fa9459Szrj   struct section_list *p;
858*a9fa9459Szrj 
859*a9fa9459Szrj   /* assert ((context & ((1 << 7) - 1)) != 0); */
860*a9fa9459Szrj 
861*a9fa9459Szrj   for (p = change_sections; p != NULL; p = p->next)
862*a9fa9459Szrj     {
863*a9fa9459Szrj       if (add)
864*a9fa9459Szrj 	{
865*a9fa9459Szrj 	  if (strcmp (p->pattern, name) == 0)
866*a9fa9459Szrj 	    {
867*a9fa9459Szrj 	      /* Check for context conflicts.  */
868*a9fa9459Szrj 	      if (((p->context & SECTION_CONTEXT_REMOVE)
869*a9fa9459Szrj 		   && (context & SECTION_CONTEXT_COPY))
870*a9fa9459Szrj 		  || ((context & SECTION_CONTEXT_REMOVE)
871*a9fa9459Szrj 		      && (p->context & SECTION_CONTEXT_COPY)))
872*a9fa9459Szrj 		fatal (_("error: %s both copied and removed"), name);
873*a9fa9459Szrj 
874*a9fa9459Szrj 	      if (((p->context & SECTION_CONTEXT_SET_VMA)
875*a9fa9459Szrj 		  && (context & SECTION_CONTEXT_ALTER_VMA))
876*a9fa9459Szrj 		  || ((context & SECTION_CONTEXT_SET_VMA)
877*a9fa9459Szrj 		      && (context & SECTION_CONTEXT_ALTER_VMA)))
878*a9fa9459Szrj 		fatal (_("error: %s both sets and alters VMA"), name);
879*a9fa9459Szrj 
880*a9fa9459Szrj 	      if (((p->context & SECTION_CONTEXT_SET_LMA)
881*a9fa9459Szrj 		  && (context & SECTION_CONTEXT_ALTER_LMA))
882*a9fa9459Szrj 		  || ((context & SECTION_CONTEXT_SET_LMA)
883*a9fa9459Szrj 		      && (context & SECTION_CONTEXT_ALTER_LMA)))
884*a9fa9459Szrj 		fatal (_("error: %s both sets and alters LMA"), name);
885*a9fa9459Szrj 
886*a9fa9459Szrj 	      /* Extend the context.  */
887*a9fa9459Szrj 	      p->context |= context;
888*a9fa9459Szrj 	      return p;
889*a9fa9459Szrj 	    }
890*a9fa9459Szrj 	}
891*a9fa9459Szrj       /* If we are not adding a new name/pattern then
892*a9fa9459Szrj 	 only check for a match if the context applies.  */
893*a9fa9459Szrj       else if ((p->context & context)
894*a9fa9459Szrj 	       /* We could check for the presence of wildchar characters
895*a9fa9459Szrj 		  first and choose between calling strcmp and fnmatch,
896*a9fa9459Szrj 		  but is that really worth it ?  */
897*a9fa9459Szrj 	       && fnmatch (p->pattern, name, 0) == 0)
898*a9fa9459Szrj 	{
899*a9fa9459Szrj 	  p->used = TRUE;
900*a9fa9459Szrj 	  return p;
901*a9fa9459Szrj 	}
902*a9fa9459Szrj     }
903*a9fa9459Szrj 
904*a9fa9459Szrj   if (! add)
905*a9fa9459Szrj     return NULL;
906*a9fa9459Szrj 
907*a9fa9459Szrj   p = (struct section_list *) xmalloc (sizeof (struct section_list));
908*a9fa9459Szrj   p->pattern = name;
909*a9fa9459Szrj   p->used = FALSE;
910*a9fa9459Szrj   p->context = context;
911*a9fa9459Szrj   p->vma_val = 0;
912*a9fa9459Szrj   p->lma_val = 0;
913*a9fa9459Szrj   p->flags = 0;
914*a9fa9459Szrj   p->next = change_sections;
915*a9fa9459Szrj   change_sections = p;
916*a9fa9459Szrj 
917*a9fa9459Szrj   return p;
918*a9fa9459Szrj }
919*a9fa9459Szrj 
920*a9fa9459Szrj /* There is htab_hash_string but no htab_eq_string. Makes sense.  */
921*a9fa9459Szrj 
922*a9fa9459Szrj static int
eq_string(const void * s1,const void * s2)923*a9fa9459Szrj eq_string (const void *s1, const void *s2)
924*a9fa9459Szrj {
925*a9fa9459Szrj   return strcmp ((const char *) s1, (const char *) s2) == 0;
926*a9fa9459Szrj }
927*a9fa9459Szrj 
928*a9fa9459Szrj static htab_t
create_symbol_htab(void)929*a9fa9459Szrj create_symbol_htab (void)
930*a9fa9459Szrj {
931*a9fa9459Szrj   return htab_create_alloc (16, htab_hash_string, eq_string, NULL, xcalloc, free);
932*a9fa9459Szrj }
933*a9fa9459Szrj 
934*a9fa9459Szrj static void
create_symbol_htabs(void)935*a9fa9459Szrj create_symbol_htabs (void)
936*a9fa9459Szrj {
937*a9fa9459Szrj   strip_specific_htab = create_symbol_htab ();
938*a9fa9459Szrj   strip_unneeded_htab = create_symbol_htab ();
939*a9fa9459Szrj   keep_specific_htab = create_symbol_htab ();
940*a9fa9459Szrj   localize_specific_htab = create_symbol_htab ();
941*a9fa9459Szrj   globalize_specific_htab = create_symbol_htab ();
942*a9fa9459Szrj   keepglobal_specific_htab = create_symbol_htab ();
943*a9fa9459Szrj   weaken_specific_htab = create_symbol_htab ();
944*a9fa9459Szrj }
945*a9fa9459Szrj 
946*a9fa9459Szrj /* Add a symbol to strip_specific_list.  */
947*a9fa9459Szrj 
948*a9fa9459Szrj static void
add_specific_symbol(const char * name,htab_t htab)949*a9fa9459Szrj add_specific_symbol (const char *name, htab_t htab)
950*a9fa9459Szrj {
951*a9fa9459Szrj   *htab_find_slot (htab, name, INSERT) = (char *) name;
952*a9fa9459Szrj }
953*a9fa9459Szrj 
954*a9fa9459Szrj /* Add symbols listed in `filename' to strip_specific_list.  */
955*a9fa9459Szrj 
956*a9fa9459Szrj #define IS_WHITESPACE(c)      ((c) == ' ' || (c) == '\t')
957*a9fa9459Szrj #define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0')
958*a9fa9459Szrj 
959*a9fa9459Szrj static void
add_specific_symbols(const char * filename,htab_t htab)960*a9fa9459Szrj add_specific_symbols (const char *filename, htab_t htab)
961*a9fa9459Szrj {
962*a9fa9459Szrj   off_t  size;
963*a9fa9459Szrj   FILE * f;
964*a9fa9459Szrj   char * line;
965*a9fa9459Szrj   char * buffer;
966*a9fa9459Szrj   unsigned int line_count;
967*a9fa9459Szrj 
968*a9fa9459Szrj   size = get_file_size (filename);
969*a9fa9459Szrj   if (size == 0)
970*a9fa9459Szrj     {
971*a9fa9459Szrj       status = 1;
972*a9fa9459Szrj       return;
973*a9fa9459Szrj     }
974*a9fa9459Szrj 
975*a9fa9459Szrj   buffer = (char *) xmalloc (size + 2);
976*a9fa9459Szrj   f = fopen (filename, FOPEN_RT);
977*a9fa9459Szrj   if (f == NULL)
978*a9fa9459Szrj     fatal (_("cannot open '%s': %s"), filename, strerror (errno));
979*a9fa9459Szrj 
980*a9fa9459Szrj   if (fread (buffer, 1, size, f) == 0 || ferror (f))
981*a9fa9459Szrj     fatal (_("%s: fread failed"), filename);
982*a9fa9459Szrj 
983*a9fa9459Szrj   fclose (f);
984*a9fa9459Szrj   buffer [size] = '\n';
985*a9fa9459Szrj   buffer [size + 1] = '\0';
986*a9fa9459Szrj 
987*a9fa9459Szrj   line_count = 1;
988*a9fa9459Szrj 
989*a9fa9459Szrj   for (line = buffer; * line != '\0'; line ++)
990*a9fa9459Szrj     {
991*a9fa9459Szrj       char * eol;
992*a9fa9459Szrj       char * name;
993*a9fa9459Szrj       char * name_end;
994*a9fa9459Szrj       int finished = FALSE;
995*a9fa9459Szrj 
996*a9fa9459Szrj       for (eol = line;; eol ++)
997*a9fa9459Szrj 	{
998*a9fa9459Szrj 	  switch (* eol)
999*a9fa9459Szrj 	    {
1000*a9fa9459Szrj 	    case '\n':
1001*a9fa9459Szrj 	      * eol = '\0';
1002*a9fa9459Szrj 	      /* Cope with \n\r.  */
1003*a9fa9459Szrj 	      if (eol[1] == '\r')
1004*a9fa9459Szrj 		++ eol;
1005*a9fa9459Szrj 	      finished = TRUE;
1006*a9fa9459Szrj 	      break;
1007*a9fa9459Szrj 
1008*a9fa9459Szrj 	    case '\r':
1009*a9fa9459Szrj 	      * eol = '\0';
1010*a9fa9459Szrj 	      /* Cope with \r\n.  */
1011*a9fa9459Szrj 	      if (eol[1] == '\n')
1012*a9fa9459Szrj 		++ eol;
1013*a9fa9459Szrj 	      finished = TRUE;
1014*a9fa9459Szrj 	      break;
1015*a9fa9459Szrj 
1016*a9fa9459Szrj 	    case 0:
1017*a9fa9459Szrj 	      finished = TRUE;
1018*a9fa9459Szrj 	      break;
1019*a9fa9459Szrj 
1020*a9fa9459Szrj 	    case '#':
1021*a9fa9459Szrj 	      /* Line comment, Terminate the line here, in case a
1022*a9fa9459Szrj 		 name is present and then allow the rest of the
1023*a9fa9459Szrj 		 loop to find the real end of the line.  */
1024*a9fa9459Szrj 	      * eol = '\0';
1025*a9fa9459Szrj 	      break;
1026*a9fa9459Szrj 
1027*a9fa9459Szrj 	    default:
1028*a9fa9459Szrj 	      break;
1029*a9fa9459Szrj 	    }
1030*a9fa9459Szrj 
1031*a9fa9459Szrj 	  if (finished)
1032*a9fa9459Szrj 	    break;
1033*a9fa9459Szrj 	}
1034*a9fa9459Szrj 
1035*a9fa9459Szrj       /* A name may now exist somewhere between 'line' and 'eol'.
1036*a9fa9459Szrj 	 Strip off leading whitespace and trailing whitespace,
1037*a9fa9459Szrj 	 then add it to the list.  */
1038*a9fa9459Szrj       for (name = line; IS_WHITESPACE (* name); name ++)
1039*a9fa9459Szrj 	;
1040*a9fa9459Szrj       for (name_end = name;
1041*a9fa9459Szrj 	   (! IS_WHITESPACE (* name_end))
1042*a9fa9459Szrj 	   && (! IS_LINE_TERMINATOR (* name_end));
1043*a9fa9459Szrj 	   name_end ++)
1044*a9fa9459Szrj 	;
1045*a9fa9459Szrj 
1046*a9fa9459Szrj       if (! IS_LINE_TERMINATOR (* name_end))
1047*a9fa9459Szrj 	{
1048*a9fa9459Szrj 	  char * extra;
1049*a9fa9459Szrj 
1050*a9fa9459Szrj 	  for (extra = name_end + 1; IS_WHITESPACE (* extra); extra ++)
1051*a9fa9459Szrj 	    ;
1052*a9fa9459Szrj 
1053*a9fa9459Szrj 	  if (! IS_LINE_TERMINATOR (* extra))
1054*a9fa9459Szrj 	    non_fatal (_("%s:%d: Ignoring rubbish found on this line"),
1055*a9fa9459Szrj 		       filename, line_count);
1056*a9fa9459Szrj 	}
1057*a9fa9459Szrj 
1058*a9fa9459Szrj       * name_end = '\0';
1059*a9fa9459Szrj 
1060*a9fa9459Szrj       if (name_end > name)
1061*a9fa9459Szrj 	add_specific_symbol (name, htab);
1062*a9fa9459Szrj 
1063*a9fa9459Szrj       /* Advance line pointer to end of line.  The 'eol ++' in the for
1064*a9fa9459Szrj 	 loop above will then advance us to the start of the next line.  */
1065*a9fa9459Szrj       line = eol;
1066*a9fa9459Szrj       line_count ++;
1067*a9fa9459Szrj     }
1068*a9fa9459Szrj }
1069*a9fa9459Szrj 
1070*a9fa9459Szrj /* See whether a symbol should be stripped or kept
1071*a9fa9459Szrj    based on strip_specific_list and keep_symbols.  */
1072*a9fa9459Szrj 
1073*a9fa9459Szrj static int
is_specified_symbol_predicate(void ** slot,void * data)1074*a9fa9459Szrj is_specified_symbol_predicate (void **slot, void *data)
1075*a9fa9459Szrj {
1076*a9fa9459Szrj   struct is_specified_symbol_predicate_data *d =
1077*a9fa9459Szrj       (struct is_specified_symbol_predicate_data *) data;
1078*a9fa9459Szrj   const char *slot_name = (char *) *slot;
1079*a9fa9459Szrj 
1080*a9fa9459Szrj   if (*slot_name != '!')
1081*a9fa9459Szrj     {
1082*a9fa9459Szrj       if (! fnmatch (slot_name, d->name, 0))
1083*a9fa9459Szrj 	{
1084*a9fa9459Szrj 	  d->found = TRUE;
1085*a9fa9459Szrj 	  /* Continue traversal, there might be a non-match rule.  */
1086*a9fa9459Szrj 	  return 1;
1087*a9fa9459Szrj 	}
1088*a9fa9459Szrj     }
1089*a9fa9459Szrj   else
1090*a9fa9459Szrj     {
1091*a9fa9459Szrj       if (! fnmatch (slot_name + 1, d->name, 0))
1092*a9fa9459Szrj 	{
1093*a9fa9459Szrj 	  d->found = FALSE;
1094*a9fa9459Szrj 	  /* Stop traversal.  */
1095*a9fa9459Szrj 	  return 0;
1096*a9fa9459Szrj 	}
1097*a9fa9459Szrj     }
1098*a9fa9459Szrj 
1099*a9fa9459Szrj   /* Continue traversal.  */
1100*a9fa9459Szrj   return 1;
1101*a9fa9459Szrj }
1102*a9fa9459Szrj 
1103*a9fa9459Szrj static bfd_boolean
is_specified_symbol(const char * name,htab_t htab)1104*a9fa9459Szrj is_specified_symbol (const char *name, htab_t htab)
1105*a9fa9459Szrj {
1106*a9fa9459Szrj   if (wildcard)
1107*a9fa9459Szrj     {
1108*a9fa9459Szrj       struct is_specified_symbol_predicate_data data;
1109*a9fa9459Szrj 
1110*a9fa9459Szrj       data.name = name;
1111*a9fa9459Szrj       data.found = FALSE;
1112*a9fa9459Szrj 
1113*a9fa9459Szrj       htab_traverse (htab, is_specified_symbol_predicate, &data);
1114*a9fa9459Szrj 
1115*a9fa9459Szrj       return data.found;
1116*a9fa9459Szrj     }
1117*a9fa9459Szrj 
1118*a9fa9459Szrj   return htab_find (htab, name) != NULL;
1119*a9fa9459Szrj }
1120*a9fa9459Szrj 
1121*a9fa9459Szrj /* Return a pointer to the symbol used as a signature for GROUP.  */
1122*a9fa9459Szrj 
1123*a9fa9459Szrj static asymbol *
group_signature(asection * group)1124*a9fa9459Szrj group_signature (asection *group)
1125*a9fa9459Szrj {
1126*a9fa9459Szrj   bfd *abfd = group->owner;
1127*a9fa9459Szrj   Elf_Internal_Shdr *ghdr;
1128*a9fa9459Szrj 
1129*a9fa9459Szrj   /* PR 20089: An earlier error may have prevented us from loading the symbol table.  */
1130*a9fa9459Szrj   if (isympp == NULL)
1131*a9fa9459Szrj     return NULL;
1132*a9fa9459Szrj 
1133*a9fa9459Szrj   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
1134*a9fa9459Szrj     return NULL;
1135*a9fa9459Szrj 
1136*a9fa9459Szrj   ghdr = &elf_section_data (group)->this_hdr;
1137*a9fa9459Szrj   if (ghdr->sh_link < elf_numsections (abfd))
1138*a9fa9459Szrj     {
1139*a9fa9459Szrj       const struct elf_backend_data *bed = get_elf_backend_data (abfd);
1140*a9fa9459Szrj       Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link];
1141*a9fa9459Szrj 
1142*a9fa9459Szrj       if (symhdr->sh_type == SHT_SYMTAB
1143*a9fa9459Szrj 	  && ghdr->sh_info > 0
1144*a9fa9459Szrj 	  && ghdr->sh_info < (symhdr->sh_size / bed->s->sizeof_sym))
1145*a9fa9459Szrj 	return isympp[ghdr->sh_info - 1];
1146*a9fa9459Szrj     }
1147*a9fa9459Szrj   return NULL;
1148*a9fa9459Szrj }
1149*a9fa9459Szrj 
1150*a9fa9459Szrj /* Return TRUE if the section is a DWO section.  */
1151*a9fa9459Szrj 
1152*a9fa9459Szrj static bfd_boolean
is_dwo_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sec)1153*a9fa9459Szrj is_dwo_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
1154*a9fa9459Szrj {
1155*a9fa9459Szrj   const char *name = bfd_get_section_name (abfd, sec);
1156*a9fa9459Szrj   int len = strlen (name);
1157*a9fa9459Szrj 
1158*a9fa9459Szrj   return strncmp (name + len - 4, ".dwo", 4) == 0;
1159*a9fa9459Szrj }
1160*a9fa9459Szrj 
1161*a9fa9459Szrj /* Return TRUE if section SEC is in the update list.  */
1162*a9fa9459Szrj 
1163*a9fa9459Szrj static bfd_boolean
is_update_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sec)1164*a9fa9459Szrj is_update_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
1165*a9fa9459Szrj {
1166*a9fa9459Szrj   if (update_sections != NULL)
1167*a9fa9459Szrj     {
1168*a9fa9459Szrj       struct section_add *pupdate;
1169*a9fa9459Szrj 
1170*a9fa9459Szrj       for (pupdate = update_sections;
1171*a9fa9459Szrj 	   pupdate != NULL;
1172*a9fa9459Szrj 	   pupdate = pupdate->next)
1173*a9fa9459Szrj 	{
1174*a9fa9459Szrj 	  if (strcmp (sec->name, pupdate->name) == 0)
1175*a9fa9459Szrj 	    return TRUE;
1176*a9fa9459Szrj 	}
1177*a9fa9459Szrj     }
1178*a9fa9459Szrj 
1179*a9fa9459Szrj   return FALSE;
1180*a9fa9459Szrj }
1181*a9fa9459Szrj 
1182*a9fa9459Szrj /* See if a non-group section is being removed.  */
1183*a9fa9459Szrj 
1184*a9fa9459Szrj static bfd_boolean
is_strip_section_1(bfd * abfd ATTRIBUTE_UNUSED,asection * sec)1185*a9fa9459Szrj is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
1186*a9fa9459Szrj {
1187*a9fa9459Szrj   if (sections_removed || sections_copied)
1188*a9fa9459Szrj     {
1189*a9fa9459Szrj       struct section_list *p;
1190*a9fa9459Szrj       struct section_list *q;
1191*a9fa9459Szrj 
1192*a9fa9459Szrj       p = find_section_list (bfd_get_section_name (abfd, sec), FALSE,
1193*a9fa9459Szrj 			     SECTION_CONTEXT_REMOVE);
1194*a9fa9459Szrj       q = find_section_list (bfd_get_section_name (abfd, sec), FALSE,
1195*a9fa9459Szrj 			     SECTION_CONTEXT_COPY);
1196*a9fa9459Szrj 
1197*a9fa9459Szrj       if (p && q)
1198*a9fa9459Szrj 	fatal (_("error: section %s matches both remove and copy options"),
1199*a9fa9459Szrj 	       bfd_get_section_name (abfd, sec));
1200*a9fa9459Szrj       if (p && is_update_section (abfd, sec))
1201*a9fa9459Szrj 	fatal (_("error: section %s matches both update and remove options"),
1202*a9fa9459Szrj 	       bfd_get_section_name (abfd, sec));
1203*a9fa9459Szrj 
1204*a9fa9459Szrj       if (p != NULL)
1205*a9fa9459Szrj 	return TRUE;
1206*a9fa9459Szrj       if (sections_copied && q == NULL)
1207*a9fa9459Szrj 	return TRUE;
1208*a9fa9459Szrj     }
1209*a9fa9459Szrj 
1210*a9fa9459Szrj   if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0)
1211*a9fa9459Szrj     {
1212*a9fa9459Szrj       if (strip_symbols == STRIP_DEBUG
1213*a9fa9459Szrj 	  || strip_symbols == STRIP_UNNEEDED
1214*a9fa9459Szrj 	  || strip_symbols == STRIP_ALL
1215*a9fa9459Szrj 	  || discard_locals == LOCALS_ALL
1216*a9fa9459Szrj 	  || convert_debugging)
1217*a9fa9459Szrj 	{
1218*a9fa9459Szrj 	  /* By default we don't want to strip .reloc section.
1219*a9fa9459Szrj 	     This section has for pe-coff special meaning.   See
1220*a9fa9459Szrj 	     pe-dll.c file in ld, and peXXigen.c in bfd for details.  */
1221*a9fa9459Szrj 	  if (strcmp (bfd_get_section_name (abfd, sec), ".reloc") != 0)
1222*a9fa9459Szrj 	    return TRUE;
1223*a9fa9459Szrj 	}
1224*a9fa9459Szrj 
1225*a9fa9459Szrj       if (strip_symbols == STRIP_DWO)
1226*a9fa9459Szrj 	return is_dwo_section (abfd, sec);
1227*a9fa9459Szrj 
1228*a9fa9459Szrj       if (strip_symbols == STRIP_NONDEBUG)
1229*a9fa9459Szrj 	return FALSE;
1230*a9fa9459Szrj     }
1231*a9fa9459Szrj 
1232*a9fa9459Szrj   if (strip_symbols == STRIP_NONDWO)
1233*a9fa9459Szrj     return !is_dwo_section (abfd, sec);
1234*a9fa9459Szrj 
1235*a9fa9459Szrj   return FALSE;
1236*a9fa9459Szrj }
1237*a9fa9459Szrj 
1238*a9fa9459Szrj /* See if a section is being removed.  */
1239*a9fa9459Szrj 
1240*a9fa9459Szrj static bfd_boolean
is_strip_section(bfd * abfd ATTRIBUTE_UNUSED,asection * sec)1241*a9fa9459Szrj is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
1242*a9fa9459Szrj {
1243*a9fa9459Szrj   if (is_strip_section_1 (abfd, sec))
1244*a9fa9459Szrj     return TRUE;
1245*a9fa9459Szrj 
1246*a9fa9459Szrj   if ((bfd_get_section_flags (abfd, sec) & SEC_GROUP) != 0)
1247*a9fa9459Szrj     {
1248*a9fa9459Szrj       asymbol *gsym;
1249*a9fa9459Szrj       const char *gname;
1250*a9fa9459Szrj       asection *elt, *first;
1251*a9fa9459Szrj 
1252*a9fa9459Szrj       /* PR binutils/3181
1253*a9fa9459Szrj 	 If we are going to strip the group signature symbol, then
1254*a9fa9459Szrj 	 strip the group section too.  */
1255*a9fa9459Szrj       gsym = group_signature (sec);
1256*a9fa9459Szrj       if (gsym != NULL)
1257*a9fa9459Szrj 	gname = gsym->name;
1258*a9fa9459Szrj       else
1259*a9fa9459Szrj 	gname = sec->name;
1260*a9fa9459Szrj       if ((strip_symbols == STRIP_ALL
1261*a9fa9459Szrj 	   && !is_specified_symbol (gname, keep_specific_htab))
1262*a9fa9459Szrj 	  || is_specified_symbol (gname, strip_specific_htab))
1263*a9fa9459Szrj 	return TRUE;
1264*a9fa9459Szrj 
1265*a9fa9459Szrj       /* Remove the group section if all members are removed.  */
1266*a9fa9459Szrj       first = elt = elf_next_in_group (sec);
1267*a9fa9459Szrj       while (elt != NULL)
1268*a9fa9459Szrj 	{
1269*a9fa9459Szrj 	  if (!is_strip_section_1 (abfd, elt))
1270*a9fa9459Szrj 	    return FALSE;
1271*a9fa9459Szrj 	  elt = elf_next_in_group (elt);
1272*a9fa9459Szrj 	  if (elt == first)
1273*a9fa9459Szrj 	    break;
1274*a9fa9459Szrj 	}
1275*a9fa9459Szrj 
1276*a9fa9459Szrj       return TRUE;
1277*a9fa9459Szrj     }
1278*a9fa9459Szrj 
1279*a9fa9459Szrj   return FALSE;
1280*a9fa9459Szrj }
1281*a9fa9459Szrj 
1282*a9fa9459Szrj static bfd_boolean
is_nondebug_keep_contents_section(bfd * ibfd,asection * isection)1283*a9fa9459Szrj is_nondebug_keep_contents_section (bfd *ibfd, asection *isection)
1284*a9fa9459Szrj {
1285*a9fa9459Szrj   /* Always keep ELF note sections.  */
1286*a9fa9459Szrj   if (ibfd->xvec->flavour == bfd_target_elf_flavour)
1287*a9fa9459Szrj     return (elf_section_type (isection) == SHT_NOTE);
1288*a9fa9459Szrj 
1289*a9fa9459Szrj   /* Always keep the .buildid section for PE/COFF.
1290*a9fa9459Szrj 
1291*a9fa9459Szrj      Strictly, this should be written "always keep the section storing the debug
1292*a9fa9459Szrj      directory", but that may be the .text section for objects produced by some
1293*a9fa9459Szrj      tools, which it is not sensible to keep.  */
1294*a9fa9459Szrj   if (ibfd->xvec->flavour == bfd_target_coff_flavour)
1295*a9fa9459Szrj     return (strcmp (bfd_get_section_name (ibfd, isection), ".buildid") == 0);
1296*a9fa9459Szrj 
1297*a9fa9459Szrj   return FALSE;
1298*a9fa9459Szrj }
1299*a9fa9459Szrj 
1300*a9fa9459Szrj /* Return true if SYM is a hidden symbol.  */
1301*a9fa9459Szrj 
1302*a9fa9459Szrj static bfd_boolean
is_hidden_symbol(asymbol * sym)1303*a9fa9459Szrj is_hidden_symbol (asymbol *sym)
1304*a9fa9459Szrj {
1305*a9fa9459Szrj   elf_symbol_type *elf_sym;
1306*a9fa9459Szrj 
1307*a9fa9459Szrj   elf_sym = elf_symbol_from (sym->the_bfd, sym);
1308*a9fa9459Szrj   if (elf_sym != NULL)
1309*a9fa9459Szrj     switch (ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other))
1310*a9fa9459Szrj       {
1311*a9fa9459Szrj       case STV_HIDDEN:
1312*a9fa9459Szrj       case STV_INTERNAL:
1313*a9fa9459Szrj 	return TRUE;
1314*a9fa9459Szrj       }
1315*a9fa9459Szrj   return FALSE;
1316*a9fa9459Szrj }
1317*a9fa9459Szrj 
1318*a9fa9459Szrj static bfd_boolean
need_sym_before(struct addsym_node ** node,const char * sym)1319*a9fa9459Szrj need_sym_before (struct addsym_node **node, const char *sym)
1320*a9fa9459Szrj {
1321*a9fa9459Szrj   int count;
1322*a9fa9459Szrj   struct addsym_node *ptr = add_sym_list;
1323*a9fa9459Szrj 
1324*a9fa9459Szrj   /* 'othersym' symbols are at the front of the list.  */
1325*a9fa9459Szrj   for (count = 0; count < add_symbols; count++)
1326*a9fa9459Szrj     {
1327*a9fa9459Szrj       if (!ptr->othersym)
1328*a9fa9459Szrj 	break;
1329*a9fa9459Szrj       else if (strcmp (ptr->othersym, sym) == 0)
1330*a9fa9459Szrj 	{
1331*a9fa9459Szrj 	  free (ptr->othersym);
1332*a9fa9459Szrj 	  ptr->othersym = ""; /* Empty name is hopefully never a valid symbol name.  */
1333*a9fa9459Szrj 	  *node = ptr;
1334*a9fa9459Szrj 	  return TRUE;
1335*a9fa9459Szrj 	}
1336*a9fa9459Szrj       ptr = ptr->next;
1337*a9fa9459Szrj     }
1338*a9fa9459Szrj   return FALSE;
1339*a9fa9459Szrj }
1340*a9fa9459Szrj 
1341*a9fa9459Szrj static asymbol *
create_new_symbol(struct addsym_node * ptr,bfd * obfd)1342*a9fa9459Szrj create_new_symbol (struct addsym_node *ptr, bfd *obfd)
1343*a9fa9459Szrj {
1344*a9fa9459Szrj   asymbol *sym = bfd_make_empty_symbol (obfd);
1345*a9fa9459Szrj 
1346*a9fa9459Szrj   bfd_asymbol_name (sym) = ptr->symdef;
1347*a9fa9459Szrj   sym->value = ptr->symval;
1348*a9fa9459Szrj   sym->flags = ptr->flags;
1349*a9fa9459Szrj   if (ptr->section)
1350*a9fa9459Szrj     {
1351*a9fa9459Szrj       asection *sec = bfd_get_section_by_name (obfd, ptr->section);
1352*a9fa9459Szrj       if (!sec)
1353*a9fa9459Szrj 	fatal (_("Section %s not found"), ptr->section);
1354*a9fa9459Szrj       sym->section = sec;
1355*a9fa9459Szrj     }
1356*a9fa9459Szrj   else
1357*a9fa9459Szrj     sym->section = bfd_abs_section_ptr;
1358*a9fa9459Szrj   return sym;
1359*a9fa9459Szrj }
1360*a9fa9459Szrj 
1361*a9fa9459Szrj /* Choose which symbol entries to copy; put the result in OSYMS.
1362*a9fa9459Szrj    We don't copy in place, because that confuses the relocs.
1363*a9fa9459Szrj    Return the number of symbols to print.  */
1364*a9fa9459Szrj 
1365*a9fa9459Szrj static unsigned int
filter_symbols(bfd * abfd,bfd * obfd,asymbol ** osyms,asymbol ** isyms,long symcount)1366*a9fa9459Szrj filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
1367*a9fa9459Szrj 		asymbol **isyms, long symcount)
1368*a9fa9459Szrj {
1369*a9fa9459Szrj   asymbol **from = isyms, **to = osyms;
1370*a9fa9459Szrj   long src_count = 0, dst_count = 0;
1371*a9fa9459Szrj   int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
1372*a9fa9459Szrj 
1373*a9fa9459Szrj   for (; src_count < symcount; src_count++)
1374*a9fa9459Szrj     {
1375*a9fa9459Szrj       asymbol *sym = from[src_count];
1376*a9fa9459Szrj       flagword flags = sym->flags;
1377*a9fa9459Szrj       char *name = (char *) bfd_asymbol_name (sym);
1378*a9fa9459Szrj       bfd_boolean keep;
1379*a9fa9459Szrj       bfd_boolean used_in_reloc = FALSE;
1380*a9fa9459Szrj       bfd_boolean undefined;
1381*a9fa9459Szrj       bfd_boolean rem_leading_char;
1382*a9fa9459Szrj       bfd_boolean add_leading_char;
1383*a9fa9459Szrj 
1384*a9fa9459Szrj       undefined = bfd_is_und_section (bfd_get_section (sym));
1385*a9fa9459Szrj 
1386*a9fa9459Szrj       if (add_sym_list)
1387*a9fa9459Szrj 	{
1388*a9fa9459Szrj 	  struct addsym_node *ptr;
1389*a9fa9459Szrj 
1390*a9fa9459Szrj 	  if (need_sym_before (&ptr, name))
1391*a9fa9459Szrj 	    to[dst_count++] = create_new_symbol (ptr, obfd);
1392*a9fa9459Szrj 	}
1393*a9fa9459Szrj 
1394*a9fa9459Szrj       if (redefine_sym_list || section_rename_list)
1395*a9fa9459Szrj 	{
1396*a9fa9459Szrj 	  char *new_name;
1397*a9fa9459Szrj 
1398*a9fa9459Szrj 	  new_name = (char *) lookup_sym_redefinition (name);
1399*a9fa9459Szrj 	  if (new_name == name
1400*a9fa9459Szrj 	      && (flags & BSF_SECTION_SYM) != 0)
1401*a9fa9459Szrj 	    new_name = (char *) find_section_rename (name, NULL);
1402*a9fa9459Szrj 	  bfd_asymbol_name (sym) = new_name;
1403*a9fa9459Szrj 	  name = new_name;
1404*a9fa9459Szrj 	}
1405*a9fa9459Szrj 
1406*a9fa9459Szrj       /* Check if we will remove the current leading character.  */
1407*a9fa9459Szrj       rem_leading_char =
1408*a9fa9459Szrj 	(name[0] == bfd_get_symbol_leading_char (abfd))
1409*a9fa9459Szrj 	&& (change_leading_char
1410*a9fa9459Szrj 	    || (remove_leading_char
1411*a9fa9459Szrj 		&& ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
1412*a9fa9459Szrj 		    || undefined
1413*a9fa9459Szrj 		    || bfd_is_com_section (bfd_get_section (sym)))));
1414*a9fa9459Szrj 
1415*a9fa9459Szrj       /* Check if we will add a new leading character.  */
1416*a9fa9459Szrj       add_leading_char =
1417*a9fa9459Szrj 	change_leading_char
1418*a9fa9459Szrj 	&& (bfd_get_symbol_leading_char (obfd) != '\0')
1419*a9fa9459Szrj 	&& (bfd_get_symbol_leading_char (abfd) == '\0'
1420*a9fa9459Szrj 	    || (name[0] == bfd_get_symbol_leading_char (abfd)));
1421*a9fa9459Szrj 
1422*a9fa9459Szrj       /* Short circuit for change_leading_char if we can do it in-place.  */
1423*a9fa9459Szrj       if (rem_leading_char && add_leading_char && !prefix_symbols_string)
1424*a9fa9459Szrj 	{
1425*a9fa9459Szrj 	  name[0] = bfd_get_symbol_leading_char (obfd);
1426*a9fa9459Szrj 	  bfd_asymbol_name (sym) = name;
1427*a9fa9459Szrj 	  rem_leading_char = FALSE;
1428*a9fa9459Szrj 	  add_leading_char = FALSE;
1429*a9fa9459Szrj 	}
1430*a9fa9459Szrj 
1431*a9fa9459Szrj       /* Remove leading char.  */
1432*a9fa9459Szrj       if (rem_leading_char)
1433*a9fa9459Szrj 	bfd_asymbol_name (sym) = ++name;
1434*a9fa9459Szrj 
1435*a9fa9459Szrj       /* Add new leading char and/or prefix.  */
1436*a9fa9459Szrj       if (add_leading_char || prefix_symbols_string)
1437*a9fa9459Szrj 	{
1438*a9fa9459Szrj 	  char *n, *ptr;
1439*a9fa9459Szrj 
1440*a9fa9459Szrj 	  ptr = n = (char *) xmalloc (1 + strlen (prefix_symbols_string)
1441*a9fa9459Szrj 				      + strlen (name) + 1);
1442*a9fa9459Szrj 	  if (add_leading_char)
1443*a9fa9459Szrj 	    *ptr++ = bfd_get_symbol_leading_char (obfd);
1444*a9fa9459Szrj 
1445*a9fa9459Szrj 	  if (prefix_symbols_string)
1446*a9fa9459Szrj 	    {
1447*a9fa9459Szrj 	      strcpy (ptr, prefix_symbols_string);
1448*a9fa9459Szrj 	      ptr += strlen (prefix_symbols_string);
1449*a9fa9459Szrj 	    }
1450*a9fa9459Szrj 
1451*a9fa9459Szrj 	  strcpy (ptr, name);
1452*a9fa9459Szrj 	  bfd_asymbol_name (sym) = n;
1453*a9fa9459Szrj 	  name = n;
1454*a9fa9459Szrj 	}
1455*a9fa9459Szrj 
1456*a9fa9459Szrj       if (strip_symbols == STRIP_ALL)
1457*a9fa9459Szrj 	keep = FALSE;
1458*a9fa9459Szrj       else if ((flags & BSF_KEEP) != 0		/* Used in relocation.  */
1459*a9fa9459Szrj 	       || ((flags & BSF_SECTION_SYM) != 0
1460*a9fa9459Szrj 		   && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags
1461*a9fa9459Szrj 		       & BSF_KEEP) != 0))
1462*a9fa9459Szrj 	{
1463*a9fa9459Szrj 	  keep = TRUE;
1464*a9fa9459Szrj 	  used_in_reloc = TRUE;
1465*a9fa9459Szrj 	}
1466*a9fa9459Szrj       else if (relocatable			/* Relocatable file.  */
1467*a9fa9459Szrj 	       && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
1468*a9fa9459Szrj 		   || bfd_is_com_section (bfd_get_section (sym))))
1469*a9fa9459Szrj 	keep = TRUE;
1470*a9fa9459Szrj       else if (bfd_decode_symclass (sym) == 'I')
1471*a9fa9459Szrj 	/* Global symbols in $idata sections need to be retained
1472*a9fa9459Szrj 	   even if relocatable is FALSE.  External users of the
1473*a9fa9459Szrj 	   library containing the $idata section may reference these
1474*a9fa9459Szrj 	   symbols.  */
1475*a9fa9459Szrj 	keep = TRUE;
1476*a9fa9459Szrj       else if ((flags & BSF_GLOBAL) != 0	/* Global symbol.  */
1477*a9fa9459Szrj 	       || (flags & BSF_WEAK) != 0
1478*a9fa9459Szrj 	       || undefined
1479*a9fa9459Szrj 	       || bfd_is_com_section (bfd_get_section (sym)))
1480*a9fa9459Szrj 	keep = strip_symbols != STRIP_UNNEEDED;
1481*a9fa9459Szrj       else if ((flags & BSF_DEBUGGING) != 0)	/* Debugging symbol.  */
1482*a9fa9459Szrj 	keep = (strip_symbols != STRIP_DEBUG
1483*a9fa9459Szrj 		&& strip_symbols != STRIP_UNNEEDED
1484*a9fa9459Szrj 		&& ! convert_debugging);
1485*a9fa9459Szrj       else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
1486*a9fa9459Szrj 	/* COMDAT sections store special information in local
1487*a9fa9459Szrj 	   symbols, so we cannot risk stripping any of them.  */
1488*a9fa9459Szrj 	keep = TRUE;
1489*a9fa9459Szrj       else			/* Local symbol.  */
1490*a9fa9459Szrj 	keep = (strip_symbols != STRIP_UNNEEDED
1491*a9fa9459Szrj 		&& (discard_locals != LOCALS_ALL
1492*a9fa9459Szrj 		    && (discard_locals != LOCALS_START_L
1493*a9fa9459Szrj 			|| ! bfd_is_local_label (abfd, sym))));
1494*a9fa9459Szrj 
1495*a9fa9459Szrj       if (keep && is_specified_symbol (name, strip_specific_htab))
1496*a9fa9459Szrj 	{
1497*a9fa9459Szrj 	  /* There are multiple ways to set 'keep' above, but if it
1498*a9fa9459Szrj 	     was the relocatable symbol case, then that's an error.  */
1499*a9fa9459Szrj 	  if (used_in_reloc)
1500*a9fa9459Szrj 	    {
1501*a9fa9459Szrj 	      non_fatal (_("not stripping symbol `%s' because it is named in a relocation"), name);
1502*a9fa9459Szrj 	      status = 1;
1503*a9fa9459Szrj 	    }
1504*a9fa9459Szrj 	  else
1505*a9fa9459Szrj 	    keep = FALSE;
1506*a9fa9459Szrj 	}
1507*a9fa9459Szrj 
1508*a9fa9459Szrj       if (keep
1509*a9fa9459Szrj 	  && !(flags & BSF_KEEP)
1510*a9fa9459Szrj 	  && is_specified_symbol (name, strip_unneeded_htab))
1511*a9fa9459Szrj 	keep = FALSE;
1512*a9fa9459Szrj 
1513*a9fa9459Szrj       if (!keep
1514*a9fa9459Szrj 	  && ((keep_file_symbols && (flags & BSF_FILE))
1515*a9fa9459Szrj 	      || is_specified_symbol (name, keep_specific_htab)))
1516*a9fa9459Szrj 	keep = TRUE;
1517*a9fa9459Szrj 
1518*a9fa9459Szrj       if (keep && is_strip_section (abfd, bfd_get_section (sym)))
1519*a9fa9459Szrj 	keep = FALSE;
1520*a9fa9459Szrj 
1521*a9fa9459Szrj       if (keep)
1522*a9fa9459Szrj 	{
1523*a9fa9459Szrj 	  if ((flags & BSF_GLOBAL) != 0
1524*a9fa9459Szrj 	      && (weaken || is_specified_symbol (name, weaken_specific_htab)))
1525*a9fa9459Szrj 	    {
1526*a9fa9459Szrj 	      sym->flags &= ~ BSF_GLOBAL;
1527*a9fa9459Szrj 	      sym->flags |= BSF_WEAK;
1528*a9fa9459Szrj 	    }
1529*a9fa9459Szrj 
1530*a9fa9459Szrj 	  if (!undefined
1531*a9fa9459Szrj 	      && (flags & (BSF_GLOBAL | BSF_WEAK))
1532*a9fa9459Szrj 	      && (is_specified_symbol (name, localize_specific_htab)
1533*a9fa9459Szrj 		  || (htab_elements (keepglobal_specific_htab) != 0
1534*a9fa9459Szrj 		      && ! is_specified_symbol (name, keepglobal_specific_htab))
1535*a9fa9459Szrj 		  || (localize_hidden && is_hidden_symbol (sym))))
1536*a9fa9459Szrj 	    {
1537*a9fa9459Szrj 	      sym->flags &= ~ (BSF_GLOBAL | BSF_WEAK);
1538*a9fa9459Szrj 	      sym->flags |= BSF_LOCAL;
1539*a9fa9459Szrj 	    }
1540*a9fa9459Szrj 
1541*a9fa9459Szrj 	  if (!undefined
1542*a9fa9459Szrj 	      && (flags & BSF_LOCAL)
1543*a9fa9459Szrj 	      && is_specified_symbol (name, globalize_specific_htab))
1544*a9fa9459Szrj 	    {
1545*a9fa9459Szrj 	      sym->flags &= ~ BSF_LOCAL;
1546*a9fa9459Szrj 	      sym->flags |= BSF_GLOBAL;
1547*a9fa9459Szrj 	    }
1548*a9fa9459Szrj 
1549*a9fa9459Szrj 	  to[dst_count++] = sym;
1550*a9fa9459Szrj 	}
1551*a9fa9459Szrj     }
1552*a9fa9459Szrj   if (add_sym_list)
1553*a9fa9459Szrj     {
1554*a9fa9459Szrj       struct addsym_node *ptr = add_sym_list;
1555*a9fa9459Szrj 
1556*a9fa9459Szrj       for (src_count = 0; src_count < add_symbols; src_count++)
1557*a9fa9459Szrj 	{
1558*a9fa9459Szrj 	  if (ptr->othersym)
1559*a9fa9459Szrj 	    {
1560*a9fa9459Szrj 	      if (strcmp (ptr->othersym, ""))
1561*a9fa9459Szrj 		fatal (_("'before=%s' not found"), ptr->othersym);
1562*a9fa9459Szrj 	    }
1563*a9fa9459Szrj 	  else
1564*a9fa9459Szrj 	    to[dst_count++] = create_new_symbol (ptr, obfd);
1565*a9fa9459Szrj 
1566*a9fa9459Szrj 	  ptr = ptr->next;
1567*a9fa9459Szrj 	}
1568*a9fa9459Szrj     }
1569*a9fa9459Szrj 
1570*a9fa9459Szrj   to[dst_count] = NULL;
1571*a9fa9459Szrj 
1572*a9fa9459Szrj   return dst_count;
1573*a9fa9459Szrj }
1574*a9fa9459Szrj 
1575*a9fa9459Szrj /* Find the redefined name of symbol SOURCE.  */
1576*a9fa9459Szrj 
1577*a9fa9459Szrj static const char *
lookup_sym_redefinition(const char * source)1578*a9fa9459Szrj lookup_sym_redefinition (const char *source)
1579*a9fa9459Szrj {
1580*a9fa9459Szrj   struct redefine_node *list;
1581*a9fa9459Szrj 
1582*a9fa9459Szrj   for (list = redefine_sym_list; list != NULL; list = list->next)
1583*a9fa9459Szrj     if (strcmp (source, list->source) == 0)
1584*a9fa9459Szrj       return list->target;
1585*a9fa9459Szrj 
1586*a9fa9459Szrj   return source;
1587*a9fa9459Szrj }
1588*a9fa9459Szrj 
1589*a9fa9459Szrj /* Add a node to a symbol redefine list.  */
1590*a9fa9459Szrj 
1591*a9fa9459Szrj static void
redefine_list_append(const char * cause,const char * source,const char * target)1592*a9fa9459Szrj redefine_list_append (const char *cause, const char *source, const char *target)
1593*a9fa9459Szrj {
1594*a9fa9459Szrj   struct redefine_node **p;
1595*a9fa9459Szrj   struct redefine_node *list;
1596*a9fa9459Szrj   struct redefine_node *new_node;
1597*a9fa9459Szrj 
1598*a9fa9459Szrj   for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next)
1599*a9fa9459Szrj     {
1600*a9fa9459Szrj       if (strcmp (source, list->source) == 0)
1601*a9fa9459Szrj 	fatal (_("%s: Multiple redefinition of symbol \"%s\""),
1602*a9fa9459Szrj 	       cause, source);
1603*a9fa9459Szrj 
1604*a9fa9459Szrj       if (strcmp (target, list->target) == 0)
1605*a9fa9459Szrj 	fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"),
1606*a9fa9459Szrj 	       cause, target);
1607*a9fa9459Szrj     }
1608*a9fa9459Szrj 
1609*a9fa9459Szrj   new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node));
1610*a9fa9459Szrj 
1611*a9fa9459Szrj   new_node->source = strdup (source);
1612*a9fa9459Szrj   new_node->target = strdup (target);
1613*a9fa9459Szrj   new_node->next = NULL;
1614*a9fa9459Szrj 
1615*a9fa9459Szrj   *p = new_node;
1616*a9fa9459Szrj }
1617*a9fa9459Szrj 
1618*a9fa9459Szrj /* Handle the --redefine-syms option.  Read lines containing "old new"
1619*a9fa9459Szrj    from the file, and add them to the symbol redefine list.  */
1620*a9fa9459Szrj 
1621*a9fa9459Szrj static void
add_redefine_syms_file(const char * filename)1622*a9fa9459Szrj add_redefine_syms_file (const char *filename)
1623*a9fa9459Szrj {
1624*a9fa9459Szrj   FILE *file;
1625*a9fa9459Szrj   char *buf;
1626*a9fa9459Szrj   size_t bufsize;
1627*a9fa9459Szrj   size_t len;
1628*a9fa9459Szrj   size_t outsym_off;
1629*a9fa9459Szrj   int c, lineno;
1630*a9fa9459Szrj 
1631*a9fa9459Szrj   file = fopen (filename, "r");
1632*a9fa9459Szrj   if (file == NULL)
1633*a9fa9459Szrj     fatal (_("couldn't open symbol redefinition file %s (error: %s)"),
1634*a9fa9459Szrj 	   filename, strerror (errno));
1635*a9fa9459Szrj 
1636*a9fa9459Szrj   bufsize = 100;
1637*a9fa9459Szrj   buf = (char *) xmalloc (bufsize + 1 /* For the terminating NUL.  */);
1638*a9fa9459Szrj 
1639*a9fa9459Szrj   lineno = 1;
1640*a9fa9459Szrj   c = getc (file);
1641*a9fa9459Szrj   len = 0;
1642*a9fa9459Szrj   outsym_off = 0;
1643*a9fa9459Szrj   while (c != EOF)
1644*a9fa9459Szrj     {
1645*a9fa9459Szrj       /* Collect the input symbol name.  */
1646*a9fa9459Szrj       while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
1647*a9fa9459Szrj 	{
1648*a9fa9459Szrj 	  if (c == '#')
1649*a9fa9459Szrj 	    goto comment;
1650*a9fa9459Szrj 	  buf[len++] = c;
1651*a9fa9459Szrj 	  if (len >= bufsize)
1652*a9fa9459Szrj 	    {
1653*a9fa9459Szrj 	      bufsize *= 2;
1654*a9fa9459Szrj 	      buf = (char *) xrealloc (buf, bufsize + 1);
1655*a9fa9459Szrj 	    }
1656*a9fa9459Szrj 	  c = getc (file);
1657*a9fa9459Szrj 	}
1658*a9fa9459Szrj       buf[len++] = '\0';
1659*a9fa9459Szrj       if (c == EOF)
1660*a9fa9459Szrj 	break;
1661*a9fa9459Szrj 
1662*a9fa9459Szrj       /* Eat white space between the symbol names.  */
1663*a9fa9459Szrj       while (IS_WHITESPACE (c))
1664*a9fa9459Szrj 	c = getc (file);
1665*a9fa9459Szrj       if (c == '#' || IS_LINE_TERMINATOR (c))
1666*a9fa9459Szrj 	goto comment;
1667*a9fa9459Szrj       if (c == EOF)
1668*a9fa9459Szrj 	break;
1669*a9fa9459Szrj 
1670*a9fa9459Szrj       /* Collect the output symbol name.  */
1671*a9fa9459Szrj       outsym_off = len;
1672*a9fa9459Szrj       while (! IS_WHITESPACE (c) && ! IS_LINE_TERMINATOR (c) && c != EOF)
1673*a9fa9459Szrj 	{
1674*a9fa9459Szrj 	  if (c == '#')
1675*a9fa9459Szrj 	    goto comment;
1676*a9fa9459Szrj 	  buf[len++] = c;
1677*a9fa9459Szrj 	  if (len >= bufsize)
1678*a9fa9459Szrj 	    {
1679*a9fa9459Szrj 	      bufsize *= 2;
1680*a9fa9459Szrj 	      buf = (char *) xrealloc (buf, bufsize + 1);
1681*a9fa9459Szrj 	    }
1682*a9fa9459Szrj 	  c = getc (file);
1683*a9fa9459Szrj 	}
1684*a9fa9459Szrj       buf[len++] = '\0';
1685*a9fa9459Szrj       if (c == EOF)
1686*a9fa9459Szrj 	break;
1687*a9fa9459Szrj 
1688*a9fa9459Szrj       /* Eat white space at end of line.  */
1689*a9fa9459Szrj       while (! IS_LINE_TERMINATOR(c) && c != EOF && IS_WHITESPACE (c))
1690*a9fa9459Szrj 	c = getc (file);
1691*a9fa9459Szrj       if (c == '#')
1692*a9fa9459Szrj 	goto comment;
1693*a9fa9459Szrj       /* Handle \r\n.  */
1694*a9fa9459Szrj       if ((c == '\r' && (c = getc (file)) == '\n')
1695*a9fa9459Szrj 	  || c == '\n' || c == EOF)
1696*a9fa9459Szrj 	{
1697*a9fa9459Szrj 	end_of_line:
1698*a9fa9459Szrj 	  /* Append the redefinition to the list.  */
1699*a9fa9459Szrj 	  if (buf[0] != '\0')
1700*a9fa9459Szrj 	    redefine_list_append (filename, &buf[0], &buf[outsym_off]);
1701*a9fa9459Szrj 
1702*a9fa9459Szrj 	  lineno++;
1703*a9fa9459Szrj 	  len = 0;
1704*a9fa9459Szrj 	  outsym_off = 0;
1705*a9fa9459Szrj 	  if (c == EOF)
1706*a9fa9459Szrj 	    break;
1707*a9fa9459Szrj 	  c = getc (file);
1708*a9fa9459Szrj 	  continue;
1709*a9fa9459Szrj 	}
1710*a9fa9459Szrj       else
1711*a9fa9459Szrj 	fatal (_("%s:%d: garbage found at end of line"), filename, lineno);
1712*a9fa9459Szrj     comment:
1713*a9fa9459Szrj       if (len != 0 && (outsym_off == 0 || outsym_off == len))
1714*a9fa9459Szrj 	fatal (_("%s:%d: missing new symbol name"), filename, lineno);
1715*a9fa9459Szrj       buf[len++] = '\0';
1716*a9fa9459Szrj 
1717*a9fa9459Szrj       /* Eat the rest of the line and finish it.  */
1718*a9fa9459Szrj       while (c != '\n' && c != EOF)
1719*a9fa9459Szrj 	c = getc (file);
1720*a9fa9459Szrj       goto end_of_line;
1721*a9fa9459Szrj     }
1722*a9fa9459Szrj 
1723*a9fa9459Szrj   if (len != 0)
1724*a9fa9459Szrj     fatal (_("%s:%d: premature end of file"), filename, lineno);
1725*a9fa9459Szrj 
1726*a9fa9459Szrj   free (buf);
1727*a9fa9459Szrj }
1728*a9fa9459Szrj 
1729*a9fa9459Szrj /* Copy unkown object file IBFD onto OBFD.
1730*a9fa9459Szrj    Returns TRUE upon success, FALSE otherwise.  */
1731*a9fa9459Szrj 
1732*a9fa9459Szrj static bfd_boolean
copy_unknown_object(bfd * ibfd,bfd * obfd)1733*a9fa9459Szrj copy_unknown_object (bfd *ibfd, bfd *obfd)
1734*a9fa9459Szrj {
1735*a9fa9459Szrj   char *cbuf;
1736*a9fa9459Szrj   int tocopy;
1737*a9fa9459Szrj   long ncopied;
1738*a9fa9459Szrj   long size;
1739*a9fa9459Szrj   struct stat buf;
1740*a9fa9459Szrj 
1741*a9fa9459Szrj   if (bfd_stat_arch_elt (ibfd, &buf) != 0)
1742*a9fa9459Szrj     {
1743*a9fa9459Szrj       bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
1744*a9fa9459Szrj       return FALSE;
1745*a9fa9459Szrj     }
1746*a9fa9459Szrj 
1747*a9fa9459Szrj   size = buf.st_size;
1748*a9fa9459Szrj   if (size < 0)
1749*a9fa9459Szrj     {
1750*a9fa9459Szrj       non_fatal (_("stat returns negative size for `%s'"),
1751*a9fa9459Szrj 		 bfd_get_archive_filename (ibfd));
1752*a9fa9459Szrj       return FALSE;
1753*a9fa9459Szrj     }
1754*a9fa9459Szrj 
1755*a9fa9459Szrj   if (bfd_seek (ibfd, (file_ptr) 0, SEEK_SET) != 0)
1756*a9fa9459Szrj     {
1757*a9fa9459Szrj       bfd_nonfatal (bfd_get_archive_filename (ibfd));
1758*a9fa9459Szrj       return FALSE;
1759*a9fa9459Szrj     }
1760*a9fa9459Szrj 
1761*a9fa9459Szrj   if (verbose)
1762*a9fa9459Szrj     printf (_("copy from `%s' [unknown] to `%s' [unknown]\n"),
1763*a9fa9459Szrj 	    bfd_get_archive_filename (ibfd), bfd_get_filename (obfd));
1764*a9fa9459Szrj 
1765*a9fa9459Szrj   cbuf = (char *) xmalloc (BUFSIZE);
1766*a9fa9459Szrj   ncopied = 0;
1767*a9fa9459Szrj   while (ncopied < size)
1768*a9fa9459Szrj     {
1769*a9fa9459Szrj       tocopy = size - ncopied;
1770*a9fa9459Szrj       if (tocopy > BUFSIZE)
1771*a9fa9459Szrj 	tocopy = BUFSIZE;
1772*a9fa9459Szrj 
1773*a9fa9459Szrj       if (bfd_bread (cbuf, (bfd_size_type) tocopy, ibfd)
1774*a9fa9459Szrj 	  != (bfd_size_type) tocopy)
1775*a9fa9459Szrj 	{
1776*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
1777*a9fa9459Szrj 	  free (cbuf);
1778*a9fa9459Szrj 	  return FALSE;
1779*a9fa9459Szrj 	}
1780*a9fa9459Szrj 
1781*a9fa9459Szrj       if (bfd_bwrite (cbuf, (bfd_size_type) tocopy, obfd)
1782*a9fa9459Szrj 	  != (bfd_size_type) tocopy)
1783*a9fa9459Szrj 	{
1784*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, obfd, NULL, NULL);
1785*a9fa9459Szrj 	  free (cbuf);
1786*a9fa9459Szrj 	  return FALSE;
1787*a9fa9459Szrj 	}
1788*a9fa9459Szrj 
1789*a9fa9459Szrj       ncopied += tocopy;
1790*a9fa9459Szrj     }
1791*a9fa9459Szrj 
1792*a9fa9459Szrj   /* We should at least to be able to read it back when copying an
1793*a9fa9459Szrj      unknown object in an archive.  */
1794*a9fa9459Szrj   chmod (bfd_get_filename (obfd), buf.st_mode | S_IRUSR);
1795*a9fa9459Szrj   free (cbuf);
1796*a9fa9459Szrj   return TRUE;
1797*a9fa9459Szrj }
1798*a9fa9459Szrj 
1799*a9fa9459Szrj /* Copy object file IBFD onto OBFD.
1800*a9fa9459Szrj    Returns TRUE upon success, FALSE otherwise.  */
1801*a9fa9459Szrj 
1802*a9fa9459Szrj static bfd_boolean
copy_object(bfd * ibfd,bfd * obfd,const bfd_arch_info_type * input_arch)1803*a9fa9459Szrj copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
1804*a9fa9459Szrj {
1805*a9fa9459Szrj   bfd_vma start;
1806*a9fa9459Szrj   long symcount;
1807*a9fa9459Szrj   asection **osections = NULL;
1808*a9fa9459Szrj   asection *gnu_debuglink_section = NULL;
1809*a9fa9459Szrj   bfd_size_type *gaps = NULL;
1810*a9fa9459Szrj   bfd_size_type max_gap = 0;
1811*a9fa9459Szrj   long symsize;
1812*a9fa9459Szrj   void *dhandle;
1813*a9fa9459Szrj   enum bfd_architecture iarch;
1814*a9fa9459Szrj   unsigned int imach;
1815*a9fa9459Szrj   unsigned int c, i;
1816*a9fa9459Szrj 
1817*a9fa9459Szrj   if (ibfd->xvec->byteorder != obfd->xvec->byteorder
1818*a9fa9459Szrj       && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
1819*a9fa9459Szrj       && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
1820*a9fa9459Szrj     {
1821*a9fa9459Szrj       /* PR 17636: Call non-fatal so that we return to our parent who
1822*a9fa9459Szrj 	 may need to tidy temporary files.  */
1823*a9fa9459Szrj       non_fatal (_("Unable to change endianness of input file(s)"));
1824*a9fa9459Szrj       return FALSE;
1825*a9fa9459Szrj     }
1826*a9fa9459Szrj 
1827*a9fa9459Szrj   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
1828*a9fa9459Szrj     {
1829*a9fa9459Szrj       bfd_nonfatal_message (NULL, obfd, NULL, NULL);
1830*a9fa9459Szrj       return FALSE;
1831*a9fa9459Szrj     }
1832*a9fa9459Szrj 
1833*a9fa9459Szrj   if (ibfd->sections == NULL)
1834*a9fa9459Szrj     {
1835*a9fa9459Szrj       non_fatal (_("error: the input file '%s' has no sections"),
1836*a9fa9459Szrj 		 bfd_get_archive_filename (ibfd));
1837*a9fa9459Szrj       return FALSE;
1838*a9fa9459Szrj     }
1839*a9fa9459Szrj 
1840*a9fa9459Szrj   if (ibfd->xvec->flavour != bfd_target_elf_flavour)
1841*a9fa9459Szrj     {
1842*a9fa9459Szrj       if ((do_debug_sections & compress) != 0
1843*a9fa9459Szrj 	  && do_debug_sections != compress)
1844*a9fa9459Szrj 	{
1845*a9fa9459Szrj 	  non_fatal (_("--compress-debug-sections=[zlib|zlib-gnu|zlib-gabi] is unsupported on `%s'"),
1846*a9fa9459Szrj 		     bfd_get_archive_filename (ibfd));
1847*a9fa9459Szrj 	  return FALSE;
1848*a9fa9459Szrj 	}
1849*a9fa9459Szrj 
1850*a9fa9459Szrj       if (do_elf_stt_common)
1851*a9fa9459Szrj 	{
1852*a9fa9459Szrj 	  non_fatal (_("--elf-stt-common=[yes|no] is unsupported on `%s'"),
1853*a9fa9459Szrj 		     bfd_get_archive_filename (ibfd));
1854*a9fa9459Szrj 	  return FALSE;
1855*a9fa9459Szrj 	}
1856*a9fa9459Szrj     }
1857*a9fa9459Szrj 
1858*a9fa9459Szrj   if (verbose)
1859*a9fa9459Szrj     printf (_("copy from `%s' [%s] to `%s' [%s]\n"),
1860*a9fa9459Szrj 	    bfd_get_archive_filename (ibfd), bfd_get_target (ibfd),
1861*a9fa9459Szrj 	    bfd_get_filename (obfd), bfd_get_target (obfd));
1862*a9fa9459Szrj 
1863*a9fa9459Szrj   if (extract_symbol)
1864*a9fa9459Szrj     start = 0;
1865*a9fa9459Szrj   else
1866*a9fa9459Szrj     {
1867*a9fa9459Szrj       if (set_start_set)
1868*a9fa9459Szrj 	start = set_start;
1869*a9fa9459Szrj       else
1870*a9fa9459Szrj 	start = bfd_get_start_address (ibfd);
1871*a9fa9459Szrj       start += change_start;
1872*a9fa9459Szrj     }
1873*a9fa9459Szrj 
1874*a9fa9459Szrj   /* Neither the start address nor the flags
1875*a9fa9459Szrj      need to be set for a core file.  */
1876*a9fa9459Szrj   if (bfd_get_format (obfd) != bfd_core)
1877*a9fa9459Szrj     {
1878*a9fa9459Szrj       flagword flags;
1879*a9fa9459Szrj 
1880*a9fa9459Szrj       flags = bfd_get_file_flags (ibfd);
1881*a9fa9459Szrj       flags |= bfd_flags_to_set;
1882*a9fa9459Szrj       flags &= ~bfd_flags_to_clear;
1883*a9fa9459Szrj       flags &= bfd_applicable_file_flags (obfd);
1884*a9fa9459Szrj 
1885*a9fa9459Szrj       if (strip_symbols == STRIP_ALL)
1886*a9fa9459Szrj 	flags &= ~HAS_RELOC;
1887*a9fa9459Szrj 
1888*a9fa9459Szrj       if (!bfd_set_start_address (obfd, start)
1889*a9fa9459Szrj 	  || !bfd_set_file_flags (obfd, flags))
1890*a9fa9459Szrj 	{
1891*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
1892*a9fa9459Szrj 	  return FALSE;
1893*a9fa9459Szrj 	}
1894*a9fa9459Szrj     }
1895*a9fa9459Szrj 
1896*a9fa9459Szrj   /* Copy architecture of input file to output file.  */
1897*a9fa9459Szrj   iarch = bfd_get_arch (ibfd);
1898*a9fa9459Szrj   imach = bfd_get_mach (ibfd);
1899*a9fa9459Szrj   if (input_arch)
1900*a9fa9459Szrj     {
1901*a9fa9459Szrj       if (bfd_get_arch_info (ibfd) == NULL
1902*a9fa9459Szrj 	  || bfd_get_arch_info (ibfd)->arch == bfd_arch_unknown)
1903*a9fa9459Szrj 	{
1904*a9fa9459Szrj 	  iarch = input_arch->arch;
1905*a9fa9459Szrj 	  imach = input_arch->mach;
1906*a9fa9459Szrj 	}
1907*a9fa9459Szrj       else
1908*a9fa9459Szrj 	non_fatal (_("Input file `%s' ignores binary architecture parameter."),
1909*a9fa9459Szrj 		   bfd_get_archive_filename (ibfd));
1910*a9fa9459Szrj     }
1911*a9fa9459Szrj   if (!bfd_set_arch_mach (obfd, iarch, imach)
1912*a9fa9459Szrj       && (ibfd->target_defaulted
1913*a9fa9459Szrj 	  || bfd_get_arch (ibfd) != bfd_get_arch (obfd)))
1914*a9fa9459Szrj     {
1915*a9fa9459Szrj       if (bfd_get_arch (ibfd) == bfd_arch_unknown)
1916*a9fa9459Szrj 	non_fatal (_("Unable to recognise the format of the input file `%s'"),
1917*a9fa9459Szrj 		   bfd_get_archive_filename (ibfd));
1918*a9fa9459Szrj       else
1919*a9fa9459Szrj 	non_fatal (_("Output file cannot represent architecture `%s'"),
1920*a9fa9459Szrj 		   bfd_printable_arch_mach (bfd_get_arch (ibfd),
1921*a9fa9459Szrj 					    bfd_get_mach (ibfd)));
1922*a9fa9459Szrj       return FALSE;
1923*a9fa9459Szrj     }
1924*a9fa9459Szrj 
1925*a9fa9459Szrj   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
1926*a9fa9459Szrj     {
1927*a9fa9459Szrj       bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
1928*a9fa9459Szrj       return FALSE;
1929*a9fa9459Szrj     }
1930*a9fa9459Szrj 
1931*a9fa9459Szrj   if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
1932*a9fa9459Szrj       && bfd_pei_p (obfd))
1933*a9fa9459Szrj     {
1934*a9fa9459Szrj       /* Set up PE parameters.  */
1935*a9fa9459Szrj       pe_data_type *pe = pe_data (obfd);
1936*a9fa9459Szrj 
1937*a9fa9459Szrj       /* Copy PE parameters before changing them.  */
1938*a9fa9459Szrj       if (ibfd->xvec->flavour == bfd_target_coff_flavour
1939*a9fa9459Szrj 	  && bfd_pei_p (ibfd))
1940*a9fa9459Szrj 	pe->pe_opthdr = pe_data (ibfd)->pe_opthdr;
1941*a9fa9459Szrj 
1942*a9fa9459Szrj       if (pe_file_alignment != (bfd_vma) -1)
1943*a9fa9459Szrj 	pe->pe_opthdr.FileAlignment = pe_file_alignment;
1944*a9fa9459Szrj       else
1945*a9fa9459Szrj 	pe_file_alignment = PE_DEF_FILE_ALIGNMENT;
1946*a9fa9459Szrj 
1947*a9fa9459Szrj       if (pe_heap_commit != (bfd_vma) -1)
1948*a9fa9459Szrj 	pe->pe_opthdr.SizeOfHeapCommit = pe_heap_commit;
1949*a9fa9459Szrj 
1950*a9fa9459Szrj       if (pe_heap_reserve != (bfd_vma) -1)
1951*a9fa9459Szrj 	pe->pe_opthdr.SizeOfHeapCommit = pe_heap_reserve;
1952*a9fa9459Szrj 
1953*a9fa9459Szrj       if (pe_image_base != (bfd_vma) -1)
1954*a9fa9459Szrj 	pe->pe_opthdr.ImageBase = pe_image_base;
1955*a9fa9459Szrj 
1956*a9fa9459Szrj       if (pe_section_alignment != (bfd_vma) -1)
1957*a9fa9459Szrj 	pe->pe_opthdr.SectionAlignment = pe_section_alignment;
1958*a9fa9459Szrj       else
1959*a9fa9459Szrj 	pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
1960*a9fa9459Szrj 
1961*a9fa9459Szrj       if (pe_stack_commit != (bfd_vma) -1)
1962*a9fa9459Szrj 	pe->pe_opthdr.SizeOfStackCommit = pe_stack_commit;
1963*a9fa9459Szrj 
1964*a9fa9459Szrj       if (pe_stack_reserve != (bfd_vma) -1)
1965*a9fa9459Szrj 	pe->pe_opthdr.SizeOfStackCommit = pe_stack_reserve;
1966*a9fa9459Szrj 
1967*a9fa9459Szrj       if (pe_subsystem != -1)
1968*a9fa9459Szrj 	pe->pe_opthdr.Subsystem = pe_subsystem;
1969*a9fa9459Szrj 
1970*a9fa9459Szrj       if (pe_major_subsystem_version != -1)
1971*a9fa9459Szrj 	pe->pe_opthdr.MajorSubsystemVersion = pe_major_subsystem_version;
1972*a9fa9459Szrj 
1973*a9fa9459Szrj       if (pe_minor_subsystem_version != -1)
1974*a9fa9459Szrj 	pe->pe_opthdr.MinorSubsystemVersion = pe_minor_subsystem_version;
1975*a9fa9459Szrj 
1976*a9fa9459Szrj       if (pe_file_alignment > pe_section_alignment)
1977*a9fa9459Szrj 	{
1978*a9fa9459Szrj 	  char file_alignment[20], section_alignment[20];
1979*a9fa9459Szrj 
1980*a9fa9459Szrj 	  sprintf_vma (file_alignment, pe_file_alignment);
1981*a9fa9459Szrj 	  sprintf_vma (section_alignment, pe_section_alignment);
1982*a9fa9459Szrj 	  non_fatal (_("warning: file alignment (0x%s) > section alignment (0x%s)"),
1983*a9fa9459Szrj 
1984*a9fa9459Szrj 		     file_alignment, section_alignment);
1985*a9fa9459Szrj 	}
1986*a9fa9459Szrj     }
1987*a9fa9459Szrj 
1988*a9fa9459Szrj   if (isympp)
1989*a9fa9459Szrj     free (isympp);
1990*a9fa9459Szrj 
1991*a9fa9459Szrj   if (osympp != isympp)
1992*a9fa9459Szrj     free (osympp);
1993*a9fa9459Szrj 
1994*a9fa9459Szrj   isympp = NULL;
1995*a9fa9459Szrj   osympp = NULL;
1996*a9fa9459Szrj 
1997*a9fa9459Szrj   symsize = bfd_get_symtab_upper_bound (ibfd);
1998*a9fa9459Szrj   if (symsize < 0)
1999*a9fa9459Szrj     {
2000*a9fa9459Szrj       bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
2001*a9fa9459Szrj       return FALSE;
2002*a9fa9459Szrj     }
2003*a9fa9459Szrj 
2004*a9fa9459Szrj   osympp = isympp = (asymbol **) xmalloc (symsize);
2005*a9fa9459Szrj   symcount = bfd_canonicalize_symtab (ibfd, isympp);
2006*a9fa9459Szrj   if (symcount < 0)
2007*a9fa9459Szrj     {
2008*a9fa9459Szrj       bfd_nonfatal_message (NULL, ibfd, NULL, NULL);
2009*a9fa9459Szrj       return FALSE;
2010*a9fa9459Szrj     }
2011*a9fa9459Szrj   /* PR 17512: file:  d6323821
2012*a9fa9459Szrj      If the symbol table could not be loaded do not pretend that we have
2013*a9fa9459Szrj      any symbols.  This trips us up later on when we load the relocs.  */
2014*a9fa9459Szrj   if (symcount == 0)
2015*a9fa9459Szrj     {
2016*a9fa9459Szrj       free (isympp);
2017*a9fa9459Szrj       osympp = isympp = NULL;
2018*a9fa9459Szrj     }
2019*a9fa9459Szrj 
2020*a9fa9459Szrj   /* BFD mandates that all output sections be created and sizes set before
2021*a9fa9459Szrj      any output is done.  Thus, we traverse all sections multiple times.  */
2022*a9fa9459Szrj   bfd_map_over_sections (ibfd, setup_section, obfd);
2023*a9fa9459Szrj 
2024*a9fa9459Szrj   if (!extract_symbol)
2025*a9fa9459Szrj     setup_bfd_headers (ibfd, obfd);
2026*a9fa9459Szrj 
2027*a9fa9459Szrj   if (add_sections != NULL)
2028*a9fa9459Szrj     {
2029*a9fa9459Szrj       struct section_add *padd;
2030*a9fa9459Szrj       struct section_list *pset;
2031*a9fa9459Szrj 
2032*a9fa9459Szrj       for (padd = add_sections; padd != NULL; padd = padd->next)
2033*a9fa9459Szrj 	{
2034*a9fa9459Szrj 	  flagword flags;
2035*a9fa9459Szrj 
2036*a9fa9459Szrj 	  pset = find_section_list (padd->name, FALSE,
2037*a9fa9459Szrj 				    SECTION_CONTEXT_SET_FLAGS);
2038*a9fa9459Szrj 	  if (pset != NULL)
2039*a9fa9459Szrj 	    flags = pset->flags | SEC_HAS_CONTENTS;
2040*a9fa9459Szrj 	  else
2041*a9fa9459Szrj 	    flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA;
2042*a9fa9459Szrj 
2043*a9fa9459Szrj 	  /* bfd_make_section_with_flags() does not return very helpful
2044*a9fa9459Szrj 	     error codes, so check for the most likely user error first.  */
2045*a9fa9459Szrj 	  if (bfd_get_section_by_name (obfd, padd->name))
2046*a9fa9459Szrj 	    {
2047*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, NULL,
2048*a9fa9459Szrj 				    _("can't add section '%s'"), padd->name);
2049*a9fa9459Szrj 	      return FALSE;
2050*a9fa9459Szrj 	    }
2051*a9fa9459Szrj 	  else
2052*a9fa9459Szrj 	    {
2053*a9fa9459Szrj 	      /* We use LINKER_CREATED here so that the backend hooks
2054*a9fa9459Szrj 		 will create any special section type information,
2055*a9fa9459Szrj 		 instead of presuming we know what we're doing merely
2056*a9fa9459Szrj 		 because we set the flags.  */
2057*a9fa9459Szrj 	      padd->section = bfd_make_section_with_flags
2058*a9fa9459Szrj 		(obfd, padd->name, flags | SEC_LINKER_CREATED);
2059*a9fa9459Szrj 	      if (padd->section == NULL)
2060*a9fa9459Szrj 		{
2061*a9fa9459Szrj 		  bfd_nonfatal_message (NULL, obfd, NULL,
2062*a9fa9459Szrj 					_("can't create section `%s'"),
2063*a9fa9459Szrj 					padd->name);
2064*a9fa9459Szrj 		  return FALSE;
2065*a9fa9459Szrj 		}
2066*a9fa9459Szrj 	    }
2067*a9fa9459Szrj 
2068*a9fa9459Szrj 	  if (! bfd_set_section_size (obfd, padd->section, padd->size))
2069*a9fa9459Szrj 	    {
2070*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
2071*a9fa9459Szrj 	      return FALSE;
2072*a9fa9459Szrj 	    }
2073*a9fa9459Szrj 
2074*a9fa9459Szrj 	  pset = find_section_list (padd->name, FALSE,
2075*a9fa9459Szrj 				    SECTION_CONTEXT_SET_VMA | SECTION_CONTEXT_ALTER_VMA);
2076*a9fa9459Szrj 	  if (pset != NULL
2077*a9fa9459Szrj 	      && ! bfd_set_section_vma (obfd, padd->section, pset->vma_val))
2078*a9fa9459Szrj 	    {
2079*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
2080*a9fa9459Szrj 	      return FALSE;
2081*a9fa9459Szrj 	    }
2082*a9fa9459Szrj 
2083*a9fa9459Szrj 	  pset = find_section_list (padd->name, FALSE,
2084*a9fa9459Szrj 				    SECTION_CONTEXT_SET_LMA | SECTION_CONTEXT_ALTER_LMA);
2085*a9fa9459Szrj 	  if (pset != NULL)
2086*a9fa9459Szrj 	    {
2087*a9fa9459Szrj 	      padd->section->lma = pset->lma_val;
2088*a9fa9459Szrj 
2089*a9fa9459Szrj 	      if (! bfd_set_section_alignment
2090*a9fa9459Szrj 		  (obfd, padd->section,
2091*a9fa9459Szrj 		   bfd_section_alignment (obfd, padd->section)))
2092*a9fa9459Szrj 		{
2093*a9fa9459Szrj 		  bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
2094*a9fa9459Szrj 		  return FALSE;
2095*a9fa9459Szrj 		}
2096*a9fa9459Szrj 	    }
2097*a9fa9459Szrj 	}
2098*a9fa9459Szrj     }
2099*a9fa9459Szrj 
2100*a9fa9459Szrj   if (update_sections != NULL)
2101*a9fa9459Szrj     {
2102*a9fa9459Szrj       struct section_add *pupdate;
2103*a9fa9459Szrj 
2104*a9fa9459Szrj       for (pupdate = update_sections;
2105*a9fa9459Szrj 	   pupdate != NULL;
2106*a9fa9459Szrj 	   pupdate = pupdate->next)
2107*a9fa9459Szrj 	{
2108*a9fa9459Szrj 	  asection *osec;
2109*a9fa9459Szrj 
2110*a9fa9459Szrj 	  pupdate->section = bfd_get_section_by_name (ibfd, pupdate->name);
2111*a9fa9459Szrj 	  if (pupdate->section == NULL)
2112*a9fa9459Szrj 	    {
2113*a9fa9459Szrj 	      non_fatal (_("error: %s not found, can't be updated"), pupdate->name);
2114*a9fa9459Szrj 	      return FALSE;
2115*a9fa9459Szrj 	    }
2116*a9fa9459Szrj 
2117*a9fa9459Szrj 	  osec = pupdate->section->output_section;
2118*a9fa9459Szrj 	  if (! bfd_set_section_size (obfd, osec, pupdate->size))
2119*a9fa9459Szrj 	    {
2120*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, osec, NULL);
2121*a9fa9459Szrj 	      return FALSE;
2122*a9fa9459Szrj 	    }
2123*a9fa9459Szrj 	}
2124*a9fa9459Szrj     }
2125*a9fa9459Szrj 
2126*a9fa9459Szrj   if (dump_sections != NULL)
2127*a9fa9459Szrj     {
2128*a9fa9459Szrj       struct section_add * pdump;
2129*a9fa9459Szrj 
2130*a9fa9459Szrj       for (pdump = dump_sections; pdump != NULL; pdump = pdump->next)
2131*a9fa9459Szrj 	{
2132*a9fa9459Szrj 	  asection * sec;
2133*a9fa9459Szrj 
2134*a9fa9459Szrj 	  sec = bfd_get_section_by_name (ibfd, pdump->name);
2135*a9fa9459Szrj 	  if (sec == NULL)
2136*a9fa9459Szrj 	    {
2137*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, ibfd, NULL,
2138*a9fa9459Szrj 				    _("can't dump section '%s' - it does not exist"),
2139*a9fa9459Szrj 				    pdump->name);
2140*a9fa9459Szrj 	      continue;
2141*a9fa9459Szrj 	    }
2142*a9fa9459Szrj 
2143*a9fa9459Szrj 	  if ((bfd_get_section_flags (ibfd, sec) & SEC_HAS_CONTENTS) == 0)
2144*a9fa9459Szrj 	    {
2145*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, ibfd, sec,
2146*a9fa9459Szrj 				    _("can't dump section - it has no contents"));
2147*a9fa9459Szrj 	      continue;
2148*a9fa9459Szrj 	    }
2149*a9fa9459Szrj 
2150*a9fa9459Szrj 	  bfd_size_type size = bfd_get_section_size (sec);
2151*a9fa9459Szrj 	  if (size == 0)
2152*a9fa9459Szrj 	    {
2153*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, ibfd, sec,
2154*a9fa9459Szrj 				    _("can't dump section - it is empty"));
2155*a9fa9459Szrj 	      continue;
2156*a9fa9459Szrj 	    }
2157*a9fa9459Szrj 
2158*a9fa9459Szrj 	  FILE * f;
2159*a9fa9459Szrj 	  f = fopen (pdump->filename, FOPEN_WB);
2160*a9fa9459Szrj 	  if (f == NULL)
2161*a9fa9459Szrj 	    {
2162*a9fa9459Szrj 	      bfd_nonfatal_message (pdump->filename, NULL, NULL,
2163*a9fa9459Szrj 				    _("could not open section dump file"));
2164*a9fa9459Szrj 	      continue;
2165*a9fa9459Szrj 	    }
2166*a9fa9459Szrj 
2167*a9fa9459Szrj 	  bfd_byte * contents = xmalloc (size);
2168*a9fa9459Szrj 	  if (bfd_get_section_contents (ibfd, sec, contents, 0, size))
2169*a9fa9459Szrj 	    {
2170*a9fa9459Szrj 	      if (fwrite (contents, 1, size, f) != size)
2171*a9fa9459Szrj 		{
2172*a9fa9459Szrj 		  non_fatal (_("error writing section contents to %s (error: %s)"),
2173*a9fa9459Szrj 			     pdump->filename,
2174*a9fa9459Szrj 			     strerror (errno));
2175*a9fa9459Szrj 		  return FALSE;
2176*a9fa9459Szrj 		}
2177*a9fa9459Szrj 	    }
2178*a9fa9459Szrj 	  else
2179*a9fa9459Szrj 	    bfd_nonfatal_message (NULL, ibfd, sec,
2180*a9fa9459Szrj 				  _("could not retrieve section contents"));
2181*a9fa9459Szrj 
2182*a9fa9459Szrj 	  fclose (f);
2183*a9fa9459Szrj 	  free (contents);
2184*a9fa9459Szrj 	}
2185*a9fa9459Szrj     }
2186*a9fa9459Szrj 
2187*a9fa9459Szrj   if (gnu_debuglink_filename != NULL)
2188*a9fa9459Szrj     {
2189*a9fa9459Szrj       /* PR 15125: Give a helpful warning message if
2190*a9fa9459Szrj 	 the debuglink section already exists, and
2191*a9fa9459Szrj 	 allow the rest of the copy to complete.  */
2192*a9fa9459Szrj       if (bfd_get_section_by_name (obfd, ".gnu_debuglink"))
2193*a9fa9459Szrj 	{
2194*a9fa9459Szrj 	  non_fatal (_("%s: debuglink section already exists"),
2195*a9fa9459Szrj 		     bfd_get_filename (obfd));
2196*a9fa9459Szrj 	  gnu_debuglink_filename = NULL;
2197*a9fa9459Szrj 	}
2198*a9fa9459Szrj       else
2199*a9fa9459Szrj 	{
2200*a9fa9459Szrj 	  gnu_debuglink_section = bfd_create_gnu_debuglink_section
2201*a9fa9459Szrj 	    (obfd, gnu_debuglink_filename);
2202*a9fa9459Szrj 
2203*a9fa9459Szrj 	  if (gnu_debuglink_section == NULL)
2204*a9fa9459Szrj 	    {
2205*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, NULL,
2206*a9fa9459Szrj 				    _("cannot create debug link section `%s'"),
2207*a9fa9459Szrj 				    gnu_debuglink_filename);
2208*a9fa9459Szrj 	      return FALSE;
2209*a9fa9459Szrj 	    }
2210*a9fa9459Szrj 
2211*a9fa9459Szrj 	  /* Special processing for PE format files.  We
2212*a9fa9459Szrj 	     have no way to distinguish PE from COFF here.  */
2213*a9fa9459Szrj 	  if (bfd_get_flavour (obfd) == bfd_target_coff_flavour)
2214*a9fa9459Szrj 	    {
2215*a9fa9459Szrj 	      bfd_vma debuglink_vma;
2216*a9fa9459Szrj 	      asection * highest_section;
2217*a9fa9459Szrj 	      asection * sec;
2218*a9fa9459Szrj 
2219*a9fa9459Szrj 	      /* The PE spec requires that all sections be adjacent and sorted
2220*a9fa9459Szrj 		 in ascending order of VMA.  It also specifies that debug
2221*a9fa9459Szrj 		 sections should be last.  This is despite the fact that debug
2222*a9fa9459Szrj 		 sections are not loaded into memory and so in theory have no
2223*a9fa9459Szrj 		 use for a VMA.
2224*a9fa9459Szrj 
2225*a9fa9459Szrj 		 This means that the debuglink section must be given a non-zero
2226*a9fa9459Szrj 		 VMA which makes it contiguous with other debug sections.  So
2227*a9fa9459Szrj 		 walk the current section list, find the section with the
2228*a9fa9459Szrj 		 highest VMA and start the debuglink section after that one.  */
2229*a9fa9459Szrj 	      for (sec = obfd->sections, highest_section = NULL;
2230*a9fa9459Szrj 		   sec != NULL;
2231*a9fa9459Szrj 		   sec = sec->next)
2232*a9fa9459Szrj 		if (sec->vma > 0
2233*a9fa9459Szrj 		    && (highest_section == NULL
2234*a9fa9459Szrj 			|| sec->vma > highest_section->vma))
2235*a9fa9459Szrj 		  highest_section = sec;
2236*a9fa9459Szrj 
2237*a9fa9459Szrj 	      if (highest_section)
2238*a9fa9459Szrj 		debuglink_vma = BFD_ALIGN (highest_section->vma
2239*a9fa9459Szrj 					   + highest_section->size,
2240*a9fa9459Szrj 					   /* FIXME: We ought to be using
2241*a9fa9459Szrj 					      COFF_PAGE_SIZE here or maybe
2242*a9fa9459Szrj 					      bfd_get_section_alignment() (if it
2243*a9fa9459Szrj 					      was set) but since this is for PE
2244*a9fa9459Szrj 					      and we know the required alignment
2245*a9fa9459Szrj 					      it is easier just to hard code it.  */
2246*a9fa9459Szrj 					   0x1000);
2247*a9fa9459Szrj 	      else
2248*a9fa9459Szrj 		/* Umm, not sure what to do in this case.  */
2249*a9fa9459Szrj 		debuglink_vma = 0x1000;
2250*a9fa9459Szrj 
2251*a9fa9459Szrj 	      bfd_set_section_vma (obfd, gnu_debuglink_section, debuglink_vma);
2252*a9fa9459Szrj 	    }
2253*a9fa9459Szrj 	}
2254*a9fa9459Szrj     }
2255*a9fa9459Szrj 
2256*a9fa9459Szrj   c = bfd_count_sections (obfd);
2257*a9fa9459Szrj   if (c != 0
2258*a9fa9459Szrj       && (gap_fill_set || pad_to_set))
2259*a9fa9459Szrj     {
2260*a9fa9459Szrj       asection **set;
2261*a9fa9459Szrj 
2262*a9fa9459Szrj       /* We must fill in gaps between the sections and/or we must pad
2263*a9fa9459Szrj 	 the last section to a specified address.  We do this by
2264*a9fa9459Szrj 	 grabbing a list of the sections, sorting them by VMA, and
2265*a9fa9459Szrj 	 increasing the section sizes as required to fill the gaps.
2266*a9fa9459Szrj 	 We write out the gap contents below.  */
2267*a9fa9459Szrj 
2268*a9fa9459Szrj       osections = (asection **) xmalloc (c * sizeof (asection *));
2269*a9fa9459Szrj       set = osections;
2270*a9fa9459Szrj       bfd_map_over_sections (obfd, get_sections, &set);
2271*a9fa9459Szrj 
2272*a9fa9459Szrj       qsort (osections, c, sizeof (asection *), compare_section_lma);
2273*a9fa9459Szrj 
2274*a9fa9459Szrj       gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type));
2275*a9fa9459Szrj       memset (gaps, 0, c * sizeof (bfd_size_type));
2276*a9fa9459Szrj 
2277*a9fa9459Szrj       if (gap_fill_set)
2278*a9fa9459Szrj 	{
2279*a9fa9459Szrj 	  for (i = 0; i < c - 1; i++)
2280*a9fa9459Szrj 	    {
2281*a9fa9459Szrj 	      flagword flags;
2282*a9fa9459Szrj 	      bfd_size_type size;
2283*a9fa9459Szrj 	      bfd_vma gap_start, gap_stop;
2284*a9fa9459Szrj 
2285*a9fa9459Szrj 	      flags = bfd_get_section_flags (obfd, osections[i]);
2286*a9fa9459Szrj 	      if ((flags & SEC_HAS_CONTENTS) == 0
2287*a9fa9459Szrj 		  || (flags & SEC_LOAD) == 0)
2288*a9fa9459Szrj 		continue;
2289*a9fa9459Szrj 
2290*a9fa9459Szrj 	      size = bfd_section_size (obfd, osections[i]);
2291*a9fa9459Szrj 	      gap_start = bfd_section_lma (obfd, osections[i]) + size;
2292*a9fa9459Szrj 	      gap_stop = bfd_section_lma (obfd, osections[i + 1]);
2293*a9fa9459Szrj 	      if (gap_start < gap_stop)
2294*a9fa9459Szrj 		{
2295*a9fa9459Szrj 		  if (! bfd_set_section_size (obfd, osections[i],
2296*a9fa9459Szrj 					      size + (gap_stop - gap_start)))
2297*a9fa9459Szrj 		    {
2298*a9fa9459Szrj 		      bfd_nonfatal_message (NULL, obfd, osections[i],
2299*a9fa9459Szrj 					    _("Can't fill gap after section"));
2300*a9fa9459Szrj 		      status = 1;
2301*a9fa9459Szrj 		      break;
2302*a9fa9459Szrj 		    }
2303*a9fa9459Szrj 		  gaps[i] = gap_stop - gap_start;
2304*a9fa9459Szrj 		  if (max_gap < gap_stop - gap_start)
2305*a9fa9459Szrj 		    max_gap = gap_stop - gap_start;
2306*a9fa9459Szrj 		}
2307*a9fa9459Szrj 	    }
2308*a9fa9459Szrj 	}
2309*a9fa9459Szrj 
2310*a9fa9459Szrj       if (pad_to_set)
2311*a9fa9459Szrj 	{
2312*a9fa9459Szrj 	  bfd_vma lma;
2313*a9fa9459Szrj 	  bfd_size_type size;
2314*a9fa9459Szrj 
2315*a9fa9459Szrj 	  lma = bfd_section_lma (obfd, osections[c - 1]);
2316*a9fa9459Szrj 	  size = bfd_section_size (obfd, osections[c - 1]);
2317*a9fa9459Szrj 	  if (lma + size < pad_to)
2318*a9fa9459Szrj 	    {
2319*a9fa9459Szrj 	      if (! bfd_set_section_size (obfd, osections[c - 1],
2320*a9fa9459Szrj 					  pad_to - lma))
2321*a9fa9459Szrj 		{
2322*a9fa9459Szrj 		  bfd_nonfatal_message (NULL, obfd, osections[c - 1],
2323*a9fa9459Szrj 					_("can't add padding"));
2324*a9fa9459Szrj 		  status = 1;
2325*a9fa9459Szrj 		}
2326*a9fa9459Szrj 	      else
2327*a9fa9459Szrj 		{
2328*a9fa9459Szrj 		  gaps[c - 1] = pad_to - (lma + size);
2329*a9fa9459Szrj 		  if (max_gap < pad_to - (lma + size))
2330*a9fa9459Szrj 		    max_gap = pad_to - (lma + size);
2331*a9fa9459Szrj 		}
2332*a9fa9459Szrj 	    }
2333*a9fa9459Szrj 	}
2334*a9fa9459Szrj     }
2335*a9fa9459Szrj 
2336*a9fa9459Szrj   /* Symbol filtering must happen after the output sections
2337*a9fa9459Szrj      have been created, but before their contents are set.  */
2338*a9fa9459Szrj   dhandle = NULL;
2339*a9fa9459Szrj   if (convert_debugging)
2340*a9fa9459Szrj     dhandle = read_debugging_info (ibfd, isympp, symcount, FALSE);
2341*a9fa9459Szrj 
2342*a9fa9459Szrj   if (strip_symbols == STRIP_DEBUG
2343*a9fa9459Szrj       || strip_symbols == STRIP_ALL
2344*a9fa9459Szrj       || strip_symbols == STRIP_UNNEEDED
2345*a9fa9459Szrj       || strip_symbols == STRIP_NONDEBUG
2346*a9fa9459Szrj       || strip_symbols == STRIP_DWO
2347*a9fa9459Szrj       || strip_symbols == STRIP_NONDWO
2348*a9fa9459Szrj       || discard_locals != LOCALS_UNDEF
2349*a9fa9459Szrj       || localize_hidden
2350*a9fa9459Szrj       || htab_elements (strip_specific_htab) != 0
2351*a9fa9459Szrj       || htab_elements (keep_specific_htab) != 0
2352*a9fa9459Szrj       || htab_elements (localize_specific_htab) != 0
2353*a9fa9459Szrj       || htab_elements (globalize_specific_htab) != 0
2354*a9fa9459Szrj       || htab_elements (keepglobal_specific_htab) != 0
2355*a9fa9459Szrj       || htab_elements (weaken_specific_htab) != 0
2356*a9fa9459Szrj       || prefix_symbols_string
2357*a9fa9459Szrj       || sections_removed
2358*a9fa9459Szrj       || sections_copied
2359*a9fa9459Szrj       || convert_debugging
2360*a9fa9459Szrj       || change_leading_char
2361*a9fa9459Szrj       || remove_leading_char
2362*a9fa9459Szrj       || redefine_sym_list
2363*a9fa9459Szrj       || section_rename_list
2364*a9fa9459Szrj       || weaken
2365*a9fa9459Szrj       || add_symbols)
2366*a9fa9459Szrj     {
2367*a9fa9459Szrj       /* Mark symbols used in output relocations so that they
2368*a9fa9459Szrj 	 are kept, even if they are local labels or static symbols.
2369*a9fa9459Szrj 
2370*a9fa9459Szrj 	 Note we iterate over the input sections examining their
2371*a9fa9459Szrj 	 relocations since the relocations for the output sections
2372*a9fa9459Szrj 	 haven't been set yet.  mark_symbols_used_in_relocations will
2373*a9fa9459Szrj 	 ignore input sections which have no corresponding output
2374*a9fa9459Szrj 	 section.  */
2375*a9fa9459Szrj       if (strip_symbols != STRIP_ALL)
2376*a9fa9459Szrj 	bfd_map_over_sections (ibfd,
2377*a9fa9459Szrj 			       mark_symbols_used_in_relocations,
2378*a9fa9459Szrj 			       isympp);
2379*a9fa9459Szrj       osympp = (asymbol **) xmalloc ((symcount + add_symbols + 1) * sizeof (asymbol *));
2380*a9fa9459Szrj       symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
2381*a9fa9459Szrj     }
2382*a9fa9459Szrj 
2383*a9fa9459Szrj   if (convert_debugging && dhandle != NULL)
2384*a9fa9459Szrj     {
2385*a9fa9459Szrj       if (! write_debugging_info (obfd, dhandle, &symcount, &osympp))
2386*a9fa9459Szrj 	{
2387*a9fa9459Szrj 	  status = 1;
2388*a9fa9459Szrj 	  return FALSE;
2389*a9fa9459Szrj 	}
2390*a9fa9459Szrj     }
2391*a9fa9459Szrj 
2392*a9fa9459Szrj   bfd_set_symtab (obfd, osympp, symcount);
2393*a9fa9459Szrj 
2394*a9fa9459Szrj   /* This has to happen before section positions are set.  */
2395*a9fa9459Szrj   bfd_map_over_sections (ibfd, copy_relocations_in_section, obfd);
2396*a9fa9459Szrj 
2397*a9fa9459Szrj   /* This has to happen after the symbol table has been set.  */
2398*a9fa9459Szrj   bfd_map_over_sections (ibfd, copy_section, obfd);
2399*a9fa9459Szrj 
2400*a9fa9459Szrj   if (add_sections != NULL)
2401*a9fa9459Szrj     {
2402*a9fa9459Szrj       struct section_add *padd;
2403*a9fa9459Szrj 
2404*a9fa9459Szrj       for (padd = add_sections; padd != NULL; padd = padd->next)
2405*a9fa9459Szrj 	{
2406*a9fa9459Szrj 	  if (! bfd_set_section_contents (obfd, padd->section, padd->contents,
2407*a9fa9459Szrj 					  0, padd->size))
2408*a9fa9459Szrj 	    {
2409*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, padd->section, NULL);
2410*a9fa9459Szrj 	      return FALSE;
2411*a9fa9459Szrj 	    }
2412*a9fa9459Szrj 	}
2413*a9fa9459Szrj     }
2414*a9fa9459Szrj 
2415*a9fa9459Szrj   if (update_sections != NULL)
2416*a9fa9459Szrj     {
2417*a9fa9459Szrj       struct section_add *pupdate;
2418*a9fa9459Szrj 
2419*a9fa9459Szrj       for (pupdate = update_sections;
2420*a9fa9459Szrj 	   pupdate != NULL;
2421*a9fa9459Szrj 	   pupdate = pupdate->next)
2422*a9fa9459Szrj 	{
2423*a9fa9459Szrj 	  asection *osec;
2424*a9fa9459Szrj 
2425*a9fa9459Szrj 	  osec = pupdate->section->output_section;
2426*a9fa9459Szrj 	  if (! bfd_set_section_contents (obfd, osec, pupdate->contents,
2427*a9fa9459Szrj 					  0, pupdate->size))
2428*a9fa9459Szrj 	    {
2429*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, obfd, osec, NULL);
2430*a9fa9459Szrj 	      return FALSE;
2431*a9fa9459Szrj 	    }
2432*a9fa9459Szrj 	}
2433*a9fa9459Szrj     }
2434*a9fa9459Szrj 
2435*a9fa9459Szrj   if (gnu_debuglink_filename != NULL)
2436*a9fa9459Szrj     {
2437*a9fa9459Szrj       if (! bfd_fill_in_gnu_debuglink_section
2438*a9fa9459Szrj 	  (obfd, gnu_debuglink_section, gnu_debuglink_filename))
2439*a9fa9459Szrj 	{
2440*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, obfd, NULL,
2441*a9fa9459Szrj 				_("cannot fill debug link section `%s'"),
2442*a9fa9459Szrj 				gnu_debuglink_filename);
2443*a9fa9459Szrj 	  return FALSE;
2444*a9fa9459Szrj 	}
2445*a9fa9459Szrj     }
2446*a9fa9459Szrj 
2447*a9fa9459Szrj   if (gap_fill_set || pad_to_set)
2448*a9fa9459Szrj     {
2449*a9fa9459Szrj       bfd_byte *buf;
2450*a9fa9459Szrj 
2451*a9fa9459Szrj       /* Fill in the gaps.  */
2452*a9fa9459Szrj       if (max_gap > 8192)
2453*a9fa9459Szrj 	max_gap = 8192;
2454*a9fa9459Szrj       buf = (bfd_byte *) xmalloc (max_gap);
2455*a9fa9459Szrj       memset (buf, gap_fill, max_gap);
2456*a9fa9459Szrj 
2457*a9fa9459Szrj       c = bfd_count_sections (obfd);
2458*a9fa9459Szrj       for (i = 0; i < c; i++)
2459*a9fa9459Szrj 	{
2460*a9fa9459Szrj 	  if (gaps[i] != 0)
2461*a9fa9459Szrj 	    {
2462*a9fa9459Szrj 	      bfd_size_type left;
2463*a9fa9459Szrj 	      file_ptr off;
2464*a9fa9459Szrj 
2465*a9fa9459Szrj 	      left = gaps[i];
2466*a9fa9459Szrj 	      off = bfd_section_size (obfd, osections[i]) - left;
2467*a9fa9459Szrj 
2468*a9fa9459Szrj 	      while (left > 0)
2469*a9fa9459Szrj 		{
2470*a9fa9459Szrj 		  bfd_size_type now;
2471*a9fa9459Szrj 
2472*a9fa9459Szrj 		  if (left > 8192)
2473*a9fa9459Szrj 		    now = 8192;
2474*a9fa9459Szrj 		  else
2475*a9fa9459Szrj 		    now = left;
2476*a9fa9459Szrj 
2477*a9fa9459Szrj 		  if (! bfd_set_section_contents (obfd, osections[i], buf,
2478*a9fa9459Szrj 						  off, now))
2479*a9fa9459Szrj 		    {
2480*a9fa9459Szrj 		      bfd_nonfatal_message (NULL, obfd, osections[i], NULL);
2481*a9fa9459Szrj 		      return FALSE;
2482*a9fa9459Szrj 		    }
2483*a9fa9459Szrj 
2484*a9fa9459Szrj 		  left -= now;
2485*a9fa9459Szrj 		  off += now;
2486*a9fa9459Szrj 		}
2487*a9fa9459Szrj 	    }
2488*a9fa9459Szrj 	}
2489*a9fa9459Szrj     }
2490*a9fa9459Szrj 
2491*a9fa9459Szrj   /* Allow the BFD backend to copy any private data it understands
2492*a9fa9459Szrj      from the input BFD to the output BFD.  This is done last to
2493*a9fa9459Szrj      permit the routine to look at the filtered symbol table, which is
2494*a9fa9459Szrj      important for the ECOFF code at least.  */
2495*a9fa9459Szrj   if (! bfd_copy_private_bfd_data (ibfd, obfd))
2496*a9fa9459Szrj     {
2497*a9fa9459Szrj       bfd_nonfatal_message (NULL, obfd, NULL,
2498*a9fa9459Szrj 			    _("error copying private BFD data"));
2499*a9fa9459Szrj       return FALSE;
2500*a9fa9459Szrj     }
2501*a9fa9459Szrj 
2502*a9fa9459Szrj   /* Switch to the alternate machine code.  We have to do this at the
2503*a9fa9459Szrj      very end, because we only initialize the header when we create
2504*a9fa9459Szrj      the first section.  */
2505*a9fa9459Szrj   if (use_alt_mach_code != 0)
2506*a9fa9459Szrj     {
2507*a9fa9459Szrj       if (! bfd_alt_mach_code (obfd, use_alt_mach_code))
2508*a9fa9459Szrj 	{
2509*a9fa9459Szrj 	  non_fatal (_("this target does not support %lu alternative machine codes"),
2510*a9fa9459Szrj 		     use_alt_mach_code);
2511*a9fa9459Szrj 	  if (bfd_get_flavour (obfd) == bfd_target_elf_flavour)
2512*a9fa9459Szrj 	    {
2513*a9fa9459Szrj 	      non_fatal (_("treating that number as an absolute e_machine value instead"));
2514*a9fa9459Szrj 	      elf_elfheader (obfd)->e_machine = use_alt_mach_code;
2515*a9fa9459Szrj 	    }
2516*a9fa9459Szrj 	  else
2517*a9fa9459Szrj 	    non_fatal (_("ignoring the alternative value"));
2518*a9fa9459Szrj 	}
2519*a9fa9459Szrj     }
2520*a9fa9459Szrj 
2521*a9fa9459Szrj   return TRUE;
2522*a9fa9459Szrj }
2523*a9fa9459Szrj 
2524*a9fa9459Szrj /* Read each archive element in turn from IBFD, copy the
2525*a9fa9459Szrj    contents to temp file, and keep the temp file handle.
2526*a9fa9459Szrj    If 'force_output_target' is TRUE then make sure that
2527*a9fa9459Szrj    all elements in the new archive are of the type
2528*a9fa9459Szrj    'output_target'.  */
2529*a9fa9459Szrj 
2530*a9fa9459Szrj static void
copy_archive(bfd * ibfd,bfd * obfd,const char * output_target,bfd_boolean force_output_target,const bfd_arch_info_type * input_arch)2531*a9fa9459Szrj copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
2532*a9fa9459Szrj 	      bfd_boolean force_output_target,
2533*a9fa9459Szrj 	      const bfd_arch_info_type *input_arch)
2534*a9fa9459Szrj {
2535*a9fa9459Szrj   struct name_list
2536*a9fa9459Szrj     {
2537*a9fa9459Szrj       struct name_list *next;
2538*a9fa9459Szrj       const char *name;
2539*a9fa9459Szrj       bfd *obfd;
2540*a9fa9459Szrj     } *list, *l;
2541*a9fa9459Szrj   bfd **ptr = &obfd->archive_head;
2542*a9fa9459Szrj   bfd *this_element;
2543*a9fa9459Szrj   char *dir;
2544*a9fa9459Szrj   const char *filename;
2545*a9fa9459Szrj 
2546*a9fa9459Szrj   /* Make a temp directory to hold the contents.  */
2547*a9fa9459Szrj   dir = make_tempdir (bfd_get_filename (obfd));
2548*a9fa9459Szrj   if (dir == NULL)
2549*a9fa9459Szrj     fatal (_("cannot create tempdir for archive copying (error: %s)"),
2550*a9fa9459Szrj 	   strerror (errno));
2551*a9fa9459Szrj 
2552*a9fa9459Szrj   if (strip_symbols == STRIP_ALL)
2553*a9fa9459Szrj     obfd->has_armap = FALSE;
2554*a9fa9459Szrj   else
2555*a9fa9459Szrj     obfd->has_armap = ibfd->has_armap;
2556*a9fa9459Szrj   obfd->is_thin_archive = ibfd->is_thin_archive;
2557*a9fa9459Szrj 
2558*a9fa9459Szrj   if (deterministic)
2559*a9fa9459Szrj     obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
2560*a9fa9459Szrj 
2561*a9fa9459Szrj   list = NULL;
2562*a9fa9459Szrj 
2563*a9fa9459Szrj   this_element = bfd_openr_next_archived_file (ibfd, NULL);
2564*a9fa9459Szrj 
2565*a9fa9459Szrj   if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
2566*a9fa9459Szrj     {
2567*a9fa9459Szrj       status = 1;
2568*a9fa9459Szrj       bfd_nonfatal_message (NULL, obfd, NULL, NULL);
2569*a9fa9459Szrj       goto cleanup_and_exit;
2570*a9fa9459Szrj     }
2571*a9fa9459Szrj 
2572*a9fa9459Szrj   while (!status && this_element != NULL)
2573*a9fa9459Szrj     {
2574*a9fa9459Szrj       char *output_name;
2575*a9fa9459Szrj       bfd *output_bfd;
2576*a9fa9459Szrj       bfd *last_element;
2577*a9fa9459Szrj       struct stat buf;
2578*a9fa9459Szrj       int stat_status = 0;
2579*a9fa9459Szrj       bfd_boolean del = TRUE;
2580*a9fa9459Szrj       bfd_boolean ok_object;
2581*a9fa9459Szrj 
2582*a9fa9459Szrj       /* PR binutils/17533: Do not allow directory traversal
2583*a9fa9459Szrj 	 outside of the current directory tree by archive members.  */
2584*a9fa9459Szrj       if (! is_valid_archive_path (bfd_get_filename (this_element)))
2585*a9fa9459Szrj 	{
2586*a9fa9459Szrj 	  non_fatal (_("illegal pathname found in archive member: %s"),
2587*a9fa9459Szrj 		     bfd_get_filename (this_element));
2588*a9fa9459Szrj 	  status = 1;
2589*a9fa9459Szrj 	  goto cleanup_and_exit;
2590*a9fa9459Szrj 	}
2591*a9fa9459Szrj 
2592*a9fa9459Szrj       /* Create an output file for this member.  */
2593*a9fa9459Szrj       output_name = concat (dir, "/",
2594*a9fa9459Szrj 			    bfd_get_filename (this_element), (char *) 0);
2595*a9fa9459Szrj 
2596*a9fa9459Szrj       /* If the file already exists, make another temp dir.  */
2597*a9fa9459Szrj       if (stat (output_name, &buf) >= 0)
2598*a9fa9459Szrj 	{
2599*a9fa9459Szrj 	  output_name = make_tempdir (output_name);
2600*a9fa9459Szrj 	  if (output_name == NULL)
2601*a9fa9459Szrj 	    {
2602*a9fa9459Szrj 	      non_fatal (_("cannot create tempdir for archive copying (error: %s)"),
2603*a9fa9459Szrj 			 strerror (errno));
2604*a9fa9459Szrj 	      status = 1;
2605*a9fa9459Szrj 	      goto cleanup_and_exit;
2606*a9fa9459Szrj 	    }
2607*a9fa9459Szrj 
2608*a9fa9459Szrj 	  l = (struct name_list *) xmalloc (sizeof (struct name_list));
2609*a9fa9459Szrj 	  l->name = output_name;
2610*a9fa9459Szrj 	  l->next = list;
2611*a9fa9459Szrj 	  l->obfd = NULL;
2612*a9fa9459Szrj 	  list = l;
2613*a9fa9459Szrj 	  output_name = concat (output_name, "/",
2614*a9fa9459Szrj 				bfd_get_filename (this_element), (char *) 0);
2615*a9fa9459Szrj 	}
2616*a9fa9459Szrj 
2617*a9fa9459Szrj       if (preserve_dates)
2618*a9fa9459Szrj 	{
2619*a9fa9459Szrj 	  stat_status = bfd_stat_arch_elt (this_element, &buf);
2620*a9fa9459Szrj 
2621*a9fa9459Szrj 	  if (stat_status != 0)
2622*a9fa9459Szrj 	    non_fatal (_("internal stat error on %s"),
2623*a9fa9459Szrj 		       bfd_get_filename (this_element));
2624*a9fa9459Szrj 	}
2625*a9fa9459Szrj 
2626*a9fa9459Szrj       l = (struct name_list *) xmalloc (sizeof (struct name_list));
2627*a9fa9459Szrj       l->name = output_name;
2628*a9fa9459Szrj       l->next = list;
2629*a9fa9459Szrj       l->obfd = NULL;
2630*a9fa9459Szrj       list = l;
2631*a9fa9459Szrj 
2632*a9fa9459Szrj       ok_object = bfd_check_format (this_element, bfd_object);
2633*a9fa9459Szrj       if (!ok_object)
2634*a9fa9459Szrj 	bfd_nonfatal_message (NULL, this_element, NULL,
2635*a9fa9459Szrj 			      _("Unable to recognise the format of file"));
2636*a9fa9459Szrj 
2637*a9fa9459Szrj       /* PR binutils/3110: Cope with archives
2638*a9fa9459Szrj 	 containing multiple target types.  */
2639*a9fa9459Szrj       if (force_output_target || !ok_object)
2640*a9fa9459Szrj 	output_bfd = bfd_openw (output_name, output_target);
2641*a9fa9459Szrj       else
2642*a9fa9459Szrj 	output_bfd = bfd_openw (output_name, bfd_get_target (this_element));
2643*a9fa9459Szrj 
2644*a9fa9459Szrj       if (output_bfd == NULL)
2645*a9fa9459Szrj 	{
2646*a9fa9459Szrj 	  bfd_nonfatal_message (output_name, NULL, NULL, NULL);
2647*a9fa9459Szrj 	  status = 1;
2648*a9fa9459Szrj 	  goto cleanup_and_exit;
2649*a9fa9459Szrj 	}
2650*a9fa9459Szrj 
2651*a9fa9459Szrj       if (ok_object)
2652*a9fa9459Szrj 	{
2653*a9fa9459Szrj 	  del = !copy_object (this_element, output_bfd, input_arch);
2654*a9fa9459Szrj 
2655*a9fa9459Szrj 	  if (del && bfd_get_arch (this_element) == bfd_arch_unknown)
2656*a9fa9459Szrj 	    /* Try again as an unknown object file.  */
2657*a9fa9459Szrj 	    ok_object = FALSE;
2658*a9fa9459Szrj 	  else if (!bfd_close (output_bfd))
2659*a9fa9459Szrj 	    {
2660*a9fa9459Szrj 	      bfd_nonfatal_message (output_name, NULL, NULL, NULL);
2661*a9fa9459Szrj 	      /* Error in new object file. Don't change archive.  */
2662*a9fa9459Szrj 	      status = 1;
2663*a9fa9459Szrj 	    }
2664*a9fa9459Szrj 	}
2665*a9fa9459Szrj 
2666*a9fa9459Szrj       if (!ok_object)
2667*a9fa9459Szrj 	{
2668*a9fa9459Szrj 	  del = !copy_unknown_object (this_element, output_bfd);
2669*a9fa9459Szrj 	  if (!bfd_close_all_done (output_bfd))
2670*a9fa9459Szrj 	    {
2671*a9fa9459Szrj 	      bfd_nonfatal_message (output_name, NULL, NULL, NULL);
2672*a9fa9459Szrj 	      /* Error in new object file. Don't change archive.  */
2673*a9fa9459Szrj 	      status = 1;
2674*a9fa9459Szrj 	    }
2675*a9fa9459Szrj 	}
2676*a9fa9459Szrj 
2677*a9fa9459Szrj       if (del)
2678*a9fa9459Szrj 	{
2679*a9fa9459Szrj 	  unlink (output_name);
2680*a9fa9459Szrj 	  status = 1;
2681*a9fa9459Szrj 	}
2682*a9fa9459Szrj       else
2683*a9fa9459Szrj 	{
2684*a9fa9459Szrj 	  if (preserve_dates && stat_status == 0)
2685*a9fa9459Szrj 	    set_times (output_name, &buf);
2686*a9fa9459Szrj 
2687*a9fa9459Szrj 	  /* Open the newly output file and attach to our list.  */
2688*a9fa9459Szrj 	  output_bfd = bfd_openr (output_name, output_target);
2689*a9fa9459Szrj 
2690*a9fa9459Szrj 	  l->obfd = output_bfd;
2691*a9fa9459Szrj 
2692*a9fa9459Szrj 	  *ptr = output_bfd;
2693*a9fa9459Szrj 	  ptr = &output_bfd->archive_next;
2694*a9fa9459Szrj 
2695*a9fa9459Szrj 	  last_element = this_element;
2696*a9fa9459Szrj 
2697*a9fa9459Szrj 	  this_element = bfd_openr_next_archived_file (ibfd, last_element);
2698*a9fa9459Szrj 
2699*a9fa9459Szrj 	  bfd_close (last_element);
2700*a9fa9459Szrj 	}
2701*a9fa9459Szrj     }
2702*a9fa9459Szrj   *ptr = NULL;
2703*a9fa9459Szrj 
2704*a9fa9459Szrj   filename = bfd_get_filename (obfd);
2705*a9fa9459Szrj   if (!bfd_close (obfd))
2706*a9fa9459Szrj     {
2707*a9fa9459Szrj       status = 1;
2708*a9fa9459Szrj       bfd_nonfatal_message (filename, NULL, NULL, NULL);
2709*a9fa9459Szrj     }
2710*a9fa9459Szrj 
2711*a9fa9459Szrj   filename = bfd_get_filename (ibfd);
2712*a9fa9459Szrj   if (!bfd_close (ibfd))
2713*a9fa9459Szrj     {
2714*a9fa9459Szrj       status = 1;
2715*a9fa9459Szrj       bfd_nonfatal_message (filename, NULL, NULL, NULL);
2716*a9fa9459Szrj     }
2717*a9fa9459Szrj 
2718*a9fa9459Szrj  cleanup_and_exit:
2719*a9fa9459Szrj   /* Delete all the files that we opened.  */
2720*a9fa9459Szrj   for (l = list; l != NULL; l = l->next)
2721*a9fa9459Szrj     {
2722*a9fa9459Szrj       if (l->obfd == NULL)
2723*a9fa9459Szrj 	rmdir (l->name);
2724*a9fa9459Szrj       else
2725*a9fa9459Szrj 	{
2726*a9fa9459Szrj 	  bfd_close (l->obfd);
2727*a9fa9459Szrj 	  unlink (l->name);
2728*a9fa9459Szrj 	}
2729*a9fa9459Szrj     }
2730*a9fa9459Szrj 
2731*a9fa9459Szrj   rmdir (dir);
2732*a9fa9459Szrj }
2733*a9fa9459Szrj 
2734*a9fa9459Szrj static void
set_long_section_mode(bfd * output_bfd,bfd * input_bfd,enum long_section_name_handling style)2735*a9fa9459Szrj set_long_section_mode (bfd *output_bfd, bfd *input_bfd, enum long_section_name_handling style)
2736*a9fa9459Szrj {
2737*a9fa9459Szrj   /* This is only relevant to Coff targets.  */
2738*a9fa9459Szrj   if (bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
2739*a9fa9459Szrj     {
2740*a9fa9459Szrj       if (style == KEEP
2741*a9fa9459Szrj 	  && bfd_get_flavour (input_bfd) == bfd_target_coff_flavour)
2742*a9fa9459Szrj 	style = bfd_coff_long_section_names (input_bfd) ? ENABLE : DISABLE;
2743*a9fa9459Szrj       bfd_coff_set_long_section_names (output_bfd, style != DISABLE);
2744*a9fa9459Szrj     }
2745*a9fa9459Szrj }
2746*a9fa9459Szrj 
2747*a9fa9459Szrj /* The top-level control.  */
2748*a9fa9459Szrj 
2749*a9fa9459Szrj static void
copy_file(const char * input_filename,const char * output_filename,const char * input_target,const char * output_target,const bfd_arch_info_type * input_arch)2750*a9fa9459Szrj copy_file (const char *input_filename, const char *output_filename,
2751*a9fa9459Szrj 	   const char *input_target,   const char *output_target,
2752*a9fa9459Szrj 	   const bfd_arch_info_type *input_arch)
2753*a9fa9459Szrj {
2754*a9fa9459Szrj   bfd *ibfd;
2755*a9fa9459Szrj   char **obj_matching;
2756*a9fa9459Szrj   char **core_matching;
2757*a9fa9459Szrj   off_t size = get_file_size (input_filename);
2758*a9fa9459Szrj 
2759*a9fa9459Szrj   if (size < 1)
2760*a9fa9459Szrj     {
2761*a9fa9459Szrj       if (size == 0)
2762*a9fa9459Szrj 	non_fatal (_("error: the input file '%s' is empty"),
2763*a9fa9459Szrj 		   input_filename);
2764*a9fa9459Szrj       status = 1;
2765*a9fa9459Szrj       return;
2766*a9fa9459Szrj     }
2767*a9fa9459Szrj 
2768*a9fa9459Szrj   /* To allow us to do "strip *" without dying on the first
2769*a9fa9459Szrj      non-object file, failures are nonfatal.  */
2770*a9fa9459Szrj   ibfd = bfd_openr (input_filename, input_target);
2771*a9fa9459Szrj   if (ibfd == NULL)
2772*a9fa9459Szrj     {
2773*a9fa9459Szrj       bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
2774*a9fa9459Szrj       status = 1;
2775*a9fa9459Szrj       return;
2776*a9fa9459Szrj     }
2777*a9fa9459Szrj 
2778*a9fa9459Szrj   switch (do_debug_sections)
2779*a9fa9459Szrj     {
2780*a9fa9459Szrj     case compress:
2781*a9fa9459Szrj     case compress_zlib:
2782*a9fa9459Szrj     case compress_gnu_zlib:
2783*a9fa9459Szrj     case compress_gabi_zlib:
2784*a9fa9459Szrj       ibfd->flags |= BFD_COMPRESS;
2785*a9fa9459Szrj       /* Don't check if input is ELF here since this information is
2786*a9fa9459Szrj 	 only available after bfd_check_format_matches is called.  */
2787*a9fa9459Szrj       if (do_debug_sections != compress_gnu_zlib)
2788*a9fa9459Szrj 	ibfd->flags |= BFD_COMPRESS_GABI;
2789*a9fa9459Szrj       break;
2790*a9fa9459Szrj     case decompress:
2791*a9fa9459Szrj       ibfd->flags |= BFD_DECOMPRESS;
2792*a9fa9459Szrj       break;
2793*a9fa9459Szrj     default:
2794*a9fa9459Szrj       break;
2795*a9fa9459Szrj     }
2796*a9fa9459Szrj 
2797*a9fa9459Szrj   switch (do_elf_stt_common)
2798*a9fa9459Szrj     {
2799*a9fa9459Szrj     case elf_stt_common:
2800*a9fa9459Szrj       ibfd->flags |= BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON;
2801*a9fa9459Szrj       break;
2802*a9fa9459Szrj       break;
2803*a9fa9459Szrj     case no_elf_stt_common:
2804*a9fa9459Szrj       ibfd->flags |= BFD_CONVERT_ELF_COMMON;
2805*a9fa9459Szrj       break;
2806*a9fa9459Szrj     default:
2807*a9fa9459Szrj       break;
2808*a9fa9459Szrj     }
2809*a9fa9459Szrj 
2810*a9fa9459Szrj   if (bfd_check_format (ibfd, bfd_archive))
2811*a9fa9459Szrj     {
2812*a9fa9459Szrj       bfd_boolean force_output_target;
2813*a9fa9459Szrj       bfd *obfd;
2814*a9fa9459Szrj 
2815*a9fa9459Szrj       /* bfd_get_target does not return the correct value until
2816*a9fa9459Szrj 	 bfd_check_format succeeds.  */
2817*a9fa9459Szrj       if (output_target == NULL)
2818*a9fa9459Szrj 	{
2819*a9fa9459Szrj 	  output_target = bfd_get_target (ibfd);
2820*a9fa9459Szrj 	  force_output_target = FALSE;
2821*a9fa9459Szrj 	}
2822*a9fa9459Szrj       else
2823*a9fa9459Szrj 	force_output_target = TRUE;
2824*a9fa9459Szrj 
2825*a9fa9459Szrj       obfd = bfd_openw (output_filename, output_target);
2826*a9fa9459Szrj       if (obfd == NULL)
2827*a9fa9459Szrj 	{
2828*a9fa9459Szrj 	  bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
2829*a9fa9459Szrj 	  status = 1;
2830*a9fa9459Szrj 	  return;
2831*a9fa9459Szrj 	}
2832*a9fa9459Szrj       /* This is a no-op on non-Coff targets.  */
2833*a9fa9459Szrj       set_long_section_mode (obfd, ibfd, long_section_names);
2834*a9fa9459Szrj 
2835*a9fa9459Szrj       copy_archive (ibfd, obfd, output_target, force_output_target, input_arch);
2836*a9fa9459Szrj     }
2837*a9fa9459Szrj   else if (bfd_check_format_matches (ibfd, bfd_object, &obj_matching))
2838*a9fa9459Szrj     {
2839*a9fa9459Szrj       bfd *obfd;
2840*a9fa9459Szrj     do_copy:
2841*a9fa9459Szrj 
2842*a9fa9459Szrj       /* bfd_get_target does not return the correct value until
2843*a9fa9459Szrj 	 bfd_check_format succeeds.  */
2844*a9fa9459Szrj       if (output_target == NULL)
2845*a9fa9459Szrj 	output_target = bfd_get_target (ibfd);
2846*a9fa9459Szrj 
2847*a9fa9459Szrj       obfd = bfd_openw (output_filename, output_target);
2848*a9fa9459Szrj       if (obfd == NULL)
2849*a9fa9459Szrj  	{
2850*a9fa9459Szrj  	  bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
2851*a9fa9459Szrj  	  status = 1;
2852*a9fa9459Szrj  	  return;
2853*a9fa9459Szrj  	}
2854*a9fa9459Szrj       /* This is a no-op on non-Coff targets.  */
2855*a9fa9459Szrj       set_long_section_mode (obfd, ibfd, long_section_names);
2856*a9fa9459Szrj 
2857*a9fa9459Szrj       if (! copy_object (ibfd, obfd, input_arch))
2858*a9fa9459Szrj 	status = 1;
2859*a9fa9459Szrj 
2860*a9fa9459Szrj       /* PR 17512: file: 0f15796a.
2861*a9fa9459Szrj 	 If the file could not be copied it may not be in a writeable
2862*a9fa9459Szrj 	 state.  So use bfd_close_all_done to avoid the possibility of
2863*a9fa9459Szrj 	 writing uninitialised data into the file.  */
2864*a9fa9459Szrj       if (! (status ? bfd_close_all_done (obfd) : bfd_close (obfd)))
2865*a9fa9459Szrj 	{
2866*a9fa9459Szrj 	  status = 1;
2867*a9fa9459Szrj 	  bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
2868*a9fa9459Szrj 	  return;
2869*a9fa9459Szrj 	}
2870*a9fa9459Szrj 
2871*a9fa9459Szrj       if (!bfd_close (ibfd))
2872*a9fa9459Szrj 	{
2873*a9fa9459Szrj 	  status = 1;
2874*a9fa9459Szrj 	  bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
2875*a9fa9459Szrj 	  return;
2876*a9fa9459Szrj 	}
2877*a9fa9459Szrj     }
2878*a9fa9459Szrj   else
2879*a9fa9459Szrj     {
2880*a9fa9459Szrj       bfd_error_type obj_error = bfd_get_error ();
2881*a9fa9459Szrj       bfd_error_type core_error;
2882*a9fa9459Szrj 
2883*a9fa9459Szrj       if (bfd_check_format_matches (ibfd, bfd_core, &core_matching))
2884*a9fa9459Szrj 	{
2885*a9fa9459Szrj 	  /* This probably can't happen..  */
2886*a9fa9459Szrj 	  if (obj_error == bfd_error_file_ambiguously_recognized)
2887*a9fa9459Szrj 	    free (obj_matching);
2888*a9fa9459Szrj 	  goto do_copy;
2889*a9fa9459Szrj 	}
2890*a9fa9459Szrj 
2891*a9fa9459Szrj       core_error = bfd_get_error ();
2892*a9fa9459Szrj       /* Report the object error in preference to the core error.  */
2893*a9fa9459Szrj       if (obj_error != core_error)
2894*a9fa9459Szrj 	bfd_set_error (obj_error);
2895*a9fa9459Szrj 
2896*a9fa9459Szrj       bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
2897*a9fa9459Szrj 
2898*a9fa9459Szrj       if (obj_error == bfd_error_file_ambiguously_recognized)
2899*a9fa9459Szrj 	{
2900*a9fa9459Szrj 	  list_matching_formats (obj_matching);
2901*a9fa9459Szrj 	  free (obj_matching);
2902*a9fa9459Szrj 	}
2903*a9fa9459Szrj       if (core_error == bfd_error_file_ambiguously_recognized)
2904*a9fa9459Szrj 	{
2905*a9fa9459Szrj 	  list_matching_formats (core_matching);
2906*a9fa9459Szrj 	  free (core_matching);
2907*a9fa9459Szrj 	}
2908*a9fa9459Szrj 
2909*a9fa9459Szrj       status = 1;
2910*a9fa9459Szrj     }
2911*a9fa9459Szrj }
2912*a9fa9459Szrj 
2913*a9fa9459Szrj /* Add a name to the section renaming list.  */
2914*a9fa9459Szrj 
2915*a9fa9459Szrj static void
add_section_rename(const char * old_name,const char * new_name,flagword flags)2916*a9fa9459Szrj add_section_rename (const char * old_name, const char * new_name,
2917*a9fa9459Szrj 		    flagword flags)
2918*a9fa9459Szrj {
2919*a9fa9459Szrj   section_rename * srename;
2920*a9fa9459Szrj 
2921*a9fa9459Szrj   /* Check for conflicts first.  */
2922*a9fa9459Szrj   for (srename = section_rename_list; srename != NULL; srename = srename->next)
2923*a9fa9459Szrj     if (strcmp (srename->old_name, old_name) == 0)
2924*a9fa9459Szrj       {
2925*a9fa9459Szrj 	/* Silently ignore duplicate definitions.  */
2926*a9fa9459Szrj 	if (strcmp (srename->new_name, new_name) == 0
2927*a9fa9459Szrj 	    && srename->flags == flags)
2928*a9fa9459Szrj 	  return;
2929*a9fa9459Szrj 
2930*a9fa9459Szrj 	fatal (_("Multiple renames of section %s"), old_name);
2931*a9fa9459Szrj       }
2932*a9fa9459Szrj 
2933*a9fa9459Szrj   srename = (section_rename *) xmalloc (sizeof (* srename));
2934*a9fa9459Szrj 
2935*a9fa9459Szrj   srename->old_name = old_name;
2936*a9fa9459Szrj   srename->new_name = new_name;
2937*a9fa9459Szrj   srename->flags    = flags;
2938*a9fa9459Szrj   srename->next     = section_rename_list;
2939*a9fa9459Szrj 
2940*a9fa9459Szrj   section_rename_list = srename;
2941*a9fa9459Szrj }
2942*a9fa9459Szrj 
2943*a9fa9459Szrj /* Check the section rename list for a new name of the input section
2944*a9fa9459Szrj    called OLD_NAME.  Returns the new name if one is found and sets
2945*a9fa9459Szrj    RETURNED_FLAGS if non-NULL to the flags to be used for this section.  */
2946*a9fa9459Szrj 
2947*a9fa9459Szrj static const char *
find_section_rename(const char * old_name,flagword * returned_flags)2948*a9fa9459Szrj find_section_rename (const char *old_name, flagword *returned_flags)
2949*a9fa9459Szrj {
2950*a9fa9459Szrj   const section_rename *srename;
2951*a9fa9459Szrj 
2952*a9fa9459Szrj   for (srename = section_rename_list; srename != NULL; srename = srename->next)
2953*a9fa9459Szrj     if (strcmp (srename->old_name, old_name) == 0)
2954*a9fa9459Szrj       {
2955*a9fa9459Szrj 	if (returned_flags != NULL && srename->flags != (flagword) -1)
2956*a9fa9459Szrj 	  *returned_flags = srename->flags;
2957*a9fa9459Szrj 
2958*a9fa9459Szrj 	return srename->new_name;
2959*a9fa9459Szrj       }
2960*a9fa9459Szrj 
2961*a9fa9459Szrj   return old_name;
2962*a9fa9459Szrj }
2963*a9fa9459Szrj 
2964*a9fa9459Szrj /* Once each of the sections is copied, we may still need to do some
2965*a9fa9459Szrj    finalization work for private section headers.  Do that here.  */
2966*a9fa9459Szrj 
2967*a9fa9459Szrj static void
setup_bfd_headers(bfd * ibfd,bfd * obfd)2968*a9fa9459Szrj setup_bfd_headers (bfd *ibfd, bfd *obfd)
2969*a9fa9459Szrj {
2970*a9fa9459Szrj   /* Allow the BFD backend to copy any private data it understands
2971*a9fa9459Szrj      from the input section to the output section.  */
2972*a9fa9459Szrj   if (! bfd_copy_private_header_data (ibfd, obfd))
2973*a9fa9459Szrj     {
2974*a9fa9459Szrj       status = 1;
2975*a9fa9459Szrj       bfd_nonfatal_message (NULL, ibfd, NULL,
2976*a9fa9459Szrj 			    _("error in private header data"));
2977*a9fa9459Szrj       return;
2978*a9fa9459Szrj     }
2979*a9fa9459Szrj 
2980*a9fa9459Szrj   /* All went well.  */
2981*a9fa9459Szrj   return;
2982*a9fa9459Szrj }
2983*a9fa9459Szrj 
2984*a9fa9459Szrj /* Create a section in OBFD with the same
2985*a9fa9459Szrj    name and attributes as ISECTION in IBFD.  */
2986*a9fa9459Szrj 
2987*a9fa9459Szrj static void
setup_section(bfd * ibfd,sec_ptr isection,void * obfdarg)2988*a9fa9459Szrj setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
2989*a9fa9459Szrj {
2990*a9fa9459Szrj   bfd *obfd = (bfd *) obfdarg;
2991*a9fa9459Szrj   struct section_list *p;
2992*a9fa9459Szrj   sec_ptr osection;
2993*a9fa9459Szrj   bfd_size_type size;
2994*a9fa9459Szrj   bfd_vma vma;
2995*a9fa9459Szrj   bfd_vma lma;
2996*a9fa9459Szrj   flagword flags;
2997*a9fa9459Szrj   const char *err;
2998*a9fa9459Szrj   const char * name;
2999*a9fa9459Szrj   char *prefix = NULL;
3000*a9fa9459Szrj   bfd_boolean make_nobits;
3001*a9fa9459Szrj 
3002*a9fa9459Szrj   if (is_strip_section (ibfd, isection))
3003*a9fa9459Szrj     return;
3004*a9fa9459Szrj 
3005*a9fa9459Szrj   /* Get the, possibly new, name of the output section.  */
3006*a9fa9459Szrj   name = bfd_section_name (ibfd, isection);
3007*a9fa9459Szrj   flags = bfd_get_section_flags (ibfd, isection);
3008*a9fa9459Szrj   name = find_section_rename (name, &flags);
3009*a9fa9459Szrj 
3010*a9fa9459Szrj   /* Prefix sections.  */
3011*a9fa9459Szrj   if ((prefix_alloc_sections_string)
3012*a9fa9459Szrj       && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC))
3013*a9fa9459Szrj     prefix = prefix_alloc_sections_string;
3014*a9fa9459Szrj   else if (prefix_sections_string)
3015*a9fa9459Szrj     prefix = prefix_sections_string;
3016*a9fa9459Szrj 
3017*a9fa9459Szrj   if (prefix)
3018*a9fa9459Szrj     {
3019*a9fa9459Szrj       char *n;
3020*a9fa9459Szrj 
3021*a9fa9459Szrj       n = (char *) xmalloc (strlen (prefix) + strlen (name) + 1);
3022*a9fa9459Szrj       strcpy (n, prefix);
3023*a9fa9459Szrj       strcat (n, name);
3024*a9fa9459Szrj       name = n;
3025*a9fa9459Szrj     }
3026*a9fa9459Szrj 
3027*a9fa9459Szrj   make_nobits = FALSE;
3028*a9fa9459Szrj 
3029*a9fa9459Szrj   p = find_section_list (bfd_section_name (ibfd, isection), FALSE,
3030*a9fa9459Szrj 			 SECTION_CONTEXT_SET_FLAGS);
3031*a9fa9459Szrj   if (p != NULL)
3032*a9fa9459Szrj     flags = p->flags | (flags & (SEC_HAS_CONTENTS | SEC_RELOC));
3033*a9fa9459Szrj   else if (strip_symbols == STRIP_NONDEBUG
3034*a9fa9459Szrj 	   && (flags & (SEC_ALLOC | SEC_GROUP)) != 0
3035*a9fa9459Szrj 	   && !is_nondebug_keep_contents_section (ibfd, isection))
3036*a9fa9459Szrj     {
3037*a9fa9459Szrj       flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP);
3038*a9fa9459Szrj       if (obfd->xvec->flavour == bfd_target_elf_flavour)
3039*a9fa9459Szrj 	{
3040*a9fa9459Szrj 	  make_nobits = TRUE;
3041*a9fa9459Szrj 
3042*a9fa9459Szrj 	  /* Twiddle the input section flags so that it seems to
3043*a9fa9459Szrj 	     elf.c:copy_private_bfd_data that section flags have not
3044*a9fa9459Szrj 	     changed between input and output sections.  This hack
3045*a9fa9459Szrj 	     prevents wholesale rewriting of the program headers.  */
3046*a9fa9459Szrj 	  isection->flags &= ~(SEC_HAS_CONTENTS | SEC_LOAD | SEC_GROUP);
3047*a9fa9459Szrj 	}
3048*a9fa9459Szrj     }
3049*a9fa9459Szrj 
3050*a9fa9459Szrj   osection = bfd_make_section_anyway_with_flags (obfd, name, flags);
3051*a9fa9459Szrj 
3052*a9fa9459Szrj   if (osection == NULL)
3053*a9fa9459Szrj     {
3054*a9fa9459Szrj       err = _("failed to create output section");
3055*a9fa9459Szrj       goto loser;
3056*a9fa9459Szrj     }
3057*a9fa9459Szrj 
3058*a9fa9459Szrj   if (make_nobits)
3059*a9fa9459Szrj     elf_section_type (osection) = SHT_NOBITS;
3060*a9fa9459Szrj 
3061*a9fa9459Szrj   size = bfd_section_size (ibfd, isection);
3062*a9fa9459Szrj   size = bfd_convert_section_size (ibfd, isection, obfd, size);
3063*a9fa9459Szrj   if (copy_byte >= 0)
3064*a9fa9459Szrj     size = (size + interleave - 1) / interleave * copy_width;
3065*a9fa9459Szrj   else if (extract_symbol)
3066*a9fa9459Szrj     size = 0;
3067*a9fa9459Szrj   if (! bfd_set_section_size (obfd, osection, size))
3068*a9fa9459Szrj     {
3069*a9fa9459Szrj       err = _("failed to set size");
3070*a9fa9459Szrj       goto loser;
3071*a9fa9459Szrj     }
3072*a9fa9459Szrj 
3073*a9fa9459Szrj   vma = bfd_section_vma (ibfd, isection);
3074*a9fa9459Szrj   p = find_section_list (bfd_section_name (ibfd, isection), FALSE,
3075*a9fa9459Szrj 			 SECTION_CONTEXT_ALTER_VMA | SECTION_CONTEXT_SET_VMA);
3076*a9fa9459Szrj   if (p != NULL)
3077*a9fa9459Szrj     {
3078*a9fa9459Szrj       if (p->context & SECTION_CONTEXT_SET_VMA)
3079*a9fa9459Szrj 	vma = p->vma_val;
3080*a9fa9459Szrj       else
3081*a9fa9459Szrj 	vma += p->vma_val;
3082*a9fa9459Szrj     }
3083*a9fa9459Szrj   else
3084*a9fa9459Szrj     vma += change_section_address;
3085*a9fa9459Szrj 
3086*a9fa9459Szrj   if (! bfd_set_section_vma (obfd, osection, vma))
3087*a9fa9459Szrj     {
3088*a9fa9459Szrj       err = _("failed to set vma");
3089*a9fa9459Szrj       goto loser;
3090*a9fa9459Szrj     }
3091*a9fa9459Szrj 
3092*a9fa9459Szrj   lma = isection->lma;
3093*a9fa9459Szrj   p = find_section_list (bfd_section_name (ibfd, isection), FALSE,
3094*a9fa9459Szrj 			 SECTION_CONTEXT_ALTER_LMA | SECTION_CONTEXT_SET_LMA);
3095*a9fa9459Szrj   if (p != NULL)
3096*a9fa9459Szrj     {
3097*a9fa9459Szrj       if (p->context & SECTION_CONTEXT_ALTER_LMA)
3098*a9fa9459Szrj 	lma += p->lma_val;
3099*a9fa9459Szrj       else
3100*a9fa9459Szrj 	lma = p->lma_val;
3101*a9fa9459Szrj     }
3102*a9fa9459Szrj   else
3103*a9fa9459Szrj     lma += change_section_address;
3104*a9fa9459Szrj 
3105*a9fa9459Szrj   osection->lma = lma;
3106*a9fa9459Szrj 
3107*a9fa9459Szrj   /* FIXME: This is probably not enough.  If we change the LMA we
3108*a9fa9459Szrj      may have to recompute the header for the file as well.  */
3109*a9fa9459Szrj   if (!bfd_set_section_alignment (obfd,
3110*a9fa9459Szrj 				  osection,
3111*a9fa9459Szrj 				  bfd_section_alignment (ibfd, isection)))
3112*a9fa9459Szrj     {
3113*a9fa9459Szrj       err = _("failed to set alignment");
3114*a9fa9459Szrj       goto loser;
3115*a9fa9459Szrj     }
3116*a9fa9459Szrj 
3117*a9fa9459Szrj   /* Copy merge entity size.  */
3118*a9fa9459Szrj   osection->entsize = isection->entsize;
3119*a9fa9459Szrj 
3120*a9fa9459Szrj   /* Copy compress status.  */
3121*a9fa9459Szrj   osection->compress_status = isection->compress_status;
3122*a9fa9459Szrj 
3123*a9fa9459Szrj   /* This used to be mangle_section; we do here to avoid using
3124*a9fa9459Szrj      bfd_get_section_by_name since some formats allow multiple
3125*a9fa9459Szrj      sections with the same name.  */
3126*a9fa9459Szrj   isection->output_section = osection;
3127*a9fa9459Szrj   isection->output_offset = 0;
3128*a9fa9459Szrj 
3129*a9fa9459Szrj   if ((isection->flags & SEC_GROUP) != 0)
3130*a9fa9459Szrj     {
3131*a9fa9459Szrj       asymbol *gsym = group_signature (isection);
3132*a9fa9459Szrj 
3133*a9fa9459Szrj       if (gsym != NULL)
3134*a9fa9459Szrj 	{
3135*a9fa9459Szrj 	  gsym->flags |= BSF_KEEP;
3136*a9fa9459Szrj 	  if (ibfd->xvec->flavour == bfd_target_elf_flavour)
3137*a9fa9459Szrj 	    elf_group_id (isection) = gsym;
3138*a9fa9459Szrj 	}
3139*a9fa9459Szrj     }
3140*a9fa9459Szrj 
3141*a9fa9459Szrj   /* Allow the BFD backend to copy any private data it understands
3142*a9fa9459Szrj      from the input section to the output section.  */
3143*a9fa9459Szrj   if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection))
3144*a9fa9459Szrj     {
3145*a9fa9459Szrj       err = _("failed to copy private data");
3146*a9fa9459Szrj       goto loser;
3147*a9fa9459Szrj     }
3148*a9fa9459Szrj 
3149*a9fa9459Szrj   /* All went well.  */
3150*a9fa9459Szrj   return;
3151*a9fa9459Szrj 
3152*a9fa9459Szrj  loser:
3153*a9fa9459Szrj   status = 1;
3154*a9fa9459Szrj   bfd_nonfatal_message (NULL, obfd, osection, err);
3155*a9fa9459Szrj }
3156*a9fa9459Szrj 
3157*a9fa9459Szrj /* Return TRUE if input section ISECTION should be skipped.  */
3158*a9fa9459Szrj 
3159*a9fa9459Szrj static bfd_boolean
skip_section(bfd * ibfd,sec_ptr isection)3160*a9fa9459Szrj skip_section (bfd *ibfd, sec_ptr isection)
3161*a9fa9459Szrj {
3162*a9fa9459Szrj   sec_ptr osection;
3163*a9fa9459Szrj   bfd_size_type size;
3164*a9fa9459Szrj   flagword flags;
3165*a9fa9459Szrj 
3166*a9fa9459Szrj   /* If we have already failed earlier on,
3167*a9fa9459Szrj      do not keep on generating complaints now.  */
3168*a9fa9459Szrj   if (status != 0)
3169*a9fa9459Szrj     return TRUE;
3170*a9fa9459Szrj 
3171*a9fa9459Szrj   if (extract_symbol)
3172*a9fa9459Szrj     return TRUE;
3173*a9fa9459Szrj 
3174*a9fa9459Szrj   if (is_strip_section (ibfd, isection))
3175*a9fa9459Szrj     return TRUE;
3176*a9fa9459Szrj 
3177*a9fa9459Szrj   if (is_update_section (ibfd, isection))
3178*a9fa9459Szrj     return TRUE;
3179*a9fa9459Szrj 
3180*a9fa9459Szrj   flags = bfd_get_section_flags (ibfd, isection);
3181*a9fa9459Szrj   if ((flags & SEC_GROUP) != 0)
3182*a9fa9459Szrj     return TRUE;
3183*a9fa9459Szrj 
3184*a9fa9459Szrj   osection = isection->output_section;
3185*a9fa9459Szrj   size = bfd_get_section_size (isection);
3186*a9fa9459Szrj 
3187*a9fa9459Szrj   if (size == 0 || osection == 0)
3188*a9fa9459Szrj     return TRUE;
3189*a9fa9459Szrj 
3190*a9fa9459Szrj   return FALSE;
3191*a9fa9459Szrj }
3192*a9fa9459Szrj 
3193*a9fa9459Szrj /* Copy relocations in input section ISECTION of IBFD to an output
3194*a9fa9459Szrj    section with the same name in OBFDARG.  If stripping then don't
3195*a9fa9459Szrj    copy any relocation info.  */
3196*a9fa9459Szrj 
3197*a9fa9459Szrj static void
copy_relocations_in_section(bfd * ibfd,sec_ptr isection,void * obfdarg)3198*a9fa9459Szrj copy_relocations_in_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
3199*a9fa9459Szrj {
3200*a9fa9459Szrj   bfd *obfd = (bfd *) obfdarg;
3201*a9fa9459Szrj   long relsize;
3202*a9fa9459Szrj   arelent **relpp;
3203*a9fa9459Szrj   long relcount;
3204*a9fa9459Szrj   sec_ptr osection;
3205*a9fa9459Szrj 
3206*a9fa9459Szrj   if (skip_section (ibfd, isection))
3207*a9fa9459Szrj     return;
3208*a9fa9459Szrj 
3209*a9fa9459Szrj   osection = isection->output_section;
3210*a9fa9459Szrj 
3211*a9fa9459Szrj   /* Core files and DWO files do not need to be relocated.  */
3212*a9fa9459Szrj   if (bfd_get_format (obfd) == bfd_core || strip_symbols == STRIP_NONDWO)
3213*a9fa9459Szrj     relsize = 0;
3214*a9fa9459Szrj   else
3215*a9fa9459Szrj     {
3216*a9fa9459Szrj       relsize = bfd_get_reloc_upper_bound (ibfd, isection);
3217*a9fa9459Szrj 
3218*a9fa9459Szrj       if (relsize < 0)
3219*a9fa9459Szrj 	{
3220*a9fa9459Szrj 	  /* Do not complain if the target does not support relocations.  */
3221*a9fa9459Szrj 	  if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
3222*a9fa9459Szrj 	    relsize = 0;
3223*a9fa9459Szrj 	  else
3224*a9fa9459Szrj 	    {
3225*a9fa9459Szrj 	      status = 1;
3226*a9fa9459Szrj 	      bfd_nonfatal_message (NULL, ibfd, isection, NULL);
3227*a9fa9459Szrj 	      return;
3228*a9fa9459Szrj 	    }
3229*a9fa9459Szrj 	}
3230*a9fa9459Szrj     }
3231*a9fa9459Szrj 
3232*a9fa9459Szrj   if (relsize == 0)
3233*a9fa9459Szrj     {
3234*a9fa9459Szrj       bfd_set_reloc (obfd, osection, NULL, 0);
3235*a9fa9459Szrj       osection->flags &= ~SEC_RELOC;
3236*a9fa9459Szrj     }
3237*a9fa9459Szrj   else
3238*a9fa9459Szrj     {
3239*a9fa9459Szrj       relpp = (arelent **) xmalloc (relsize);
3240*a9fa9459Szrj       relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, isympp);
3241*a9fa9459Szrj       if (relcount < 0)
3242*a9fa9459Szrj 	{
3243*a9fa9459Szrj 	  status = 1;
3244*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, ibfd, isection,
3245*a9fa9459Szrj 				_("relocation count is negative"));
3246*a9fa9459Szrj 	  return;
3247*a9fa9459Szrj 	}
3248*a9fa9459Szrj 
3249*a9fa9459Szrj       if (strip_symbols == STRIP_ALL)
3250*a9fa9459Szrj 	{
3251*a9fa9459Szrj 	  /* Remove relocations which are not in
3252*a9fa9459Szrj 	     keep_strip_specific_list.  */
3253*a9fa9459Szrj 	  arelent **temp_relpp;
3254*a9fa9459Szrj 	  long temp_relcount = 0;
3255*a9fa9459Szrj 	  long i;
3256*a9fa9459Szrj 
3257*a9fa9459Szrj 	  temp_relpp = (arelent **) xmalloc (relsize);
3258*a9fa9459Szrj 	  for (i = 0; i < relcount; i++)
3259*a9fa9459Szrj 	    {
3260*a9fa9459Szrj 	      /* PR 17512: file: 9e907e0c.  */
3261*a9fa9459Szrj 	      if (relpp[i]->sym_ptr_ptr
3262*a9fa9459Szrj 		  /* PR 20096 */
3263*a9fa9459Szrj 		  && * relpp[i]->sym_ptr_ptr)
3264*a9fa9459Szrj 		if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
3265*a9fa9459Szrj 					 keep_specific_htab))
3266*a9fa9459Szrj 		  temp_relpp [temp_relcount++] = relpp [i];
3267*a9fa9459Szrj 	    }
3268*a9fa9459Szrj 	  relcount = temp_relcount;
3269*a9fa9459Szrj 	  free (relpp);
3270*a9fa9459Szrj 	  relpp = temp_relpp;
3271*a9fa9459Szrj 	}
3272*a9fa9459Szrj 
3273*a9fa9459Szrj       bfd_set_reloc (obfd, osection, relcount == 0 ? NULL : relpp, relcount);
3274*a9fa9459Szrj       if (relcount == 0)
3275*a9fa9459Szrj 	{
3276*a9fa9459Szrj 	  osection->flags &= ~SEC_RELOC;
3277*a9fa9459Szrj 	  free (relpp);
3278*a9fa9459Szrj 	}
3279*a9fa9459Szrj     }
3280*a9fa9459Szrj }
3281*a9fa9459Szrj 
3282*a9fa9459Szrj /* Copy the data of input section ISECTION of IBFD
3283*a9fa9459Szrj    to an output section with the same name in OBFD.  */
3284*a9fa9459Szrj 
3285*a9fa9459Szrj static void
copy_section(bfd * ibfd,sec_ptr isection,void * obfdarg)3286*a9fa9459Szrj copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
3287*a9fa9459Szrj {
3288*a9fa9459Szrj   bfd *obfd = (bfd *) obfdarg;
3289*a9fa9459Szrj   struct section_list *p;
3290*a9fa9459Szrj   sec_ptr osection;
3291*a9fa9459Szrj   bfd_size_type size;
3292*a9fa9459Szrj 
3293*a9fa9459Szrj   if (skip_section (ibfd, isection))
3294*a9fa9459Szrj     return;
3295*a9fa9459Szrj 
3296*a9fa9459Szrj   osection = isection->output_section;
3297*a9fa9459Szrj   /* The output SHF_COMPRESSED section size is different from input if
3298*a9fa9459Szrj      ELF classes of input and output aren't the same.  We can't use
3299*a9fa9459Szrj      the output section size since --interleave will shrink the output
3300*a9fa9459Szrj      section.   Size will be updated if the section is converted.   */
3301*a9fa9459Szrj   size = bfd_get_section_size (isection);
3302*a9fa9459Szrj 
3303*a9fa9459Szrj   if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
3304*a9fa9459Szrj       && bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
3305*a9fa9459Szrj     {
3306*a9fa9459Szrj       bfd_byte *memhunk = NULL;
3307*a9fa9459Szrj 
3308*a9fa9459Szrj       if (!bfd_get_full_section_contents (ibfd, isection, &memhunk)
3309*a9fa9459Szrj 	  || !bfd_convert_section_contents (ibfd, isection, obfd,
3310*a9fa9459Szrj 					    &memhunk, &size))
3311*a9fa9459Szrj 	{
3312*a9fa9459Szrj 	  status = 1;
3313*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, ibfd, isection, NULL);
3314*a9fa9459Szrj 	  return;
3315*a9fa9459Szrj 	}
3316*a9fa9459Szrj 
3317*a9fa9459Szrj       if (reverse_bytes)
3318*a9fa9459Szrj 	{
3319*a9fa9459Szrj 	  /* We don't handle leftover bytes (too many possible behaviors,
3320*a9fa9459Szrj 	     and we don't know what the user wants).  The section length
3321*a9fa9459Szrj 	     must be a multiple of the number of bytes to swap.  */
3322*a9fa9459Szrj 	  if ((size % reverse_bytes) == 0)
3323*a9fa9459Szrj 	    {
3324*a9fa9459Szrj 	      unsigned long i, j;
3325*a9fa9459Szrj 	      bfd_byte b;
3326*a9fa9459Szrj 
3327*a9fa9459Szrj 	      for (i = 0; i < size; i += reverse_bytes)
3328*a9fa9459Szrj 		for (j = 0; j < (unsigned long)(reverse_bytes / 2); j++)
3329*a9fa9459Szrj 		  {
3330*a9fa9459Szrj 		    bfd_byte *m = (bfd_byte *) memhunk;
3331*a9fa9459Szrj 
3332*a9fa9459Szrj 		    b = m[i + j];
3333*a9fa9459Szrj 		    m[i + j] = m[(i + reverse_bytes) - (j + 1)];
3334*a9fa9459Szrj 		    m[(i + reverse_bytes) - (j + 1)] = b;
3335*a9fa9459Szrj 		  }
3336*a9fa9459Szrj 	    }
3337*a9fa9459Szrj 	  else
3338*a9fa9459Szrj 	    /* User must pad the section up in order to do this.  */
3339*a9fa9459Szrj 	    fatal (_("cannot reverse bytes: length of section %s must be evenly divisible by %d"),
3340*a9fa9459Szrj 		   bfd_section_name (ibfd, isection), reverse_bytes);
3341*a9fa9459Szrj 	}
3342*a9fa9459Szrj 
3343*a9fa9459Szrj       if (copy_byte >= 0)
3344*a9fa9459Szrj 	{
3345*a9fa9459Szrj 	  /* Keep only every `copy_byte'th byte in MEMHUNK.  */
3346*a9fa9459Szrj 	  char *from = (char *) memhunk + copy_byte;
3347*a9fa9459Szrj 	  char *to = (char *) memhunk;
3348*a9fa9459Szrj 	  char *end = (char *) memhunk + size;
3349*a9fa9459Szrj 	  int i;
3350*a9fa9459Szrj 
3351*a9fa9459Szrj 	  for (; from < end; from += interleave)
3352*a9fa9459Szrj 	    for (i = 0; i < copy_width; i++)
3353*a9fa9459Szrj 	      {
3354*a9fa9459Szrj 		if (&from[i] >= end)
3355*a9fa9459Szrj 		  break;
3356*a9fa9459Szrj 		*to++ = from[i];
3357*a9fa9459Szrj 	      }
3358*a9fa9459Szrj 
3359*a9fa9459Szrj 	  size = (size + interleave - 1 - copy_byte) / interleave * copy_width;
3360*a9fa9459Szrj 	  osection->lma /= interleave;
3361*a9fa9459Szrj 	}
3362*a9fa9459Szrj 
3363*a9fa9459Szrj       if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
3364*a9fa9459Szrj 	{
3365*a9fa9459Szrj 	  status = 1;
3366*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, obfd, osection, NULL);
3367*a9fa9459Szrj 	  return;
3368*a9fa9459Szrj 	}
3369*a9fa9459Szrj       free (memhunk);
3370*a9fa9459Szrj     }
3371*a9fa9459Szrj   else if ((p = find_section_list (bfd_get_section_name (ibfd, isection),
3372*a9fa9459Szrj 				   FALSE, SECTION_CONTEXT_SET_FLAGS)) != NULL
3373*a9fa9459Szrj 	   && (p->flags & SEC_HAS_CONTENTS) != 0)
3374*a9fa9459Szrj     {
3375*a9fa9459Szrj       void *memhunk = xmalloc (size);
3376*a9fa9459Szrj 
3377*a9fa9459Szrj       /* We don't permit the user to turn off the SEC_HAS_CONTENTS
3378*a9fa9459Szrj 	 flag--they can just remove the section entirely and add it
3379*a9fa9459Szrj 	 back again.  However, we do permit them to turn on the
3380*a9fa9459Szrj 	 SEC_HAS_CONTENTS flag, and take it to mean that the section
3381*a9fa9459Szrj 	 contents should be zeroed out.  */
3382*a9fa9459Szrj 
3383*a9fa9459Szrj       memset (memhunk, 0, size);
3384*a9fa9459Szrj       if (! bfd_set_section_contents (obfd, osection, memhunk, 0, size))
3385*a9fa9459Szrj 	{
3386*a9fa9459Szrj 	  status = 1;
3387*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, obfd, osection, NULL);
3388*a9fa9459Szrj 	  return;
3389*a9fa9459Szrj 	}
3390*a9fa9459Szrj       free (memhunk);
3391*a9fa9459Szrj     }
3392*a9fa9459Szrj }
3393*a9fa9459Szrj 
3394*a9fa9459Szrj /* Get all the sections.  This is used when --gap-fill or --pad-to is
3395*a9fa9459Szrj    used.  */
3396*a9fa9459Szrj 
3397*a9fa9459Szrj static void
get_sections(bfd * obfd ATTRIBUTE_UNUSED,asection * osection,void * secppparg)3398*a9fa9459Szrj get_sections (bfd *obfd ATTRIBUTE_UNUSED, asection *osection, void *secppparg)
3399*a9fa9459Szrj {
3400*a9fa9459Szrj   asection ***secppp = (asection ***) secppparg;
3401*a9fa9459Szrj 
3402*a9fa9459Szrj   **secppp = osection;
3403*a9fa9459Szrj   ++(*secppp);
3404*a9fa9459Szrj }
3405*a9fa9459Szrj 
3406*a9fa9459Szrj /* Sort sections by VMA.  This is called via qsort, and is used when
3407*a9fa9459Szrj    --gap-fill or --pad-to is used.  We force non loadable or empty
3408*a9fa9459Szrj    sections to the front, where they are easier to ignore.  */
3409*a9fa9459Szrj 
3410*a9fa9459Szrj static int
compare_section_lma(const void * arg1,const void * arg2)3411*a9fa9459Szrj compare_section_lma (const void *arg1, const void *arg2)
3412*a9fa9459Szrj {
3413*a9fa9459Szrj   const asection *const *sec1 = (const asection * const *) arg1;
3414*a9fa9459Szrj   const asection *const *sec2 = (const asection * const *) arg2;
3415*a9fa9459Szrj   flagword flags1, flags2;
3416*a9fa9459Szrj 
3417*a9fa9459Szrj   /* Sort non loadable sections to the front.  */
3418*a9fa9459Szrj   flags1 = (*sec1)->flags;
3419*a9fa9459Szrj   flags2 = (*sec2)->flags;
3420*a9fa9459Szrj   if ((flags1 & SEC_HAS_CONTENTS) == 0
3421*a9fa9459Szrj       || (flags1 & SEC_LOAD) == 0)
3422*a9fa9459Szrj     {
3423*a9fa9459Szrj       if ((flags2 & SEC_HAS_CONTENTS) != 0
3424*a9fa9459Szrj 	  && (flags2 & SEC_LOAD) != 0)
3425*a9fa9459Szrj 	return -1;
3426*a9fa9459Szrj     }
3427*a9fa9459Szrj   else
3428*a9fa9459Szrj     {
3429*a9fa9459Szrj       if ((flags2 & SEC_HAS_CONTENTS) == 0
3430*a9fa9459Szrj 	  || (flags2 & SEC_LOAD) == 0)
3431*a9fa9459Szrj 	return 1;
3432*a9fa9459Szrj     }
3433*a9fa9459Szrj 
3434*a9fa9459Szrj   /* Sort sections by LMA.  */
3435*a9fa9459Szrj   if ((*sec1)->lma > (*sec2)->lma)
3436*a9fa9459Szrj     return 1;
3437*a9fa9459Szrj   else if ((*sec1)->lma < (*sec2)->lma)
3438*a9fa9459Szrj     return -1;
3439*a9fa9459Szrj 
3440*a9fa9459Szrj   /* Sort sections with the same LMA by size.  */
3441*a9fa9459Szrj   if (bfd_get_section_size (*sec1) > bfd_get_section_size (*sec2))
3442*a9fa9459Szrj     return 1;
3443*a9fa9459Szrj   else if (bfd_get_section_size (*sec1) < bfd_get_section_size (*sec2))
3444*a9fa9459Szrj     return -1;
3445*a9fa9459Szrj 
3446*a9fa9459Szrj   return 0;
3447*a9fa9459Szrj }
3448*a9fa9459Szrj 
3449*a9fa9459Szrj /* Mark all the symbols which will be used in output relocations with
3450*a9fa9459Szrj    the BSF_KEEP flag so that those symbols will not be stripped.
3451*a9fa9459Szrj 
3452*a9fa9459Szrj    Ignore relocations which will not appear in the output file.  */
3453*a9fa9459Szrj 
3454*a9fa9459Szrj static void
mark_symbols_used_in_relocations(bfd * ibfd,sec_ptr isection,void * symbolsarg)3455*a9fa9459Szrj mark_symbols_used_in_relocations (bfd *ibfd, sec_ptr isection, void *symbolsarg)
3456*a9fa9459Szrj {
3457*a9fa9459Szrj   asymbol **symbols = (asymbol **) symbolsarg;
3458*a9fa9459Szrj   long relsize;
3459*a9fa9459Szrj   arelent **relpp;
3460*a9fa9459Szrj   long relcount, i;
3461*a9fa9459Szrj 
3462*a9fa9459Szrj   /* Ignore an input section with no corresponding output section.  */
3463*a9fa9459Szrj   if (isection->output_section == NULL)
3464*a9fa9459Szrj     return;
3465*a9fa9459Szrj 
3466*a9fa9459Szrj   relsize = bfd_get_reloc_upper_bound (ibfd, isection);
3467*a9fa9459Szrj   if (relsize < 0)
3468*a9fa9459Szrj     {
3469*a9fa9459Szrj       /* Do not complain if the target does not support relocations.  */
3470*a9fa9459Szrj       if (relsize == -1 && bfd_get_error () == bfd_error_invalid_operation)
3471*a9fa9459Szrj 	return;
3472*a9fa9459Szrj       bfd_fatal (bfd_get_filename (ibfd));
3473*a9fa9459Szrj     }
3474*a9fa9459Szrj 
3475*a9fa9459Szrj   if (relsize == 0)
3476*a9fa9459Szrj     return;
3477*a9fa9459Szrj 
3478*a9fa9459Szrj   relpp = (arelent **) xmalloc (relsize);
3479*a9fa9459Szrj   relcount = bfd_canonicalize_reloc (ibfd, isection, relpp, symbols);
3480*a9fa9459Szrj   if (relcount < 0)
3481*a9fa9459Szrj     bfd_fatal (bfd_get_filename (ibfd));
3482*a9fa9459Szrj 
3483*a9fa9459Szrj   /* Examine each symbol used in a relocation.  If it's not one of the
3484*a9fa9459Szrj      special bfd section symbols, then mark it with BSF_KEEP.  */
3485*a9fa9459Szrj   for (i = 0; i < relcount; i++)
3486*a9fa9459Szrj     {
3487*a9fa9459Szrj       if (*relpp[i]->sym_ptr_ptr != bfd_com_section_ptr->symbol
3488*a9fa9459Szrj 	  && *relpp[i]->sym_ptr_ptr != bfd_abs_section_ptr->symbol
3489*a9fa9459Szrj 	  && *relpp[i]->sym_ptr_ptr != bfd_und_section_ptr->symbol)
3490*a9fa9459Szrj 	(*relpp[i]->sym_ptr_ptr)->flags |= BSF_KEEP;
3491*a9fa9459Szrj     }
3492*a9fa9459Szrj 
3493*a9fa9459Szrj   if (relpp != NULL)
3494*a9fa9459Szrj     free (relpp);
3495*a9fa9459Szrj }
3496*a9fa9459Szrj 
3497*a9fa9459Szrj /* Write out debugging information.  */
3498*a9fa9459Szrj 
3499*a9fa9459Szrj static bfd_boolean
write_debugging_info(bfd * obfd,void * dhandle,long * symcountp ATTRIBUTE_UNUSED,asymbol *** symppp ATTRIBUTE_UNUSED)3500*a9fa9459Szrj write_debugging_info (bfd *obfd, void *dhandle,
3501*a9fa9459Szrj 		      long *symcountp ATTRIBUTE_UNUSED,
3502*a9fa9459Szrj 		      asymbol ***symppp ATTRIBUTE_UNUSED)
3503*a9fa9459Szrj {
3504*a9fa9459Szrj   if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour)
3505*a9fa9459Szrj     return write_ieee_debugging_info (obfd, dhandle);
3506*a9fa9459Szrj 
3507*a9fa9459Szrj   if (bfd_get_flavour (obfd) == bfd_target_coff_flavour
3508*a9fa9459Szrj       || bfd_get_flavour (obfd) == bfd_target_elf_flavour)
3509*a9fa9459Szrj     {
3510*a9fa9459Szrj       bfd_byte *syms, *strings;
3511*a9fa9459Szrj       bfd_size_type symsize, stringsize;
3512*a9fa9459Szrj       asection *stabsec, *stabstrsec;
3513*a9fa9459Szrj       flagword flags;
3514*a9fa9459Szrj 
3515*a9fa9459Szrj       if (! write_stabs_in_sections_debugging_info (obfd, dhandle, &syms,
3516*a9fa9459Szrj 						    &symsize, &strings,
3517*a9fa9459Szrj 						    &stringsize))
3518*a9fa9459Szrj 	return FALSE;
3519*a9fa9459Szrj 
3520*a9fa9459Szrj       flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
3521*a9fa9459Szrj       stabsec = bfd_make_section_with_flags (obfd, ".stab", flags);
3522*a9fa9459Szrj       stabstrsec = bfd_make_section_with_flags (obfd, ".stabstr", flags);
3523*a9fa9459Szrj       if (stabsec == NULL
3524*a9fa9459Szrj 	  || stabstrsec == NULL
3525*a9fa9459Szrj 	  || ! bfd_set_section_size (obfd, stabsec, symsize)
3526*a9fa9459Szrj 	  || ! bfd_set_section_size (obfd, stabstrsec, stringsize)
3527*a9fa9459Szrj 	  || ! bfd_set_section_alignment (obfd, stabsec, 2)
3528*a9fa9459Szrj 	  || ! bfd_set_section_alignment (obfd, stabstrsec, 0))
3529*a9fa9459Szrj 	{
3530*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, obfd, NULL,
3531*a9fa9459Szrj 				_("can't create debugging section"));
3532*a9fa9459Szrj 	  return FALSE;
3533*a9fa9459Szrj 	}
3534*a9fa9459Szrj 
3535*a9fa9459Szrj       /* We can get away with setting the section contents now because
3536*a9fa9459Szrj 	 the next thing the caller is going to do is copy over the
3537*a9fa9459Szrj 	 real sections.  We may someday have to split the contents
3538*a9fa9459Szrj 	 setting out of this function.  */
3539*a9fa9459Szrj       if (! bfd_set_section_contents (obfd, stabsec, syms, 0, symsize)
3540*a9fa9459Szrj 	  || ! bfd_set_section_contents (obfd, stabstrsec, strings, 0,
3541*a9fa9459Szrj 					 stringsize))
3542*a9fa9459Szrj 	{
3543*a9fa9459Szrj 	  bfd_nonfatal_message (NULL, obfd, NULL,
3544*a9fa9459Szrj 				_("can't set debugging section contents"));
3545*a9fa9459Szrj 	  return FALSE;
3546*a9fa9459Szrj 	}
3547*a9fa9459Szrj 
3548*a9fa9459Szrj       return TRUE;
3549*a9fa9459Szrj     }
3550*a9fa9459Szrj 
3551*a9fa9459Szrj   bfd_nonfatal_message (NULL, obfd, NULL,
3552*a9fa9459Szrj 			_("don't know how to write debugging information for %s"),
3553*a9fa9459Szrj 			bfd_get_target (obfd));
3554*a9fa9459Szrj   return FALSE;
3555*a9fa9459Szrj }
3556*a9fa9459Szrj 
3557*a9fa9459Szrj /* If neither -D nor -U was specified explicitly,
3558*a9fa9459Szrj    then use the configured default.  */
3559*a9fa9459Szrj static void
default_deterministic(void)3560*a9fa9459Szrj default_deterministic (void)
3561*a9fa9459Szrj {
3562*a9fa9459Szrj   if (deterministic < 0)
3563*a9fa9459Szrj     deterministic = DEFAULT_AR_DETERMINISTIC;
3564*a9fa9459Szrj }
3565*a9fa9459Szrj 
3566*a9fa9459Szrj static int
strip_main(int argc,char * argv[])3567*a9fa9459Szrj strip_main (int argc, char *argv[])
3568*a9fa9459Szrj {
3569*a9fa9459Szrj   char *input_target = NULL;
3570*a9fa9459Szrj   char *output_target = NULL;
3571*a9fa9459Szrj   bfd_boolean show_version = FALSE;
3572*a9fa9459Szrj   bfd_boolean formats_info = FALSE;
3573*a9fa9459Szrj   int c;
3574*a9fa9459Szrj   int i;
3575*a9fa9459Szrj   char *output_file = NULL;
3576*a9fa9459Szrj 
3577*a9fa9459Szrj   while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXHhVvwDU",
3578*a9fa9459Szrj 			   strip_options, (int *) 0)) != EOF)
3579*a9fa9459Szrj     {
3580*a9fa9459Szrj       switch (c)
3581*a9fa9459Szrj 	{
3582*a9fa9459Szrj 	case 'I':
3583*a9fa9459Szrj 	  input_target = optarg;
3584*a9fa9459Szrj 	  break;
3585*a9fa9459Szrj 	case 'O':
3586*a9fa9459Szrj 	  output_target = optarg;
3587*a9fa9459Szrj 	  break;
3588*a9fa9459Szrj 	case 'F':
3589*a9fa9459Szrj 	  input_target = output_target = optarg;
3590*a9fa9459Szrj 	  break;
3591*a9fa9459Szrj 	case 'R':
3592*a9fa9459Szrj 	  find_section_list (optarg, TRUE, SECTION_CONTEXT_REMOVE);
3593*a9fa9459Szrj 	  sections_removed = TRUE;
3594*a9fa9459Szrj 	  break;
3595*a9fa9459Szrj 	case 's':
3596*a9fa9459Szrj 	  strip_symbols = STRIP_ALL;
3597*a9fa9459Szrj 	  break;
3598*a9fa9459Szrj 	case 'S':
3599*a9fa9459Szrj 	case 'g':
3600*a9fa9459Szrj 	case 'd':	/* Historic BSD alias for -g.  Used by early NetBSD.  */
3601*a9fa9459Szrj 	  strip_symbols = STRIP_DEBUG;
3602*a9fa9459Szrj 	  break;
3603*a9fa9459Szrj 	case OPTION_STRIP_DWO:
3604*a9fa9459Szrj 	  strip_symbols = STRIP_DWO;
3605*a9fa9459Szrj 	  break;
3606*a9fa9459Szrj 	case OPTION_STRIP_UNNEEDED:
3607*a9fa9459Szrj 	  strip_symbols = STRIP_UNNEEDED;
3608*a9fa9459Szrj 	  break;
3609*a9fa9459Szrj 	case 'K':
3610*a9fa9459Szrj 	  add_specific_symbol (optarg, keep_specific_htab);
3611*a9fa9459Szrj 	  break;
3612*a9fa9459Szrj 	case 'N':
3613*a9fa9459Szrj 	  add_specific_symbol (optarg, strip_specific_htab);
3614*a9fa9459Szrj 	  break;
3615*a9fa9459Szrj 	case 'o':
3616*a9fa9459Szrj 	  output_file = optarg;
3617*a9fa9459Szrj 	  break;
3618*a9fa9459Szrj 	case 'p':
3619*a9fa9459Szrj 	  preserve_dates = TRUE;
3620*a9fa9459Szrj 	  break;
3621*a9fa9459Szrj 	case 'D':
3622*a9fa9459Szrj 	  deterministic = TRUE;
3623*a9fa9459Szrj 	  break;
3624*a9fa9459Szrj 	case 'U':
3625*a9fa9459Szrj 	  deterministic = FALSE;
3626*a9fa9459Szrj 	  break;
3627*a9fa9459Szrj 	case 'x':
3628*a9fa9459Szrj 	  discard_locals = LOCALS_ALL;
3629*a9fa9459Szrj 	  break;
3630*a9fa9459Szrj 	case 'X':
3631*a9fa9459Szrj 	  discard_locals = LOCALS_START_L;
3632*a9fa9459Szrj 	  break;
3633*a9fa9459Szrj 	case 'v':
3634*a9fa9459Szrj 	  verbose = TRUE;
3635*a9fa9459Szrj 	  break;
3636*a9fa9459Szrj 	case 'V':
3637*a9fa9459Szrj 	  show_version = TRUE;
3638*a9fa9459Szrj 	  break;
3639*a9fa9459Szrj 	case OPTION_FORMATS_INFO:
3640*a9fa9459Szrj 	  formats_info = TRUE;
3641*a9fa9459Szrj 	  break;
3642*a9fa9459Szrj 	case OPTION_ONLY_KEEP_DEBUG:
3643*a9fa9459Szrj 	  strip_symbols = STRIP_NONDEBUG;
3644*a9fa9459Szrj 	  break;
3645*a9fa9459Szrj 	case OPTION_KEEP_FILE_SYMBOLS:
3646*a9fa9459Szrj 	  keep_file_symbols = 1;
3647*a9fa9459Szrj 	  break;
3648*a9fa9459Szrj 	case 0:
3649*a9fa9459Szrj 	  /* We've been given a long option.  */
3650*a9fa9459Szrj 	  break;
3651*a9fa9459Szrj 	case 'w':
3652*a9fa9459Szrj 	  wildcard = TRUE;
3653*a9fa9459Szrj 	  break;
3654*a9fa9459Szrj 	case 'H':
3655*a9fa9459Szrj 	case 'h':
3656*a9fa9459Szrj 	  strip_usage (stdout, 0);
3657*a9fa9459Szrj 	default:
3658*a9fa9459Szrj 	  strip_usage (stderr, 1);
3659*a9fa9459Szrj 	}
3660*a9fa9459Szrj     }
3661*a9fa9459Szrj 
3662*a9fa9459Szrj   if (formats_info)
3663*a9fa9459Szrj     {
3664*a9fa9459Szrj       display_info ();
3665*a9fa9459Szrj       return 0;
3666*a9fa9459Szrj     }
3667*a9fa9459Szrj 
3668*a9fa9459Szrj   if (show_version)
3669*a9fa9459Szrj     print_version ("strip");
3670*a9fa9459Szrj 
3671*a9fa9459Szrj   default_deterministic ();
3672*a9fa9459Szrj 
3673*a9fa9459Szrj   /* Default is to strip all symbols.  */
3674*a9fa9459Szrj   if (strip_symbols == STRIP_UNDEF
3675*a9fa9459Szrj       && discard_locals == LOCALS_UNDEF
3676*a9fa9459Szrj       && htab_elements (strip_specific_htab) == 0)
3677*a9fa9459Szrj     strip_symbols = STRIP_ALL;
3678*a9fa9459Szrj 
3679*a9fa9459Szrj   if (output_target == NULL)
3680*a9fa9459Szrj     output_target = input_target;
3681*a9fa9459Szrj 
3682*a9fa9459Szrj   i = optind;
3683*a9fa9459Szrj   if (i == argc
3684*a9fa9459Szrj       || (output_file != NULL && (i + 1) < argc))
3685*a9fa9459Szrj     strip_usage (stderr, 1);
3686*a9fa9459Szrj 
3687*a9fa9459Szrj   for (; i < argc; i++)
3688*a9fa9459Szrj     {
3689*a9fa9459Szrj       int hold_status = status;
3690*a9fa9459Szrj       struct stat statbuf;
3691*a9fa9459Szrj       char *tmpname;
3692*a9fa9459Szrj 
3693*a9fa9459Szrj       if (get_file_size (argv[i]) < 1)
3694*a9fa9459Szrj 	{
3695*a9fa9459Szrj 	  status = 1;
3696*a9fa9459Szrj 	  continue;
3697*a9fa9459Szrj 	}
3698*a9fa9459Szrj 
3699*a9fa9459Szrj       if (preserve_dates)
3700*a9fa9459Szrj 	/* No need to check the return value of stat().
3701*a9fa9459Szrj 	   It has already been checked in get_file_size().  */
3702*a9fa9459Szrj 	stat (argv[i], &statbuf);
3703*a9fa9459Szrj 
3704*a9fa9459Szrj       if (output_file == NULL
3705*a9fa9459Szrj 	  || filename_cmp (argv[i], output_file) == 0)
3706*a9fa9459Szrj 	tmpname = make_tempname (argv[i]);
3707*a9fa9459Szrj       else
3708*a9fa9459Szrj 	tmpname = output_file;
3709*a9fa9459Szrj 
3710*a9fa9459Szrj       if (tmpname == NULL)
3711*a9fa9459Szrj 	{
3712*a9fa9459Szrj 	  bfd_nonfatal_message (argv[i], NULL, NULL,
3713*a9fa9459Szrj 				_("could not create temporary file to hold stripped copy"));
3714*a9fa9459Szrj 	  status = 1;
3715*a9fa9459Szrj 	  continue;
3716*a9fa9459Szrj 	}
3717*a9fa9459Szrj 
3718*a9fa9459Szrj       status = 0;
3719*a9fa9459Szrj       copy_file (argv[i], tmpname, input_target, output_target, NULL);
3720*a9fa9459Szrj       if (status == 0)
3721*a9fa9459Szrj 	{
3722*a9fa9459Szrj 	  if (preserve_dates)
3723*a9fa9459Szrj 	    set_times (tmpname, &statbuf);
3724*a9fa9459Szrj 	  if (output_file != tmpname)
3725*a9fa9459Szrj 	    status = (smart_rename (tmpname,
3726*a9fa9459Szrj 				    output_file ? output_file : argv[i],
3727*a9fa9459Szrj 				    preserve_dates) != 0);
3728*a9fa9459Szrj 	  if (status == 0)
3729*a9fa9459Szrj 	    status = hold_status;
3730*a9fa9459Szrj 	}
3731*a9fa9459Szrj       else
3732*a9fa9459Szrj 	unlink_if_ordinary (tmpname);
3733*a9fa9459Szrj       if (output_file != tmpname)
3734*a9fa9459Szrj 	free (tmpname);
3735*a9fa9459Szrj     }
3736*a9fa9459Szrj 
3737*a9fa9459Szrj   return status;
3738*a9fa9459Szrj }
3739*a9fa9459Szrj 
3740*a9fa9459Szrj /* Set up PE subsystem.  */
3741*a9fa9459Szrj 
3742*a9fa9459Szrj static void
set_pe_subsystem(const char * s)3743*a9fa9459Szrj set_pe_subsystem (const char *s)
3744*a9fa9459Szrj {
3745*a9fa9459Szrj   const char *version, *subsystem;
3746*a9fa9459Szrj   size_t i;
3747*a9fa9459Szrj   static const struct
3748*a9fa9459Szrj     {
3749*a9fa9459Szrj       const char *name;
3750*a9fa9459Szrj       const char set_def;
3751*a9fa9459Szrj       const short value;
3752*a9fa9459Szrj     }
3753*a9fa9459Szrj   v[] =
3754*a9fa9459Szrj     {
3755*a9fa9459Szrj       { "native", 0, IMAGE_SUBSYSTEM_NATIVE },
3756*a9fa9459Szrj       { "windows", 0, IMAGE_SUBSYSTEM_WINDOWS_GUI },
3757*a9fa9459Szrj       { "console", 0, IMAGE_SUBSYSTEM_WINDOWS_CUI },
3758*a9fa9459Szrj       { "posix", 0, IMAGE_SUBSYSTEM_POSIX_CUI },
3759*a9fa9459Szrj       { "wince", 0, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI },
3760*a9fa9459Szrj       { "efi-app", 1, IMAGE_SUBSYSTEM_EFI_APPLICATION },
3761*a9fa9459Szrj       { "efi-bsd", 1, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER },
3762*a9fa9459Szrj       { "efi-rtd", 1, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER },
3763*a9fa9459Szrj       { "sal-rtd", 1, IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER },
3764*a9fa9459Szrj       { "xbox", 0, IMAGE_SUBSYSTEM_XBOX }
3765*a9fa9459Szrj     };
3766*a9fa9459Szrj   short value;
3767*a9fa9459Szrj   char *copy;
3768*a9fa9459Szrj   int set_def = -1;
3769*a9fa9459Szrj 
3770*a9fa9459Szrj   /* Check for the presence of a version number.  */
3771*a9fa9459Szrj   version = strchr (s, ':');
3772*a9fa9459Szrj   if (version == NULL)
3773*a9fa9459Szrj     subsystem = s;
3774*a9fa9459Szrj   else
3775*a9fa9459Szrj     {
3776*a9fa9459Szrj       int len = version - s;
3777*a9fa9459Szrj       copy = xstrdup (s);
3778*a9fa9459Szrj       subsystem = copy;
3779*a9fa9459Szrj       copy[len] = '\0';
3780*a9fa9459Szrj       version = copy + 1 + len;
3781*a9fa9459Szrj       pe_major_subsystem_version = strtoul (version, &copy, 0);
3782*a9fa9459Szrj       if (*copy == '.')
3783*a9fa9459Szrj 	pe_minor_subsystem_version = strtoul (copy + 1, &copy, 0);
3784*a9fa9459Szrj       if (*copy != '\0')
3785*a9fa9459Szrj 	non_fatal (_("%s: bad version in PE subsystem"), s);
3786*a9fa9459Szrj     }
3787*a9fa9459Szrj 
3788*a9fa9459Szrj   /* Check for numeric subsystem.  */
3789*a9fa9459Szrj   value = (short) strtol (subsystem, &copy, 0);
3790*a9fa9459Szrj   if (*copy == '\0')
3791*a9fa9459Szrj     {
3792*a9fa9459Szrj       for (i = 0; i < ARRAY_SIZE (v); i++)
3793*a9fa9459Szrj 	if (v[i].value == value)
3794*a9fa9459Szrj 	  {
3795*a9fa9459Szrj 	    pe_subsystem = value;
3796*a9fa9459Szrj 	    set_def = v[i].set_def;
3797*a9fa9459Szrj 	    break;
3798*a9fa9459Szrj 	  }
3799*a9fa9459Szrj     }
3800*a9fa9459Szrj   else
3801*a9fa9459Szrj     {
3802*a9fa9459Szrj       /* Search for subsystem by name.  */
3803*a9fa9459Szrj       for (i = 0; i < ARRAY_SIZE (v); i++)
3804*a9fa9459Szrj 	if (strcmp (subsystem, v[i].name) == 0)
3805*a9fa9459Szrj 	  {
3806*a9fa9459Szrj 	    pe_subsystem = v[i].value;
3807*a9fa9459Szrj 	    set_def = v[i].set_def;
3808*a9fa9459Szrj 	    break;
3809*a9fa9459Szrj 	  }
3810*a9fa9459Szrj     }
3811*a9fa9459Szrj 
3812*a9fa9459Szrj   switch (set_def)
3813*a9fa9459Szrj     {
3814*a9fa9459Szrj     case -1:
3815*a9fa9459Szrj       fatal (_("unknown PE subsystem: %s"), s);
3816*a9fa9459Szrj       break;
3817*a9fa9459Szrj     case 0:
3818*a9fa9459Szrj       break;
3819*a9fa9459Szrj     default:
3820*a9fa9459Szrj       if (pe_file_alignment == (bfd_vma) -1)
3821*a9fa9459Szrj 	pe_file_alignment = PE_DEF_FILE_ALIGNMENT;
3822*a9fa9459Szrj       if (pe_section_alignment == (bfd_vma) -1)
3823*a9fa9459Szrj 	pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
3824*a9fa9459Szrj       break;
3825*a9fa9459Szrj     }
3826*a9fa9459Szrj   if (s != subsystem)
3827*a9fa9459Szrj     free ((char *) subsystem);
3828*a9fa9459Szrj }
3829*a9fa9459Szrj 
3830*a9fa9459Szrj /* Convert EFI target to PEI target.  */
3831*a9fa9459Szrj 
3832*a9fa9459Szrj static void
convert_efi_target(char * efi)3833*a9fa9459Szrj convert_efi_target (char *efi)
3834*a9fa9459Szrj {
3835*a9fa9459Szrj   efi[0] = 'p';
3836*a9fa9459Szrj   efi[1] = 'e';
3837*a9fa9459Szrj   efi[2] = 'i';
3838*a9fa9459Szrj 
3839*a9fa9459Szrj   if (strcmp (efi + 4, "ia32") == 0)
3840*a9fa9459Szrj     {
3841*a9fa9459Szrj       /* Change ia32 to i386.  */
3842*a9fa9459Szrj       efi[5]= '3';
3843*a9fa9459Szrj       efi[6]= '8';
3844*a9fa9459Szrj       efi[7]= '6';
3845*a9fa9459Szrj     }
3846*a9fa9459Szrj   else if (strcmp (efi + 4, "x86_64") == 0)
3847*a9fa9459Szrj     {
3848*a9fa9459Szrj       /* Change x86_64 to x86-64.  */
3849*a9fa9459Szrj       efi[7] = '-';
3850*a9fa9459Szrj     }
3851*a9fa9459Szrj }
3852*a9fa9459Szrj 
3853*a9fa9459Szrj /* Allocate and return a pointer to a struct section_add, initializing the
3854*a9fa9459Szrj    structure using ARG, a string in the format "sectionname=filename".
3855*a9fa9459Szrj    The returned structure will have its next pointer set to NEXT.  The
3856*a9fa9459Szrj    OPTION field is the name of the command line option currently being
3857*a9fa9459Szrj    parsed, and is only used if an error needs to be reported.  */
3858*a9fa9459Szrj 
3859*a9fa9459Szrj static struct section_add *
init_section_add(const char * arg,struct section_add * next,const char * option)3860*a9fa9459Szrj init_section_add (const char *arg,
3861*a9fa9459Szrj 		  struct section_add *next,
3862*a9fa9459Szrj 		  const char *option)
3863*a9fa9459Szrj {
3864*a9fa9459Szrj   struct section_add *pa;
3865*a9fa9459Szrj   const char *s;
3866*a9fa9459Szrj 
3867*a9fa9459Szrj   s = strchr (arg, '=');
3868*a9fa9459Szrj   if (s == NULL)
3869*a9fa9459Szrj     fatal (_("bad format for %s"), option);
3870*a9fa9459Szrj 
3871*a9fa9459Szrj   pa = (struct section_add *) xmalloc (sizeof (struct section_add));
3872*a9fa9459Szrj   pa->name = xstrndup (arg, s - arg);
3873*a9fa9459Szrj   pa->filename = s + 1;
3874*a9fa9459Szrj   pa->next = next;
3875*a9fa9459Szrj   pa->contents = NULL;
3876*a9fa9459Szrj   pa->size = 0;
3877*a9fa9459Szrj 
3878*a9fa9459Szrj   return pa;
3879*a9fa9459Szrj }
3880*a9fa9459Szrj 
3881*a9fa9459Szrj /* Load the file specified in PA, allocating memory to hold the file
3882*a9fa9459Szrj    contents, and store a pointer to the allocated memory in the contents
3883*a9fa9459Szrj    field of PA.  The size field of PA is also updated.  All errors call
3884*a9fa9459Szrj    FATAL.  */
3885*a9fa9459Szrj 
3886*a9fa9459Szrj static void
section_add_load_file(struct section_add * pa)3887*a9fa9459Szrj section_add_load_file (struct section_add *pa)
3888*a9fa9459Szrj {
3889*a9fa9459Szrj   size_t off, alloc;
3890*a9fa9459Szrj   FILE *f;
3891*a9fa9459Szrj 
3892*a9fa9459Szrj   /* We don't use get_file_size so that we can do
3893*a9fa9459Szrj      --add-section .note.GNU_stack=/dev/null
3894*a9fa9459Szrj      get_file_size doesn't work on /dev/null.  */
3895*a9fa9459Szrj 
3896*a9fa9459Szrj   f = fopen (pa->filename, FOPEN_RB);
3897*a9fa9459Szrj   if (f == NULL)
3898*a9fa9459Szrj     fatal (_("cannot open: %s: %s"),
3899*a9fa9459Szrj 	   pa->filename, strerror (errno));
3900*a9fa9459Szrj 
3901*a9fa9459Szrj   off = 0;
3902*a9fa9459Szrj   alloc = 4096;
3903*a9fa9459Szrj   pa->contents = (bfd_byte *) xmalloc (alloc);
3904*a9fa9459Szrj   while (!feof (f))
3905*a9fa9459Szrj     {
3906*a9fa9459Szrj       off_t got;
3907*a9fa9459Szrj 
3908*a9fa9459Szrj       if (off == alloc)
3909*a9fa9459Szrj 	{
3910*a9fa9459Szrj 	  alloc <<= 1;
3911*a9fa9459Szrj 	  pa->contents = (bfd_byte *) xrealloc (pa->contents, alloc);
3912*a9fa9459Szrj 	}
3913*a9fa9459Szrj 
3914*a9fa9459Szrj       got = fread (pa->contents + off, 1, alloc - off, f);
3915*a9fa9459Szrj       if (ferror (f))
3916*a9fa9459Szrj 	fatal (_("%s: fread failed"), pa->filename);
3917*a9fa9459Szrj 
3918*a9fa9459Szrj       off += got;
3919*a9fa9459Szrj     }
3920*a9fa9459Szrj 
3921*a9fa9459Szrj   pa->size = off;
3922*a9fa9459Szrj 
3923*a9fa9459Szrj   fclose (f);
3924*a9fa9459Szrj }
3925*a9fa9459Szrj 
3926*a9fa9459Szrj static int
copy_main(int argc,char * argv[])3927*a9fa9459Szrj copy_main (int argc, char *argv[])
3928*a9fa9459Szrj {
3929*a9fa9459Szrj   char *input_filename = NULL;
3930*a9fa9459Szrj   char *output_filename = NULL;
3931*a9fa9459Szrj   char *tmpname;
3932*a9fa9459Szrj   char *input_target = NULL;
3933*a9fa9459Szrj   char *output_target = NULL;
3934*a9fa9459Szrj   bfd_boolean show_version = FALSE;
3935*a9fa9459Szrj   bfd_boolean change_warn = TRUE;
3936*a9fa9459Szrj   bfd_boolean formats_info = FALSE;
3937*a9fa9459Szrj   int c;
3938*a9fa9459Szrj   struct stat statbuf;
3939*a9fa9459Szrj   const bfd_arch_info_type *input_arch = NULL;
3940*a9fa9459Szrj 
3941*a9fa9459Szrj   while ((c = getopt_long (argc, argv, "b:B:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXHhVvW:wDU",
3942*a9fa9459Szrj 			   copy_options, (int *) 0)) != EOF)
3943*a9fa9459Szrj     {
3944*a9fa9459Szrj       switch (c)
3945*a9fa9459Szrj 	{
3946*a9fa9459Szrj 	case 'b':
3947*a9fa9459Szrj 	  copy_byte = atoi (optarg);
3948*a9fa9459Szrj 	  if (copy_byte < 0)
3949*a9fa9459Szrj 	    fatal (_("byte number must be non-negative"));
3950*a9fa9459Szrj 	  break;
3951*a9fa9459Szrj 
3952*a9fa9459Szrj 	case 'B':
3953*a9fa9459Szrj 	  input_arch = bfd_scan_arch (optarg);
3954*a9fa9459Szrj 	  if (input_arch == NULL)
3955*a9fa9459Szrj 	    fatal (_("architecture %s unknown"), optarg);
3956*a9fa9459Szrj 	  break;
3957*a9fa9459Szrj 
3958*a9fa9459Szrj 	case 'i':
3959*a9fa9459Szrj 	  if (optarg)
3960*a9fa9459Szrj 	    {
3961*a9fa9459Szrj 	      interleave = atoi (optarg);
3962*a9fa9459Szrj 	      if (interleave < 1)
3963*a9fa9459Szrj 		fatal (_("interleave must be positive"));
3964*a9fa9459Szrj 	    }
3965*a9fa9459Szrj 	  else
3966*a9fa9459Szrj 	    interleave = 4;
3967*a9fa9459Szrj 	  break;
3968*a9fa9459Szrj 
3969*a9fa9459Szrj 	case OPTION_INTERLEAVE_WIDTH:
3970*a9fa9459Szrj 	  copy_width = atoi (optarg);
3971*a9fa9459Szrj 	  if (copy_width < 1)
3972*a9fa9459Szrj 	    fatal(_("interleave width must be positive"));
3973*a9fa9459Szrj 	  break;
3974*a9fa9459Szrj 
3975*a9fa9459Szrj 	case 'I':
3976*a9fa9459Szrj 	case 's':		/* "source" - 'I' is preferred */
3977*a9fa9459Szrj 	  input_target = optarg;
3978*a9fa9459Szrj 	  break;
3979*a9fa9459Szrj 
3980*a9fa9459Szrj 	case 'O':
3981*a9fa9459Szrj 	case 'd':		/* "destination" - 'O' is preferred */
3982*a9fa9459Szrj 	  output_target = optarg;
3983*a9fa9459Szrj 	  break;
3984*a9fa9459Szrj 
3985*a9fa9459Szrj 	case 'F':
3986*a9fa9459Szrj 	  input_target = output_target = optarg;
3987*a9fa9459Szrj 	  break;
3988*a9fa9459Szrj 
3989*a9fa9459Szrj 	case 'j':
3990*a9fa9459Szrj 	  find_section_list (optarg, TRUE, SECTION_CONTEXT_COPY);
3991*a9fa9459Szrj 	  sections_copied = TRUE;
3992*a9fa9459Szrj 	  break;
3993*a9fa9459Szrj 
3994*a9fa9459Szrj 	case 'R':
3995*a9fa9459Szrj 	  find_section_list (optarg, TRUE, SECTION_CONTEXT_REMOVE);
3996*a9fa9459Szrj 	  sections_removed = TRUE;
3997*a9fa9459Szrj 	  break;
3998*a9fa9459Szrj 
3999*a9fa9459Szrj 	case 'S':
4000*a9fa9459Szrj 	  strip_symbols = STRIP_ALL;
4001*a9fa9459Szrj 	  break;
4002*a9fa9459Szrj 
4003*a9fa9459Szrj 	case 'g':
4004*a9fa9459Szrj 	  strip_symbols = STRIP_DEBUG;
4005*a9fa9459Szrj 	  break;
4006*a9fa9459Szrj 
4007*a9fa9459Szrj 	case OPTION_STRIP_DWO:
4008*a9fa9459Szrj 	  strip_symbols = STRIP_DWO;
4009*a9fa9459Szrj 	  break;
4010*a9fa9459Szrj 
4011*a9fa9459Szrj 	case OPTION_STRIP_UNNEEDED:
4012*a9fa9459Szrj 	  strip_symbols = STRIP_UNNEEDED;
4013*a9fa9459Szrj 	  break;
4014*a9fa9459Szrj 
4015*a9fa9459Szrj 	case OPTION_ONLY_KEEP_DEBUG:
4016*a9fa9459Szrj 	  strip_symbols = STRIP_NONDEBUG;
4017*a9fa9459Szrj 	  break;
4018*a9fa9459Szrj 
4019*a9fa9459Szrj 	case OPTION_KEEP_FILE_SYMBOLS:
4020*a9fa9459Szrj 	  keep_file_symbols = 1;
4021*a9fa9459Szrj 	  break;
4022*a9fa9459Szrj 
4023*a9fa9459Szrj 	case OPTION_ADD_GNU_DEBUGLINK:
4024*a9fa9459Szrj 	  long_section_names = ENABLE ;
4025*a9fa9459Szrj 	  gnu_debuglink_filename = optarg;
4026*a9fa9459Szrj 	  break;
4027*a9fa9459Szrj 
4028*a9fa9459Szrj 	case 'K':
4029*a9fa9459Szrj 	  add_specific_symbol (optarg, keep_specific_htab);
4030*a9fa9459Szrj 	  break;
4031*a9fa9459Szrj 
4032*a9fa9459Szrj 	case 'N':
4033*a9fa9459Szrj 	  add_specific_symbol (optarg, strip_specific_htab);
4034*a9fa9459Szrj 	  break;
4035*a9fa9459Szrj 
4036*a9fa9459Szrj 	case OPTION_STRIP_UNNEEDED_SYMBOL:
4037*a9fa9459Szrj 	  add_specific_symbol (optarg, strip_unneeded_htab);
4038*a9fa9459Szrj 	  break;
4039*a9fa9459Szrj 
4040*a9fa9459Szrj 	case 'L':
4041*a9fa9459Szrj 	  add_specific_symbol (optarg, localize_specific_htab);
4042*a9fa9459Szrj 	  break;
4043*a9fa9459Szrj 
4044*a9fa9459Szrj 	case OPTION_GLOBALIZE_SYMBOL:
4045*a9fa9459Szrj 	  add_specific_symbol (optarg, globalize_specific_htab);
4046*a9fa9459Szrj 	  break;
4047*a9fa9459Szrj 
4048*a9fa9459Szrj 	case 'G':
4049*a9fa9459Szrj 	  add_specific_symbol (optarg, keepglobal_specific_htab);
4050*a9fa9459Szrj 	  break;
4051*a9fa9459Szrj 
4052*a9fa9459Szrj 	case 'W':
4053*a9fa9459Szrj 	  add_specific_symbol (optarg, weaken_specific_htab);
4054*a9fa9459Szrj 	  break;
4055*a9fa9459Szrj 
4056*a9fa9459Szrj 	case 'p':
4057*a9fa9459Szrj 	  preserve_dates = TRUE;
4058*a9fa9459Szrj 	  break;
4059*a9fa9459Szrj 
4060*a9fa9459Szrj 	case 'D':
4061*a9fa9459Szrj 	  deterministic = TRUE;
4062*a9fa9459Szrj 	  break;
4063*a9fa9459Szrj 
4064*a9fa9459Szrj 	case 'U':
4065*a9fa9459Szrj 	  deterministic = FALSE;
4066*a9fa9459Szrj 	  break;
4067*a9fa9459Szrj 
4068*a9fa9459Szrj 	case 'w':
4069*a9fa9459Szrj 	  wildcard = TRUE;
4070*a9fa9459Szrj 	  break;
4071*a9fa9459Szrj 
4072*a9fa9459Szrj 	case 'x':
4073*a9fa9459Szrj 	  discard_locals = LOCALS_ALL;
4074*a9fa9459Szrj 	  break;
4075*a9fa9459Szrj 
4076*a9fa9459Szrj 	case 'X':
4077*a9fa9459Szrj 	  discard_locals = LOCALS_START_L;
4078*a9fa9459Szrj 	  break;
4079*a9fa9459Szrj 
4080*a9fa9459Szrj 	case 'v':
4081*a9fa9459Szrj 	  verbose = TRUE;
4082*a9fa9459Szrj 	  break;
4083*a9fa9459Szrj 
4084*a9fa9459Szrj 	case 'V':
4085*a9fa9459Szrj 	  show_version = TRUE;
4086*a9fa9459Szrj 	  break;
4087*a9fa9459Szrj 
4088*a9fa9459Szrj 	case OPTION_FORMATS_INFO:
4089*a9fa9459Szrj 	  formats_info = TRUE;
4090*a9fa9459Szrj 	  break;
4091*a9fa9459Szrj 
4092*a9fa9459Szrj 	case OPTION_WEAKEN:
4093*a9fa9459Szrj 	  weaken = TRUE;
4094*a9fa9459Szrj 	  break;
4095*a9fa9459Szrj 
4096*a9fa9459Szrj 	case OPTION_ADD_SECTION:
4097*a9fa9459Szrj 	  add_sections = init_section_add (optarg, add_sections,
4098*a9fa9459Szrj 					   "--add-section");
4099*a9fa9459Szrj 	  section_add_load_file (add_sections);
4100*a9fa9459Szrj 	  break;
4101*a9fa9459Szrj 
4102*a9fa9459Szrj 	case OPTION_UPDATE_SECTION:
4103*a9fa9459Szrj 	  update_sections = init_section_add (optarg, update_sections,
4104*a9fa9459Szrj 					      "--update-section");
4105*a9fa9459Szrj 	  section_add_load_file (update_sections);
4106*a9fa9459Szrj 	  break;
4107*a9fa9459Szrj 
4108*a9fa9459Szrj 	case OPTION_DUMP_SECTION:
4109*a9fa9459Szrj 	  dump_sections = init_section_add (optarg, dump_sections,
4110*a9fa9459Szrj 					    "--dump-section");
4111*a9fa9459Szrj 	  break;
4112*a9fa9459Szrj 
4113*a9fa9459Szrj 	case OPTION_ADD_SYMBOL:
4114*a9fa9459Szrj 	  {
4115*a9fa9459Szrj 	    char *s, *t;
4116*a9fa9459Szrj 	    struct addsym_node *newsym = xmalloc (sizeof *newsym);
4117*a9fa9459Szrj 
4118*a9fa9459Szrj 	    newsym->next = NULL;
4119*a9fa9459Szrj 	    s = strchr (optarg, '=');
4120*a9fa9459Szrj 	    if (s == NULL)
4121*a9fa9459Szrj 	      fatal (_("bad format for %s"), "--add-symbol");
4122*a9fa9459Szrj 	    t = strchr (s + 1, ':');
4123*a9fa9459Szrj 
4124*a9fa9459Szrj 	    newsym->symdef = xstrndup (optarg, s - optarg);
4125*a9fa9459Szrj 	    if (t)
4126*a9fa9459Szrj 	      {
4127*a9fa9459Szrj 		newsym->section = xstrndup (s + 1, t - (s + 1));
4128*a9fa9459Szrj 		newsym->symval = strtol (t + 1, NULL, 0);
4129*a9fa9459Szrj 	      }
4130*a9fa9459Szrj 	    else
4131*a9fa9459Szrj 	      {
4132*a9fa9459Szrj 		newsym->section = NULL;
4133*a9fa9459Szrj 		newsym->symval = strtol (s + 1, NULL, 0);
4134*a9fa9459Szrj 		t = s;
4135*a9fa9459Szrj 	      }
4136*a9fa9459Szrj 
4137*a9fa9459Szrj 	    t = strchr (t + 1, ',');
4138*a9fa9459Szrj 	    newsym->othersym = NULL;
4139*a9fa9459Szrj 	    if (t)
4140*a9fa9459Szrj 	      newsym->flags = parse_symflags (t+1, &newsym->othersym);
4141*a9fa9459Szrj 	    else
4142*a9fa9459Szrj 	      newsym->flags = BSF_GLOBAL;
4143*a9fa9459Szrj 
4144*a9fa9459Szrj 	    /* Keep 'othersym' symbols at the front of the list.  */
4145*a9fa9459Szrj 	    if (newsym->othersym)
4146*a9fa9459Szrj 	      {
4147*a9fa9459Szrj 		newsym->next = add_sym_list;
4148*a9fa9459Szrj 		if (!add_sym_list)
4149*a9fa9459Szrj 		  add_sym_tail = &newsym->next;
4150*a9fa9459Szrj 		add_sym_list = newsym;
4151*a9fa9459Szrj 	      }
4152*a9fa9459Szrj 	    else
4153*a9fa9459Szrj 	      {
4154*a9fa9459Szrj 		*add_sym_tail = newsym;
4155*a9fa9459Szrj 		add_sym_tail = &newsym->next;
4156*a9fa9459Szrj 	      }
4157*a9fa9459Szrj 	    add_symbols++;
4158*a9fa9459Szrj 	  }
4159*a9fa9459Szrj 	  break;
4160*a9fa9459Szrj 
4161*a9fa9459Szrj 	case OPTION_CHANGE_START:
4162*a9fa9459Szrj 	  change_start = parse_vma (optarg, "--change-start");
4163*a9fa9459Szrj 	  break;
4164*a9fa9459Szrj 
4165*a9fa9459Szrj 	case OPTION_CHANGE_SECTION_ADDRESS:
4166*a9fa9459Szrj 	case OPTION_CHANGE_SECTION_LMA:
4167*a9fa9459Szrj 	case OPTION_CHANGE_SECTION_VMA:
4168*a9fa9459Szrj 	  {
4169*a9fa9459Szrj 	    struct section_list * p;
4170*a9fa9459Szrj 	    unsigned int context = 0;
4171*a9fa9459Szrj 	    const char *s;
4172*a9fa9459Szrj 	    int len;
4173*a9fa9459Szrj 	    char *name;
4174*a9fa9459Szrj 	    char *option = NULL;
4175*a9fa9459Szrj 	    bfd_vma val;
4176*a9fa9459Szrj 
4177*a9fa9459Szrj 	    switch (c)
4178*a9fa9459Szrj 	      {
4179*a9fa9459Szrj 	      case OPTION_CHANGE_SECTION_ADDRESS:
4180*a9fa9459Szrj 		option = "--change-section-address";
4181*a9fa9459Szrj 		context = SECTION_CONTEXT_ALTER_LMA | SECTION_CONTEXT_ALTER_VMA;
4182*a9fa9459Szrj 		break;
4183*a9fa9459Szrj 	      case OPTION_CHANGE_SECTION_LMA:
4184*a9fa9459Szrj 		option = "--change-section-lma";
4185*a9fa9459Szrj 		context = SECTION_CONTEXT_ALTER_LMA;
4186*a9fa9459Szrj 		break;
4187*a9fa9459Szrj 	      case OPTION_CHANGE_SECTION_VMA:
4188*a9fa9459Szrj 		option = "--change-section-vma";
4189*a9fa9459Szrj 		context = SECTION_CONTEXT_ALTER_VMA;
4190*a9fa9459Szrj 		break;
4191*a9fa9459Szrj 	      }
4192*a9fa9459Szrj 
4193*a9fa9459Szrj 	    s = strchr (optarg, '=');
4194*a9fa9459Szrj 	    if (s == NULL)
4195*a9fa9459Szrj 	      {
4196*a9fa9459Szrj 		s = strchr (optarg, '+');
4197*a9fa9459Szrj 		if (s == NULL)
4198*a9fa9459Szrj 		  {
4199*a9fa9459Szrj 		    s = strchr (optarg, '-');
4200*a9fa9459Szrj 		    if (s == NULL)
4201*a9fa9459Szrj 		      fatal (_("bad format for %s"), option);
4202*a9fa9459Szrj 		  }
4203*a9fa9459Szrj 	      }
4204*a9fa9459Szrj 	    else
4205*a9fa9459Szrj 	      {
4206*a9fa9459Szrj 		/* Correct the context.  */
4207*a9fa9459Szrj 		switch (c)
4208*a9fa9459Szrj 		  {
4209*a9fa9459Szrj 		  case OPTION_CHANGE_SECTION_ADDRESS:
4210*a9fa9459Szrj 		    context = SECTION_CONTEXT_SET_LMA | SECTION_CONTEXT_SET_VMA;
4211*a9fa9459Szrj 		    break;
4212*a9fa9459Szrj 		  case OPTION_CHANGE_SECTION_LMA:
4213*a9fa9459Szrj 		    context = SECTION_CONTEXT_SET_LMA;
4214*a9fa9459Szrj 		    break;
4215*a9fa9459Szrj 		  case OPTION_CHANGE_SECTION_VMA:
4216*a9fa9459Szrj 		    context = SECTION_CONTEXT_SET_VMA;
4217*a9fa9459Szrj 		    break;
4218*a9fa9459Szrj 		  }
4219*a9fa9459Szrj 	      }
4220*a9fa9459Szrj 
4221*a9fa9459Szrj 	    len = s - optarg;
4222*a9fa9459Szrj 	    name = (char *) xmalloc (len + 1);
4223*a9fa9459Szrj 	    strncpy (name, optarg, len);
4224*a9fa9459Szrj 	    name[len] = '\0';
4225*a9fa9459Szrj 
4226*a9fa9459Szrj 	    p = find_section_list (name, TRUE, context);
4227*a9fa9459Szrj 
4228*a9fa9459Szrj 	    val = parse_vma (s + 1, option);
4229*a9fa9459Szrj 	    if (*s == '-')
4230*a9fa9459Szrj 	      val = - val;
4231*a9fa9459Szrj 
4232*a9fa9459Szrj 	    switch (c)
4233*a9fa9459Szrj 	      {
4234*a9fa9459Szrj 	      case OPTION_CHANGE_SECTION_ADDRESS:
4235*a9fa9459Szrj 		p->vma_val = val;
4236*a9fa9459Szrj 		/* Drop through.  */
4237*a9fa9459Szrj 
4238*a9fa9459Szrj 	      case OPTION_CHANGE_SECTION_LMA:
4239*a9fa9459Szrj 		p->lma_val = val;
4240*a9fa9459Szrj 		break;
4241*a9fa9459Szrj 
4242*a9fa9459Szrj 	      case OPTION_CHANGE_SECTION_VMA:
4243*a9fa9459Szrj 		p->vma_val = val;
4244*a9fa9459Szrj 		break;
4245*a9fa9459Szrj 	      }
4246*a9fa9459Szrj 	  }
4247*a9fa9459Szrj 	  break;
4248*a9fa9459Szrj 
4249*a9fa9459Szrj 	case OPTION_CHANGE_ADDRESSES:
4250*a9fa9459Szrj 	  change_section_address = parse_vma (optarg, "--change-addresses");
4251*a9fa9459Szrj 	  change_start = change_section_address;
4252*a9fa9459Szrj 	  break;
4253*a9fa9459Szrj 
4254*a9fa9459Szrj 	case OPTION_CHANGE_WARNINGS:
4255*a9fa9459Szrj 	  change_warn = TRUE;
4256*a9fa9459Szrj 	  break;
4257*a9fa9459Szrj 
4258*a9fa9459Szrj 	case OPTION_CHANGE_LEADING_CHAR:
4259*a9fa9459Szrj 	  change_leading_char = TRUE;
4260*a9fa9459Szrj 	  break;
4261*a9fa9459Szrj 
4262*a9fa9459Szrj 	case OPTION_COMPRESS_DEBUG_SECTIONS:
4263*a9fa9459Szrj 	  if (optarg)
4264*a9fa9459Szrj 	    {
4265*a9fa9459Szrj 	      if (strcasecmp (optarg, "none") == 0)
4266*a9fa9459Szrj 		do_debug_sections = decompress;
4267*a9fa9459Szrj 	      else if (strcasecmp (optarg, "zlib") == 0)
4268*a9fa9459Szrj 		do_debug_sections = compress_zlib;
4269*a9fa9459Szrj 	      else if (strcasecmp (optarg, "zlib-gnu") == 0)
4270*a9fa9459Szrj 		do_debug_sections = compress_gnu_zlib;
4271*a9fa9459Szrj 	      else if (strcasecmp (optarg, "zlib-gabi") == 0)
4272*a9fa9459Szrj 		do_debug_sections = compress_gabi_zlib;
4273*a9fa9459Szrj 	      else
4274*a9fa9459Szrj 		fatal (_("unrecognized --compress-debug-sections type `%s'"),
4275*a9fa9459Szrj 		       optarg);
4276*a9fa9459Szrj 	    }
4277*a9fa9459Szrj 	  else
4278*a9fa9459Szrj 	    do_debug_sections = compress;
4279*a9fa9459Szrj 	  break;
4280*a9fa9459Szrj 
4281*a9fa9459Szrj 	case OPTION_DEBUGGING:
4282*a9fa9459Szrj 	  convert_debugging = TRUE;
4283*a9fa9459Szrj 	  break;
4284*a9fa9459Szrj 
4285*a9fa9459Szrj 	case OPTION_DECOMPRESS_DEBUG_SECTIONS:
4286*a9fa9459Szrj 	  do_debug_sections = decompress;
4287*a9fa9459Szrj 	  break;
4288*a9fa9459Szrj 
4289*a9fa9459Szrj 	case OPTION_ELF_STT_COMMON:
4290*a9fa9459Szrj 	  if (strcasecmp (optarg, "yes") == 0)
4291*a9fa9459Szrj 	    do_elf_stt_common = elf_stt_common;
4292*a9fa9459Szrj 	  else if (strcasecmp (optarg, "no") == 0)
4293*a9fa9459Szrj 	    do_elf_stt_common = no_elf_stt_common;
4294*a9fa9459Szrj 	  else
4295*a9fa9459Szrj 	    fatal (_("unrecognized --elf-stt-common= option `%s'"),
4296*a9fa9459Szrj 		   optarg);
4297*a9fa9459Szrj 	  break;
4298*a9fa9459Szrj 
4299*a9fa9459Szrj 	case OPTION_GAP_FILL:
4300*a9fa9459Szrj 	  {
4301*a9fa9459Szrj 	    bfd_vma gap_fill_vma;
4302*a9fa9459Szrj 
4303*a9fa9459Szrj 	    gap_fill_vma = parse_vma (optarg, "--gap-fill");
4304*a9fa9459Szrj 	    gap_fill = (bfd_byte) gap_fill_vma;
4305*a9fa9459Szrj 	    if ((bfd_vma) gap_fill != gap_fill_vma)
4306*a9fa9459Szrj 	      {
4307*a9fa9459Szrj 		char buff[20];
4308*a9fa9459Szrj 
4309*a9fa9459Szrj 		sprintf_vma (buff, gap_fill_vma);
4310*a9fa9459Szrj 
4311*a9fa9459Szrj 		non_fatal (_("Warning: truncating gap-fill from 0x%s to 0x%x"),
4312*a9fa9459Szrj 			   buff, gap_fill);
4313*a9fa9459Szrj 	      }
4314*a9fa9459Szrj 	    gap_fill_set = TRUE;
4315*a9fa9459Szrj 	  }
4316*a9fa9459Szrj 	  break;
4317*a9fa9459Szrj 
4318*a9fa9459Szrj 	case OPTION_NO_CHANGE_WARNINGS:
4319*a9fa9459Szrj 	  change_warn = FALSE;
4320*a9fa9459Szrj 	  break;
4321*a9fa9459Szrj 
4322*a9fa9459Szrj 	case OPTION_PAD_TO:
4323*a9fa9459Szrj 	  pad_to = parse_vma (optarg, "--pad-to");
4324*a9fa9459Szrj 	  pad_to_set = TRUE;
4325*a9fa9459Szrj 	  break;
4326*a9fa9459Szrj 
4327*a9fa9459Szrj 	case OPTION_REMOVE_LEADING_CHAR:
4328*a9fa9459Szrj 	  remove_leading_char = TRUE;
4329*a9fa9459Szrj 	  break;
4330*a9fa9459Szrj 
4331*a9fa9459Szrj 	case OPTION_REDEFINE_SYM:
4332*a9fa9459Szrj 	  {
4333*a9fa9459Szrj 	    /* Push this redefinition onto redefine_symbol_list.  */
4334*a9fa9459Szrj 
4335*a9fa9459Szrj 	    int len;
4336*a9fa9459Szrj 	    const char *s;
4337*a9fa9459Szrj 	    const char *nextarg;
4338*a9fa9459Szrj 	    char *source, *target;
4339*a9fa9459Szrj 
4340*a9fa9459Szrj 	    s = strchr (optarg, '=');
4341*a9fa9459Szrj 	    if (s == NULL)
4342*a9fa9459Szrj 	      fatal (_("bad format for %s"), "--redefine-sym");
4343*a9fa9459Szrj 
4344*a9fa9459Szrj 	    len = s - optarg;
4345*a9fa9459Szrj 	    source = (char *) xmalloc (len + 1);
4346*a9fa9459Szrj 	    strncpy (source, optarg, len);
4347*a9fa9459Szrj 	    source[len] = '\0';
4348*a9fa9459Szrj 
4349*a9fa9459Szrj 	    nextarg = s + 1;
4350*a9fa9459Szrj 	    len = strlen (nextarg);
4351*a9fa9459Szrj 	    target = (char *) xmalloc (len + 1);
4352*a9fa9459Szrj 	    strcpy (target, nextarg);
4353*a9fa9459Szrj 
4354*a9fa9459Szrj 	    redefine_list_append ("--redefine-sym", source, target);
4355*a9fa9459Szrj 
4356*a9fa9459Szrj 	    free (source);
4357*a9fa9459Szrj 	    free (target);
4358*a9fa9459Szrj 	  }
4359*a9fa9459Szrj 	  break;
4360*a9fa9459Szrj 
4361*a9fa9459Szrj 	case OPTION_REDEFINE_SYMS:
4362*a9fa9459Szrj 	  add_redefine_syms_file (optarg);
4363*a9fa9459Szrj 	  break;
4364*a9fa9459Szrj 
4365*a9fa9459Szrj 	case OPTION_SET_SECTION_FLAGS:
4366*a9fa9459Szrj 	  {
4367*a9fa9459Szrj 	    struct section_list *p;
4368*a9fa9459Szrj 	    const char *s;
4369*a9fa9459Szrj 	    int len;
4370*a9fa9459Szrj 	    char *name;
4371*a9fa9459Szrj 
4372*a9fa9459Szrj 	    s = strchr (optarg, '=');
4373*a9fa9459Szrj 	    if (s == NULL)
4374*a9fa9459Szrj 	      fatal (_("bad format for %s"), "--set-section-flags");
4375*a9fa9459Szrj 
4376*a9fa9459Szrj 	    len = s - optarg;
4377*a9fa9459Szrj 	    name = (char *) xmalloc (len + 1);
4378*a9fa9459Szrj 	    strncpy (name, optarg, len);
4379*a9fa9459Szrj 	    name[len] = '\0';
4380*a9fa9459Szrj 
4381*a9fa9459Szrj 	    p = find_section_list (name, TRUE, SECTION_CONTEXT_SET_FLAGS);
4382*a9fa9459Szrj 
4383*a9fa9459Szrj 	    p->flags = parse_flags (s + 1);
4384*a9fa9459Szrj 	  }
4385*a9fa9459Szrj 	  break;
4386*a9fa9459Szrj 
4387*a9fa9459Szrj 	case OPTION_RENAME_SECTION:
4388*a9fa9459Szrj 	  {
4389*a9fa9459Szrj 	    flagword flags;
4390*a9fa9459Szrj 	    const char *eq, *fl;
4391*a9fa9459Szrj 	    char *old_name;
4392*a9fa9459Szrj 	    char *new_name;
4393*a9fa9459Szrj 	    unsigned int len;
4394*a9fa9459Szrj 
4395*a9fa9459Szrj 	    eq = strchr (optarg, '=');
4396*a9fa9459Szrj 	    if (eq == NULL)
4397*a9fa9459Szrj 	      fatal (_("bad format for %s"), "--rename-section");
4398*a9fa9459Szrj 
4399*a9fa9459Szrj 	    len = eq - optarg;
4400*a9fa9459Szrj 	    if (len == 0)
4401*a9fa9459Szrj 	      fatal (_("bad format for %s"), "--rename-section");
4402*a9fa9459Szrj 
4403*a9fa9459Szrj 	    old_name = (char *) xmalloc (len + 1);
4404*a9fa9459Szrj 	    strncpy (old_name, optarg, len);
4405*a9fa9459Szrj 	    old_name[len] = 0;
4406*a9fa9459Szrj 
4407*a9fa9459Szrj 	    eq++;
4408*a9fa9459Szrj 	    fl = strchr (eq, ',');
4409*a9fa9459Szrj 	    if (fl)
4410*a9fa9459Szrj 	      {
4411*a9fa9459Szrj 		flags = parse_flags (fl + 1);
4412*a9fa9459Szrj 		len = fl - eq;
4413*a9fa9459Szrj 	      }
4414*a9fa9459Szrj 	    else
4415*a9fa9459Szrj 	      {
4416*a9fa9459Szrj 		flags = -1;
4417*a9fa9459Szrj 		len = strlen (eq);
4418*a9fa9459Szrj 	      }
4419*a9fa9459Szrj 
4420*a9fa9459Szrj 	    if (len == 0)
4421*a9fa9459Szrj 	      fatal (_("bad format for %s"), "--rename-section");
4422*a9fa9459Szrj 
4423*a9fa9459Szrj 	    new_name = (char *) xmalloc (len + 1);
4424*a9fa9459Szrj 	    strncpy (new_name, eq, len);
4425*a9fa9459Szrj 	    new_name[len] = 0;
4426*a9fa9459Szrj 
4427*a9fa9459Szrj 	    add_section_rename (old_name, new_name, flags);
4428*a9fa9459Szrj 	  }
4429*a9fa9459Szrj 	  break;
4430*a9fa9459Szrj 
4431*a9fa9459Szrj 	case OPTION_SET_START:
4432*a9fa9459Szrj 	  set_start = parse_vma (optarg, "--set-start");
4433*a9fa9459Szrj 	  set_start_set = TRUE;
4434*a9fa9459Szrj 	  break;
4435*a9fa9459Szrj 
4436*a9fa9459Szrj 	case OPTION_SREC_LEN:
4437*a9fa9459Szrj 	  Chunk = parse_vma (optarg, "--srec-len");
4438*a9fa9459Szrj 	  break;
4439*a9fa9459Szrj 
4440*a9fa9459Szrj 	case OPTION_SREC_FORCES3:
4441*a9fa9459Szrj 	  S3Forced = TRUE;
4442*a9fa9459Szrj 	  break;
4443*a9fa9459Szrj 
4444*a9fa9459Szrj 	case OPTION_STRIP_SYMBOLS:
4445*a9fa9459Szrj 	  add_specific_symbols (optarg, strip_specific_htab);
4446*a9fa9459Szrj 	  break;
4447*a9fa9459Szrj 
4448*a9fa9459Szrj 	case OPTION_STRIP_UNNEEDED_SYMBOLS:
4449*a9fa9459Szrj 	  add_specific_symbols (optarg, strip_unneeded_htab);
4450*a9fa9459Szrj 	  break;
4451*a9fa9459Szrj 
4452*a9fa9459Szrj 	case OPTION_KEEP_SYMBOLS:
4453*a9fa9459Szrj 	  add_specific_symbols (optarg, keep_specific_htab);
4454*a9fa9459Szrj 	  break;
4455*a9fa9459Szrj 
4456*a9fa9459Szrj 	case OPTION_LOCALIZE_HIDDEN:
4457*a9fa9459Szrj 	  localize_hidden = TRUE;
4458*a9fa9459Szrj 	  break;
4459*a9fa9459Szrj 
4460*a9fa9459Szrj 	case OPTION_LOCALIZE_SYMBOLS:
4461*a9fa9459Szrj 	  add_specific_symbols (optarg, localize_specific_htab);
4462*a9fa9459Szrj 	  break;
4463*a9fa9459Szrj 
4464*a9fa9459Szrj 	case OPTION_LONG_SECTION_NAMES:
4465*a9fa9459Szrj 	  if (!strcmp ("enable", optarg))
4466*a9fa9459Szrj 	    long_section_names = ENABLE;
4467*a9fa9459Szrj 	  else if (!strcmp ("disable", optarg))
4468*a9fa9459Szrj 	    long_section_names = DISABLE;
4469*a9fa9459Szrj 	  else if (!strcmp ("keep", optarg))
4470*a9fa9459Szrj 	    long_section_names = KEEP;
4471*a9fa9459Szrj 	  else
4472*a9fa9459Szrj 	    fatal (_("unknown long section names option '%s'"), optarg);
4473*a9fa9459Szrj 	  break;
4474*a9fa9459Szrj 
4475*a9fa9459Szrj 	case OPTION_GLOBALIZE_SYMBOLS:
4476*a9fa9459Szrj 	  add_specific_symbols (optarg, globalize_specific_htab);
4477*a9fa9459Szrj 	  break;
4478*a9fa9459Szrj 
4479*a9fa9459Szrj 	case OPTION_KEEPGLOBAL_SYMBOLS:
4480*a9fa9459Szrj 	  add_specific_symbols (optarg, keepglobal_specific_htab);
4481*a9fa9459Szrj 	  break;
4482*a9fa9459Szrj 
4483*a9fa9459Szrj 	case OPTION_WEAKEN_SYMBOLS:
4484*a9fa9459Szrj 	  add_specific_symbols (optarg, weaken_specific_htab);
4485*a9fa9459Szrj 	  break;
4486*a9fa9459Szrj 
4487*a9fa9459Szrj 	case OPTION_ALT_MACH_CODE:
4488*a9fa9459Szrj 	  use_alt_mach_code = strtoul (optarg, NULL, 0);
4489*a9fa9459Szrj 	  if (use_alt_mach_code == 0)
4490*a9fa9459Szrj 	    fatal (_("unable to parse alternative machine code"));
4491*a9fa9459Szrj 	  break;
4492*a9fa9459Szrj 
4493*a9fa9459Szrj 	case OPTION_PREFIX_SYMBOLS:
4494*a9fa9459Szrj 	  prefix_symbols_string = optarg;
4495*a9fa9459Szrj 	  break;
4496*a9fa9459Szrj 
4497*a9fa9459Szrj 	case OPTION_PREFIX_SECTIONS:
4498*a9fa9459Szrj 	  prefix_sections_string = optarg;
4499*a9fa9459Szrj 	  break;
4500*a9fa9459Szrj 
4501*a9fa9459Szrj 	case OPTION_PREFIX_ALLOC_SECTIONS:
4502*a9fa9459Szrj 	  prefix_alloc_sections_string = optarg;
4503*a9fa9459Szrj 	  break;
4504*a9fa9459Szrj 
4505*a9fa9459Szrj 	case OPTION_READONLY_TEXT:
4506*a9fa9459Szrj 	  bfd_flags_to_set |= WP_TEXT;
4507*a9fa9459Szrj 	  bfd_flags_to_clear &= ~WP_TEXT;
4508*a9fa9459Szrj 	  break;
4509*a9fa9459Szrj 
4510*a9fa9459Szrj 	case OPTION_WRITABLE_TEXT:
4511*a9fa9459Szrj 	  bfd_flags_to_clear |= WP_TEXT;
4512*a9fa9459Szrj 	  bfd_flags_to_set &= ~WP_TEXT;
4513*a9fa9459Szrj 	  break;
4514*a9fa9459Szrj 
4515*a9fa9459Szrj 	case OPTION_PURE:
4516*a9fa9459Szrj 	  bfd_flags_to_set |= D_PAGED;
4517*a9fa9459Szrj 	  bfd_flags_to_clear &= ~D_PAGED;
4518*a9fa9459Szrj 	  break;
4519*a9fa9459Szrj 
4520*a9fa9459Szrj 	case OPTION_IMPURE:
4521*a9fa9459Szrj 	  bfd_flags_to_clear |= D_PAGED;
4522*a9fa9459Szrj 	  bfd_flags_to_set &= ~D_PAGED;
4523*a9fa9459Szrj 	  break;
4524*a9fa9459Szrj 
4525*a9fa9459Szrj 	case OPTION_EXTRACT_DWO:
4526*a9fa9459Szrj 	  strip_symbols = STRIP_NONDWO;
4527*a9fa9459Szrj 	  break;
4528*a9fa9459Szrj 
4529*a9fa9459Szrj 	case OPTION_EXTRACT_SYMBOL:
4530*a9fa9459Szrj 	  extract_symbol = TRUE;
4531*a9fa9459Szrj 	  break;
4532*a9fa9459Szrj 
4533*a9fa9459Szrj 	case OPTION_REVERSE_BYTES:
4534*a9fa9459Szrj 	  {
4535*a9fa9459Szrj 	    int prev = reverse_bytes;
4536*a9fa9459Szrj 
4537*a9fa9459Szrj 	    reverse_bytes = atoi (optarg);
4538*a9fa9459Szrj 	    if ((reverse_bytes <= 0) || ((reverse_bytes % 2) != 0))
4539*a9fa9459Szrj 	      fatal (_("number of bytes to reverse must be positive and even"));
4540*a9fa9459Szrj 
4541*a9fa9459Szrj 	    if (prev && prev != reverse_bytes)
4542*a9fa9459Szrj 	      non_fatal (_("Warning: ignoring previous --reverse-bytes value of %d"),
4543*a9fa9459Szrj 			 prev);
4544*a9fa9459Szrj 	    break;
4545*a9fa9459Szrj 	  }
4546*a9fa9459Szrj 
4547*a9fa9459Szrj 	case OPTION_FILE_ALIGNMENT:
4548*a9fa9459Szrj 	  pe_file_alignment = parse_vma (optarg, "--file-alignment");
4549*a9fa9459Szrj 	  break;
4550*a9fa9459Szrj 
4551*a9fa9459Szrj 	case OPTION_HEAP:
4552*a9fa9459Szrj 	  {
4553*a9fa9459Szrj 	    char *end;
4554*a9fa9459Szrj 	    pe_heap_reserve = strtoul (optarg, &end, 0);
4555*a9fa9459Szrj 	    if (end == optarg
4556*a9fa9459Szrj 		|| (*end != '.' && *end != '\0'))
4557*a9fa9459Szrj 	      non_fatal (_("%s: invalid reserve value for --heap"),
4558*a9fa9459Szrj 			 optarg);
4559*a9fa9459Szrj 	    else if (*end != '\0')
4560*a9fa9459Szrj 	      {
4561*a9fa9459Szrj 		pe_heap_commit = strtoul (end + 1, &end, 0);
4562*a9fa9459Szrj 		if (*end != '\0')
4563*a9fa9459Szrj 		  non_fatal (_("%s: invalid commit value for --heap"),
4564*a9fa9459Szrj 			     optarg);
4565*a9fa9459Szrj 	      }
4566*a9fa9459Szrj 	  }
4567*a9fa9459Szrj 	  break;
4568*a9fa9459Szrj 
4569*a9fa9459Szrj 	case OPTION_IMAGE_BASE:
4570*a9fa9459Szrj 	  pe_image_base = parse_vma (optarg, "--image-base");
4571*a9fa9459Szrj 	  break;
4572*a9fa9459Szrj 
4573*a9fa9459Szrj 	case OPTION_SECTION_ALIGNMENT:
4574*a9fa9459Szrj 	  pe_section_alignment = parse_vma (optarg,
4575*a9fa9459Szrj 					    "--section-alignment");
4576*a9fa9459Szrj 	  break;
4577*a9fa9459Szrj 
4578*a9fa9459Szrj 	case OPTION_SUBSYSTEM:
4579*a9fa9459Szrj 	  set_pe_subsystem (optarg);
4580*a9fa9459Szrj 	  break;
4581*a9fa9459Szrj 
4582*a9fa9459Szrj 	case OPTION_STACK:
4583*a9fa9459Szrj 	  {
4584*a9fa9459Szrj 	    char *end;
4585*a9fa9459Szrj 	    pe_stack_reserve = strtoul (optarg, &end, 0);
4586*a9fa9459Szrj 	    if (end == optarg
4587*a9fa9459Szrj 		|| (*end != '.' && *end != '\0'))
4588*a9fa9459Szrj 	      non_fatal (_("%s: invalid reserve value for --stack"),
4589*a9fa9459Szrj 			 optarg);
4590*a9fa9459Szrj 	    else if (*end != '\0')
4591*a9fa9459Szrj 	      {
4592*a9fa9459Szrj 		pe_stack_commit = strtoul (end + 1, &end, 0);
4593*a9fa9459Szrj 		if (*end != '\0')
4594*a9fa9459Szrj 		  non_fatal (_("%s: invalid commit value for --stack"),
4595*a9fa9459Szrj 			     optarg);
4596*a9fa9459Szrj 	      }
4597*a9fa9459Szrj 	  }
4598*a9fa9459Szrj 	  break;
4599*a9fa9459Szrj 
4600*a9fa9459Szrj 	case 0:
4601*a9fa9459Szrj 	  /* We've been given a long option.  */
4602*a9fa9459Szrj 	  break;
4603*a9fa9459Szrj 
4604*a9fa9459Szrj 	case 'H':
4605*a9fa9459Szrj 	case 'h':
4606*a9fa9459Szrj 	  copy_usage (stdout, 0);
4607*a9fa9459Szrj 
4608*a9fa9459Szrj 	default:
4609*a9fa9459Szrj 	  copy_usage (stderr, 1);
4610*a9fa9459Szrj 	}
4611*a9fa9459Szrj     }
4612*a9fa9459Szrj 
4613*a9fa9459Szrj   if (formats_info)
4614*a9fa9459Szrj     {
4615*a9fa9459Szrj       display_info ();
4616*a9fa9459Szrj       return 0;
4617*a9fa9459Szrj     }
4618*a9fa9459Szrj 
4619*a9fa9459Szrj   if (show_version)
4620*a9fa9459Szrj     print_version ("objcopy");
4621*a9fa9459Szrj 
4622*a9fa9459Szrj   if (interleave && copy_byte == -1)
4623*a9fa9459Szrj     fatal (_("interleave start byte must be set with --byte"));
4624*a9fa9459Szrj 
4625*a9fa9459Szrj   if (copy_byte >= interleave)
4626*a9fa9459Szrj     fatal (_("byte number must be less than interleave"));
4627*a9fa9459Szrj 
4628*a9fa9459Szrj   if (copy_width > interleave - copy_byte)
4629*a9fa9459Szrj     fatal (_("interleave width must be less than or equal to interleave - byte`"));
4630*a9fa9459Szrj 
4631*a9fa9459Szrj   if (optind == argc || optind + 2 < argc)
4632*a9fa9459Szrj     copy_usage (stderr, 1);
4633*a9fa9459Szrj 
4634*a9fa9459Szrj   input_filename = argv[optind];
4635*a9fa9459Szrj   if (optind + 1 < argc)
4636*a9fa9459Szrj     output_filename = argv[optind + 1];
4637*a9fa9459Szrj 
4638*a9fa9459Szrj   default_deterministic ();
4639*a9fa9459Szrj 
4640*a9fa9459Szrj   /* Default is to strip no symbols.  */
4641*a9fa9459Szrj   if (strip_symbols == STRIP_UNDEF && discard_locals == LOCALS_UNDEF)
4642*a9fa9459Szrj     strip_symbols = STRIP_NONE;
4643*a9fa9459Szrj 
4644*a9fa9459Szrj   if (output_target == NULL)
4645*a9fa9459Szrj     output_target = input_target;
4646*a9fa9459Szrj 
4647*a9fa9459Szrj   /* Convert input EFI target to PEI target.  */
4648*a9fa9459Szrj   if (input_target != NULL
4649*a9fa9459Szrj       && strncmp (input_target, "efi-", 4) == 0)
4650*a9fa9459Szrj     {
4651*a9fa9459Szrj       char *efi;
4652*a9fa9459Szrj 
4653*a9fa9459Szrj       efi = xstrdup (output_target + 4);
4654*a9fa9459Szrj       if (strncmp (efi, "bsdrv-", 6) == 0
4655*a9fa9459Szrj 	  || strncmp (efi, "rtdrv-", 6) == 0)
4656*a9fa9459Szrj 	efi += 2;
4657*a9fa9459Szrj       else if (strncmp (efi, "app-", 4) != 0)
4658*a9fa9459Szrj 	fatal (_("unknown input EFI target: %s"), input_target);
4659*a9fa9459Szrj 
4660*a9fa9459Szrj       input_target = efi;
4661*a9fa9459Szrj       convert_efi_target (efi);
4662*a9fa9459Szrj     }
4663*a9fa9459Szrj 
4664*a9fa9459Szrj   /* Convert output EFI target to PEI target.  */
4665*a9fa9459Szrj   if (output_target != NULL
4666*a9fa9459Szrj       && strncmp (output_target, "efi-", 4) == 0)
4667*a9fa9459Szrj     {
4668*a9fa9459Szrj       char *efi;
4669*a9fa9459Szrj 
4670*a9fa9459Szrj       efi = xstrdup (output_target + 4);
4671*a9fa9459Szrj       if (strncmp (efi, "app-", 4) == 0)
4672*a9fa9459Szrj 	{
4673*a9fa9459Szrj 	  if (pe_subsystem == -1)
4674*a9fa9459Szrj 	    pe_subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
4675*a9fa9459Szrj 	}
4676*a9fa9459Szrj       else if (strncmp (efi, "bsdrv-", 6) == 0)
4677*a9fa9459Szrj 	{
4678*a9fa9459Szrj 	  if (pe_subsystem == -1)
4679*a9fa9459Szrj 	    pe_subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
4680*a9fa9459Szrj 	  efi += 2;
4681*a9fa9459Szrj 	}
4682*a9fa9459Szrj       else if (strncmp (efi, "rtdrv-", 6) == 0)
4683*a9fa9459Szrj 	{
4684*a9fa9459Szrj 	  if (pe_subsystem == -1)
4685*a9fa9459Szrj 	    pe_subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
4686*a9fa9459Szrj 	  efi += 2;
4687*a9fa9459Szrj 	}
4688*a9fa9459Szrj       else
4689*a9fa9459Szrj 	fatal (_("unknown output EFI target: %s"), output_target);
4690*a9fa9459Szrj 
4691*a9fa9459Szrj       if (pe_file_alignment == (bfd_vma) -1)
4692*a9fa9459Szrj 	pe_file_alignment = PE_DEF_FILE_ALIGNMENT;
4693*a9fa9459Szrj       if (pe_section_alignment == (bfd_vma) -1)
4694*a9fa9459Szrj 	pe_section_alignment = PE_DEF_SECTION_ALIGNMENT;
4695*a9fa9459Szrj 
4696*a9fa9459Szrj       output_target = efi;
4697*a9fa9459Szrj       convert_efi_target (efi);
4698*a9fa9459Szrj     }
4699*a9fa9459Szrj 
4700*a9fa9459Szrj   if (preserve_dates)
4701*a9fa9459Szrj     if (stat (input_filename, & statbuf) < 0)
4702*a9fa9459Szrj       fatal (_("warning: could not locate '%s'.  System error message: %s"),
4703*a9fa9459Szrj 	     input_filename, strerror (errno));
4704*a9fa9459Szrj 
4705*a9fa9459Szrj   /* If there is no destination file, or the source and destination files
4706*a9fa9459Szrj      are the same, then create a temp and rename the result into the input.  */
4707*a9fa9459Szrj   if (output_filename == NULL
4708*a9fa9459Szrj       || filename_cmp (input_filename, output_filename) == 0)
4709*a9fa9459Szrj     tmpname = make_tempname (input_filename);
4710*a9fa9459Szrj   else
4711*a9fa9459Szrj     tmpname = output_filename;
4712*a9fa9459Szrj 
4713*a9fa9459Szrj   if (tmpname == NULL)
4714*a9fa9459Szrj     fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
4715*a9fa9459Szrj 	   input_filename, strerror (errno));
4716*a9fa9459Szrj 
4717*a9fa9459Szrj   copy_file (input_filename, tmpname, input_target, output_target, input_arch);
4718*a9fa9459Szrj   if (status == 0)
4719*a9fa9459Szrj     {
4720*a9fa9459Szrj       if (preserve_dates)
4721*a9fa9459Szrj 	set_times (tmpname, &statbuf);
4722*a9fa9459Szrj       if (tmpname != output_filename)
4723*a9fa9459Szrj 	status = (smart_rename (tmpname, input_filename,
4724*a9fa9459Szrj 				preserve_dates) != 0);
4725*a9fa9459Szrj     }
4726*a9fa9459Szrj   else
4727*a9fa9459Szrj     unlink_if_ordinary (tmpname);
4728*a9fa9459Szrj 
4729*a9fa9459Szrj   if (change_warn)
4730*a9fa9459Szrj     {
4731*a9fa9459Szrj       struct section_list *p;
4732*a9fa9459Szrj 
4733*a9fa9459Szrj       for (p = change_sections; p != NULL; p = p->next)
4734*a9fa9459Szrj 	{
4735*a9fa9459Szrj 	  if (! p->used)
4736*a9fa9459Szrj 	    {
4737*a9fa9459Szrj 	      if (p->context & (SECTION_CONTEXT_SET_VMA | SECTION_CONTEXT_ALTER_VMA))
4738*a9fa9459Szrj 		{
4739*a9fa9459Szrj 		  char buff [20];
4740*a9fa9459Szrj 
4741*a9fa9459Szrj 		  sprintf_vma (buff, p->vma_val);
4742*a9fa9459Szrj 
4743*a9fa9459Szrj 		  /* xgettext:c-format */
4744*a9fa9459Szrj 		  non_fatal (_("%s %s%c0x%s never used"),
4745*a9fa9459Szrj 			     "--change-section-vma",
4746*a9fa9459Szrj 			     p->pattern,
4747*a9fa9459Szrj 			     p->context & SECTION_CONTEXT_SET_VMA ? '=' : '+',
4748*a9fa9459Szrj 			     buff);
4749*a9fa9459Szrj 		}
4750*a9fa9459Szrj 
4751*a9fa9459Szrj 	      if (p->context & (SECTION_CONTEXT_SET_LMA | SECTION_CONTEXT_ALTER_LMA))
4752*a9fa9459Szrj 		{
4753*a9fa9459Szrj 		  char buff [20];
4754*a9fa9459Szrj 
4755*a9fa9459Szrj 		  sprintf_vma (buff, p->lma_val);
4756*a9fa9459Szrj 
4757*a9fa9459Szrj 		  /* xgettext:c-format */
4758*a9fa9459Szrj 		  non_fatal (_("%s %s%c0x%s never used"),
4759*a9fa9459Szrj 			     "--change-section-lma",
4760*a9fa9459Szrj 			     p->pattern,
4761*a9fa9459Szrj 			     p->context & SECTION_CONTEXT_SET_LMA ? '=' : '+',
4762*a9fa9459Szrj 			     buff);
4763*a9fa9459Szrj 		}
4764*a9fa9459Szrj 	    }
4765*a9fa9459Szrj 	}
4766*a9fa9459Szrj     }
4767*a9fa9459Szrj 
4768*a9fa9459Szrj   return 0;
4769*a9fa9459Szrj }
4770*a9fa9459Szrj 
4771*a9fa9459Szrj int
main(int argc,char * argv[])4772*a9fa9459Szrj main (int argc, char *argv[])
4773*a9fa9459Szrj {
4774*a9fa9459Szrj #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
4775*a9fa9459Szrj   setlocale (LC_MESSAGES, "");
4776*a9fa9459Szrj #endif
4777*a9fa9459Szrj #if defined (HAVE_SETLOCALE)
4778*a9fa9459Szrj   setlocale (LC_CTYPE, "");
4779*a9fa9459Szrj #endif
4780*a9fa9459Szrj   bindtextdomain (PACKAGE, LOCALEDIR);
4781*a9fa9459Szrj   textdomain (PACKAGE);
4782*a9fa9459Szrj 
4783*a9fa9459Szrj   program_name = argv[0];
4784*a9fa9459Szrj   xmalloc_set_program_name (program_name);
4785*a9fa9459Szrj 
4786*a9fa9459Szrj   START_PROGRESS (program_name, 0);
4787*a9fa9459Szrj 
4788*a9fa9459Szrj   expandargv (&argc, &argv);
4789*a9fa9459Szrj 
4790*a9fa9459Szrj   strip_symbols = STRIP_UNDEF;
4791*a9fa9459Szrj   discard_locals = LOCALS_UNDEF;
4792*a9fa9459Szrj 
4793*a9fa9459Szrj   bfd_init ();
4794*a9fa9459Szrj   set_default_bfd_target ();
4795*a9fa9459Szrj 
4796*a9fa9459Szrj   if (is_strip < 0)
4797*a9fa9459Szrj     {
4798*a9fa9459Szrj       int i = strlen (program_name);
4799*a9fa9459Szrj #ifdef HAVE_DOS_BASED_FILE_SYSTEM
4800*a9fa9459Szrj       /* Drop the .exe suffix, if any.  */
4801*a9fa9459Szrj       if (i > 4 && FILENAME_CMP (program_name + i - 4, ".exe") == 0)
4802*a9fa9459Szrj 	{
4803*a9fa9459Szrj 	  i -= 4;
4804*a9fa9459Szrj 	  program_name[i] = '\0';
4805*a9fa9459Szrj 	}
4806*a9fa9459Szrj #endif
4807*a9fa9459Szrj       is_strip = (i >= 5 && FILENAME_CMP (program_name + i - 5, "strip") == 0);
4808*a9fa9459Szrj     }
4809*a9fa9459Szrj 
4810*a9fa9459Szrj   create_symbol_htabs ();
4811*a9fa9459Szrj 
4812*a9fa9459Szrj   if (argv != NULL)
4813*a9fa9459Szrj     bfd_set_error_program_name (argv[0]);
4814*a9fa9459Szrj 
4815*a9fa9459Szrj   if (is_strip)
4816*a9fa9459Szrj     strip_main (argc, argv);
4817*a9fa9459Szrj   else
4818*a9fa9459Szrj     copy_main (argc, argv);
4819*a9fa9459Szrj 
4820*a9fa9459Szrj   END_PROGRESS (program_name);
4821*a9fa9459Szrj 
4822*a9fa9459Szrj   return status;
4823*a9fa9459Szrj }
4824