?? sunos.c
字號:
/* BFD backend for SunOS binaries. Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 2000 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. */#define TARGETNAME "a.out-sunos-big"#define MY(OP) CAT(sunos_big_,OP)#include "bfd.h"#include "bfdlink.h"#include "libaout.h"/* Static routines defined in this file. */static boolean sunos_read_dynamic_info PARAMS ((bfd *));static long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *));static boolean sunos_slurp_dynamic_symtab PARAMS ((bfd *));static long sunos_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));static long sunos_get_dynamic_reloc_upper_bound PARAMS ((bfd *));static long sunos_canonicalize_dynamic_reloc PARAMS ((bfd *, arelent **, asymbol **));static struct bfd_hash_entry *sunos_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_link_hash_table *sunos_link_hash_table_create PARAMS ((bfd *));static boolean sunos_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *, boolean));static boolean sunos_add_dynamic_symbols PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **, bfd_size_type *, char **));static boolean sunos_add_one_symbol PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *, bfd_vma, const char *, boolean, boolean, struct bfd_link_hash_entry **));static boolean sunos_scan_relocs PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_size_type));static boolean sunos_scan_std_relocs PARAMS ((struct bfd_link_info *, bfd *, asection *, const struct reloc_std_external *, bfd_size_type));static boolean sunos_scan_ext_relocs PARAMS ((struct bfd_link_info *, bfd *, asection *, const struct reloc_ext_external *, bfd_size_type));static boolean sunos_link_dynamic_object PARAMS ((struct bfd_link_info *, bfd *));static boolean sunos_write_dynamic_symbol PARAMS ((bfd *, struct bfd_link_info *, struct aout_link_hash_entry *));static boolean sunos_check_dynamic_reloc PARAMS ((struct bfd_link_info *, bfd *, asection *, struct aout_link_hash_entry *, PTR, bfd_byte *, boolean *, bfd_vma *));static boolean sunos_finish_dynamic_link PARAMS ((bfd *, struct bfd_link_info *));#define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound#define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab#define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound#define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc#define MY_bfd_link_hash_table_create sunos_link_hash_table_create#define MY_add_dynamic_symbols sunos_add_dynamic_symbols#define MY_add_one_symbol sunos_add_one_symbol#define MY_link_dynamic_object sunos_link_dynamic_object#define MY_write_dynamic_symbol sunos_write_dynamic_symbol#define MY_check_dynamic_reloc sunos_check_dynamic_reloc#define MY_finish_dynamic_link sunos_finish_dynamic_link/* ??? Where should this go? */#define MACHTYPE_OK(mtype) \ (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \ || ((mtype) == M_SPARCLET \ && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \ || ((mtype) == M_SPARCLITE_LE \ && bfd_lookup_arch (bfd_arch_sparc, bfd_mach_sparc_sparclet) != NULL) \ || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \ && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))/* Include the usual a.out support. */#include "aoutf1.h"/* The SunOS 4.1.4 /usr/include/locale.h defines valid as a macro. */#undef valid/* SunOS shared library support. We store a pointer to this structure in obj_aout_dynamic_info (abfd). */struct sunos_dynamic_info{ /* Whether we found any dynamic information. */ boolean valid; /* Dynamic information. */ struct internal_sun4_dynamic_link dyninfo; /* Number of dynamic symbols. */ unsigned long dynsym_count; /* Read in nlists for dynamic symbols. */ struct external_nlist *dynsym; /* asymbol structures for dynamic symbols. */ aout_symbol_type *canonical_dynsym; /* Read in dynamic string table. */ char *dynstr; /* Number of dynamic relocs. */ unsigned long dynrel_count; /* Read in dynamic relocs. This may be reloc_std_external or reloc_ext_external. */ PTR dynrel; /* arelent structures for dynamic relocs. */ arelent *canonical_dynrel;};/* The hash table of dynamic symbols is composed of two word entries. See include/aout/sun4.h for details. */#define HASH_ENTRY_SIZE (2 * BYTES_IN_WORD)/* Read in the basic dynamic information. This locates the __DYNAMIC structure and uses it to find the dynamic_link structure. It creates and saves a sunos_dynamic_info structure. If it can't find __DYNAMIC, it sets the valid field of the sunos_dynamic_info structure to false to avoid doing this work again. */static booleansunos_read_dynamic_info (abfd) bfd *abfd;{ struct sunos_dynamic_info *info; asection *dynsec; bfd_vma dynoff; struct external_sun4_dynamic dyninfo; unsigned long dynver; struct external_sun4_dynamic_link linkinfo; if (obj_aout_dynamic_info (abfd) != (PTR) NULL) return true; if ((abfd->flags & DYNAMIC) == 0) { bfd_set_error (bfd_error_invalid_operation); return false; } info = ((struct sunos_dynamic_info *) bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info))); if (!info) return false; info->valid = false; info->dynsym = NULL; info->dynstr = NULL; info->canonical_dynsym = NULL; info->dynrel = NULL; info->canonical_dynrel = NULL; obj_aout_dynamic_info (abfd) = (PTR) info; /* This code used to look for the __DYNAMIC symbol to locate the dynamic linking information. However this inhibits recovering the dynamic symbols from a stripped object file, so blindly assume that the dynamic linking information is located at the start of the data section. We could verify this assumption later by looking through the dynamic symbols for the __DYNAMIC symbol. */ if ((abfd->flags & DYNAMIC) == 0) return true; if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo, (file_ptr) 0, sizeof dyninfo)) return true; dynver = GET_WORD (abfd, dyninfo.ld_version); if (dynver != 2 && dynver != 3) return true; dynoff = GET_WORD (abfd, dyninfo.ld); /* dynoff is a virtual address. It is probably always in the .data section, but this code should work even if it moves. */ if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd))) dynsec = obj_textsec (abfd); else dynsec = obj_datasec (abfd); dynoff -= bfd_get_section_vma (abfd, dynsec); if (dynoff > bfd_section_size (abfd, dynsec)) return true; /* This executable appears to be dynamically linked in a way that we can understand. */ if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, dynoff, (bfd_size_type) sizeof linkinfo)) return true; /* Swap in the dynamic link information. */ info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded); info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need); info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules); info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got); info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt); info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel); info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash); info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab); info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash); info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets); info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols); info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size); info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text); info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz); /* Reportedly the addresses need to be offset by the size of the exec header in an NMAGIC file. */ if (adata (abfd).magic == n_magic) { unsigned long exec_bytes_size = adata (abfd).exec_bytes_size; info->dyninfo.ld_need += exec_bytes_size; info->dyninfo.ld_rules += exec_bytes_size; info->dyninfo.ld_rel += exec_bytes_size; info->dyninfo.ld_hash += exec_bytes_size; info->dyninfo.ld_stab += exec_bytes_size; info->dyninfo.ld_symbols += exec_bytes_size; } /* The only way to get the size of the symbol information appears to be to determine the distance between it and the string table. */ info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab) / EXTERNAL_NLIST_SIZE); BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE == (unsigned long) (info->dyninfo.ld_symbols - info->dyninfo.ld_stab)); /* Similarly, the relocs end at the hash table. */ info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel) / obj_reloc_entry_size (abfd)); BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd) == (unsigned long) (info->dyninfo.ld_hash - info->dyninfo.ld_rel)); info->valid = true; return true;}/* Return the amount of memory required for the dynamic symbols. */static longsunos_get_dynamic_symtab_upper_bound (abfd) bfd *abfd;{ struct sunos_dynamic_info *info; if (! sunos_read_dynamic_info (abfd)) return -1; info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); if (! info->valid) { bfd_set_error (bfd_error_no_symbols); return -1; } return (info->dynsym_count + 1) * sizeof (asymbol *);}/* Read the external dynamic symbols. */static booleansunos_slurp_dynamic_symtab (abfd) bfd *abfd;{ struct sunos_dynamic_info *info; /* Get the general dynamic information. */ if (obj_aout_dynamic_info (abfd) == NULL) { if (! sunos_read_dynamic_info (abfd)) return false; } info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd); if (! info->valid) { bfd_set_error (bfd_error_no_symbols); return false; } /* Get the dynamic nlist structures. */ if (info->dynsym == (struct external_nlist *) NULL) { info->dynsym = ((struct external_nlist *) bfd_alloc (abfd, (info->dynsym_count * EXTERNAL_NLIST_SIZE))); if (info->dynsym == NULL && info->dynsym_count != 0) return false; if (bfd_seek (abfd, info->dyninfo.ld_stab, SEEK_SET) != 0 || (bfd_read ((PTR) info->dynsym, info->dynsym_count, EXTERNAL_NLIST_SIZE, abfd) != info->dynsym_count * EXTERNAL_NLIST_SIZE)) { if (info->dynsym != NULL) { bfd_release (abfd, info->dynsym); info->dynsym = NULL; } return false; } } /* Get the dynamic strings. */ if (info->dynstr == (char *) NULL) { info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size); if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0) return false; if (bfd_seek (abfd, info->dyninfo.ld_symbols, SEEK_SET) != 0 || (bfd_read ((PTR) info->dynstr, 1, info->dyninfo.ld_symb_size, abfd) != info->dyninfo.ld_symb_size)) { if (info->dynstr != NULL) { bfd_release (abfd, info->dynstr); info->dynstr = NULL; } return false; } } return true;}/* Read in the dynamic symbols. */static longsunos_canonicalize_dynamic_symtab (abfd, storage) bfd *abfd; asymbol **storage;{ struct sunos_dynamic_info *info; unsigned long i; if (! sunos_slurp_dynamic_symtab (abfd)) return -1; info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);#ifdef CHECK_DYNAMIC_HASH /* Check my understanding of the dynamic hash table by making sure that each symbol can be located in the hash table. */ { bfd_size_type table_size; bfd_byte *table; bfd_size_type i; if (info->dyninfo.ld_buckets > info->dynsym_count) abort (); table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash; table = (bfd_byte *) bfd_malloc (table_size); if (table == NULL && table_size != 0) abort (); if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0 || bfd_read ((PTR) table, 1, table_size, abfd) != table_size) abort (); for (i = 0; i < info->dynsym_count; i++) { unsigned char *name; unsigned long hash; name = ((unsigned char *) info->dynstr + GET_WORD (abfd, info->dynsym[i].e_strx)); hash = 0; while (*name != '\0') hash = (hash << 1) + *name++; hash &= 0x7fffffff; hash %= info->dyninfo.ld_buckets; while (GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE) != i) { hash = GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD); if (hash == 0 || hash >= table_size / HASH_ENTRY_SIZE) abort (); } } free (table); }#endif /* CHECK_DYNAMIC_HASH */ /* Get the asymbol structures corresponding to the dynamic nlist structures. */ if (info->canonical_dynsym == (aout_symbol_type *) NULL) { info->canonical_dynsym = ((aout_symbol_type *) bfd_alloc (abfd, (info->dynsym_count * sizeof (aout_symbol_type)))); if (info->canonical_dynsym == NULL && info->dynsym_count != 0) return -1; if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym, info->dynsym, info->dynsym_count, info->dynstr, info->dyninfo.ld_symb_size, true)) { if (info->canonical_dynsym != NULL) { bfd_release (abfd, info->canonical_dynsym); info->canonical_dynsym = NULL; } return -1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -