📄 riscix.c
字号:
/* BFD back-end for RISC iX (Acorn, arm) binaries. Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)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. *//* RISC iX overloads the MAGIC field to indicate more than just the usual [ZNO]MAGIC values. Also included are squeezing information and shared library usage. *//* The following come from the man page. */#define SHLIBLEN 60#define MF_IMPURE 00200#define MF_SQUEEZED 01000#define MF_USES_SL 02000#define MF_IS_SL 04000/* Common combinations. */#define IMAGIC (MF_IMPURE|ZMAGIC) /* Demand load (impure text) */#define SPOMAGIC (MF_USES_SL|OMAGIC) /* OMAGIC with large header */ /* -- may contain a ref to a */ /* shared lib required by the */ /* object. */#define SLOMAGIC (MF_IS_SL|OMAGIC) /* A reference to a shared library */ /* The text portion of the object */ /* contains "overflow text" from */ /* the shared library to be linked */ /* in with an object */#define QMAGIC (MF_SQUEEZED|ZMAGIC) /* Sqeezed demand paged. */ /* NOTE: This interpretation of */ /* QMAGIC seems to be at variance */ /* With that used on other */ /* architectures. */#define SPZMAGIC (MF_USES_SL|ZMAGIC) /* program which uses sl */#define SPQMAGIC (MF_USES_SL|QMAGIC) /* sqeezed ditto */#define SLZMAGIC (MF_IS_SL|ZMAGIC) /* shared lib part of prog */#define SLPZMAGIC (MF_USES_SL|SLZMAGIC) /* sl which uses another */#define N_SHARED_LIB(x) ((x).a_info & MF_USES_SL)/* Only a pure OMAGIC file has the minimal header */#define N_TXTOFF(x) \ ((x).a_info == OMAGIC ? 32 \ : (N_MAGIC(x) == ZMAGIC) ? TARGET_PAGE_SIZE \ : 999)#define N_TXTADDR(x) \ (N_MAGIC(x) != ZMAGIC ? 0 /* object file or NMAGIC */ \ /* Programs with shared libs are loaded at the first page after all the \ text segments of the shared library programs. Without looking this \ up we can't know exactly what the address will be. A reasonable guess \ is that a_entry will be in the first page of the executable. */ \ : N_SHARED_LIB(x) ? ((x).a_entry & ~(TARGET_PAGE_SIZE - 1)) \ : TEXT_START_ADDR)#define N_SYMOFF(x) \ (N_TXTOFF (x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)#define N_STROFF(x) (N_SYMOFF (x) + (x).a_syms)#define TEXT_START_ADDR 32768#define TARGET_PAGE_SIZE 32768#define SEGMENT_SIZE TARGET_PAGE_SIZE#define DEFAULT_ARCH bfd_arch_arm#define MY(OP) CAT(riscix_,OP)#define TARGETNAME "a.out-riscix"#define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) && \ (((x).a_info & ~006000) != OMAGIC) && \ ((x).a_info != NMAGIC))#define N_MAGIC(x) ((x).a_info & ~07200)#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#define WRITE_HEADERS(abfd, execp) \ { \ bfd_size_type text_size; /* dummy vars */ \ file_ptr text_end; \ if (adata(abfd).magic == undecided_magic) \ NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \ \ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \ execp->a_entry = bfd_get_start_address (abfd); \ \ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \ obj_reloc_entry_size (abfd)); \ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \ obj_reloc_entry_size (abfd)); \ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \ \ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return false; \ if (bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd) \ != EXEC_BYTES_SIZE) \ return false; \ /* Now write out reloc info, followed by syms and strings */ \ \ if (bfd_get_outsymbols (abfd) != (asymbol **) NULL \ && bfd_get_symcount (abfd) != 0) \ { \ if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0) \ return false; \ \ if (! NAME(aout,write_syms) (abfd)) return false; \ \ if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) != 0) \ return false; \ \ if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd))) \ return false; \ if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) != 0) \ return false; \ \ if (!NAME(aout,squirt_out_relocs) (abfd, obj_datasec (abfd))) \ return false; \ } \ }#include "libaout.h"#include "aout/aout64.h"static bfd_reloc_status_typeriscix_fix_pcrel_26_done PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_typeriscix_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static reloc_howto_type riscix_std_reloc_howto[] = { /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false), HOWTO( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false), HOWTO( 3, 2, 3, 26, true, 0, complain_overflow_signed, riscix_fix_pcrel_26 , "ARM26", true, 0x00ffffff,0x00ffffff, false), HOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, true), HOWTO( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, true), HOWTO( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, true), HOWTO( 7, 2, 3, 26, false, 0, complain_overflow_signed, riscix_fix_pcrel_26_done, "ARM26D",true,0x00ffffff,0x00ffffff, false), EMPTY_HOWTO (-1), HOWTO( 9, 0, -1, 16, false, 0, complain_overflow_bitfield,0,"NEG16", true, 0x0000ffff,0x0000ffff, false), HOWTO( 10, 0, -2, 32, false, 0, complain_overflow_bitfield,0,"NEG32", true, 0xffffffff,0xffffffff, false)};#define RISCIX_TABLE_SIZE \ (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))static bfd_reloc_status_typeriscix_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; PTR data ATTRIBUTE_UNUSED; asection *input_section ATTRIBUTE_UNUSED; bfd *output_bfd ATTRIBUTE_UNUSED; char **error_message ATTRIBUTE_UNUSED;{ /* This is dead simple at present. */ return bfd_reloc_ok;}static bfd_reloc_status_typeriscix_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ bfd_vma relocation; bfd_size_type addr = reloc_entry->address; long target = bfd_get_32 (abfd, (bfd_byte *) data + addr); bfd_reloc_status_type flag = bfd_reloc_ok; /* If this is an undefined symbol, return error */ if (symbol->section == &bfd_und_section && (symbol->flags & BSF_WEAK) == 0) return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined; /* If the sections are different, and we are doing a partial relocation, just ignore it for now. */ if (symbol->section->name != input_section->name && output_bfd != (bfd *)NULL) return bfd_reloc_continue; relocation = (target & 0x00ffffff) << 2; relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */ relocation += symbol->value; relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; relocation += reloc_entry->addend; relocation -= input_section->output_section->vma; relocation -= input_section->output_offset; relocation -= addr; if (relocation & 3) return bfd_reloc_overflow; /* Check for overflow */ if (relocation & 0x02000000) { if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff) flag = bfd_reloc_overflow; } else if (relocation & ~0x03ffffff) flag = bfd_reloc_overflow; target &= ~0x00ffffff; target |= (relocation >> 2) & 0x00ffffff; bfd_put_32 (abfd, target, (bfd_byte *) data + addr); /* Now the ARM magic... Change the reloc type so that it is marked as done. Strictly this is only necessary if we are doing a partial relocation. */ reloc_entry->howto = &riscix_std_reloc_howto[7]; return flag;}reloc_howto_type *riscix_reloc_type_lookup (abfd, code) bfd *abfd; bfd_reloc_code_real_type code;{#define ASTD(i,j) case i: return &riscix_std_reloc_howto[j] if (code == BFD_RELOC_CTOR) switch (bfd_get_arch_info (abfd)->bits_per_address) { case 32: code = BFD_RELOC_32; break; default: return (reloc_howto_type *) NULL; } switch (code) { ASTD (BFD_RELOC_16, 1); ASTD (BFD_RELOC_32, 2); ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3); ASTD (BFD_RELOC_8_PCREL, 4); ASTD (BFD_RELOC_16_PCREL, 5); ASTD (BFD_RELOC_32_PCREL, 6); default: return (reloc_howto_type *) NULL; }}#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols#define MY_final_link_callback should_not_be_used#define MY_bfd_final_link _bfd_generic_final_link#define MY_bfd_reloc_type_lookup riscix_reloc_type_lookup#define MY_canonicalize_reloc riscix_canonicalize_reloc#define MY_object_p riscix_object_pstatic const bfd_target *riscix_callback PARAMS ((bfd *));voidriscix_swap_std_reloc_out (abfd, g, natptr) bfd *abfd; arelent *g; struct reloc_std_external *natptr;{ int r_index; asymbol *sym = *(g->sym_ptr_ptr); int r_extern; int r_length; int r_pcrel; int r_neg = 0; /* Negative relocs use the BASEREL bit. */ asection *output_section = sym->section->output_section; PUT_WORD(abfd, g->address, natptr->r_address); r_length = g->howto->size ; /* Size as a power of two */ if (r_length < 0) { r_length = -r_length; r_neg = 1; } r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the relocation has been done already (Only for the 26-bit one I think)???!!! */ if (r_length == 3) r_pcrel = r_pcrel ? 0 : 1;#if 0 /* For a standard reloc, the addend is in the object file. */ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;#endif /* name was clobbered by aout_write_syms to be symbol index */ /* If this relocation is relative to a symbol then set the r_index to the symbols index, and the r_extern bit. Absolute symbols can come in in two ways, either as an offset from the abs section, or as a symbol which has an abs value.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -