📄 som.c
字号:
/* bfd back-end for HP PA-RISC SOM objects. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by the Center for Software Science at the University of Utah. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the 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 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "alloca-conf.h"#include "bfd.h"#include "sysdep.h"#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF) || defined(HOST_HPPAMPEIX)#include "libbfd.h"#include "som.h"#include <sys/param.h>#include <signal.h>#include <machine/reg.h>#include <sys/file.h>#include <ctype.h>/* Magic not defined in standard HP-UX header files until 8.0 */#ifndef CPU_PA_RISC1_0#define CPU_PA_RISC1_0 0x20B#endif /* CPU_PA_RISC1_0 */#ifndef CPU_PA_RISC1_1#define CPU_PA_RISC1_1 0x210#endif /* CPU_PA_RISC1_1 */#ifndef CPU_PA_RISC2_0#define CPU_PA_RISC2_0 0x214#endif /* CPU_PA_RISC2_0 */#ifndef _PA_RISC1_0_ID#define _PA_RISC1_0_ID CPU_PA_RISC1_0#endif /* _PA_RISC1_0_ID */#ifndef _PA_RISC1_1_ID#define _PA_RISC1_1_ID CPU_PA_RISC1_1#endif /* _PA_RISC1_1_ID */#ifndef _PA_RISC2_0_ID#define _PA_RISC2_0_ID CPU_PA_RISC2_0#endif /* _PA_RISC2_0_ID */#ifndef _PA_RISC_MAXID#define _PA_RISC_MAXID 0x2FF#endif /* _PA_RISC_MAXID */#ifndef _PA_RISC_ID#define _PA_RISC_ID(__m_num) \ (((__m_num) == _PA_RISC1_0_ID) || \ ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))#endif /* _PA_RISC_ID *//* HIUX in it's infinite stupidity changed the names for several "well known" constants. Work around such braindamage. Try the HPUX version first, then the HIUX version, and finally provide a default. */#ifdef HPUX_AUX_ID#define EXEC_AUX_ID HPUX_AUX_ID#endif#if !defined (EXEC_AUX_ID) && defined (HIUX_AUX_ID)#define EXEC_AUX_ID HIUX_AUX_ID#endif#ifndef EXEC_AUX_ID#define EXEC_AUX_ID 0#endif/* Size (in chars) of the temporary buffers used during fixup and string table writes. */#define SOM_TMP_BUFSIZE 8192/* Size of the hash table in archives. */#define SOM_LST_HASH_SIZE 31/* Max number of SOMs to be found in an archive. */#define SOM_LST_MODULE_LIMIT 1024/* Generic alignment macro. */#define SOM_ALIGN(val, alignment) \ (((val) + (alignment) - 1) & ~((alignment) - 1))/* SOM allows any one of the four previous relocations to be reused with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP relocations are always a single byte, using a R_PREV_FIXUP instead of some multi-byte relocation makes object files smaller. Note one side effect of using a R_PREV_FIXUP is the relocation that is being repeated moves to the front of the queue. */struct reloc_queue { unsigned char *reloc; unsigned int size;} reloc_queue[4];/* This fully describes the symbol types which may be attached to an EXPORT or IMPORT directive. Only SOM uses this formation (ELF has no need for it). */typedef enum { SYMBOL_TYPE_UNKNOWN, SYMBOL_TYPE_ABSOLUTE, SYMBOL_TYPE_CODE, SYMBOL_TYPE_DATA, SYMBOL_TYPE_ENTRY, SYMBOL_TYPE_MILLICODE, SYMBOL_TYPE_PLABEL, SYMBOL_TYPE_PRI_PROG, SYMBOL_TYPE_SEC_PROG,} pa_symbol_type;struct section_to_type { char *section; char type;};/* Assorted symbol information that needs to be derived from the BFD symbol and/or the BFD backend private symbol data. */struct som_misc_symbol_info { unsigned int symbol_type; unsigned int symbol_scope; unsigned int arg_reloc; unsigned int symbol_info; unsigned int symbol_value; unsigned int priv_level; unsigned int secondary_def;};/* Forward declarations */static boolean som_mkobject PARAMS ((bfd *));static const bfd_target * som_object_setup PARAMS ((bfd *, struct header *, struct som_exec_auxhdr *, unsigned long));static boolean setup_sections PARAMS ((bfd *, struct header *, unsigned long));static const bfd_target * som_object_p PARAMS ((bfd *));static boolean som_write_object_contents PARAMS ((bfd *));static boolean som_slurp_string_table PARAMS ((bfd *));static unsigned int som_slurp_symbol_table PARAMS ((bfd *));static long som_get_symtab_upper_bound PARAMS ((bfd *));static long som_canonicalize_reloc PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));static long som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));static unsigned int som_set_reloc_info PARAMS ((unsigned char *, unsigned int, arelent *, asection *, asymbol **, boolean));static boolean som_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **, boolean));static long som_get_symtab PARAMS ((bfd *, asymbol **));static asymbol * som_make_empty_symbol PARAMS ((bfd *));static void som_print_symbol PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));static boolean som_new_section_hook PARAMS ((bfd *, asection *));static boolean som_bfd_copy_private_symbol_data PARAMS ((bfd *, asymbol *, bfd *, asymbol *));static boolean som_bfd_copy_private_section_data PARAMS ((bfd *, asection *, bfd *, asection *));static boolean som_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));#define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data#define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flagsstatic boolean som_bfd_is_local_label_name PARAMS ((bfd *, const char *));static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));static boolean som_get_section_contents PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture, unsigned long));static boolean som_find_nearest_line PARAMS ((bfd *, asection *, asymbol **, bfd_vma, CONST char **, CONST char **, unsigned int *));static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));static asection * bfd_section_from_som_symbol PARAMS ((bfd *, struct symbol_dictionary_record *));static int log2 PARAMS ((unsigned int));static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int, struct reloc_queue *));static void som_reloc_queue_fix PARAMS ((struct reloc_queue *, unsigned int));static int som_reloc_queue_find PARAMS ((unsigned char *, unsigned int, struct reloc_queue *));static unsigned char * try_prev_fixup PARAMS ((bfd *, int *, unsigned char *, unsigned int, struct reloc_queue *));static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int, unsigned char *, unsigned int *, struct reloc_queue *));static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *, unsigned int *, struct reloc_queue *));static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *, unsigned int *, arelent *, int, struct reloc_queue *));static unsigned long som_count_spaces PARAMS ((bfd *));static unsigned long som_count_subspaces PARAMS ((bfd *));static int compare_syms PARAMS ((const void *, const void *));static int compare_subspaces PARAMS ((const void *, const void *));static unsigned long som_compute_checksum PARAMS ((bfd *));static boolean som_prep_headers PARAMS ((bfd *));static int som_sizeof_headers PARAMS ((bfd *, boolean));static boolean som_finish_writing PARAMS ((bfd *));static boolean som_build_and_write_symbol_table PARAMS ((bfd *));static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));static boolean som_write_space_strings PARAMS ((bfd *, unsigned long, unsigned int *));static boolean som_write_symbol_strings PARAMS ((bfd *, unsigned long, asymbol **, unsigned int, unsigned *, COMPUNIT *));static boolean som_begin_writing PARAMS ((bfd *));static reloc_howto_type * som_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));static char som_section_type PARAMS ((const char *));static int som_decode_symclass PARAMS ((asymbol *));static boolean som_bfd_count_ar_symbols PARAMS ((bfd *, struct lst_header *, symindex *));static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *, carsym **syms));static boolean som_slurp_armap PARAMS ((bfd *));static boolean som_write_armap PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));static void som_bfd_derive_misc_symbol_info PARAMS ((bfd *, asymbol *, struct som_misc_symbol_info *));static boolean som_bfd_prep_for_ar_write PARAMS ((bfd *, unsigned int *, unsigned int *));static unsigned int som_bfd_ar_symbol_hash PARAMS ((asymbol *));static boolean som_bfd_ar_write_symbol_stuff PARAMS ((bfd *, unsigned int, unsigned int, struct lst_header, unsigned int));static boolean som_is_space PARAMS ((asection *));static boolean som_is_subspace PARAMS ((asection *));static boolean som_is_container PARAMS ((asection *, asection *));static boolean som_bfd_free_cached_info PARAMS ((bfd *));static boolean som_bfd_link_split_section PARAMS ((bfd *, asection *));/* Map SOM section names to POSIX/BSD single-character symbol types. This table includes all the standard subspaces as defined in the current "PRO ABI for PA-RISC Systems", $UNWIND$ which for some reason was left out, and sections specific to embedded stabs. */static const struct section_to_type stt[] = { {"$TEXT$", 't'}, {"$SHLIB_INFO$", 't'}, {"$MILLICODE$", 't'}, {"$LIT$", 't'}, {"$CODE$", 't'}, {"$UNWIND_START$", 't'}, {"$UNWIND$", 't'}, {"$PRIVATE$", 'd'}, {"$PLT$", 'd'}, {"$SHLIB_DATA$", 'd'}, {"$DATA$", 'd'}, {"$SHORTDATA$", 'g'}, {"$DLT$", 'd'}, {"$GLOBAL$", 'g'}, {"$SHORTBSS$", 's'}, {"$BSS$", 'b'}, {"$GDB_STRINGS$", 'N'}, {"$GDB_SYMBOLS$", 'N'}, {0, 0}};/* About the relocation formatting table... There are 256 entries in the table, one for each possible relocation opcode available in SOM. We index the table by the relocation opcode. The names and operations are those defined by a.out_800 (4). Right now this table is only used to count and perform minimal processing on relocation streams so that they can be internalized into BFD and symbolically printed by utilities. To make actual use of them would be much more difficult, BFD's concept of relocations is far too simple to handle SOM relocations. The basic assumption that a relocation can be completely processed independent of other relocations before an object file is written is invalid for SOM. The SOM relocations are meant to be processed as a stream, they specify copying of data from the input section to the output section while possibly modifying the data in some manner. They also can specify that a variable number of zeros or uninitialized data be inserted on in the output segment at the current offset. Some relocations specify that some previous relocation be re-applied at the current location in the input/output sections. And finally a number of relocations have effects on other sections (R_ENTRY, R_EXIT, R_UNWIND_AUX and a variety of others). There isn't even enough room in the BFD relocation data structure to store enough information to perform all the relocations. Each entry in the table has three fields. The first entry is an index into this "class" of relocations. This index can then be used as a variable within the relocation itself. The second field is a format string which actually controls processing of the relocation. It uses a simple postfix machine to do calculations based on variables/constants found in the string and the relocation stream. The third field specifys whether or not this relocation may use a constant (V) from the previous R_DATA_OVERRIDE rather than a constant stored in the instruction. Variables: L = input space byte count D = index into class of relocations M = output space byte count N = statement number (unused?) O = stack operation R = parameter relocation bits S = symbol index T = first 32 bits of stack unwind information U = second 32 bits of stack unwind information V = a literal constant (usually used in the next relocation) P = a previous relocation Lower case letters (starting with 'b') refer to following bytes in the relocation stream. 'b' is the next 1 byte, c is the next 2 bytes, d is the next 3 bytes, etc... This is the variable part of the relocation entries that makes our life a living hell. numerical constants are also used in the format string. Note the constants are represented in decimal. '+', "*" and "=" represents the obvious postfix operators. '<' represents a left shift. Stack Operations: Parameter Relocation Bits: Unwind Entries: Previous Relocations: The index field represents which in the queue of 4 previous fixups should be re-applied. Literal Constants: These are generally used to represent addend parts of relocations when these constants are not stored in the fields of the instructions themselves. For example the instruction addil foo-$global$-0x1234 would use an override for "0x1234" rather than storing it into the addil itself. */struct fixup_format { int D; const char *format;};static const struct fixup_format som_fixup_formats[256] = { /* R_NO_RELOCATION */ 0, "LD1+4*=", /* 0x00 */ 1, "LD1+4*=", /* 0x01 */ 2, "LD1+4*=", /* 0x02 */ 3, "LD1+4*=", /* 0x03 */ 4, "LD1+4*=", /* 0x04 */ 5, "LD1+4*=", /* 0x05 */ 6, "LD1+4*=", /* 0x06 */ 7, "LD1+4*=", /* 0x07 */ 8, "LD1+4*=", /* 0x08 */ 9, "LD1+4*=", /* 0x09 */ 10, "LD1+4*=", /* 0x0a */ 11, "LD1+4*=", /* 0x0b */ 12, "LD1+4*=", /* 0x0c */ 13, "LD1+4*=", /* 0x0d */ 14, "LD1+4*=", /* 0x0e */ 15, "LD1+4*=", /* 0x0f */ 16, "LD1+4*=", /* 0x10 */ 17, "LD1+4*=", /* 0x11 */ 18, "LD1+4*=", /* 0x12 */ 19, "LD1+4*=", /* 0x13 */ 20, "LD1+4*=", /* 0x14 */ 21, "LD1+4*=", /* 0x15 */ 22, "LD1+4*=", /* 0x16 */ 23, "LD1+4*=", /* 0x17 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -