📄 objcopy.c
字号:
else start = bfd_get_start_address (ibfd); start += change_start; if (!bfd_set_start_address (obfd, start) || !bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) & bfd_applicable_file_flags (obfd)))) RETURN_NONFATAL (bfd_get_filename (ibfd)); /* Copy architecture of input file to output file */ if (!bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd))) non_fatal (_("Warning: Output file cannot represent architecture %s"), bfd_printable_arch_mach (bfd_get_arch (ibfd), bfd_get_mach (ibfd))); if (!bfd_set_format (obfd, bfd_get_format (ibfd))) RETURN_NONFATAL (bfd_get_filename (ibfd)); if (isympp) free (isympp); if (osympp != isympp) free (osympp); /* BFD mandates that all output sections be created and sizes set before any output is done. Thus, we traverse all sections multiple times. */ bfd_map_over_sections (ibfd, setup_section, (void *) obfd); if (add_sections != NULL) { struct section_add *padd; struct section_list *pset; for (padd = add_sections; padd != NULL; padd = padd->next) { padd->section = bfd_make_section (obfd, padd->name); if (padd->section == NULL) { non_fatal (_("can't create section `%s': %s"), padd->name, bfd_errmsg (bfd_get_error ())); status = 1; return; } else { flagword flags; if (! bfd_set_section_size (obfd, padd->section, padd->size)) RETURN_NONFATAL (bfd_get_filename (obfd)); pset = find_section_list (padd->name, false); if (pset != NULL) pset->used = true; if (pset != NULL && pset->set_flags) flags = pset->flags | SEC_HAS_CONTENTS; else flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DATA; if (! bfd_set_section_flags (obfd, padd->section, flags)) RETURN_NONFATAL (bfd_get_filename (obfd)); if (pset != NULL) { if (pset->change_vma != CHANGE_IGNORE) if (! bfd_set_section_vma (obfd, padd->section, pset->vma_val)) RETURN_NONFATAL (bfd_get_filename (obfd)); if (pset->change_lma != CHANGE_IGNORE) { padd->section->lma = pset->lma_val; if (! bfd_set_section_alignment (obfd, padd->section, bfd_section_alignment (obfd, padd->section))) RETURN_NONFATAL (bfd_get_filename (obfd)); } } } } } if (gap_fill_set || pad_to_set) { asection **set; unsigned int c, i; /* We must fill in gaps between the sections and/or we must pad the last section to a specified address. We do this by grabbing a list of the sections, sorting them by VMA, and increasing the section sizes as required to fill the gaps. We write out the gap contents below. */ c = bfd_count_sections (obfd); osections = (asection **) xmalloc (c * sizeof (asection *)); set = osections; bfd_map_over_sections (obfd, get_sections, (void *) &set); qsort (osections, c, sizeof (asection *), compare_section_lma); gaps = (bfd_size_type *) xmalloc (c * sizeof (bfd_size_type)); memset (gaps, 0, c * sizeof (bfd_size_type)); if (gap_fill_set) { for (i = 0; i < c - 1; i++) { flagword flags; bfd_size_type size; bfd_vma gap_start, gap_stop; flags = bfd_get_section_flags (obfd, osections[i]); if ((flags & SEC_HAS_CONTENTS) == 0 || (flags & SEC_LOAD) == 0) continue; size = bfd_section_size (obfd, osections[i]); gap_start = bfd_section_lma (obfd, osections[i]) + size; gap_stop = bfd_section_lma (obfd, osections[i + 1]); if (gap_start < gap_stop) { if (! bfd_set_section_size (obfd, osections[i], size + (gap_stop - gap_start))) { non_fatal (_("Can't fill gap after %s: %s"), bfd_get_section_name (obfd, osections[i]), bfd_errmsg (bfd_get_error ())); status = 1; break; } gaps[i] = gap_stop - gap_start; if (max_gap < gap_stop - gap_start) max_gap = gap_stop - gap_start; } } } if (pad_to_set) { bfd_vma lma; bfd_size_type size; lma = bfd_section_lma (obfd, osections[c - 1]); size = bfd_section_size (obfd, osections[c - 1]); if (lma + size < pad_to) { if (! bfd_set_section_size (obfd, osections[c - 1], pad_to - lma)) { non_fatal (_("Can't add padding to %s: %s"), bfd_get_section_name (obfd, osections[c - 1]), bfd_errmsg (bfd_get_error ())); status = 1; } else { gaps[c - 1] = pad_to - (lma + size); if (max_gap < pad_to - (lma + size)) max_gap = pad_to - (lma + size); } } } } /* Symbol filtering must happen after the output sections have been created, but before their contents are set. */ dhandle = NULL; symsize = bfd_get_symtab_upper_bound (ibfd); if (symsize < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); osympp = isympp = (asymbol **) xmalloc (symsize); symcount = bfd_canonicalize_symtab (ibfd, isympp); if (symcount < 0) RETURN_NONFATAL (bfd_get_filename (ibfd)); if (convert_debugging) dhandle = read_debugging_info (ibfd, isympp, symcount); if (strip_symbols == STRIP_DEBUG || strip_symbols == STRIP_ALL || strip_symbols == STRIP_UNNEEDED || discard_locals != LOCALS_UNDEF || strip_specific_list != NULL || keep_specific_list != NULL || localize_specific_list != NULL || keepglobal_specific_list != NULL || weaken_specific_list != NULL || sections_removed || sections_copied || convert_debugging || change_leading_char || remove_leading_char || redefine_sym_list || weaken) { /* Mark symbols used in output relocations so that they are kept, even if they are local labels or static symbols. Note we iterate over the input sections examining their relocations since the relocations for the output sections haven't been set yet. mark_symbols_used_in_relocations will ignore input sections which have no corresponding output section. */ if (strip_symbols != STRIP_ALL) bfd_map_over_sections (ibfd, mark_symbols_used_in_relocations, (PTR)isympp); osympp = (asymbol **) xmalloc ((symcount + 1) * sizeof (asymbol *)); symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount); } if (convert_debugging && dhandle != NULL) { if (! write_debugging_info (obfd, dhandle, &symcount, &osympp)) { status = 1; return; } } bfd_set_symtab (obfd, osympp, symcount); /* This has to happen after the symbol table has been set. */ bfd_map_over_sections (ibfd, copy_section, (void *) obfd); if (add_sections != NULL) { struct section_add *padd; for (padd = add_sections; padd != NULL; padd = padd->next) { if (! bfd_set_section_contents (obfd, padd->section, (PTR) padd->contents, (file_ptr) 0, (bfd_size_type) padd->size)) RETURN_NONFATAL (bfd_get_filename (obfd)); } } if (gap_fill_set || pad_to_set) { bfd_byte *buf; int c, i; /* Fill in the gaps. */ if (max_gap > 8192) max_gap = 8192; buf = (bfd_byte *) xmalloc (max_gap); memset (buf, gap_fill, (size_t) max_gap); c = bfd_count_sections (obfd); for (i = 0; i < c; i++) { if (gaps[i] != 0) { bfd_size_type left; file_ptr off; left = gaps[i]; off = bfd_section_size (obfd, osections[i]) - left; while (left > 0) { bfd_size_type now; if (left > 8192) now = 8192; else now = left; if (! bfd_set_section_contents (obfd, osections[i], buf, off, now)) RETURN_NONFATAL (bfd_get_filename (obfd)); left -= now; off += now; } } } } /* Allow the BFD backend to copy any private data it understands from the input BFD to the output BFD. This is done last to permit the routine to look at the filtered symbol table, which is important for the ECOFF code at least. */ if (!bfd_copy_private_bfd_data (ibfd, obfd)) { non_fatal (_("%s: error copying private BFD data: %s"), bfd_get_filename (obfd), bfd_errmsg (bfd_get_error ())); status = 1; return; }}/* Read each archive element in turn from IBFD, copy the contents to temp file, and keep the temp file handle. */static voidcopy_archive (ibfd, obfd, output_target) bfd *ibfd; bfd *obfd; const char *output_target;{ struct name_list { struct name_list *next; char *name; bfd *obfd; } *list, *l; bfd **ptr = &obfd->archive_head; bfd *this_element; char *dir = make_tempname (bfd_get_filename (obfd)); /* Make a temp directory to hold the contents. */#if defined (_WIN32) && !defined (__CYGWIN32__) if (mkdir (dir) != 0)#else if (mkdir (dir, 0700) != 0)#endif { fatal (_("cannot mkdir %s for archive copying (error: %s)"), dir, strerror (errno)); } obfd->has_armap = ibfd->has_armap; list = NULL; this_element = bfd_openr_next_archived_file (ibfd, NULL); while (!status && this_element != (bfd *) NULL) { /* Create an output file for this member. */ char *output_name = concat (dir, "/", bfd_get_filename (this_element), (char *) NULL); bfd *output_bfd = bfd_openw (output_name, output_target); bfd *last_element; struct stat buf; int stat_status = 0; if (preserve_dates) { stat_status = bfd_stat_arch_elt (this_element, &buf); if (stat_status != 0) non_fatal (_("internal stat error on %s"), bfd_get_filename (this_element)); } l = (struct name_list *) xmalloc (sizeof (struct name_list)); l->name = output_name; l->next = list; list = l; if (output_bfd == (bfd *) NULL) RETURN_NONFATAL (output_name); if (!bfd_set_format (obfd, bfd_get_format (ibfd))) RETURN_NONFATAL (bfd_get_filename (obfd)); if (bfd_check_format (this_element, bfd_object) == true) copy_object (this_element, output_bfd); if (!bfd_close (output_bfd)) { bfd_nonfatal (bfd_get_filename (output_bfd)); /* Error in new object file. Don't change archive. */ status = 1; } if (preserve_dates && stat_status == 0) set_times (output_name, &buf); /* Open the newly output file and attach to our list. */ output_bfd = bfd_openr (output_name, output_target); l->obfd = output_bfd; *ptr = output_bfd; ptr = &output_bfd->next; last_element = this_element; this_element = bfd_openr_next_archived_file (ibfd, last_element); bfd_close (last_element); } *ptr = (bfd *) NULL; if (!bfd_close (obfd)) RETURN_NONFATAL (bfd_get_filename (obfd)); if (!bfd_close (ibfd)) RETURN_NONFATAL (bfd_get_filename (ibfd)); /* Delete all the files that we opened. */ for (l = list; l != NULL; l = l->next) { bfd_close (l->obfd); unlink (l->name); } rmdir (dir);}/* The top-level control. */static voidcopy_file (input_filename, output_filename, input_target, output_target) const char *input_filename; const char *output_filename; const char *input_target; const char *output_target;{ bfd *ibfd; char **matching; /* To allow us to do "strip *" without dying on the first non-object file, failures are nonfatal. */ ibfd = bfd_openr (input_filename, input_target); if (ibfd == NULL) RETURN_NONFATAL (input_filename); if (bfd_check_format (ibfd, bfd_archive)) { bfd *obfd; /* bfd_get_target does not return the correct value until bfd_check_format succeeds. */ if (output_target == NULL) output_target = bfd_get_target (ibfd); obfd = bfd_openw (output_filename, output_target); if (obfd == NULL) RETURN_NONFATAL (output_filename); copy_archive (ibfd, obfd, output_target); } else if (bfd_check_format_matches (ibfd, bfd_object, &matching)) { bfd *obfd; /* bfd_get_target does not return the correct value until bfd_check_format succeeds. */ if (output_target == NULL) output_target = bfd_get_target (ibfd); obfd = bfd_openw (output_filename, output_target); if (obfd == NULL) RETURN_NONFATAL (output_filename); copy_object (ibfd, obfd); if (!bfd_close (obfd)) RETURN_NONFATAL (output_filename); if (!bfd_close (ibfd)) RETURN_NONFATAL (input_filename); } else { bfd_nonfatal (input_filename); if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -