This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Add ability for objcopy to insert new symbols into a binary.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2b35fb28f397a26c0da03f7579116d28af2af824

commit 2b35fb28f397a26c0da03f7579116d28af2af824
Author: Ronald Hoogenbllon <rhoogenboom@irdeto.com>
Date:   Wed Oct 21 15:16:35 2015 +0100

    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.

Diff:
---
 binutils/ChangeLog                           |  14 +
 binutils/NEWS                                |   3 +
 binutils/doc/binutils.texi                   |  13 +
 binutils/objcopy.c                           | 403 ++++++++++++++++++++-------
 binutils/testsuite/ChangeLog                 |   6 +
 binutils/testsuite/binutils-all/add-symbol.d |  16 ++
 binutils/testsuite/binutils-all/objcopy.exp  |   1 +
 7 files changed, 356 insertions(+), 100 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 512471c..7b7f748 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,17 @@
+2015-10-21  Ronald Hoogenbllon  <rhoogenboom@irdeto.com>
+
+	PR binutils/19104
+	* 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.
+
 2015-10-18  Paul Pluzhnikov  <ppluzhnikov@google.com>
 
 	PR binutils/19147
diff --git a/binutils/NEWS b/binutils/NEWS
index fb36cf1..b0508f8 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add option to objcopy to insert new symbols into a file:
+  --add-symbol <name>=[<section>:]<value>[,<flags>]
+
 * Add support for the ARC EM/HS, and ARC600/700 architectures.
 
 * Extend objcopy --compress-debug-sections option to support
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index d993664..7dc09c3 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1106,6 +1106,7 @@ objcopy [@option{-F} @var{bfdname}|@option{--target=}@var{bfdname}]
         [@option{--localize-symbols=}@var{filename}]
         [@option{--globalize-symbols=}@var{filename}]
         [@option{--weaken-symbols=}@var{filename}]
+        [@option{--add-symbol} @var{name}=[@var{section}:]@var{value}[,@var{flags}]
         [@option{--alt-machine-code=}@var{index}]
         [@option{--prefix-symbols=}@var{string}]
         [@option{--prefix-sections=}@var{string}]
@@ -1504,6 +1505,18 @@ command line.  In this case, pass the original section name to
 @option{--update-section}, and the original and new section names to
 @option{--rename-section}.
 
+@item --add-symbol @var{name}=[@var{section}:]@var{value}[,@var{flags}]
+Add a new symbol named @var{name} while copying the file.  This option may be
+specified multiple times.  If the @var{section} is given, the symbol will be
+associated with and relative to that section, otherwise it will be an ABS
+symbol.  Specifying an undefined section will result in a fatal error.  There
+is no check for the value, it will be taken as specified.  Symbol flags can
+be specified and not all flags will be meaningful for all object file
+formats.  By default, the symbol will be global.  The special flag
+'before=@var{othersym}' will insert the new symbol in front of the specified
+@var{othersym}, otherwise the symbol(s) will be added at the end of the
+symbol table in the order they appear.
+
 @item --rename-section @var{oldname}=@var{newname}[,@var{flags}]
 Rename a section from @var{oldname} to @var{newname}, optionally
 changing the section's flags to @var{flags} in the process.  This has
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 324456a..6f0f62a 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -50,7 +50,7 @@ static short pe_minor_subsystem_version = -1;
 
 struct is_specified_symbol_predicate_data
 {
-  const char	*name;
+  const char *  name;
   bfd_boolean	found;
 };
 
@@ -62,6 +62,16 @@ struct redefine_node
   struct redefine_node *next;
 };
 
+struct addsym_node
+{
+  struct addsym_node *next;
+  char *    symdef;
+  long      symval;
+  flagword  flags;
+  char *    section;
+  char *    othersym;
+};
+
 typedef struct section_rename
 {
   const char *            old_name;
@@ -88,26 +98,26 @@ static int deterministic = -1;		/* Enable deterministic archives.  */
 static int status = 0;		/* Exit status.  */
 
 enum strip_action
-  {
-    STRIP_UNDEF,
-    STRIP_NONE,			/* Don't strip.  */
-    STRIP_DEBUG,		/* Strip all debugger symbols.  */
-    STRIP_UNNEEDED,		/* Strip unnecessary symbols.  */
-    STRIP_NONDEBUG,		/* Strip everything but debug info.  */
-    STRIP_DWO,			/* Strip all DWO info.  */
-    STRIP_NONDWO,		/* Strip everything but DWO info.  */
-    STRIP_ALL			/* Strip all symbols.  */
-  };
+{
+  STRIP_UNDEF,
+  STRIP_NONE,		/* Don't strip.  */
+  STRIP_DEBUG,		/* Strip all debugger symbols.  */
+  STRIP_UNNEEDED,	/* Strip unnecessary symbols.  */
+  STRIP_NONDEBUG,	/* Strip everything but debug info.  */
+  STRIP_DWO,		/* Strip all DWO info.  */
+  STRIP_NONDWO,		/* Strip everything but DWO info.  */
+  STRIP_ALL		/* Strip all symbols.  */
+};
 
 /* Which symbols to remove.  */
 static enum strip_action strip_symbols = STRIP_UNDEF;
 
 enum locals_action
-  {
-    LOCALS_UNDEF,
-    LOCALS_START_L,		/* Discard locals starting with L.  */
-    LOCALS_ALL			/* Discard all locals.  */
-  };
+{
+  LOCALS_UNDEF,
+  LOCALS_START_L,	/* Discard locals starting with L.  */
+  LOCALS_ALL		/* Discard all locals.  */
+};
 
 /* Which local symbols to remove.  Overrides STRIP_ALL.  */
 static enum locals_action discard_locals;
@@ -232,6 +242,8 @@ static htab_t globalize_specific_htab = NULL;
 static htab_t keepglobal_specific_htab = NULL;
 static htab_t weaken_specific_htab = NULL;
 static struct redefine_node *redefine_sym_list = NULL;
+static struct addsym_node *add_sym_list = NULL, **add_sym_tail = &add_sym_list;
+static int add_symbols = 0;
 
 /* If this is TRUE, we weaken global symbols (set BSF_WEAK).  */
 static bfd_boolean weaken = FALSE;
@@ -254,11 +266,11 @@ static int reverse_bytes = 0;
 /* For Coff objects, we may want to allow or disallow long section names,
    or preserve them where found in the inputs.  Debug info relies on them.  */
 enum long_section_name_handling
-  {
-    DISABLE,
-    ENABLE,
-    KEEP
-  };
+{
+  DISABLE,
+  ENABLE,
+  KEEP
+};
 
 /* The default long section handling mode is to preserve them.
    This is also the only behaviour for 'strip'.  */
@@ -266,68 +278,69 @@ static enum long_section_name_handling long_section_names = KEEP;
 
 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
 enum command_line_switch
-  {
-    OPTION_ADD_SECTION=150,
-    OPTION_UPDATE_SECTION,
-    OPTION_DUMP_SECTION,
-    OPTION_CHANGE_ADDRESSES,
-    OPTION_CHANGE_LEADING_CHAR,
-    OPTION_CHANGE_START,
-    OPTION_CHANGE_SECTION_ADDRESS,
-    OPTION_CHANGE_SECTION_LMA,
-    OPTION_CHANGE_SECTION_VMA,
-    OPTION_CHANGE_WARNINGS,
-    OPTION_COMPRESS_DEBUG_SECTIONS,
-    OPTION_DEBUGGING,
-    OPTION_DECOMPRESS_DEBUG_SECTIONS,
-    OPTION_GAP_FILL,
-    OPTION_NO_CHANGE_WARNINGS,
-    OPTION_PAD_TO,
-    OPTION_REMOVE_LEADING_CHAR,
-    OPTION_SET_SECTION_FLAGS,
-    OPTION_SET_START,
-    OPTION_STRIP_UNNEEDED,
-    OPTION_WEAKEN,
-    OPTION_REDEFINE_SYM,
-    OPTION_REDEFINE_SYMS,
-    OPTION_SREC_LEN,
-    OPTION_SREC_FORCES3,
-    OPTION_STRIP_SYMBOLS,
-    OPTION_STRIP_UNNEEDED_SYMBOL,
-    OPTION_STRIP_UNNEEDED_SYMBOLS,
-    OPTION_KEEP_SYMBOLS,
-    OPTION_LOCALIZE_HIDDEN,
-    OPTION_LOCALIZE_SYMBOLS,
-    OPTION_LONG_SECTION_NAMES,
-    OPTION_GLOBALIZE_SYMBOL,
-    OPTION_GLOBALIZE_SYMBOLS,
-    OPTION_KEEPGLOBAL_SYMBOLS,
-    OPTION_WEAKEN_SYMBOLS,
-    OPTION_RENAME_SECTION,
-    OPTION_ALT_MACH_CODE,
-    OPTION_PREFIX_SYMBOLS,
-    OPTION_PREFIX_SECTIONS,
-    OPTION_PREFIX_ALLOC_SECTIONS,
-    OPTION_FORMATS_INFO,
-    OPTION_ADD_GNU_DEBUGLINK,
-    OPTION_ONLY_KEEP_DEBUG,
-    OPTION_KEEP_FILE_SYMBOLS,
-    OPTION_READONLY_TEXT,
-    OPTION_WRITABLE_TEXT,
-    OPTION_PURE,
-    OPTION_IMPURE,
-    OPTION_EXTRACT_SYMBOL,
-    OPTION_REVERSE_BYTES,
-    OPTION_FILE_ALIGNMENT,
-    OPTION_HEAP,
-    OPTION_IMAGE_BASE,
-    OPTION_SECTION_ALIGNMENT,
-    OPTION_STACK,
-    OPTION_INTERLEAVE_WIDTH,
-    OPTION_SUBSYSTEM,
-    OPTION_EXTRACT_DWO,
-    OPTION_STRIP_DWO
-  };
+{
+  OPTION_ADD_SECTION=150,
+  OPTION_ADD_GNU_DEBUGLINK,
+  OPTION_ADD_SYMBOL,
+  OPTION_ALT_MACH_CODE,
+  OPTION_CHANGE_ADDRESSES,
+  OPTION_CHANGE_LEADING_CHAR,
+  OPTION_CHANGE_SECTION_ADDRESS,
+  OPTION_CHANGE_SECTION_LMA,
+  OPTION_CHANGE_SECTION_VMA,
+  OPTION_CHANGE_START,
+  OPTION_CHANGE_WARNINGS,
+  OPTION_COMPRESS_DEBUG_SECTIONS,
+  OPTION_DEBUGGING,
+  OPTION_DECOMPRESS_DEBUG_SECTIONS,
+  OPTION_DUMP_SECTION,
+  OPTION_EXTRACT_DWO,
+  OPTION_EXTRACT_SYMBOL,
+  OPTION_FILE_ALIGNMENT,
+  OPTION_FORMATS_INFO,
+  OPTION_GAP_FILL,
+  OPTION_GLOBALIZE_SYMBOL,
+  OPTION_GLOBALIZE_SYMBOLS,
+  OPTION_HEAP,
+  OPTION_IMAGE_BASE,
+  OPTION_IMPURE,
+  OPTION_INTERLEAVE_WIDTH,
+  OPTION_KEEPGLOBAL_SYMBOLS,
+  OPTION_KEEP_FILE_SYMBOLS,
+  OPTION_KEEP_SYMBOLS,
+  OPTION_LOCALIZE_HIDDEN,
+  OPTION_LOCALIZE_SYMBOLS,
+  OPTION_LONG_SECTION_NAMES,
+  OPTION_NO_CHANGE_WARNINGS,
+  OPTION_ONLY_KEEP_DEBUG,
+  OPTION_PAD_TO,
+  OPTION_PREFIX_ALLOC_SECTIONS,
+  OPTION_PREFIX_SECTIONS,
+  OPTION_PREFIX_SYMBOLS,
+  OPTION_PURE,
+  OPTION_READONLY_TEXT,
+  OPTION_REDEFINE_SYM,
+  OPTION_REDEFINE_SYMS,
+  OPTION_REMOVE_LEADING_CHAR,
+  OPTION_RENAME_SECTION,
+  OPTION_REVERSE_BYTES,
+  OPTION_SECTION_ALIGNMENT,
+  OPTION_SET_SECTION_FLAGS,
+  OPTION_SET_START,
+  OPTION_SREC_FORCES3,
+  OPTION_SREC_LEN,
+  OPTION_STACK,
+  OPTION_STRIP_DWO,
+  OPTION_STRIP_SYMBOLS,
+  OPTION_STRIP_UNNEEDED,
+  OPTION_STRIP_UNNEEDED_SYMBOL,
+  OPTION_STRIP_UNNEEDED_SYMBOLS,
+  OPTION_SUBSYSTEM,
+  OPTION_UPDATE_SECTION,
+  OPTION_WEAKEN,
+  OPTION_WEAKEN_SYMBOLS,
+  OPTION_WRITABLE_TEXT
+};
 
 /* Options to handle if running as "strip".  */
 
@@ -345,16 +358,16 @@ static struct option strip_options[] =
   {"keep-file-symbols", no_argument, 0, OPTION_KEEP_FILE_SYMBOLS},
   {"keep-symbol", required_argument, 0, 'K'},
   {"only-keep-debug", no_argument, 0, OPTION_ONLY_KEEP_DEBUG},
+  {"output-file", required_argument, 0, 'o'},
   {"output-format", required_argument, 0, 'O'},	/* Obsolete */
   {"output-target", required_argument, 0, 'O'},
-  {"output-file", required_argument, 0, 'o'},
   {"preserve-dates", no_argument, 0, 'p'},
   {"remove-section", required_argument, 0, 'R'},
   {"strip-all", no_argument, 0, 's'},
   {"strip-debug", no_argument, 0, 'S'},
   {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
-  {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
   {"strip-symbol", required_argument, 0, 'N'},
+  {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
   {"target", required_argument, 0, 'F'},
   {"verbose", no_argument, 0, 'v'},
   {"version", no_argument, 0, 'V'},
@@ -368,10 +381,10 @@ static struct option copy_options[] =
 {
   {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
-  {"update-section", required_argument, 0, OPTION_UPDATE_SECTION},
+  {"add-symbol", required_argument, 0, OPTION_ADD_SYMBOL},
+  {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
   {"adjust-start", required_argument, 0, OPTION_CHANGE_START},
   {"adjust-vma", required_argument, 0, OPTION_CHANGE_ADDRESSES},
-  {"adjust-section-vma", required_argument, 0, OPTION_CHANGE_SECTION_ADDRESS},
   {"adjust-warnings", no_argument, 0, OPTION_CHANGE_WARNINGS},
   {"alt-machine-code", required_argument, 0, OPTION_ALT_MACH_CODE},
   {"binary-architecture", required_argument, 0, 'B'},
@@ -393,11 +406,14 @@ static struct option copy_options[] =
   {"enable-deterministic-archives", no_argument, 0, 'D'},
   {"extract-dwo", no_argument, 0, OPTION_EXTRACT_DWO},
   {"extract-symbol", no_argument, 0, OPTION_EXTRACT_SYMBOL},
+  {"file-alignment", required_argument, 0, OPTION_FILE_ALIGNMENT},
   {"format", required_argument, 0, 'F'}, /* Obsolete */
   {"gap-fill", required_argument, 0, OPTION_GAP_FILL},
   {"globalize-symbol", required_argument, 0, OPTION_GLOBALIZE_SYMBOL},
   {"globalize-symbols", required_argument, 0, OPTION_GLOBALIZE_SYMBOLS},
+  {"heap", required_argument, 0, OPTION_HEAP},
   {"help", no_argument, 0, 'h'},
+  {"image-base", required_argument, 0 , OPTION_IMAGE_BASE},
   {"impure", no_argument, 0, OPTION_IMPURE},
   {"info", no_argument, 0, OPTION_FORMATS_INFO},
   {"input-format", required_argument, 0, 'I'}, /* Obsolete */
@@ -420,9 +436,9 @@ static struct option copy_options[] =
   {"output-format", required_argument, 0, 'O'},	/* Obsolete */
   {"output-target", required_argument, 0, 'O'},
   {"pad-to", required_argument, 0, OPTION_PAD_TO},
-  {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
-  {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
   {"prefix-alloc-sections", required_argument, 0, OPTION_PREFIX_ALLOC_SECTIONS},
+  {"prefix-sections", required_argument, 0, OPTION_PREFIX_SECTIONS},
+  {"prefix-symbols", required_argument, 0, OPTION_PREFIX_SYMBOLS},
   {"preserve-dates", no_argument, 0, 'p'},
   {"pure", no_argument, 0, OPTION_PURE},
   {"readonly-text", no_argument, 0, OPTION_READONLY_TEXT},
@@ -432,19 +448,23 @@ static struct option copy_options[] =
   {"remove-section", required_argument, 0, 'R'},
   {"rename-section", required_argument, 0, OPTION_RENAME_SECTION},
   {"reverse-bytes", required_argument, 0, OPTION_REVERSE_BYTES},
+  {"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
   {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS},
   {"set-start", required_argument, 0, OPTION_SET_START},
-  {"srec-len", required_argument, 0, OPTION_SREC_LEN},
   {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3},
+  {"srec-len", required_argument, 0, OPTION_SREC_LEN},
+  {"stack", required_argument, 0, OPTION_STACK},
   {"strip-all", no_argument, 0, 'S'},
   {"strip-debug", no_argument, 0, 'g'},
   {"strip-dwo", no_argument, 0, OPTION_STRIP_DWO},
+  {"strip-symbol", required_argument, 0, 'N'},
+  {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
   {"strip-unneeded", no_argument, 0, OPTION_STRIP_UNNEEDED},
   {"strip-unneeded-symbol", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOL},
   {"strip-unneeded-symbols", required_argument, 0, OPTION_STRIP_UNNEEDED_SYMBOLS},
-  {"strip-symbol", required_argument, 0, 'N'},
-  {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS},
+  {"subsystem", required_argument, 0, OPTION_SUBSYSTEM},
   {"target", required_argument, 0, 'F'},
+  {"update-section", required_argument, 0, OPTION_UPDATE_SECTION},
   {"verbose", no_argument, 0, 'v'},
   {"version", no_argument, 0, 'V'},
   {"weaken", no_argument, 0, OPTION_WEAKEN},
@@ -452,12 +472,6 @@ static struct option copy_options[] =
   {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS},
   {"wildcard", no_argument, 0, 'w'},
   {"writable-text", no_argument, 0, OPTION_WRITABLE_TEXT},
-  {"file-alignment", required_argument, 0, OPTION_FILE_ALIGNMENT},
-  {"heap", required_argument, 0, OPTION_HEAP},
-  {"image-base", required_argument, 0 , OPTION_IMAGE_BASE},
-  {"section-alignment", required_argument, 0, OPTION_SECTION_ALIGNMENT},
-  {"stack", required_argument, 0, OPTION_STACK},
-  {"subsystem", required_argument, 0, OPTION_SUBSYSTEM},
   {0, no_argument, 0, 0}
 };
 
@@ -585,6 +599,7 @@ copy_usage (FILE *stream, int exit_status)
      --globalize-symbols <file>    --globalize-symbol for all in <file>\n\
      --keep-global-symbols <file>  -G for all symbols listed in <file>\n\
      --weaken-symbols <file>       -W for all symbols listed in <file>\n\
+     --add-symbol <name>=[<section>:]<value>[,<flags>]  Add a symbol\n\
      --alt-machine-code <index>    Use the target's <index>'th alternative machine\n\
      --writable-text               Mark the output text as writable\n\
      --readonly-text               Make the output text write protected\n\
@@ -727,6 +742,78 @@ parse_flags (const char *s)
   return ret;
 }
 
+/* Parse symbol flags into a flagword, with a fatal error if the
+   string can't be parsed.  */
+
+static flagword
+parse_symflags (const char *s, char **other)
+{
+  flagword ret;
+  const char *snext;
+  int len;
+
+  ret = BSF_NO_FLAGS;
+
+  do
+    {
+      snext = strchr (s, ',');
+      if (snext == NULL)
+	  len = strlen (s);
+      else
+	{
+	  len = snext - s;
+	  ++snext;
+	}
+
+#define PARSE_FLAG(fname,fval)							  \
+      else if (len == (int) sizeof fname - 1 && strncasecmp (fname, s, len) == 0) \
+	ret |= fval
+
+#define PARSE_OTHER(fname,fval)								   \
+      else if (len >= (int) sizeof fname && strncasecmp (fname, s, sizeof fname - 1) == 0) \
+	fval = strndup (s + sizeof fname - 1, len - sizeof fname + 1)
+      
+      if (0) ;
+      PARSE_FLAG ("local", BSF_LOCAL);
+      PARSE_FLAG ("global", BSF_GLOBAL);
+      PARSE_FLAG ("export", BSF_EXPORT);
+      PARSE_FLAG ("debug", BSF_DEBUGGING);
+      PARSE_FLAG ("function", BSF_FUNCTION);
+      PARSE_FLAG ("weak", BSF_WEAK);
+      PARSE_FLAG ("section", BSF_SECTION_SYM);
+      PARSE_FLAG ("constructor", BSF_CONSTRUCTOR);
+      PARSE_FLAG ("warning", BSF_WARNING);
+      PARSE_FLAG ("indirect", BSF_INDIRECT);
+      PARSE_FLAG ("file", BSF_FILE);
+      PARSE_FLAG ("object", BSF_OBJECT);
+      PARSE_FLAG ("synthetic", BSF_SYNTHETIC);
+      PARSE_FLAG ("indirect-function", BSF_GNU_INDIRECT_FUNCTION | BSF_FUNCTION);
+      PARSE_FLAG ("unique-object", BSF_GNU_UNIQUE | BSF_OBJECT);
+      PARSE_OTHER ("before=", *other);
+
+#undef PARSE_FLAG
+#undef PARSE_OTHER
+      else
+	{
+	  char *copy;
+
+	  copy = (char *) xmalloc (len + 1);
+	  strncpy (copy, s, len);
+	  copy[len] = '\0';
+	  non_fatal (_("unrecognized symbol flag `%s'"), copy);
+	  fatal (_("supported flags: %s"),
+		  "local, global, export, debug, function, weak, section, "
+		  "constructor, warning, indirect, file, object, synthetic, "
+		  "indirect-function, unique-object, before=<othersym>");
+	}
+
+      s = snext;
+    }
+  while (s != NULL);
+
+  return ret;
+}
+
 /* Find and optionally add an entry in the change_sections list.
 
    We need to be careful in how we match section names because of the support
@@ -1213,6 +1300,49 @@ is_hidden_symbol (asymbol *sym)
   return FALSE;
 }
 
+static bfd_boolean
+need_sym_before (struct addsym_node **node, const char *sym)
+{
+  int count;
+  struct addsym_node *ptr = add_sym_list;
+
+  /* 'othersym' symbols are at the front of the list.  */
+  for (count = 0; count < add_symbols; count++)
+    {
+      if (!ptr->othersym)
+	break;
+      else if (strcmp (ptr->othersym, sym) == 0)
+	{
+	  free (ptr->othersym);
+	  ptr->othersym = ""; /* Empty name is hopefully never a valid symbol name.  */
+	  *node = ptr;
+	  return TRUE;
+	}
+      ptr = ptr->next;
+    }
+  return FALSE;
+}
+
+static asymbol *
+create_new_symbol (struct addsym_node *ptr, bfd *obfd)
+{
+  asymbol *sym = bfd_make_empty_symbol(obfd);
+
+  bfd_asymbol_name(sym) = ptr->symdef;
+  sym->value = ptr->symval;
+  sym->flags = ptr->flags;
+  if (ptr->section)
+    {
+      asection *sec = bfd_get_section_by_name (obfd, ptr->section);
+      if (!sec)
+	fatal (_("Section %s not found"), ptr->section);
+      sym->section = sec;
+    }
+  else 
+      sym->section = bfd_abs_section_ptr;
+  return sym;
+}
+
 /* Choose which symbol entries to copy; put the result in OSYMS.
    We don't copy in place, because that confuses the relocs.
    Return the number of symbols to print.  */
@@ -1238,6 +1368,14 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
 
       undefined = bfd_is_und_section (bfd_get_section (sym));
 
+      if (add_sym_list)
+	{
+	  struct addsym_node *ptr;
+
+	  if (need_sym_before (&ptr, name))
+	    to[dst_count++] = create_new_symbol (ptr, obfd);
+	}
+
       if (redefine_sym_list)
 	{
 	  char *old_name, *new_name;
@@ -1394,6 +1532,23 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
 	  to[dst_count++] = sym;
 	}
     }
+  if (add_sym_list)
+    {
+      struct addsym_node *ptr = add_sym_list;
+
+      for (src_count = 0; src_count < add_symbols; src_count++)
+	{
+	  if (ptr->othersym)
+	    {
+	      if (strcmp (ptr->othersym, ""))
+		fatal (_("'before=%s' not found"), ptr->othersym);
+	    }
+	  else
+	    to[dst_count++] = create_new_symbol (ptr, obfd);
+
+	  ptr = ptr->next;
+	}
+    }
 
   to[dst_count] = NULL;
 
@@ -2179,7 +2334,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
       || change_leading_char
       || remove_leading_char
       || redefine_sym_list
-      || weaken)
+      || weaken
+      || add_symbols)
     {
       /* Mark symbols used in output relocations so that they
 	 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)
 	bfd_map_over_sections (ibfd,
 			       mark_symbols_used_in_relocations,
 			       isympp);
-      osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *));
+      osympp = (asymbol **) xmalloc ((symcount + add_symbols + 1) * sizeof (asymbol *));
       symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount);
     }
 
@@ -3920,6 +4076,53 @@ copy_main (int argc, char *argv[])
                                             "--dump-section");
 	  break;
 
+	case OPTION_ADD_SYMBOL:
+	  {
+	    char *s, *t;
+	    struct addsym_node *newsym = xmalloc (sizeof *newsym);
+
+	    newsym->next = NULL;
+	    s = strchr (optarg, '=');
+	    if (s == NULL)
+	      fatal (_("bad format for %s"), "--add-symbol");
+	    t = strchr (s + 1, ':');
+
+	    newsym->symdef = strndup (optarg, s - optarg);
+	    if (t)
+	      {
+		newsym->section = strndup (s + 1, t - (s + 1));
+		newsym->symval = strtol (t + 1, NULL, 0);
+	      }
+	    else
+	      {
+		newsym->section = NULL;
+		newsym->symval = strtol (s + 1, NULL, 0);
+		t = s;
+	      }
+
+	    t = strchr (t + 1, ',');
+	    if (t)
+	      newsym->flags = parse_symflags (t+1, &newsym->othersym);
+	    else
+	      newsym->flags = BSF_GLOBAL;
+
+	    /* Keep 'othersym' symbols at the front of the list.  */
+	    if (newsym->othersym)
+	      {
+		newsym->next = add_sym_list;
+		if (!add_sym_list)
+		  add_sym_tail = &newsym->next;
+		add_sym_list = newsym;
+	      }
+	    else
+	      {
+		*add_sym_tail = newsym;
+		add_sym_tail = &newsym->next;
+	      }
+	    add_symbols++;
+	  }
+	  break;
+
 	case OPTION_CHANGE_START:
 	  change_start = parse_vma (optarg, "--change-start");
 	  break;
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
index 79b5b25..a442136 100644
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2015-10-21  Ronald Hoogenbllon  <rhoogenboom@irdeto.com>
+
+	PR binutils/19104
+	* binutils-all/add-symbol.d: New test.
+	* binutils-all/objcopy.exp: Run the new test.
+
 2015-10-15  Alan Modra  <amodra@gmail.com>
 
 	* binutils-all/objcopy.exp: Delete trailing whitespace.  Use
diff --git a/binutils/testsuite/binutils-all/add-symbol.d b/binutils/testsuite/binutils-all/add-symbol.d
new file mode 100644
index 0000000..d421dc9
--- /dev/null
+++ b/binutils/testsuite/binutils-all/add-symbol.d
@@ -0,0 +1,16 @@
+#PROG: objcopy
+#name: objcopy add-symbol
+#source: symbols.s
+#objcopy: --add-symbol NEW=0x1234 --add-symbol NEW_DATA=.data:0x4321,local
+#objdump: --syms
+# MIPS targets swap the order of the symbols in the output.
+#not-target: mips-*-* tx39-*-*
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+04321 l[ 	]+.data[ 	]+0+00 NEW_DATA
+#...
+0+01234 g[ 	]+\*ABS\*[ 	]+0+00 NEW
+#pass
diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
index 252cb49..bac0ccd 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -1097,6 +1097,7 @@ if [is_elf_format] {
     run_dump_test "testranges-ia64"
 
     run_dump_test "add-section"
+    run_dump_test "add-symbol"
     run_dump_test "add-empty-section"
 
     run_dump_test "exclude-1a"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]