X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=binutils%2Fobjcopy.c;h=1d29059b8df90eebab2dc9ec99ff1796f7ff2a3b;hb=34156b23862e9719355569182d594c7a9e38047e;hp=77193b155e376cfb17e1bc072a8d6cf8f00f7b71;hpb=6f156d7a4ad1c245b357dc50f63f3564d397839e;p=binutils-gdb.git diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 77193b155e3..1d29059b8df 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -253,6 +253,14 @@ static htab_t redefine_specific_reverse_htab = NULL; static struct addsym_node *add_sym_list = NULL, **add_sym_tail = &add_sym_list; static int add_symbols = 0; +static char *strip_specific_buffer = NULL; +static char *strip_unneeded_buffer = NULL; +static char *keep_specific_buffer = NULL; +static char *localize_specific_buffer = NULL; +static char *globalize_specific_buffer = NULL; +static char *keepglobal_specific_buffer = NULL; +static char *weaken_specific_buffer = NULL; + /* If this is TRUE, we weaken global symbols (set BSF_WEAK). */ static bfd_boolean weaken = FALSE; @@ -1034,7 +1042,7 @@ add_specific_symbol_node (const void *node, htab_t htab) #define IS_LINE_TERMINATOR(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') static void -add_specific_symbols (const char *filename, htab_t htab) +add_specific_symbols (const char *filename, htab_t htab, char **buffer_p) { off_t size; FILE * f; @@ -1142,6 +1150,10 @@ add_specific_symbols (const char *filename, htab_t htab) line = eol; line_count ++; } + + /* Do not free the buffer. Parts of it will have been referenced + in the calls to add_specific_symbol. */ + *buffer_p = buffer; } /* See whether a symbol should be stripped or kept @@ -1211,14 +1223,13 @@ group_signature (asection *group) return NULL; ghdr = &elf_section_data (group)->this_hdr; - if (ghdr->sh_link < elf_numsections (abfd)) + if (ghdr->sh_link == elf_onesymtab (abfd)) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); - Elf_Internal_Shdr *symhdr = elf_elfsections (abfd) [ghdr->sh_link]; + Elf_Internal_Shdr *symhdr = &elf_symtab_hdr (abfd); - if (symhdr->sh_type == SHT_SYMTAB - && ghdr->sh_info > 0 - && ghdr->sh_info < (symhdr->sh_size / bed->s->sizeof_sym)) + if (ghdr->sh_info > 0 + && ghdr->sh_info < symhdr->sh_size / bed->s->sizeof_sym) return isympp[ghdr->sh_info - 1]; } return NULL; @@ -1344,14 +1355,15 @@ is_strip_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) const char *gname; asection *elt, *first; + gsym = group_signature (sec); + /* Strip groups without a valid signature. */ + if (gsym == NULL) + return TRUE; + /* PR binutils/3181 If we are going to strip the group signature symbol, then strip the group section too. */ - gsym = group_signature (sec); - if (gsym != NULL) - gname = gsym->name; - else - gname = sec->name; + gname = gsym->name; if ((strip_symbols == STRIP_ALL && !is_specified_symbol (gname, keep_specific_htab)) || is_specified_symbol (gname, strip_specific_htab)) @@ -1817,6 +1829,7 @@ add_redefine_syms_file (const char *filename) fatal (_("%s:%d: premature end of file"), filename, lineno); free (buf); + fclose (file); } /* Copy unknown object file IBFD onto OBFD. @@ -2064,7 +2077,7 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte For now though, since v1 and v2 was not intended to handle gaps, we chose an artificially large end address. */ - end = 0x7ffffffffffffffUL; + end = (bfd_vma) -1; break; case 8: @@ -2083,7 +2096,7 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte For now though, since v1 and v2 was not intended to handle gaps, we chose an artificially large end address. */ - end = 0x7ffffffffffffffUL; + end = (bfd_vma) -1; } break; @@ -2174,7 +2187,7 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte 3. Eliminate any NT_GNU_BUILD_ATTRIBUTE_OPEN notes that have the same full name field as the immediately preceeding note with the same type of name and whose address ranges coincide. - IE - it there are gaps in the coverage of the notes, then these gaps + IE - if there are gaps in the coverage of the notes, then these gaps must be preserved. 4. Combine the numeric value of any NT_GNU_BUILD_ATTRIBUTE_OPEN notes of type GNU_BUILD_ATTRIBUTE_STACK_SIZE. @@ -2182,16 +2195,48 @@ merge_gnu_build_notes (bfd * abfd, asection * sec, bfd_size_type size, bfd_byte its description field is empty then the nearest preceeding OPEN note with a non-empty description field must also be preserved *OR* the description field of the note must be changed to contain the starting - address to which it refers. */ + address to which it refers. + 6. Notes with the same start and end address can be deleted. */ for (pnote = pnotes + 1; pnote < pnotes_end; pnote ++) { int note_type; objcopy_internal_note * back; objcopy_internal_note * prev_open_with_range = NULL; + /* Rule 6 - delete 0-range notes. */ + if (pnote->start == pnote->end) + { + duplicate_found = TRUE; + pnote->note.type = 0; + continue; + } + /* Rule 2 - preserve function notes. */ if (! is_open_note (pnote)) - continue; + { + int iter; + + /* Check to see if there is an identical previous function note. + This can happen with overlays for example. */ + for (iter = 0, back = pnote -1; back >= pnotes; back --) + { + if (back->start == pnote->start + && back->end == pnote->end + && back->note.namesz == pnote->note.namesz + && memcmp (back->note.namedata, pnote->note.namedata, pnote->note.namesz) == 0) + { + fprintf (stderr, "DUP FUNXC\n"); + duplicate_found = TRUE; + pnote->note.type = 0; + break; + } + + /* Don't scan too far back however. */ + if (iter ++ > 16) + break; + } + continue; + } note_type = pnote->note.namedata[attribute_type_byte]; @@ -2823,6 +2868,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) pdump->filename, strerror (errno)); free (contents); + fclose (f); return FALSE; } } @@ -3023,9 +3069,18 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) ignore input sections which have no corresponding output section. */ if (strip_symbols != STRIP_ALL) - bfd_map_over_sections (ibfd, - mark_symbols_used_in_relocations, - isympp); + { + bfd_set_error (bfd_error_no_error); + bfd_map_over_sections (ibfd, + mark_symbols_used_in_relocations, + isympp); + if (bfd_get_error () != bfd_error_no_error) + { + status = 1; + return FALSE; + } + } + osympp = (asymbol **) xmalloc ((symcount + add_symbols + 1) * sizeof (asymbol *)); symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount); } @@ -3144,6 +3199,7 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) off, now)) { bfd_nonfatal_message (NULL, obfd, osections[i], NULL); + free (buf); return FALSE; } @@ -3152,6 +3208,10 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) } } } + + free (buf); + free (gaps); + gaps = NULL; } /* Allow the BFD backend to copy any private data it understands @@ -3262,8 +3322,10 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, /* If the file already exists, make another temp dir. */ if (stat (output_name, &buf) >= 0) { - output_name = make_tempdir (output_name); - if (output_name == NULL) + char * tmpdir = make_tempdir (output_name); + + free (output_name); + if (tmpdir == NULL) { non_fatal (_("cannot create tempdir for archive copying (error: %s)"), strerror (errno)); @@ -3272,11 +3334,11 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, } l = (struct name_list *) xmalloc (sizeof (struct name_list)); - l->name = output_name; + l->name = tmpdir; l->next = list; l->obfd = NULL; list = l; - output_name = concat (output_name, "/", + output_name = concat (tmpdir, "/", bfd_get_filename (this_element), (char *) 0); } @@ -3383,16 +3445,22 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target, cleanup_and_exit: /* Delete all the files that we opened. */ - for (l = list; l != NULL; l = l->next) - { - if (l->obfd == NULL) - rmdir (l->name); - else - { - bfd_close (l->obfd); - unlink (l->name); - } - } + { + struct name_list * next; + + for (l = list; l != NULL; l = next) + { + if (l->obfd == NULL) + rmdir (l->name); + else + { + bfd_close (l->obfd); + unlink (l->name); + } + next = l->next; + free (l); + } + } rmdir (dir); } @@ -3884,21 +3952,22 @@ discard_relocations (bfd *ibfd ATTRIBUTE_UNUSED, asection *isection) /* Wrapper for dealing with --remove-section (-R) command line arguments. A special case is detected here, if the user asks to remove a relocation - section (one starting with ".rela." or ".rel.") then this removal must - be done using a different technique. */ + section (one starting with ".rela" or ".rel") then this removal must + be done using a different technique in a relocatable object. */ static void handle_remove_section_option (const char *section_pattern) { - if (strncmp (section_pattern, ".rela.", 6) == 0) - handle_remove_relocations_option (section_pattern + 5); - else if (strncmp (section_pattern, ".rel.", 5) == 0) - handle_remove_relocations_option (section_pattern + 4); - else + find_section_list (section_pattern, TRUE, SECTION_CONTEXT_REMOVE); + if (strncmp (section_pattern, ".rel", 4) == 0) { - find_section_list (section_pattern, TRUE, SECTION_CONTEXT_REMOVE); - sections_removed = TRUE; + section_pattern += 4; + if (*section_pattern == 'a') + section_pattern++; + if (*section_pattern) + handle_remove_relocations_option (section_pattern); } + sections_removed = TRUE; } /* Copy relocations in input section ISECTION of IBFD to an output @@ -4242,13 +4311,10 @@ write_debugging_info (bfd *obfd, void *dhandle, long *symcountp ATTRIBUTE_UNUSED, asymbol ***symppp ATTRIBUTE_UNUSED) { - if (bfd_get_flavour (obfd) == bfd_target_ieee_flavour) - return write_ieee_debugging_info (obfd, dhandle); - if (bfd_get_flavour (obfd) == bfd_target_coff_flavour || bfd_get_flavour (obfd) == bfd_target_elf_flavour) { - bfd_byte *syms, *strings; + bfd_byte *syms, *strings = NULL; bfd_size_type symsize, stringsize; asection *stabsec, *stabstrsec; flagword flags; @@ -4270,6 +4336,7 @@ write_debugging_info (bfd *obfd, void *dhandle, { bfd_nonfatal_message (NULL, obfd, NULL, _("can't create debugging section")); + free (strings); return FALSE; } @@ -4283,6 +4350,7 @@ write_debugging_info (bfd *obfd, void *dhandle, { bfd_nonfatal_message (NULL, obfd, NULL, _("can't set debugging section contents")); + free (strings); return FALSE; } @@ -4685,6 +4753,8 @@ copy_main (int argc, char *argv[]) bfd_boolean show_version = FALSE; bfd_boolean change_warn = TRUE; bfd_boolean formats_info = FALSE; + bfd_boolean use_globalize = FALSE; + bfd_boolean use_keep_global = FALSE; int c; struct stat statbuf; const bfd_arch_info_type *input_arch = NULL; @@ -4803,10 +4873,12 @@ copy_main (int argc, char *argv[]) break; case OPTION_GLOBALIZE_SYMBOL: + use_globalize = TRUE; add_specific_symbol (optarg, globalize_specific_htab); break; case 'G': + use_keep_global = TRUE; add_specific_symbol (optarg, keepglobal_specific_htab); break; @@ -5203,15 +5275,18 @@ copy_main (int argc, char *argv[]) break; case OPTION_STRIP_SYMBOLS: - add_specific_symbols (optarg, strip_specific_htab); + add_specific_symbols (optarg, strip_specific_htab, + &strip_specific_buffer); break; case OPTION_STRIP_UNNEEDED_SYMBOLS: - add_specific_symbols (optarg, strip_unneeded_htab); + add_specific_symbols (optarg, strip_unneeded_htab, + &strip_unneeded_buffer); break; case OPTION_KEEP_SYMBOLS: - add_specific_symbols (optarg, keep_specific_htab); + add_specific_symbols (optarg, keep_specific_htab, + &keep_specific_buffer); break; case OPTION_LOCALIZE_HIDDEN: @@ -5219,7 +5294,8 @@ copy_main (int argc, char *argv[]) break; case OPTION_LOCALIZE_SYMBOLS: - add_specific_symbols (optarg, localize_specific_htab); + add_specific_symbols (optarg, localize_specific_htab, + &localize_specific_buffer); break; case OPTION_LONG_SECTION_NAMES: @@ -5234,15 +5310,20 @@ copy_main (int argc, char *argv[]) break; case OPTION_GLOBALIZE_SYMBOLS: - add_specific_symbols (optarg, globalize_specific_htab); + use_globalize = TRUE; + add_specific_symbols (optarg, globalize_specific_htab, + &globalize_specific_buffer); break; case OPTION_KEEPGLOBAL_SYMBOLS: - add_specific_symbols (optarg, keepglobal_specific_htab); + use_keep_global = TRUE; + add_specific_symbols (optarg, keepglobal_specific_htab, + &keepglobal_specific_buffer); break; case OPTION_WEAKEN_SYMBOLS: - add_specific_symbols (optarg, weaken_specific_htab); + add_specific_symbols (optarg, weaken_specific_htab, + &weaken_specific_buffer); break; case OPTION_ALT_MACH_CODE: @@ -5371,6 +5452,9 @@ copy_main (int argc, char *argv[]) } } + if (use_globalize && use_keep_global) + fatal(_("--globalize-symbol(s) is incompatible with -G/--keep-global-symbol(s)")); + if (formats_info) { display_info (); @@ -5529,6 +5613,27 @@ copy_main (int argc, char *argv[]) } } + if (strip_specific_buffer) + free (strip_specific_buffer); + + if (strip_unneeded_buffer) + free (strip_unneeded_buffer); + + if (keep_specific_buffer) + free (keep_specific_buffer); + + if (localize_specific_buffer) + free (globalize_specific_buffer); + + if (globalize_specific_buffer) + free (globalize_specific_buffer); + + if (keepglobal_specific_buffer) + free (keepglobal_specific_buffer); + + if (weaken_specific_buffer) + free (weaken_specific_buffer); + return 0; } @@ -5554,7 +5659,8 @@ main (int argc, char *argv[]) strip_symbols = STRIP_UNDEF; discard_locals = LOCALS_UNDEF; - bfd_init (); + if (bfd_init () != BFD_INIT_MAGIC) + fatal (_("fatal error: libbfd ABI mismatch")); set_default_bfd_target (); if (is_strip < 0)