📄 objcopy.c
字号:
PARSE_FLAG ("contents", SEC_HAS_CONTENTS);#undef PARSE_FLAG else { char *copy; copy = xmalloc (len + 1); strncpy (copy, s, len); copy[len] = '\0'; non_fatal (_("unrecognized section flag `%s'"), copy); fatal (_("supported flags: %s"), "alloc, load, noload, readonly, debug, code, data, rom, share, contents"); } s = snext; } while (s != NULL); return ret;}/* Find and optionally add an entry in the change_sections list. */static struct section_list *find_section_list (name, add) const char *name; boolean add;{ register struct section_list *p; for (p = change_sections; p != NULL; p = p->next) if (strcmp (p->name, name) == 0) return p; if (! add) return NULL; p = (struct section_list *) xmalloc (sizeof (struct section_list)); p->name = name; p->used = false; p->remove = false; p->copy = false; p->change_vma = CHANGE_IGNORE; p->change_lma = CHANGE_IGNORE; p->vma_val = 0; p->lma_val = 0; p->set_flags = false; p->flags = 0; p->next = change_sections; change_sections = p; return p;}/* Add a symbol to strip_specific_list. */static voidadd_specific_symbol (name, list) const char *name; struct symlist **list;{ struct symlist *tmp_list; tmp_list = (struct symlist *) xmalloc (sizeof (struct symlist)); tmp_list->name = name; tmp_list->next = *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 voidadd_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. */static booleanis_specified_symbol (name, list) const char *name; struct symlist *list;{ struct symlist *tmp_list; for (tmp_list = list; tmp_list; tmp_list = tmp_list->next) { if (strcmp (name, tmp_list->name) == 0) return true; } return false;}/* See if a section is being removed. */static booleanis_strip_section (abfd, sec) bfd *abfd ATTRIBUTE_UNUSED; asection *sec;{ struct section_list *p; if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING) != 0 && (strip_symbols == STRIP_DEBUG || strip_symbols == STRIP_UNNEEDED || strip_symbols == STRIP_ALL || discard_locals == LOCALS_ALL || convert_debugging)) return true; if (! sections_removed && ! sections_copied) return false; p = find_section_list (bfd_get_section_name (abfd, sec), false); if (sections_removed && p != NULL && p->remove) return true; if (sections_copied && (p == NULL || ! p->copy)) return true; return false;}/* 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. */static unsigned intfilter_symbols (abfd, obfd, osyms, isyms, symcount) bfd *abfd; bfd *obfd; asymbol **osyms, **isyms; long symcount;{ register asymbol **from = isyms, **to = osyms; long src_count = 0, dst_count = 0; int relocatable = (abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) == HAS_RELOC; for (; src_count < symcount; src_count++) { asymbol *sym = from[src_count]; flagword flags = sym->flags; 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)) && (bfd_get_symbol_leading_char (abfd) == '\0' || (name[0] == bfd_get_symbol_leading_char (abfd)))) { if (bfd_get_symbol_leading_char (obfd) == '\0') name = bfd_asymbol_name (sym) = name + 1; else { char *n; n = xmalloc (strlen (name) + 2); n[0] = bfd_get_symbol_leading_char (obfd); if (bfd_get_symbol_leading_char (abfd) == '\0') strcpy (n + 1, name); else strcpy (n + 1, name + 1); name = bfd_asymbol_name (sym) = n; } } if (remove_leading_char && ((flags & BSF_GLOBAL) != 0 || (flags & BSF_WEAK) != 0 || bfd_is_und_section (bfd_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym))) && name[0] == bfd_get_symbol_leading_char (abfd)) name = bfd_asymbol_name (sym) = name + 1; if (strip_symbols == STRIP_ALL) keep = 0; else if ((flags & BSF_KEEP) != 0 /* Used in relocation. */ || ((flags & BSF_SECTION_SYM) != 0 && ((*bfd_get_section (sym)->symbol_ptr_ptr)->flags & BSF_KEEP) != 0)) keep = 1; 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)) || bfd_is_com_section (bfd_get_section (sym))) keep = strip_symbols != STRIP_UNNEEDED; else if ((flags & BSF_DEBUGGING) != 0) /* Debugging symbol. */ keep = (strip_symbols != STRIP_DEBUG && strip_symbols != STRIP_UNNEEDED && ! convert_debugging); else /* Local symbol. */ keep = (strip_symbols != STRIP_UNNEEDED && (discard_locals != LOCALS_ALL && (discard_locals != LOCALS_START_L || ! bfd_is_local_label (abfd, sym)))); if (keep && is_specified_symbol (name, strip_specific_list)) keep = 0; if (!keep && is_specified_symbol (name, keep_specific_list)) keep = 1; if (keep && is_strip_section (abfd, bfd_get_section (sym))) keep = 0; if (keep && (flags & BSF_GLOBAL) != 0 && (weaken || is_specified_symbol (name, weaken_specific_list))) { sym->flags &=~ BSF_GLOBAL; sym->flags |= BSF_WEAK; } if (keep && (flags & (BSF_GLOBAL | BSF_WEAK)) && (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; } if (keep) to[dst_count++] = sym; } to[dst_count] = NULL; 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 voidredefine_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) { fatal (_("%s: Multiple redefinition of symbol \"%s\""), "--redefine-sym", source); } if (strcmp (target, list->target) == 0) { fatal (_("%s: Symbol \"%s\" is target of more than one redefinition"), "--redefine-sym", target); } } 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. */static voidfilter_bytes (memhunk, size) char *memhunk; bfd_size_type *size;{ char *from = memhunk + copy_byte, *to = memhunk, *end = memhunk + *size; for (; from < end; from += interleave) *to++ = *from; if (*size % interleave > (bfd_size_type) copy_byte) *size = (*size / interleave) + 1; else *size /= interleave;}/* Copy object file IBFD onto OBFD. */static voidcopy_object (ibfd, obfd) bfd *ibfd; bfd *obfd;{ bfd_vma start; long symcount; asection **osections = NULL; bfd_size_type *gaps = NULL; bfd_size_type max_gap = 0; long symsize; PTR dhandle; if (ibfd->xvec->byteorder != obfd->xvec->byteorder && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) { fatal (_("Unable to change endianness of input file(s)")); return; } if (!bfd_set_format (obfd, bfd_get_format (ibfd))) RETURN_NONFATAL (bfd_get_filename (obfd)); if (verbose) printf (_("copy from %s(%s) to %s(%s)\n"), bfd_get_filename (ibfd), bfd_get_target (ibfd), bfd_get_filename (obfd), bfd_get_target (obfd)); if (set_start_set) start = set_start;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -