From 2b35fb28f397a26c0da03f7579116d28af2af824 Mon Sep 17 00:00:00 2001 From: Ronald Hoogenbllon Date: Wed, 21 Oct 2015 15:16:35 +0100 Subject: [PATCH] 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. --- 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(-) create mode 100644 binutils/testsuite/binutils-all/add-symbol.d diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 512471c555a..7b7f7486eb3 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,17 @@ +2015-10-21 Ronald Hoogenbllon + + 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 PR binutils/19147 diff --git a/binutils/NEWS b/binutils/NEWS index fb36cf1e036..b0508f880e8 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 =[
:][,] + * 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 d9936645677..7dc09c32139 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 324456aaf21..6f0f62a0f9f 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 --globalize-symbol for all in \n\ --keep-global-symbols -G for all symbols listed in \n\ --weaken-symbols -W for all symbols listed in \n\ + --add-symbol =[
:][,] Add a symbol\n\ --alt-machine-code Use the target's '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="); + } + + 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 79b5b250bd4..a44213614b8 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-10-21 Ronald Hoogenbllon + + PR binutils/19104 + * binutils-all/add-symbol.d: New test. + * binutils-all/objcopy.exp: Run the new test. + 2015-10-15 Alan Modra * 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 00000000000..d421dc96cba --- /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 252cb490928..bac0ccdb156 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" -- 2.30.2