diff options
Diffstat (limited to 'binutils/objcopy.c')
-rw-r--r-- | binutils/objcopy.c | 175 |
1 files changed, 172 insertions, 3 deletions
diff --git a/binutils/objcopy.c b/binutils/objcopy.c index de053b1..4afec5b 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -57,6 +57,7 @@ static void copy_section PARAMS ((bfd *, asection *, PTR)); static void get_sections PARAMS ((bfd *, asection *, PTR)); static int compare_section_lma PARAMS ((const PTR, const PTR)); static void add_specific_symbol PARAMS ((const char *, struct symlist **)); +static void add_specific_symbols PARAMS ((const char *, struct symlist **)); static boolean is_specified_symbol PARAMS ((const char *, struct symlist *)); static boolean is_strip_section PARAMS ((bfd *, asection *)); static unsigned int filter_symbols @@ -184,11 +185,13 @@ static boolean change_leading_char = false; static boolean remove_leading_char = false; -/* List of symbols to strip, keep, localize, weaken, or redefine. */ +/* List of symbols to strip, keep, localize, keep-global, 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 *keepglobal_specific_list = NULL; static struct symlist *weaken_specific_list = NULL; static struct redefine_node *redefine_sym_list = NULL; @@ -218,6 +221,11 @@ static boolean weaken = false; #define OPTION_REDEFINE_SYM (OPTION_WEAKEN + 1) #define OPTION_SREC_LEN (OPTION_REDEFINE_SYM + 1) #define OPTION_SREC_FORCES3 (OPTION_SREC_LEN + 1) +#define OPTION_STRIP_SYMBOLS (OPTION_SREC_FORCES3 + 1) +#define OPTION_KEEP_SYMBOLS (OPTION_STRIP_SYMBOLS + 1) +#define OPTION_LOCALIZE_SYMBOLS (OPTION_KEEP_SYMBOLS + 1) +#define OPTION_KEEPGLOBAL_SYMBOLS (OPTION_LOCALIZE_SYMBOLS + 1) +#define OPTION_WEAKEN_SYMBOLS (OPTION_KEEPGLOBAL_SYMBOLS + 1) /* Options to handle if running as "strip". */ @@ -280,6 +288,7 @@ static struct option copy_options[] = {"pad-to", required_argument, 0, OPTION_PAD_TO}, {"preserve-dates", no_argument, 0, 'p'}, {"localize-symbol", required_argument, 0, 'L'}, + {"keep-global-symbol", required_argument, 0, 'G'}, {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR}, {"remove-section", required_argument, 0, 'R'}, {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS}, @@ -296,6 +305,11 @@ static struct option copy_options[] = {"redefine-sym", required_argument, 0, OPTION_REDEFINE_SYM}, {"srec-len", required_argument, 0, OPTION_SREC_LEN}, {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3}, + {"keep-symbols", required_argument, 0, OPTION_KEEP_SYMBOLS}, + {"strip-symbols", required_argument, 0, OPTION_STRIP_SYMBOLS}, + {"keep-global-symbols", required_argument, 0, OPTION_KEEPGLOBAL_SYMBOLS}, + {"localize-symbols", required_argument, 0, OPTION_LOCALIZE_SYMBOLS}, + {"weaken-symbols", required_argument, 0, OPTION_WEAKEN_SYMBOLS}, {0, no_argument, 0, 0} }; @@ -341,6 +355,7 @@ copy_usage (stream, exit_status) -N --strip-symbol <name> Do not copy symbol <name>\n\ -K --keep-symbol <name> Only copy symbol <name>\n\ -L --localize-symbol <name> Force symbol <name> to be marked as a local\n\ + -G --keep-global-symbol <name> Localize all symbols except <name>\n\ -W --weaken-symbol <name> Force symbol <name> to be marked as a weak\n\ --weaken Force all global symbols to be marked as weak\n\ -x --discard-all Remove all non-global symbols\n\ @@ -370,6 +385,11 @@ copy_usage (stream, exit_status) --redefine-sym <old>=<new> Redefine symbol name <old> to <new>\n\ --srec-len <number> Restrict the length of generated Srecords\n\ --srec-forceS3 Restrict the type of generated Srecords to S3\n\ + --strip-symbols <file> -N for all symbols listed in <file>\n\ + --keep-symbols <file> -K for all symbols listed in <file>\n\ + --localize-symbols <file> -L for all symbols listed 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\ -v --verbose List all object files modified\n\ -V --version Display this program's version number\n\ -h --help Display this output\n\ @@ -518,6 +538,122 @@ add_specific_symbol (name, list) *list = tmp_list; } +/* Add symbols listed in `filename' to strip_specific_list. */ + +#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\t') +#define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') + +static void +add_specific_symbols (filename, list) + const char *filename; + struct symlist **list; +{ + struct stat st; + FILE * f; + char * line; + char * buffer; + unsigned int line_count; + + if (stat (filename, & st) < 0) + fatal (_("cannot stat: %s: %s"), filename, strerror (errno)); + if (st.st_size == 0) + return; + + buffer = (char *) xmalloc (st.st_size + 2); + f = fopen (filename, FOPEN_RT); + if (f == NULL) + fatal (_("cannot open: %s: %s"), filename, strerror (errno)); + + if (fread (buffer, 1, st.st_size, f) == 0 || ferror (f)) + fatal (_("%s: fread failed"), filename); + + fclose (f); + buffer [st.st_size] = '\n'; + buffer [st.st_size + 1] = '\0'; + + line_count = 1; + + for (line = buffer; * line != '\0'; line ++) + { + char * eol; + char * name; + char * name_end; + int finished = false; + + for (eol = line;; eol ++) + { + switch (* eol) + { + case '\n': + * eol = '\0'; + /* Cope with \n\r. */ + if (eol[1] == '\r') + ++ eol; + finished = true; + break; + + case '\r': + * eol = '\0'; + /* Cope with \r\n. */ + if (eol[1] == '\n') + ++ eol; + finished = true; + break; + + case 0: + finished = true; + break; + + case '#': + /* Line comment, Terminate the line here, in case a + name is present and then allow the rest of the + loop to find the real end of the line. */ + * eol = '\0'; + break; + + default: + break; + } + + if (finished) + break; + } + + /* A name may now exist somewhere between 'line' and 'eol'. + Strip off leading whitespace and trailing whitespace, + then add it to the list. */ + for (name = line; IS_WHITESPACE (* name); name ++) + ; + for (name_end = name; + (! IS_WHITESPACE (* name_end)) + && (! IS_LINE_TERMINATOR (* name_end)); + name_end ++) + ; + + if (! IS_LINE_TERMINATOR (* name_end)) + { + char * extra; + + for (extra = name_end + 1; IS_WHITESPACE (* extra); extra ++) + ; + + if (! IS_LINE_TERMINATOR (* extra)) + non_fatal (_("Ignoring rubbish found on line %d of %s"), + line_count, filename); + } + + * name_end = '\0'; + + if (name_end > name) + add_specific_symbol (name, list); + + /* Advance line pointer to end of line. The 'eol ++' in the for + loop above will then advance us to the start of the next line. */ + line = eol; + line_count ++; + } +} + /* See whether a symbol should be stripped or kept based on strip_specific_list and keep_symbols. */ @@ -636,6 +772,12 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) else if (relocatable /* Relocatable file. */ && (flags & (BSF_GLOBAL | BSF_WEAK)) != 0) keep = 1; + else if (bfd_decode_symclass (sym) == 'I') + /* Global symbols in $idata sections need to be retained + even if relocatable is false. External users of the + library containing the $idata section may reference these + symbols. */ + keep = 1; else if ((flags & BSF_GLOBAL) != 0 /* Global symbol. */ || (flags & BSF_WEAK) != 0 || bfd_is_und_section (bfd_get_section (sym)) @@ -665,7 +807,9 @@ filter_symbols (abfd, obfd, osyms, isyms, symcount) sym->flags |= BSF_WEAK; } if (keep && (flags & (BSF_GLOBAL | BSF_WEAK)) - && is_specified_symbol (name, localize_specific_list)) + && (is_specified_symbol (name, localize_specific_list) + || (keepglobal_specific_list != NULL + && ! is_specified_symbol (name, keepglobal_specific_list)))) { sym->flags &= ~(BSF_GLOBAL | BSF_WEAK); sym->flags |= BSF_LOCAL; @@ -977,6 +1121,7 @@ copy_object (ibfd, obfd) || strip_specific_list != NULL || keep_specific_list != NULL || localize_specific_list != NULL + || keepglobal_specific_list != NULL || weaken_specific_list != NULL || sections_removed || sections_copied @@ -1695,7 +1840,7 @@ strip_main (argc, argv) struct section_list *p; char *output_file = NULL; - while ((c = getopt_long (argc, argv, "I:O:F:K:N:R:o:sSpdgxXVv", + while ((c = getopt_long (argc, argv, "b:i:I:j:K:N:s:O:d:F:L:G:R:SpgxXVvW:", strip_options, (int *) 0)) != EOF) { switch (c) @@ -1903,6 +2048,10 @@ copy_main (argc, argv) add_specific_symbol (optarg, &localize_specific_list); break; + case 'G': + add_specific_symbol (optarg, &keepglobal_specific_list); + break; + case 'W': add_specific_symbol (optarg, &weaken_specific_list); break; @@ -2169,6 +2318,26 @@ copy_main (argc, argv) S3Forced = true; break; + case OPTION_STRIP_SYMBOLS: + add_specific_symbols (optarg, &strip_specific_list); + break; + + case OPTION_KEEP_SYMBOLS: + add_specific_symbols (optarg, &keep_specific_list); + break; + + case OPTION_LOCALIZE_SYMBOLS: + add_specific_symbols (optarg, &localize_specific_list); + break; + + case OPTION_KEEPGLOBAL_SYMBOLS: + add_specific_symbols (optarg, &keepglobal_specific_list); + break; + + case OPTION_WEAKEN_SYMBOLS: + add_specific_symbols (optarg, &weaken_specific_list); + break; + case 0: break; /* we've been given a long option */ |