This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Re: objcopy --redefine-sym
- To: Doug Evans <dje at transmeta dot com>
- Subject: Re: objcopy --redefine-sym
- From: Alan Modra <alan at linuxcare dot com dot au>
- Date: Wed, 5 Apr 2000 01:44:17 +1000 (EST)
- cc: ian at zembu dot com, binutils at sourceware dot cygnus dot com
On Tue, 15 Feb 2000, Doug Evans wrote:
> [I didn't see any reference to it in the mailing list archives
> so I'm guessing it hasn't been submitted (recently at least).]
Attached is a version I've sanitized and rewritten in places.
--
Linuxcare. Support for the Revolution.
binutils/ChangeLog
from Matthew Benjamin <matt@linuxbox.nu>
* objcopy.c (struct redefine_node): New.
(redefine_sym_list): New.
(redefine_list_append): New.
(lookup_sym_redefinition): New.
(OPTION_REDEFINE_SYM): New.
(copy_options): Add --redefine-sym option.
(copy_usage): Mention it.
(filter_symbols): Rename symbols on redefine_sym_list.
(copy_object): Call filter_symbols if redefine_sym_list != NULL.
(copy_main): Add some white space. Handle OPTION_REDEFINE_SYM.
--- binutils/objcopy.c.orig Tue Apr 4 22:27:47 2000
+++ binutils/objcopy.c Tue Apr 4 22:27:47 2000
@@ -38,6 +38,14 @@ struct symlist
struct symlist *next;
};
+/* A list to support redefine_sym. */
+struct redefine_node
+{
+ char *source;
+ char *target;
+ struct redefine_node *next;
+};
+
static void copy_usage PARAMS ((FILE *, int));
static void strip_usage PARAMS ((FILE *, int));
static flagword parse_flags PARAMS ((const char *));
@@ -60,6 +68,8 @@ static void copy_file
PARAMS ((const char *, const char *, const char *, const char *));
static int strip_main PARAMS ((int, char **));
static int copy_main PARAMS ((int, char **));
+static const char *lookup_sym_redefinition PARAMS((const char *));
+static void redefine_list_append PARAMS ((const char *, const char *));
#define RETURN_NONFATAL(s) {bfd_nonfatal (s); status = 1; return;}
@@ -172,12 +182,13 @@ static boolean change_leading_char = fal
static boolean remove_leading_char = false;
-/* List of symbols to strip, keep, localize, and weaken. */
+/* List of symbols to strip, keep, localize, weaken, or redefine. */
static struct symlist *strip_specific_list = NULL;
static struct symlist *keep_specific_list = NULL;
static struct symlist *localize_specific_list = NULL;
static struct symlist *weaken_specific_list = NULL;
+static struct redefine_node *redefine_sym_list = NULL;
/* If this is true, we weaken global symbols (set BSF_WEAK). */
@@ -202,6 +213,7 @@ static boolean weaken = false;
#define OPTION_SET_START (OPTION_SET_SECTION_FLAGS + 1)
#define OPTION_STRIP_UNNEEDED (OPTION_SET_START + 1)
#define OPTION_WEAKEN (OPTION_STRIP_UNNEEDED + 1)
+#define OPTION_REDEFINE_SYM (OPTION_WEAKEN + 1)
/* Options to handle if running as "strip". */
@@ -276,6 +288,7 @@ static struct option copy_options[] =
{"version", no_argument, 0, 'V'},
{"weaken", no_argument, 0, OPTION_WEAKEN},
{"weaken-symbol", required_argument, 0, 'W'},
+ {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM},
{0, no_argument, 0, 0}
};
@@ -335,6 +348,7 @@ copy_usage (stream, exit_status)
--add-section <name>=<file> Add section <name> found in <file> to output\n\
--change-leading-char Force output format's leading character style\n\
--remove-leading-char Remove leading character from global symbols\n\
+ --redefine-sym <old>=<new> Redefine symbol name <old> to <new>\n\
-v --verbose List all object files modified\n\
-V --version Display this program's version number\n\
-h --help Display this output\n\
@@ -549,6 +563,15 @@ filter_symbols (abfd, obfd, osyms, isyms
const char *name = bfd_asymbol_name (sym);
int keep;
+ if (redefine_sym_list)
+ {
+ const char *old_name, *new_name;
+
+ old_name = bfd_asymbol_name (sym);
+ new_name = lookup_sym_redefinition (old_name);
+ name = bfd_asymbol_name (sym) = new_name;
+ }
+
if (change_leading_char
&& (bfd_get_symbol_leading_char (abfd)
!= bfd_get_symbol_leading_char (obfd))
@@ -630,6 +653,66 @@ filter_symbols (abfd, obfd, osyms, isyms
return dst_count;
}
+static const char *
+lookup_sym_redefinition (source)
+ const char *source;
+{
+ const char *result;
+ struct redefine_node *list;
+
+ result = source;
+
+ for (list = redefine_sym_list; list != NULL; list = list->next)
+ {
+ if (strcmp (source, list->source) == 0)
+ {
+ result = list->target;
+ break;
+ }
+ }
+ return result;
+}
+
+/* Add a node to a symbol redefine list */
+
+static void
+redefine_list_append (source, target)
+ const char *source;
+ const char *target;
+{
+ struct redefine_node **p;
+ struct redefine_node *list;
+ struct redefine_node *new_node;
+
+ for (p = &redefine_sym_list; (list = *p) != NULL; p = &list->next)
+ {
+ if (strcmp (source, list->source) == 0)
+ {
+ fprintf(stderr,
+ "redefine-sym: Multiple redefinition of symbol \"%s\"\n",
+ source);
+ exit (1);
+ }
+
+ if (strcmp (target, list->target) == 0)
+ {
+ fprintf(stderr,
+ "redefine-sym: Symbol \"%s\" is target of more than one redefinition",
+ target);
+ exit (1);
+ }
+ }
+
+ new_node = (struct redefine_node *) xmalloc (sizeof (struct redefine_node));
+
+ new_node->source = strdup (source);
+ new_node->target = strdup (target);
+ new_node->next = NULL;
+
+ *p = new_node;
+}
+
+
/* Keep only every `copy_byte'th byte in MEMHUNK, which is *SIZE bytes long.
Adjust *SIZE. */
@@ -868,6 +951,7 @@ copy_object (ibfd, obfd)
|| convert_debugging
|| change_leading_char
|| remove_leading_char
+ || redefine_sym_list
|| weaken)
{
/* Mark symbols used in output relocations so that they
@@ -1720,22 +1804,27 @@ copy_main (argc, argv)
if (copy_byte < 0)
fatal (_("byte number must be non-negative"));
break;
+
case 'i':
interleave = atoi (optarg);
if (interleave < 1)
fatal (_("interleave must be positive"));
break;
+
case 'I':
case 's': /* "source" - 'I' is preferred */
input_target = optarg;
break;
+
case 'O':
case 'd': /* "destination" - 'O' is preferred */
output_target = optarg;
break;
+
case 'F':
input_target = output_target = optarg;
break;
+
case 'j':
p = find_section_list (optarg, true);
if (p->remove)
@@ -1743,6 +1832,7 @@ copy_main (argc, argv)
p->copy = true;
sections_copied = true;
break;
+
case 'R':
p = find_section_list (optarg, true);
if (p->copy)
@@ -1750,45 +1840,59 @@ copy_main (argc, argv)
p->remove = true;
sections_removed = true;
break;
+
case 'S':
strip_symbols = STRIP_ALL;
break;
+
case 'g':
strip_symbols = STRIP_DEBUG;
break;
+
case OPTION_STRIP_UNNEEDED:
strip_symbols = STRIP_UNNEEDED;
break;
+
case 'K':
add_specific_symbol (optarg, &keep_specific_list);
break;
+
case 'N':
add_specific_symbol (optarg, &strip_specific_list);
break;
+
case 'L':
add_specific_symbol (optarg, &localize_specific_list);
break;
+
case 'W':
add_specific_symbol (optarg, &weaken_specific_list);
break;
+
case 'p':
preserve_dates = true;
break;
+
case 'x':
discard_locals = LOCALS_ALL;
break;
+
case 'X':
discard_locals = LOCALS_START_L;
break;
+
case 'v':
verbose = true;
break;
+
case 'V':
show_version = true;
break;
+
case OPTION_WEAKEN:
weaken = true;
break;
+
case OPTION_ADD_SECTION:
{
const char *s;
@@ -1834,9 +1938,11 @@ copy_main (argc, argv)
add_sections = pa;
}
break;
+
case OPTION_CHANGE_START:
change_start = parse_vma (optarg, "--change-start");
break;
+
case OPTION_CHANGE_SECTION_ADDRESS:
case OPTION_CHANGE_SECTION_LMA:
case OPTION_CHANGE_SECTION_VMA:
@@ -1908,19 +2014,24 @@ copy_main (argc, argv)
}
}
break;
+
case OPTION_CHANGE_ADDRESSES:
change_section_address = parse_vma (optarg, "--change-addresses");
change_start = change_section_address;
break;
+
case OPTION_CHANGE_WARNINGS:
change_warn = true;
break;
+
case OPTION_CHANGE_LEADING_CHAR:
change_leading_char = true;
break;
+
case OPTION_DEBUGGING:
convert_debugging = true;
break;
+
case OPTION_GAP_FILL:
{
bfd_vma gap_fill_vma;
@@ -1939,16 +2050,54 @@ copy_main (argc, argv)
gap_fill_set = true;
}
break;
+
case OPTION_NO_CHANGE_WARNINGS:
change_warn = false;
break;
+
case OPTION_PAD_TO:
pad_to = parse_vma (optarg, "--pad-to");
pad_to_set = true;
break;
+
case OPTION_REMOVE_LEADING_CHAR:
remove_leading_char = true;
break;
+
+ case OPTION_REDEFINE_SYM:
+ {
+ /* Push this redefinition onto redefine_symbol_list. */
+
+ int len;
+ const char *s;
+ const char *nextarg;
+ char *source, *target;
+
+ s = strchr (optarg, '=');
+ if (s == NULL)
+ {
+ fprintf (stderr, "%s: bad format for --redefine-sym\n",
+ program_name);
+ exit (1);
+ }
+
+ len = s - optarg;
+ source = (char *) xmalloc (len + 1);
+ strncpy (source, optarg, len);
+ source[len] = '\0';
+
+ nextarg = s + 1;
+ len = strlen (nextarg);
+ target = (char *) xmalloc (len + 1);
+ strcpy (target, nextarg);
+
+ redefine_list_append (source, target);
+
+ free (source);
+ free (target);
+ }
+ break;
+
case OPTION_SET_SECTION_FLAGS:
{
const char *s;
@@ -1970,14 +2119,18 @@ copy_main (argc, argv)
p->flags = parse_flags (s + 1);
}
break;
+
case OPTION_SET_START:
set_start = parse_vma (optarg, "--set-start");
set_start_set = true;
break;
+
case 0:
break; /* we've been given a long option */
+
case 'h':
copy_usage (stdout, 0);
+
default:
copy_usage (stderr, 1);
}