• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修訂2b35fb28f397a26c0da03f7579116d28af2af824 (tree)
時間2015-10-21 23:16:35
作者Ronald Hoogenbllon <rhoogenboom@irde...>
CommiterNick Clifton

Log Message

Add ability for objcopy to insert new symbols into a binary.

PR binutils/19104
binutils * objcopy.c (command_line_switch): Add OPTION_ADD_SYMBOL.
(copy_options): Add add-symbol.
(copy_usage): Likewise.
(parse_symflags): New function.
(need_sym_before): New function.
(create_new_symbol): New function.
(filter_symbols): Add code to insert new symbols.
(copy_main): Process OPTION_ADD_SYMBOL.
* doc/binutils.texi: Document new feature.
* NEWS: Add note about the new feature.

tests * binutils-all/add-symbol.d: New test.
* binutils-all/objcopy.exp: Run the new test.

Change Summary

差異

--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,17 @@
1+2015-10-21 Ronald Hoogenbllon <rhoogenboom@irdeto.com>
2+
3+ PR binutils/19104
4+ * objcopy.c (command_line_switch): Add OPTION_ADD_SYMBOL.
5+ (copy_options): Add add-symbol.
6+ (copy_usage): Likewise.
7+ (parse_symflags): New function.
8+ (need_sym_before): New function.
9+ (create_new_symbol): New function.
10+ (filter_symbols): Add code to insert new symbols.
11+ (copy_main): Process OPTION_ADD_SYMBOL.
12+ * doc/binutils.texi: Document new feature.
13+ * NEWS: Add note about the new feature.
14+
115 2015-10-18 Paul Pluzhnikov <ppluzhnikov@google.com>
216
317 PR binutils/19147
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,8 @@
11 -*- text -*-
22
3+* Add option to objcopy to insert new symbols into a file:
4+ --add-symbol <name>=[<section>:]<value>[,<flags>]
5+
36 * Add support for the ARC EM/HS, and ARC600/700 architectures.
47
58 * Extend objcopy --compress-debug-sections option to support
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1106,6 +1106,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
11061106 [@option{--localize-symbols=}@var{filename}]
11071107 [@option{--globalize-symbols=}@var{filename}]
11081108 [@option{--weaken-symbols=}@var{filename}]
1109+ [@option{--add-symbol} @var{name}=[@var{section}:]@var{value}[,@var{flags}]
11091110 [@option{--alt-machine-code=}@var{index}]
11101111 [@option{--prefix-symbols=}@var{string}]
11111112 [@option{--prefix-sections=}@var{string}]
@@ -1504,6 +1505,18 @@ command line. In this case, pass the original section name to
15041505 @option{--update-section}, and the original and new section names to
15051506 @option{--rename-section}.
15061507
1508+@item --add-symbol @var{name}=[@var{section}:]@var{value}[,@var{flags}]
1509+Add a new symbol named @var{name} while copying the file. This option may be
1510+specified multiple times. If the @var{section} is given, the symbol will be
1511+associated with and relative to that section, otherwise it will be an ABS
1512+symbol. Specifying an undefined section will result in a fatal error. There
1513+is no check for the value, it will be taken as specified. Symbol flags can
1514+be specified and not all flags will be meaningful for all object file
1515+formats. By default, the symbol will be global. The special flag
1516+'before=@var{othersym}' will insert the new symbol in front of the specified
1517+@var{othersym}, otherwise the symbol(s) will be added at the end of the
1518+symbol table in the order they appear.
1519+
15071520 @item --rename-section @var{oldname}=@var{newname}[,@var{flags}]
15081521 Rename a section from @var{oldname} to @var{newname}, optionally
15091522 changing the section's flags to @var{flags} in the process. This has
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -50,7 +50,7 @@ static short pe_minor_subsystem_version = -1;
5050
5151 struct is_specified_symbol_predicate_data
5252 {
53- const char *name;
53+ const char * name;
5454 bfd_boolean found;
5555 };
5656
@@ -62,6 +62,16 @@ struct redefine_node
6262 struct redefine_node *next;
6363 };
6464
65+struct addsym_node
66+{
67+ struct addsym_node *next;
68+ char * symdef;
69+ long symval;
70+ flagword flags;
71+ char * section;
72+ char * othersym;
73+};
74+
6575 typedef struct section_rename
6676 {
6777 const char * old_name;
@@ -88,26 +98,26 @@ static int deterministic = -1; /* Enable deterministic archives. */
8898 static int status = 0; /* Exit status. */
8999
90100 enum strip_action
91- {
92- STRIP_UNDEF,
93- STRIP_NONE, /* Don't strip. */
94- STRIP_DEBUG, /* Strip all debugger symbols. */
95- STRIP_UNNEEDED, /* Strip unnecessary symbols. */
96- STRIP_NONDEBUG, /* Strip everything but debug info. */
97- STRIP_DWO, /* Strip all DWO info. */
98- STRIP_NONDWO, /* Strip everything but DWO info. */
99- STRIP_ALL /* Strip all symbols. */
100- };
101+{
102+ STRIP_UNDEF,
103+ STRIP_NONE, /* Don't strip. */
104+ STRIP_DEBUG, /* Strip all debugger symbols. */
105+ STRIP_UNNEEDED, /* Strip unnecessary symbols. */
106+ STRIP_NONDEBUG, /* Strip everything but debug info. */
107+ STRIP_DWO, /* Strip all DWO info. */
108+ STRIP_NONDWO, /* Strip everything but DWO info. */
109+ STRIP_ALL /* Strip all symbols. */
110+};
101111
102112 /* Which symbols to remove. */
103113 static enum strip_action strip_symbols = STRIP_UNDEF;
104114
105115 enum locals_action
106- {
107- LOCALS_UNDEF,
108- LOCALS_START_L, /* Discard locals starting with L. */
109- LOCALS_ALL /* Discard all locals. */
110- };
116+{
117+ LOCALS_UNDEF,
118+ LOCALS_START_L, /* Discard locals starting with L. */
119+ LOCALS_ALL /* Discard all locals. */
120+};
111121
112122 /* Which local symbols to remove. Overrides STRIP_ALL. */
113123 static enum locals_action discard_locals;
@@ -232,6 +242,8 @@ static htab_t globalize_specific_htab = NULL;
232242 static htab_t keepglobal_specific_htab = NULL;
233243 static htab_t weaken_specific_htab = NULL;
234244 static struct redefine_node *redefine_sym_list = NULL;
245+static struct addsym_node *add_sym_list = NULL, **add_sym_tail = &add_sym_list;
246+static int add_symbols = 0;
235247
236248 /* If this is TRUE, we weaken global symbols (set BSF_WEAK). */
237249 static bfd_boolean weaken = FALSE;
@@ -254,11 +266,11 @@ static int reverse_bytes = 0;
254266 /* For Coff objects, we may want to allow or disallow long section names,
255267 or preserve them where found in the inputs. Debug info relies on them. */
256268 enum long_section_name_handling
257- {
258- DISABLE,
259- ENABLE,
260- KEEP
261- };
269+{
270+ DISABLE,
271+ ENABLE,
272+ KEEP
273+};
262274
263275 /* The default long section handling mode is to preserve them.
264276 This is also the only behaviour for 'strip'. */
@@ -266,68 +278,69 @@ static enum long_section_name_handling long_section_names = KEEP;
266278
267279 /* 150 isn't special; it's just an arbitrary non-ASCII char value. */
268280 enum command_line_switch
269- {
270- OPTION_ADD_SECTION=150,
271- OPTION_UPDATE_SECTION,
272- OPTION_DUMP_SECTION,
273- OPTION_CHANGE_ADDRESSES,
274- OPTION_CHANGE_LEADING_CHAR,
275- OPTION_CHANGE_START,
276- OPTION_CHANGE_SECTION_ADDRESS,
277- OPTION_CHANGE_SECTION_LMA,
278- OPTION_CHANGE_SECTION_VMA,
279- OPTION_CHANGE_WARNINGS,
280- OPTION_COMPRESS_DEBUG_SECTIONS,
281- OPTION_DEBUGGING,
282- OPTION_DECOMPRESS_DEBUG_SECTIONS,
283- OPTION_GAP_FILL,
284- OPTION_NO_CHANGE_WARNINGS,
285- OPTION_PAD_TO,
286- OPTION_REMOVE_LEADING_CHAR,
287- OPTION_SET_SECTION_FLAGS,
288- OPTION_SET_START,
289- OPTION_STRIP_UNNEEDED,
290- OPTION_WEAKEN,
291- OPTION_REDEFINE_SYM,
292- OPTION_REDEFINE_SYMS,
293- OPTION_SREC_LEN,
294- OPTION_SREC_FORCES3,
295- OPTION_STRIP_SYMBOLS,
296- OPTION_STRIP_UNNEEDED_SYMBOL,
297- OPTION_STRIP_UNNEEDED_SYMBOLS,
298- OPTION_KEEP_SYMBOLS,
299- OPTION_LOCALIZE_HIDDEN,
300- OPTION_LOCALIZE_SYMBOLS,
301- OPTION_LONG_SECTION_NAMES,
302- OPTION_GLOBALIZE_SYMBOL,
303- OPTION_GLOBALIZE_SYMBOLS,
304- OPTION_KEEPGLOBAL_SYMBOLS,
305- OPTION_WEAKEN_SYMBOLS,
306- OPTION_RENAME_SECTION,
307- OPTION_ALT_MACH_CODE,
308- OPTION_PREFIX_SYMBOLS,
309- OPTION_PREFIX_SECTIONS,
310- OPTION_PREFIX_ALLOC_SECTIONS,
311- OPTION_FORMATS_INFO,
312- OPTION_ADD_GNU_DEBUGLINK,
313- OPTION_ONLY_KEEP_DEBUG,
314- OPTION_KEEP_FILE_SYMBOLS,
315- OPTION_READONLY_TEXT,
316- OPTION_WRITABLE_TEXT,
317- OPTION_PURE,
318- OPTION_IMPURE,
319- OPTION_EXTRACT_SYMBOL,
320- OPTION_REVERSE_BYTES,
321- OPTION_FILE_ALIGNMENT,
322- OPTION_HEAP,
323- OPTION_IMAGE_BASE,
324- OPTION_SECTION_ALIGNMENT,
325- OPTION_STACK,
326- OPTION_INTERLEAVE_WIDTH,
327- OPTION_SUBSYSTEM,
328- OPTION_EXTRACT_DWO,
329- OPTION_STRIP_DWO
330- };
281+{
282+ OPTION_ADD_SECTION=150,
283+ OPTION_ADD_GNU_DEBUGLINK,
284+ OPTION_ADD_SYMBOL,
285+ OPTION_ALT_MACH_CODE,
286+ OPTION_CHANGE_ADDRESSES,
287+ OPTION_CHANGE_LEADING_CHAR,
288+ OPTION_CHANGE_SECTION_ADDRESS,
289+ OPTION_CHANGE_SECTION_LMA,
290+ OPTION_CHANGE_SECTION_VMA,
291+ OPTION_CHANGE_START,
292+ OPTION_CHANGE_WARNINGS,
293+ OPTION_COMPRESS_DEBUG_SECTIONS,
294+ OPTION_DEBUGGING,
295+ OPTION_DECOMPRESS_DEBUG_SECTIONS,
296+ OPTION_DUMP_SECTION,
297+ OPTION_EXTRACT_DWO,
298+ OPTION_EXTRACT_SYMBOL,
299+ OPTION_FILE_ALIGNMENT,
300+ OPTION_FORMATS_INFO,
301+ OPTION_GAP_FILL,
302+ OPTION_GLOBALIZE_SYMBOL,
303+ OPTION_GLOBALIZE_SYMBOLS,
304+ OPTION_HEAP,
305+ OPTION_IMAGE_BASE,
306+ OPTION_IMPURE,
307+ OPTION_INTERLEAVE_WIDTH,
308+ OPTION_KEEPGLOBAL_SYMBOLS,
309+ OPTION_KEEP_FILE_SYMBOLS,
310+ OPTION_KEEP_SYMBOLS,
311+ OPTION_LOCALIZE_HIDDEN,
312+ OPTION_LOCALIZE_SYMBOLS,
313+ OPTION_LONG_SECTION_NAMES,
314+ OPTION_NO_CHANGE_WARNINGS,
315+ OPTION_ONLY_KEEP_DEBUG,
316+ OPTION_PAD_TO,
317+ OPTION_PREFIX_ALLOC_SECTIONS,
318+ OPTION_PREFIX_SECTIONS,
319+ OPTION_PREFIX_SYMBOLS,
320+ OPTION_PURE,
321+ OPTION_READONLY_TEXT,
322+ OPTION_REDEFINE_SYM,
323+ OPTION_REDEFINE_SYMS,
324+ OPTION_REMOVE_LEADING_CHAR,
325+ OPTION_RENAME_SECTION,
326+ OPTION_REVERSE_BYTES,
327+ OPTION_SECTION_ALIGNMENT,
328+ OPTION_SET_SECTION_FLAGS,
329+ OPTION_SET_START,
330+ OPTION_SREC_FORCES3,
331+ OPTION_SREC_LEN,
332+ OPTION_STACK,
333+ OPTION_STRIP_DWO,
334+ OPTION_STRIP_SYMBOLS,
335+ OPTION_STRIP_UNNEEDED,
336+ OPTION_STRIP_UNNEEDED_SYMBOL,
337+ OPTION_STRIP_UNNEEDED_SYMBOLS,
338+ OPTION_SUBSYSTEM,
339+ OPTION_UPDATE_SECTION,
340+ OPTION_WEAKEN,
341+ OPTION_WEAKEN_SYMBOLS,
342+ OPTION_WRITABLE_TEXT
343+};
331344
332345 /* Options to handle if running as "strip". */
333346
@@ -345,16 +358,16 @@ static struct option strip_options[] =
345358 {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
346359 {"keep-symbol", required_argument, 0, 'K'},
347360 {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
361+ {"output-file", required_argument, 0, 'o'},
348362 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
349363 {"output-target", required_argument, 0, 'O'},
350- {"output-file", required_argument, 0, 'o'},
351364 {"preserve-dates", no_argument, 0, 'p'},
352365 {"remove-section", required_argument, 0, 'R'},
353366 {"strip-all", no_argument, 0, 's'},
354367 {"strip-debug", no_argument, 0, 'S'},
355368 {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
356- {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
357369 {"strip-symbol", required_argument, 0, 'N'},
370+ {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
358371 {"target", required_argument, 0, 'F'},
359372 {"verbose", no_argument, 0, 'v'},
360373 {"version", no_argument, 0, 'V'},
@@ -368,10 +381,10 @@ static struct option copy_options[] =
368381 {
369382 {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
370383 {"add-section", required_argument, 0, OPTION_ADD_SECTION},
371- {"update-section", required_argument, 0, OPTION_UPDATE_SECTION},
384+ {"add-symbol", required_argument, 0, OPTION_ADD_SYMBOL},
385+ {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
372386 {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
373387 {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
374- {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
375388 {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
376389 {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
377390 {"binary-architecture", required_argument, 0, 'B'},
@@ -393,11 +406,14 @@ static struct option copy_options[] =
393406 {"enable-deterministic-archives", no_argument, 0, 'D'},
394407 {"extract-dwo", no_argument, 0, OPTION_EXTRACT_DWO},
395408 {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
409+ {"file-alignment", required_argument, 0, OPTION_FILE_ALIGNMENT},
396410 {"format", required_argument, 0, 'F'}, /* Obsolete */
397411 {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
398412 {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
399413 {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
414+ {"heap", required_argument, 0, OPTION_HEAP},
400415 {"help", no_argument, 0, 'h'},
416+ {"image-base", required_argument, 0 , OPTION_IMAGE_BASE},
401417 {"impure", no_argument, 0, OPTION_IMPURE},
402418 {"info", no_argument, 0, OPTION_FORMATS_INFO},
403419 {"input-format", required_argument, 0, 'I'}, /* Obsolete */
@@ -420,9 +436,9 @@ static struct option copy_options[] =
420436 {"output-format", required_argument, 0, 'O'}, /* Obsolete */
421437 {"output-target", required_argument, 0, 'O'},
422438 {"pad-to", required_argument, 0, OPTION_PAD_TO},
423- {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
424- {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
425439 {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
440+ {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
441+ {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
426442 {"preserve-dates", no_argument, 0, 'p'},
427443 {"pure", no_argument, 0, OPTION_PURE},
428444 {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
@@ -432,19 +448,23 @@ static struct option copy_options[] =
432448 {"remove-section", required_argument, 0, 'R'},
433449 {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
434450 {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
451+ {"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
435452 {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
436453 {"set-start", required_argument, 0, OPTION_SET_START},
437- {"srec-len", required_argument, 0, OPTION_SREC_LEN},
438454 {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
455+ {"srec-len", required_argument, 0, OPTION_SREC_LEN},
456+ {"stack", required_argument, 0, OPTION_STACK},
439457 {"strip-all", no_argument, 0, 'S'},
440458 {"strip-debug", no_argument, 0, 'g'},
441459 {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
460+ {"strip-symbol", required_argument, 0, 'N'},
461+ {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
442462 {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
443463 {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
444464 {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
445- {"strip-symbol", required_argument, 0, 'N'},
446- {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
465+ {"subsystem", required_argument, 0, OPTION_SUBSYSTEM},
447466 {"target", required_argument, 0, 'F'},
467+ {"update-section", required_argument, 0, OPTION_UPDATE_SECTION},
448468 {"verbose", no_argument, 0, 'v'},
449469 {"version", no_argument, 0, 'V'},
450470 {"weaken", no_argument, 0, OPTION_WEAKEN},
@@ -452,12 +472,6 @@ static struct option copy_options[] =
452472 {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
453473 {"wildcard", no_argument, 0, 'w'},
454474 {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
455- {"file-alignment", required_argument, 0, OPTION_FILE_ALIGNMENT},
456- {"heap", required_argument, 0, OPTION_HEAP},
457- {"image-base", required_argument, 0 , OPTION_IMAGE_BASE},
458- {"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
459- {"stack", required_argument, 0, OPTION_STACK},
460- {"subsystem", required_argument, 0, OPTION_SUBSYSTEM},
461475 {0, no_argument, 0, 0}
462476 };
463477
@@ -585,6 +599,7 @@ copy_usage (FILE *stream, int exit_status)
585599 --globalize-symbols <file> --globalize-symbol for all in <file>\n\
586600 --keep-global-symbols <file> -G for all symbols listed in <file>\n\
587601 --weaken-symbols <file> -W for all symbols listed in <file>\n\
602+ --add-symbol <name>=[<section>:]<value>[,<flags>] Add a symbol\n\
588603 --alt-machine-code <index> Use the target's <index>'th alternative machine\n\
589604 --writable-text Mark the output text as writable\n\
590605 --readonly-text Make the output text write protected\n\
@@ -727,6 +742,78 @@ parse_flags (const char *s)
727742 return ret;
728743 }
729744
745+/* Parse symbol flags into a flagword, with a fatal error if the
746+ string can't be parsed. */
747+
748+static flagword
749+parse_symflags (const char *s, char **other)
750+{
751+ flagword ret;
752+ const char *snext;
753+ int len;
754+
755+ ret = BSF_NO_FLAGS;
756+
757+ do
758+ {
759+ snext = strchr (s, ',');
760+ if (snext == NULL)
761+ len = strlen (s);
762+ else
763+ {
764+ len = snext - s;
765+ ++snext;
766+ }
767+
768+#define PARSE_FLAG(fname,fval) \
769+ else if (len == (int) sizeof fname - 1 && strncasecmp (fname, s, len) == 0) \
770+ ret |= fval
771+
772+#define PARSE_OTHER(fname,fval) \
773+ else if (len >= (int) sizeof fname && strncasecmp (fname, s, sizeof fname - 1) == 0) \
774+ fval = strndup (s + sizeof fname - 1, len - sizeof fname + 1)
775+
776+ if (0) ;
777+ PARSE_FLAG ("local", BSF_LOCAL);
778+ PARSE_FLAG ("global", BSF_GLOBAL);
779+ PARSE_FLAG ("export", BSF_EXPORT);
780+ PARSE_FLAG ("debug", BSF_DEBUGGING);
781+ PARSE_FLAG ("function", BSF_FUNCTION);
782+ PARSE_FLAG ("weak", BSF_WEAK);
783+ PARSE_FLAG ("section", BSF_SECTION_SYM);
784+ PARSE_FLAG ("constructor", BSF_CONSTRUCTOR);
785+ PARSE_FLAG ("warning", BSF_WARNING);
786+ PARSE_FLAG ("indirect", BSF_INDIRECT);
787+ PARSE_FLAG ("file", BSF_FILE);
788+ PARSE_FLAG ("object", BSF_OBJECT);
789+ PARSE_FLAG ("synthetic", BSF_SYNTHETIC);
790+ PARSE_FLAG ("indirect-function", BSF_GNU_INDIRECT_FUNCTION | BSF_FUNCTION);
791+ PARSE_FLAG ("unique-object", BSF_GNU_UNIQUE | BSF_OBJECT);
792+ PARSE_OTHER ("before=", *other);
793+
794+#undef PARSE_FLAG
795+#undef PARSE_OTHER
796+ else
797+ {
798+ char *copy;
799+
800+ copy = (char *) xmalloc (len + 1);
801+ strncpy (copy, s, len);
802+ copy[len] = '\0';
803+ non_fatal (_("unrecognized symbol flag `%s'"), copy);
804+ fatal (_("supported flags: %s"),
805+ "local, global, export, debug, function, weak, section, "
806+ "constructor, warning, indirect, file, object, synthetic, "
807+ "indirect-function, unique-object, before=<othersym>");
808+ }
809+
810+ s = snext;
811+ }
812+ while (s != NULL);
813+
814+ return ret;
815+}
816+
730817 /* Find and optionally add an entry in the change_sections list.
731818
732819 We need to be careful in how we match section names because of the support
@@ -1213,6 +1300,49 @@ is_hidden_symbol (asymbol *sym)
12131300 return FALSE;
12141301 }
12151302
1303+static bfd_boolean
1304+need_sym_before (struct addsym_node **node, const char *sym)
1305+{
1306+ int count;
1307+ struct addsym_node *ptr = add_sym_list;
1308+
1309+ /* 'othersym' symbols are at the front of the list. */
1310+ for (count = 0; count < add_symbols; count++)
1311+ {
1312+ if (!ptr->othersym)
1313+ break;
1314+ else if (strcmp (ptr->othersym, sym) == 0)
1315+ {
1316+ free (ptr->othersym);
1317+ ptr->othersym = ""; /* Empty name is hopefully never a valid symbol name. */
1318+ *node = ptr;
1319+ return TRUE;
1320+ }
1321+ ptr = ptr->next;
1322+ }
1323+ return FALSE;
1324+}
1325+
1326+static asymbol *
1327+create_new_symbol (struct addsym_node *ptr, bfd *obfd)
1328+{
1329+ asymbol *sym = bfd_make_empty_symbol(obfd);
1330+
1331+ bfd_asymbol_name(sym) = ptr->symdef;
1332+ sym->value = ptr->symval;
1333+ sym->flags = ptr->flags;
1334+ if (ptr->section)
1335+ {
1336+ asection *sec = bfd_get_section_by_name (obfd, ptr->section);
1337+ if (!sec)
1338+ fatal (_("Section %s not found"), ptr->section);
1339+ sym->section = sec;
1340+ }
1341+ else
1342+ sym->section = bfd_abs_section_ptr;
1343+ return sym;
1344+}
1345+
12161346 /* Choose which symbol entries to copy; put the result in OSYMS.
12171347 We don't copy in place, because that confuses the relocs.
12181348 Return the number of symbols to print. */
@@ -1238,6 +1368,14 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
12381368
12391369 undefined = bfd_is_und_section (bfd_get_section (sym));
12401370
1371+ if (add_sym_list)
1372+ {
1373+ struct addsym_node *ptr;
1374+
1375+ if (need_sym_before (&ptr, name))
1376+ to[dst_count++] = create_new_symbol (ptr, obfd);
1377+ }
1378+
12411379 if (redefine_sym_list)
12421380 {
12431381 char *old_name, *new_name;
@@ -1394,6 +1532,23 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
13941532 to[dst_count++] = sym;
13951533 }
13961534 }
1535+ if (add_sym_list)
1536+ {
1537+ struct addsym_node *ptr = add_sym_list;
1538+
1539+ for (src_count = 0; src_count < add_symbols; src_count++)
1540+ {
1541+ if (ptr->othersym)
1542+ {
1543+ if (strcmp (ptr->othersym, ""))
1544+ fatal (_("'before=%s' not found"), ptr->othersym);
1545+ }
1546+ else
1547+ to[dst_count++] = create_new_symbol (ptr, obfd);
1548+
1549+ ptr = ptr->next;
1550+ }
1551+ }
13971552
13981553 to[dst_count] = NULL;
13991554
@@ -2179,7 +2334,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
21792334 || change_leading_char
21802335 || remove_leading_char
21812336 || redefine_sym_list
2182- || weaken)
2337+ || weaken
2338+ || add_symbols)
21832339 {
21842340 /* Mark symbols used in output relocations so that they
21852341 are kept, even if they are local labels or static symbols.
@@ -2193,7 +2349,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
21932349 bfd_map_over_sections (ibfd,
21942350 mark_symbols_used_in_relocations,
21952351 isympp);
2196- osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
2352+ osympp = (asymbol **) xmalloc ((symcount + add_symbols + 1) * sizeof (asymbol *));
21972353 symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
21982354 }
21992355
@@ -3920,6 +4076,53 @@ copy_main (int argc, char *argv[])
39204076 "--dump-section");
39214077 break;
39224078
4079+ case OPTION_ADD_SYMBOL:
4080+ {
4081+ char *s, *t;
4082+ struct addsym_node *newsym = xmalloc (sizeof *newsym);
4083+
4084+ newsym->next = NULL;
4085+ s = strchr (optarg, '=');
4086+ if (s == NULL)
4087+ fatal (_("bad format for %s"), "--add-symbol");
4088+ t = strchr (s + 1, ':');
4089+
4090+ newsym->symdef = strndup (optarg, s - optarg);
4091+ if (t)
4092+ {
4093+ newsym->section = strndup (s + 1, t - (s + 1));
4094+ newsym->symval = strtol (t + 1, NULL, 0);
4095+ }
4096+ else
4097+ {
4098+ newsym->section = NULL;
4099+ newsym->symval = strtol (s + 1, NULL, 0);
4100+ t = s;
4101+ }
4102+
4103+ t = strchr (t + 1, ',');
4104+ if (t)
4105+ newsym->flags = parse_symflags (t+1, &newsym->othersym);
4106+ else
4107+ newsym->flags = BSF_GLOBAL;
4108+
4109+ /* Keep 'othersym' symbols at the front of the list. */
4110+ if (newsym->othersym)
4111+ {
4112+ newsym->next = add_sym_list;
4113+ if (!add_sym_list)
4114+ add_sym_tail = &newsym->next;
4115+ add_sym_list = newsym;
4116+ }
4117+ else
4118+ {
4119+ *add_sym_tail = newsym;
4120+ add_sym_tail = &newsym->next;
4121+ }
4122+ add_symbols++;
4123+ }
4124+ break;
4125+
39234126 case OPTION_CHANGE_START:
39244127 change_start = parse_vma (optarg, "--change-start");
39254128 break;
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,3 +1,9 @@
1+2015-10-21 Ronald Hoogenbllon <rhoogenboom@irdeto.com>
2+
3+ PR binutils/19104
4+ * binutils-all/add-symbol.d: New test.
5+ * binutils-all/objcopy.exp: Run the new test.
6+
17 2015-10-15 Alan Modra <amodra@gmail.com>
28
39 * binutils-all/objcopy.exp: Delete trailing whitespace. Use
--- /dev/null
+++ b/binutils/testsuite/binutils-all/add-symbol.d
@@ -0,0 +1,16 @@
1+#PROG: objcopy
2+#name: objcopy add-symbol
3+#source: symbols.s
4+#objcopy: --add-symbol NEW=0x1234 --add-symbol NEW_DATA=.data:0x4321,local
5+#objdump: --syms
6+# MIPS targets swap the order of the symbols in the output.
7+#not-target: mips-*-* tx39-*-*
8+
9+.*: +file format .*
10+
11+SYMBOL TABLE:
12+#...
13+0+04321 l[ ]+.data[ ]+0+00 NEW_DATA
14+#...
15+0+01234 g[ ]+\*ABS\*[ ]+0+00 NEW
16+#pass
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -1097,6 +1097,7 @@ if [is_elf_format] {
10971097 run_dump_test "testranges-ia64"
10981098
10991099 run_dump_test "add-section"
1100+ run_dump_test "add-symbol"
11001101 run_dump_test "add-empty-section"
11011102
11021103 run_dump_test "exclude-1a"