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, ©, 0);
3782*a9fa9459Szrj if (*copy == '.')
3783*a9fa9459Szrj pe_minor_subsystem_version = strtoul (copy + 1, ©, 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, ©, 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