This is the mail archive of the binutils@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]

[PATCH] 'add symbol' feature in objcopy


Objcopy allows to strip/remove and manipulate all kinds of symbols in an object. Sometimes it might be
useful to be able to ADD a symbol too.

The attached patch does just that. It adds the --add-symbol option (can be used multiple times) that
allows to add a new symbol to the end of the symbol table with an arbitrary absolute value.

I've added the section support. <symbol>=[<section>:]<value>
This binds the new symbol to (and makes it relative to) the specified section.

Extended the --add-symbol with the possibility to specify symbol flags. Some symbol flags depend on
the ordering of symbols in the symtab (warning, indirect) if I understand correctly... so I preserved
the order of the added symbols. Maybe one more useful feature could be to add a symbol in front of
another existing symbol, to enhance the usability of the warning flag (does it actually have the effect
as it is described in the bfd.h file?).

Refer to bugzilla item 19104.

The patch was made against the binutils-2.24-32 from fedora 21. It may apply with some fuzz.


--- binutils/objcopy.c.orig	2015-10-08 21:30:08.907350631 +0200
+++ binutils/objcopy.c	2015-10-10 17:48:13.791061147 +0200
@@ -62,6 +62,15 @@
   struct redefine_node *next;
 };
 
+struct addsym_node
+{
+	struct addsym_node *next;
+	char *symdef;
+	long symval;
+	flagword flags;
+	char *section;
+};
+
 typedef struct section_rename
 {
   const char *            old_name;
@@ -223,6 +232,8 @@
 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;
@@ -259,6 +270,7 @@
 enum command_line_switch
   {
     OPTION_ADD_SECTION=150,
+	OPTION_ADD_SYMBOL,
     OPTION_CHANGE_ADDRESSES,
     OPTION_CHANGE_LEADING_CHAR,
     OPTION_CHANGE_START,
@@ -357,6 +369,7 @@
 {
   {"add-gnu-debuglink", required_argument, 0, OPTION_ADD_GNU_DEBUGLINK},
   {"add-section", required_argument, 0, OPTION_ADD_SECTION},
+  {"add-symbol", required_argument, 0, OPTION_ADD_SYMBOL},
   {"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},
@@ -548,6 +561,7 @@
      --set-section-flags <name>=<flags>\n\
                                    Set section <name>'s properties to <flags>\n\
      --add-section <name>=<file>   Add section <name> found in <file> to output\n\
+     --add-symbol <name>=[<section>:]<value>[,<flags>]  Add a symbol\n\
      --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>\n\
      --long-section-names {enable|disable|keep}\n\
                                    Handle long section names in Coff objects.\n\
@@ -709,6 +723,67 @@
   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)
+{
+	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;
+		}
+
+		if (0) ;
+#define PARSE_FLAG(fname,fval) \
+		else if (strncasecmp (fname, s, len) == 0) ret |= fval
+		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);
+#undef PARSE_FLAG
+		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");
+		}
+
+		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
@@ -1310,6 +1385,30 @@
 	  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++)
+	  {
+		  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;
+		  to[dst_count++] = sym;
+		  ptr = ptr->next;
+	  }
+  }
 
   to[dst_count] = NULL;
 
@@ -1979,7 +2078,8 @@
       || 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.
@@ -1993,7 +2093,7 @@
 	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);
     }
 
@@ -3629,6 +3729,43 @@
 	  }
 	  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);
+		  }
+		  else
+		  {
+			  newsym->flags=BSF_GLOBAL;
+		  }
+		  *add_sym_tail=newsym;
+		  add_sym_tail=&newsym->next;
+		  add_symbols++;
+	  }
+	  break;
+
 	case OPTION_CHANGE_START:
 	  change_start = parse_vma (optarg, "--change-start");
 	  break;

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