coff-alpha.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,226 行 · 第 1/5 页
C
2,226 行
/* BFD back-end for ALPHA Extended-Coff files. Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Modified from coff-mips.c by Steve Chamberlain <sac@cygnus.com> and Ian Lance Taylor <ian@cygnus.com>.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. */#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libbfd.h"#include "coff/internal.h"#include "coff/sym.h"#include "coff/symconst.h"#include "coff/ecoff.h"#include "coff/alpha.h"#include "aout/ar.h"#include "libcoff.h"#include "libecoff.h"/* Prototypes for static functions. */static const bfd_target *alpha_ecoff_object_p PARAMS ((bfd *));static boolean alpha_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));static PTR alpha_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr));static void alpha_ecoff_swap_reloc_in PARAMS ((bfd *, PTR, struct internal_reloc *));static void alpha_ecoff_swap_reloc_out PARAMS ((bfd *, const struct internal_reloc *, PTR));static void alpha_adjust_reloc_in PARAMS ((bfd *, const struct internal_reloc *, arelent *));static void alpha_adjust_reloc_out PARAMS ((bfd *, const arelent *, struct internal_reloc *));static reloc_howto_type *alpha_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));static bfd_byte *alpha_ecoff_get_relocated_section_contents PARAMS ((bfd *abfd, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *data, boolean relocateable, asymbol **symbols));static bfd_vma alpha_convert_external_reloc PARAMS ((bfd *, struct bfd_link_info *, bfd *, struct external_reloc *, struct ecoff_link_hash_entry *));static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));static boolean alpha_adjust_headers PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *));static PTR alpha_ecoff_read_ar_hdr PARAMS ((bfd *));static bfd *alpha_ecoff_get_elt_at_filepos PARAMS ((bfd *, file_ptr));static bfd *alpha_ecoff_openr_next_archived_file PARAMS ((bfd *, bfd *));static bfd *alpha_ecoff_get_elt_at_index PARAMS ((bfd *, symindex));/* ECOFF has COFF sections, but the debugging information is stored in a completely different format. ECOFF targets use some of the swapping routines from coffswap.h, and some of the generic COFF routines in coffgen.c, but, unlike the real COFF targets, do not use coffcode.h itself. Get the generic COFF swapping routines, except for the reloc, symbol, and lineno ones. Give them ecoff names. Define some accessor macros for the large sizes used for Alpha ECOFF. */#define GET_FILEHDR_SYMPTR bfd_h_get_64#define PUT_FILEHDR_SYMPTR bfd_h_put_64#define GET_AOUTHDR_TSIZE bfd_h_get_64#define PUT_AOUTHDR_TSIZE bfd_h_put_64#define GET_AOUTHDR_DSIZE bfd_h_get_64#define PUT_AOUTHDR_DSIZE bfd_h_put_64#define GET_AOUTHDR_BSIZE bfd_h_get_64#define PUT_AOUTHDR_BSIZE bfd_h_put_64#define GET_AOUTHDR_ENTRY bfd_h_get_64#define PUT_AOUTHDR_ENTRY bfd_h_put_64#define GET_AOUTHDR_TEXT_START bfd_h_get_64#define PUT_AOUTHDR_TEXT_START bfd_h_put_64#define GET_AOUTHDR_DATA_START bfd_h_get_64#define PUT_AOUTHDR_DATA_START bfd_h_put_64#define GET_SCNHDR_PADDR bfd_h_get_64#define PUT_SCNHDR_PADDR bfd_h_put_64#define GET_SCNHDR_VADDR bfd_h_get_64#define PUT_SCNHDR_VADDR bfd_h_put_64#define GET_SCNHDR_SIZE bfd_h_get_64#define PUT_SCNHDR_SIZE bfd_h_put_64#define GET_SCNHDR_SCNPTR bfd_h_get_64#define PUT_SCNHDR_SCNPTR bfd_h_put_64#define GET_SCNHDR_RELPTR bfd_h_get_64#define PUT_SCNHDR_RELPTR bfd_h_put_64#define GET_SCNHDR_LNNOPTR bfd_h_get_64#define PUT_SCNHDR_LNNOPTR bfd_h_put_64#define ALPHAECOFF#define NO_COFF_RELOCS#define NO_COFF_SYMBOLS#define NO_COFF_LINENOS#define coff_swap_filehdr_in alpha_ecoff_swap_filehdr_in#define coff_swap_filehdr_out alpha_ecoff_swap_filehdr_out#define coff_swap_aouthdr_in alpha_ecoff_swap_aouthdr_in#define coff_swap_aouthdr_out alpha_ecoff_swap_aouthdr_out#define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in#define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out#include "coffswap.h"/* Get the ECOFF swapping routines. */#define ECOFF_64#include "ecoffswap.h"/* How to process the various reloc types. */static bfd_reloc_status_typereloc_nil PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_typereloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc ATTRIBUTE_UNUSED; asymbol *sym ATTRIBUTE_UNUSED; PTR data ATTRIBUTE_UNUSED; asection *sec ATTRIBUTE_UNUSED; bfd *output_bfd ATTRIBUTE_UNUSED; char **error_message ATTRIBUTE_UNUSED;{ return bfd_reloc_ok;}/* In case we're on a 32-bit machine, construct a 64-bit "-1" value from smaller values. Start with zero, widen, *then* decrement. */#define MINUS_ONE (((bfd_vma)0) - 1)static reloc_howto_type alpha_howto_table[] ={ /* Reloc type 0 is ignored by itself. However, it appears after a GPDISP reloc to identify the location where the low order 16 bits of the gp register are loaded. */ HOWTO (ALPHA_R_IGNORE, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ reloc_nil, /* special_function */ "IGNORE", /* name */ true, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ true), /* pcrel_offset */ /* A 32 bit reference to a symbol. */ HOWTO (ALPHA_R_REFLONG, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "REFLONG", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ /* A 64 bit reference to a symbol. */ HOWTO (ALPHA_R_REFQUAD, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "REFQUAD", /* name */ true, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ false), /* pcrel_offset */ /* A 32 bit GP relative offset. This is just like REFLONG except that when the value is used the value of the gp register will be added in. */ HOWTO (ALPHA_R_GPREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "GPREL32", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ /* Used for an instruction that refers to memory off the GP register. The offset is 16 bits of the 32 bit instruction. This reloc always seems to be against the .lita section. */ HOWTO (ALPHA_R_LITERAL, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "LITERAL", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* This reloc only appears immediately following a LITERAL reloc. It identifies a use of the literal. It seems that the linker can use this to eliminate a portion of the .lita section. The symbol index is special: 1 means the literal address is in the base register of a memory format instruction; 2 means the literal address is in the byte offset register of a byte-manipulation instruction; 3 means the literal address is in the target register of a jsr instruction. This does not actually do any relocation. */ HOWTO (ALPHA_R_LITUSE, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ reloc_nil, /* special_function */ "LITUSE", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* Load the gp register. This is always used for a ldah instruction which loads the upper 16 bits of the gp register. The next reloc will be an IGNORE reloc which identifies the location of the lda instruction which loads the lower 16 bits. The symbol index of the GPDISP instruction appears to actually be the number of bytes between the ldah and lda instructions. This gives two different ways to determine where the lda instruction is; I don't know why both are used. The value to use for the relocation is the difference between the GP value and the current location; the load will always be done against a register holding the current address. */ HOWTO (ALPHA_R_GPDISP, /* type */ 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ reloc_nil, /* special_function */ "GPDISP", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ true), /* pcrel_offset */ /* A 21 bit branch. The native assembler generates these for branches within the text segment, and also fills in the PC relative offset in the instruction. */ HOWTO (ALPHA_R_BRADDR, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 21, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "BRADDR", /* name */ true, /* partial_inplace */ 0x1fffff, /* src_mask */ 0x1fffff, /* dst_mask */ false), /* pcrel_offset */ /* A hint for a jump to a register. */ HOWTO (ALPHA_R_HINT, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 14, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "HINT", /* name */ true, /* partial_inplace */ 0x3fff, /* src_mask */ 0x3fff, /* dst_mask */ false), /* pcrel_offset */ /* 16 bit PC relative offset. */ HOWTO (ALPHA_R_SREL16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "SREL16", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* 32 bit PC relative offset. */ HOWTO (ALPHA_R_SREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "SREL32", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ /* A 64 bit PC relative offset. */ HOWTO (ALPHA_R_SREL64, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "SREL64", /* name */ true, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ false), /* pcrel_offset */ /* Push a value on the reloc evaluation stack. */ HOWTO (ALPHA_R_OP_PUSH, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_PUSH", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* Store the value from the stack at the given address. Store it in a bitfield of size r_size starting at bit position r_offset. */ HOWTO (ALPHA_R_OP_STORE, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_STORE", /* name */ false, /* partial_inplace */ 0, /* src_mask */ MINUS_ONE, /* dst_mask */ false), /* pcrel_offset */ /* Subtract the reloc address from the value on the top of the relocation stack. */ HOWTO (ALPHA_R_OP_PSUB, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_PSUB", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* Shift the value on the top of the relocation stack right by the given value. */ HOWTO (ALPHA_R_OP_PRSHIFT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_PRSHIFT", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* Adjust the GP value for a new range in the object file. */ HOWTO (ALPHA_R_GPVALUE, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "GPVALUE", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false) /* pcrel_offset */};/* Recognize an Alpha ECOFF file. */static const bfd_target *alpha_ecoff_object_p (abfd) bfd *abfd;{ static const bfd_target *ret; ret = coff_object_p (abfd); if (ret != NULL) { asection *sec;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?