coffgen.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,343 行 · 第 1/5 页
C
2,343 行
/* Support for the generic parts of COFF, for BFD. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Written by Cygnus Support.This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Most of this hacked by Steve Chamberlain, sac@cygnus.com. Split out of coffcode.h by Ian Taylor, ian@cygnus.com. *//* This file contains COFF code that is not dependent on any particular COFF target. There is only one version of this file in libbfd.a, so no target specific code may be put in here. Or, to put it another way, ********** DO NOT PUT TARGET SPECIFIC CODE IN THIS FILE ********** If you need to add some target specific behaviour, add a new hook function to bfd_coff_backend_data. Some of these functions are also called by the ECOFF routines. Those functions may not use any COFF specific information, such as coff_data (abfd). */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "coff/internal.h"#include "libcoff.h"static void coff_fix_symbol_name PARAMS ((bfd *, asymbol *, combined_entry_type *, bfd_size_type *, asection **, bfd_size_type *));static boolean coff_write_symbol PARAMS ((bfd *, asymbol *, combined_entry_type *, unsigned int *, bfd_size_type *, asection **, bfd_size_type *));static boolean coff_write_alien_symbol PARAMS ((bfd *, asymbol *, unsigned int *, bfd_size_type *, asection **, bfd_size_type *));static boolean coff_write_native_symbol PARAMS ((bfd *, coff_symbol_type *, unsigned int *, bfd_size_type *, asection **, bfd_size_type *));static void coff_pointerize_aux PARAMS ((bfd *, combined_entry_type *, combined_entry_type *, unsigned int, combined_entry_type *));static boolean make_a_section_from_file PARAMS ((bfd *, struct internal_scnhdr *, unsigned int));static const bfd_target *coff_real_object_p PARAMS ((bfd *, unsigned, struct internal_filehdr *, struct internal_aouthdr *));static void fixup_symbol_value PARAMS ((bfd *, coff_symbol_type *, struct internal_syment *));static char *build_debug_section PARAMS ((bfd *));static char *copy_name PARAMS ((bfd *, char *, int));#define STRING_SIZE_SIZE (4)/* Take a section header read from a coff file (in HOST byte order), and make a BFD "section" out of it. This is used by ECOFF. */static booleanmake_a_section_from_file (abfd, hdr, target_index) bfd *abfd; struct internal_scnhdr *hdr; unsigned int target_index;{ asection *return_section; char *name; name = NULL; /* Handle long section names as in PE. */ if (bfd_coff_long_section_names (abfd) && hdr->s_name[0] == '/') { char buf[SCNNMLEN]; long strindex; char *p; const char *strings; memcpy (buf, hdr->s_name + 1, SCNNMLEN - 1); buf[SCNNMLEN - 1] = '\0'; strindex = strtol (buf, &p, 10); if (*p == '\0' && strindex >= 0) { strings = _bfd_coff_read_string_table (abfd); if (strings == NULL) return false; /* FIXME: For extra safety, we should make sure that strindex does not run us past the end, but right now we don't know the length of the string table. */ strings += strindex; name = bfd_alloc (abfd, strlen (strings) + 1); if (name == NULL) return false; strcpy (name, strings); } } if (name == NULL) { /* Assorted wastage to null-terminate the name, thanks AT&T! */ name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1); if (name == NULL) return false; strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name)); name[sizeof (hdr->s_name)] = 0; } return_section = bfd_make_section_anyway (abfd, name); if (return_section == NULL) return false; return_section->vma = hdr->s_vaddr; return_section->lma = hdr->s_paddr; return_section->_raw_size = hdr->s_size; return_section->filepos = hdr->s_scnptr; return_section->rel_filepos = hdr->s_relptr; return_section->reloc_count = hdr->s_nreloc; bfd_coff_set_alignment_hook (abfd, return_section, hdr); return_section->line_filepos = hdr->s_lnnoptr; return_section->lineno_count = hdr->s_nlnno; return_section->userdata = NULL; return_section->next = (asection *) NULL; return_section->target_index = target_index; return_section->flags = bfd_coff_styp_to_sec_flags_hook (abfd, hdr, name, return_section); /* At least on i386-coff, the line number count for a shared library section must be ignored. */ if ((return_section->flags & SEC_COFF_SHARED_LIBRARY) != 0) return_section->lineno_count = 0; if (hdr->s_nreloc != 0) return_section->flags |= SEC_RELOC; /* FIXME: should this check 'hdr->s_size > 0' */ if (hdr->s_scnptr != 0) return_section->flags |= SEC_HAS_CONTENTS; return true;}/* Read in a COFF object and make it into a BFD. This is used by ECOFF as well. */static const bfd_target *coff_real_object_p (abfd, nscns, internal_f, internal_a) bfd *abfd; unsigned nscns; struct internal_filehdr *internal_f; struct internal_aouthdr *internal_a;{ flagword oflags = abfd->flags; bfd_vma ostart = bfd_get_start_address (abfd); PTR tdata; size_t readsize; /* length of file_info */ unsigned int scnhsz; char *external_sections; if (!(internal_f->f_flags & F_RELFLG)) abfd->flags |= HAS_RELOC; if ((internal_f->f_flags & F_EXEC)) abfd->flags |= EXEC_P; if (!(internal_f->f_flags & F_LNNO)) abfd->flags |= HAS_LINENO; if (!(internal_f->f_flags & F_LSYMS)) abfd->flags |= HAS_LOCALS; /* FIXME: How can we set D_PAGED correctly? */ if ((internal_f->f_flags & F_EXEC) != 0) abfd->flags |= D_PAGED; bfd_get_symcount (abfd) = internal_f->f_nsyms; if (internal_f->f_nsyms) abfd->flags |= HAS_SYMS; if (internal_a != (struct internal_aouthdr *) NULL) bfd_get_start_address (abfd) = internal_a->entry; else bfd_get_start_address (abfd) = 0; /* Set up the tdata area. ECOFF uses its own routine, and overrides abfd->flags. */ tdata = bfd_coff_mkobject_hook (abfd, (PTR) internal_f, (PTR) internal_a); if (tdata == NULL) return 0; scnhsz = bfd_coff_scnhsz (abfd); readsize = nscns * scnhsz; external_sections = (char *) bfd_alloc (abfd, readsize); if (!external_sections) goto fail; if (bfd_read ((PTR) external_sections, 1, readsize, abfd) != readsize) goto fail; /* Set the arch/mach *before* swapping in sections; section header swapping may depend on arch/mach info. */ if (bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f) == false) goto fail; /* Now copy data as required; construct all asections etc */ if (nscns != 0) { unsigned int i; for (i = 0; i < nscns; i++) { struct internal_scnhdr tmp; bfd_coff_swap_scnhdr_in (abfd, (PTR) (external_sections + i * scnhsz), (PTR) & tmp); if (! make_a_section_from_file (abfd, &tmp, i + 1)) goto fail; } } /* make_abs_section (abfd); */ return abfd->xvec; fail: bfd_release (abfd, tdata); abfd->flags = oflags; bfd_get_start_address (abfd) = ostart; return (const bfd_target *) NULL;}/* Turn a COFF file into a BFD, but fail with bfd_error_wrong_format if it is not a COFF file. This is also used by ECOFF. */const bfd_target *coff_object_p (abfd) bfd *abfd;{ unsigned int filhsz; unsigned int aoutsz; int nscns; PTR filehdr; struct internal_filehdr internal_f; struct internal_aouthdr internal_a; /* figure out how much to read */ filhsz = bfd_coff_filhsz (abfd); aoutsz = bfd_coff_aoutsz (abfd); filehdr = bfd_alloc (abfd, filhsz); if (filehdr == NULL) return 0; if (bfd_read (filehdr, 1, filhsz, abfd) != filhsz) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return 0; } bfd_coff_swap_filehdr_in (abfd, filehdr, &internal_f); bfd_release (abfd, filehdr); if (bfd_coff_bad_format_hook (abfd, &internal_f) == false) { bfd_set_error (bfd_error_wrong_format); return 0; } nscns = internal_f.f_nscns; if (internal_f.f_opthdr) { PTR opthdr; opthdr = bfd_alloc (abfd, aoutsz); if (opthdr == NULL) return 0;; if (bfd_read (opthdr, 1, internal_f.f_opthdr, abfd) != internal_f.f_opthdr) { return 0; } bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) &internal_a); } return coff_real_object_p (abfd, nscns, &internal_f, (internal_f.f_opthdr != 0 ? &internal_a : (struct internal_aouthdr *) NULL));}/* Get the BFD section from a COFF symbol section number. */asection *coff_section_from_bfd_index (abfd, index) bfd *abfd; int index;{ struct sec *answer = abfd->sections; if (index == N_ABS) return bfd_abs_section_ptr; if (index == N_UNDEF) return bfd_und_section_ptr; if (index == N_DEBUG) return bfd_abs_section_ptr; while (answer) { if (answer->target_index == index) return answer; answer = answer->next; } /* We should not reach this point, but the SCO 3.2v4 /lib/libc_s.a has a bad symbol table in biglitpow.o. */ return bfd_und_section_ptr;}/* Get the upper bound of a COFF symbol table. */longcoff_get_symtab_upper_bound (abfd) bfd *abfd;{ if (!bfd_coff_slurp_symbol_table (abfd)) return -1; return (bfd_get_symcount (abfd) + 1) * (sizeof (coff_symbol_type *));}/* Canonicalize a COFF symbol table. */longcoff_get_symtab (abfd, alocation) bfd *abfd; asymbol **alocation;{ unsigned int counter; coff_symbol_type *symbase; coff_symbol_type **location = (coff_symbol_type **) alocation; if (!bfd_coff_slurp_symbol_table (abfd)) return -1; symbase = obj_symbols (abfd); counter = bfd_get_symcount (abfd); while (counter-- > 0) *location++ = symbase++; *location = NULL; return bfd_get_symcount (abfd);}/* Get the name of a symbol. The caller must pass in a buffer of size >= SYMNMLEN + 1. */const char *_bfd_coff_internal_syment_name (abfd, sym, buf) bfd *abfd; const struct internal_syment *sym; char *buf;{ /* FIXME: It's not clear this will work correctly if sizeof (_n_zeroes) != 4. */ if (sym->_n._n_n._n_zeroes != 0 || sym->_n._n_n._n_offset == 0) { memcpy (buf, sym->_n._n_name, SYMNMLEN); buf[SYMNMLEN] = '\0'; return buf; } else { const char *strings; BFD_ASSERT (sym->_n._n_n._n_offset >= STRING_SIZE_SIZE); strings = obj_coff_strings (abfd); if (strings == NULL) { strings = _bfd_coff_read_string_table (abfd); if (strings == NULL) return NULL; } return strings + sym->_n._n_n._n_offset; }}/* Read in and swap the relocs. This returns a buffer holding the relocs for section SEC in file ABFD. If CACHE is true and INTERNAL_RELOCS is NULL, the relocs read in will be saved in case the function is called again. If EXTERNAL_RELOCS is not NULL, it is a buffer large enough to hold the unswapped relocs. If INTERNAL_RELOCS is not NULL, it is a buffer large enough to hold the swapped relocs. If REQUIRE_INTERNAL is true, then the return value must be INTERNAL_RELOCS. The function returns NULL on error. */struct internal_reloc *_bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs, require_internal, internal_relocs) bfd *abfd; asection *sec; boolean cache; bfd_byte *external_relocs; boolean require_internal; struct internal_reloc *internal_relocs;{ bfd_size_type relsz; bfd_byte *free_external = NULL; struct internal_reloc *free_internal = NULL; bfd_byte *erel; bfd_byte *erel_end; struct internal_reloc *irel; if (coff_section_data (abfd, sec) != NULL && coff_section_data (abfd, sec)->relocs != NULL) { if (! require_internal) return coff_section_data (abfd, sec)->relocs; memcpy (internal_relocs, coff_section_data (abfd, sec)->relocs, sec->reloc_count * sizeof (struct internal_reloc)); return internal_relocs; } relsz = bfd_coff_relsz (abfd); if (external_relocs == NULL) { free_external = (bfd_byte *) bfd_malloc (sec->reloc_count * relsz); if (free_external == NULL && sec->reloc_count > 0) goto error_return; external_relocs = free_external; } if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0 || (bfd_read (external_relocs, relsz, sec->reloc_count, abfd) != relsz * sec->reloc_count)) goto error_return; if (internal_relocs == NULL) { free_internal = ((struct internal_reloc *) bfd_malloc (sec->reloc_count * sizeof (struct internal_reloc))); if (free_internal == NULL && sec->reloc_count > 0) goto error_return; internal_relocs = free_internal; } /* Swap in the relocs. */ erel = external_relocs; erel_end = erel + relsz * sec->reloc_count; irel = internal_relocs; for (; erel < erel_end; erel += relsz, irel++) bfd_coff_swap_reloc_in (abfd, (PTR) erel, (PTR) irel);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?