Back to index

cell-binutils  2.17cvs20070401
som.c
Go to the documentation of this file.
00001 /* bfd back-end for HP PA-RISC SOM objects.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005 
00006    Contributed by the Center for Software Science at the
00007    University of Utah.
00008 
00009    This file is part of BFD, the Binary File Descriptor library.
00010 
00011    This program is free software; you can redistribute it and/or modify
00012    it under the terms of the GNU General Public License as published by
00013    the Free Software Foundation; either version 2 of the License, or
00014    (at your option) any later version.
00015 
00016    This program is distributed in the hope that it will be useful,
00017    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019    GNU General Public License for more details.
00020 
00021    You should have received a copy of the GNU General Public License
00022    along with this program; if not, write to the Free Software
00023    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00024    02110-1301, USA.  */
00025 
00026 #include "alloca-conf.h"
00027 #include "bfd.h"
00028 #include "sysdep.h"
00029 
00030 #if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF) || defined(HOST_HPPAMPEIX)
00031 
00032 #include "libbfd.h"
00033 #include "som.h"
00034 #include "safe-ctype.h"
00035 
00036 #include <sys/param.h>
00037 #include <signal.h>
00038 #include <machine/reg.h>
00039 #include <sys/file.h>
00040 
00041 static bfd_reloc_status_type hppa_som_reloc
00042   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
00043 static bfd_boolean som_mkobject (bfd *);
00044 static bfd_boolean som_is_space (asection *);
00045 static bfd_boolean som_is_subspace (asection *);
00046 static int compare_subspaces (const void *, const void *);
00047 static unsigned long som_compute_checksum (bfd *);
00048 static bfd_boolean som_build_and_write_symbol_table (bfd *);
00049 static unsigned int som_slurp_symbol_table (bfd *);
00050 
00051 /* Magic not defined in standard HP-UX header files until 8.0.  */
00052 
00053 #ifndef CPU_PA_RISC1_0
00054 #define CPU_PA_RISC1_0 0x20B
00055 #endif /* CPU_PA_RISC1_0 */
00056 
00057 #ifndef CPU_PA_RISC1_1
00058 #define CPU_PA_RISC1_1 0x210
00059 #endif /* CPU_PA_RISC1_1 */
00060 
00061 #ifndef CPU_PA_RISC2_0
00062 #define CPU_PA_RISC2_0 0x214
00063 #endif /* CPU_PA_RISC2_0 */
00064 
00065 #ifndef _PA_RISC1_0_ID
00066 #define _PA_RISC1_0_ID CPU_PA_RISC1_0
00067 #endif /* _PA_RISC1_0_ID */
00068 
00069 #ifndef _PA_RISC1_1_ID
00070 #define _PA_RISC1_1_ID CPU_PA_RISC1_1
00071 #endif /* _PA_RISC1_1_ID */
00072 
00073 #ifndef _PA_RISC2_0_ID
00074 #define _PA_RISC2_0_ID CPU_PA_RISC2_0
00075 #endif /* _PA_RISC2_0_ID */
00076 
00077 #ifndef _PA_RISC_MAXID
00078 #define _PA_RISC_MAXID      0x2FF
00079 #endif /* _PA_RISC_MAXID */
00080 
00081 #ifndef _PA_RISC_ID
00082 #define _PA_RISC_ID(__m_num)              \
00083     (((__m_num) == _PA_RISC1_0_ID) ||     \
00084      ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
00085 #endif /* _PA_RISC_ID */
00086 
00087 /* HIUX in it's infinite stupidity changed the names for several "well
00088    known" constants.  Work around such braindamage.  Try the HPUX version
00089    first, then the HIUX version, and finally provide a default.  */
00090 #ifdef HPUX_AUX_ID
00091 #define EXEC_AUX_ID HPUX_AUX_ID
00092 #endif
00093 
00094 #if !defined (EXEC_AUX_ID) && defined (HIUX_AUX_ID)
00095 #define EXEC_AUX_ID HIUX_AUX_ID
00096 #endif
00097 
00098 #ifndef EXEC_AUX_ID
00099 #define EXEC_AUX_ID 0
00100 #endif
00101 
00102 /* Size (in chars) of the temporary buffers used during fixup and string
00103    table writes.   */
00104 
00105 #define SOM_TMP_BUFSIZE 8192
00106 
00107 /* Size of the hash table in archives.  */
00108 #define SOM_LST_HASH_SIZE 31
00109 
00110 /* Max number of SOMs to be found in an archive.  */
00111 #define SOM_LST_MODULE_LIMIT 1024
00112 
00113 /* Generic alignment macro.  */
00114 #define SOM_ALIGN(val, alignment) \
00115   (((val) + (alignment) - 1) &~ ((unsigned long) (alignment) - 1))
00116 
00117 /* SOM allows any one of the four previous relocations to be reused
00118    with a "R_PREV_FIXUP" relocation entry.  Since R_PREV_FIXUP
00119    relocations are always a single byte, using a R_PREV_FIXUP instead
00120    of some multi-byte relocation makes object files smaller.
00121 
00122    Note one side effect of using a R_PREV_FIXUP is the relocation that
00123    is being repeated moves to the front of the queue.  */
00124 struct reloc_queue
00125 {
00126   unsigned char *reloc;
00127   unsigned int size;
00128 } reloc_queue[4];
00129 
00130 /* This fully describes the symbol types which may be attached to
00131    an EXPORT or IMPORT directive.  Only SOM uses this formation
00132    (ELF has no need for it).  */
00133 typedef enum
00134 {
00135   SYMBOL_TYPE_UNKNOWN,
00136   SYMBOL_TYPE_ABSOLUTE,
00137   SYMBOL_TYPE_CODE,
00138   SYMBOL_TYPE_DATA,
00139   SYMBOL_TYPE_ENTRY,
00140   SYMBOL_TYPE_MILLICODE,
00141   SYMBOL_TYPE_PLABEL,
00142   SYMBOL_TYPE_PRI_PROG,
00143   SYMBOL_TYPE_SEC_PROG,
00144 } pa_symbol_type;
00145 
00146 struct section_to_type
00147 {
00148   char *section;
00149   char type;
00150 };
00151 
00152 /* Assorted symbol information that needs to be derived from the BFD symbol
00153    and/or the BFD backend private symbol data.  */
00154 struct som_misc_symbol_info
00155 {
00156   unsigned int symbol_type;
00157   unsigned int symbol_scope;
00158   unsigned int arg_reloc;
00159   unsigned int symbol_info;
00160   unsigned int symbol_value;
00161   unsigned int priv_level;
00162   unsigned int secondary_def;
00163   unsigned int is_comdat;
00164   unsigned int is_common;
00165   unsigned int dup_common;
00166 };
00167 
00168 /* Map SOM section names to POSIX/BSD single-character symbol types.
00169 
00170    This table includes all the standard subspaces as defined in the
00171    current "PRO ABI for PA-RISC Systems", $UNWIND$ which for
00172    some reason was left out, and sections specific to embedded stabs.  */
00173 
00174 static const struct section_to_type stt[] =
00175 {
00176   {"$TEXT$", 't'},
00177   {"$SHLIB_INFO$", 't'},
00178   {"$MILLICODE$", 't'},
00179   {"$LIT$", 't'},
00180   {"$CODE$", 't'},
00181   {"$UNWIND_START$", 't'},
00182   {"$UNWIND$", 't'},
00183   {"$PRIVATE$", 'd'},
00184   {"$PLT$", 'd'},
00185   {"$SHLIB_DATA$", 'd'},
00186   {"$DATA$", 'd'},
00187   {"$SHORTDATA$", 'g'},
00188   {"$DLT$", 'd'},
00189   {"$GLOBAL$", 'g'},
00190   {"$SHORTBSS$", 's'},
00191   {"$BSS$", 'b'},
00192   {"$GDB_STRINGS$", 'N'},
00193   {"$GDB_SYMBOLS$", 'N'},
00194   {0, 0}
00195 };
00196 
00197 /* About the relocation formatting table...
00198 
00199    There are 256 entries in the table, one for each possible
00200    relocation opcode available in SOM.  We index the table by
00201    the relocation opcode.  The names and operations are those
00202    defined by a.out_800 (4).
00203 
00204    Right now this table is only used to count and perform minimal
00205    processing on relocation streams so that they can be internalized
00206    into BFD and symbolically printed by utilities.  To make actual use
00207    of them would be much more difficult, BFD's concept of relocations
00208    is far too simple to handle SOM relocations.  The basic assumption
00209    that a relocation can be completely processed independent of other
00210    relocations before an object file is written is invalid for SOM.
00211 
00212    The SOM relocations are meant to be processed as a stream, they
00213    specify copying of data from the input section to the output section
00214    while possibly modifying the data in some manner.  They also can
00215    specify that a variable number of zeros or uninitialized data be
00216    inserted on in the output segment at the current offset.  Some
00217    relocations specify that some previous relocation be re-applied at
00218    the current location in the input/output sections.  And finally a number
00219    of relocations have effects on other sections (R_ENTRY, R_EXIT,
00220    R_UNWIND_AUX and a variety of others).  There isn't even enough room
00221    in the BFD relocation data structure to store enough information to
00222    perform all the relocations.
00223 
00224    Each entry in the table has three fields.
00225 
00226    The first entry is an index into this "class" of relocations.  This
00227    index can then be used as a variable within the relocation itself.
00228 
00229    The second field is a format string which actually controls processing
00230    of the relocation.  It uses a simple postfix machine to do calculations
00231    based on variables/constants found in the string and the relocation
00232    stream.
00233 
00234    The third field specifys whether or not this relocation may use
00235    a constant (V) from the previous R_DATA_OVERRIDE rather than a constant
00236    stored in the instruction.
00237 
00238    Variables:
00239 
00240    L = input space byte count
00241    D = index into class of relocations
00242    M = output space byte count
00243    N = statement number (unused?)
00244    O = stack operation
00245    R = parameter relocation bits
00246    S = symbol index
00247    T = first 32 bits of stack unwind information
00248    U = second 32 bits of stack unwind information
00249    V = a literal constant (usually used in the next relocation)
00250    P = a previous relocation
00251 
00252    Lower case letters (starting with 'b') refer to following
00253    bytes in the relocation stream.  'b' is the next 1 byte,
00254    c is the next 2 bytes, d is the next 3 bytes, etc...
00255    This is the variable part of the relocation entries that
00256    makes our life a living hell.
00257 
00258    numerical constants are also used in the format string.  Note
00259    the constants are represented in decimal.
00260 
00261    '+', "*" and "=" represents the obvious postfix operators.
00262    '<' represents a left shift.
00263 
00264    Stack Operations:
00265 
00266    Parameter Relocation Bits:
00267 
00268    Unwind Entries:
00269 
00270    Previous Relocations:  The index field represents which in the queue
00271    of 4 previous fixups should be re-applied.
00272 
00273    Literal Constants:  These are generally used to represent addend
00274    parts of relocations when these constants are not stored in the
00275    fields of the instructions themselves.  For example the instruction
00276    addil foo-$global$-0x1234 would use an override for "0x1234" rather
00277    than storing it into the addil itself.  */
00278 
00279 struct fixup_format
00280 {
00281   int D;
00282   const char *format;
00283 };
00284 
00285 static const struct fixup_format som_fixup_formats[256] =
00286 {
00287   /* R_NO_RELOCATION.  */
00288   {  0, "LD1+4*=" },        /* 0x00 */
00289   {  1, "LD1+4*=" },        /* 0x01 */
00290   {  2, "LD1+4*=" },        /* 0x02 */
00291   {  3, "LD1+4*=" },        /* 0x03 */
00292   {  4, "LD1+4*=" },        /* 0x04 */
00293   {  5, "LD1+4*=" },        /* 0x05 */
00294   {  6, "LD1+4*=" },        /* 0x06 */
00295   {  7, "LD1+4*=" },        /* 0x07 */
00296   {  8, "LD1+4*=" },        /* 0x08 */
00297   {  9, "LD1+4*=" },        /* 0x09 */
00298   { 10, "LD1+4*=" },        /* 0x0a */
00299   { 11, "LD1+4*=" },        /* 0x0b */
00300   { 12, "LD1+4*=" },        /* 0x0c */
00301   { 13, "LD1+4*=" },        /* 0x0d */
00302   { 14, "LD1+4*=" },        /* 0x0e */
00303   { 15, "LD1+4*=" },        /* 0x0f */
00304   { 16, "LD1+4*=" },        /* 0x10 */
00305   { 17, "LD1+4*=" },        /* 0x11 */
00306   { 18, "LD1+4*=" },        /* 0x12 */
00307   { 19, "LD1+4*=" },        /* 0x13 */
00308   { 20, "LD1+4*=" },        /* 0x14 */
00309   { 21, "LD1+4*=" },        /* 0x15 */
00310   { 22, "LD1+4*=" },        /* 0x16 */
00311   { 23, "LD1+4*=" },        /* 0x17 */
00312   {  0, "LD8<b+1+4*=" },    /* 0x18 */
00313   {  1, "LD8<b+1+4*=" },    /* 0x19 */
00314   {  2, "LD8<b+1+4*=" },    /* 0x1a */
00315   {  3, "LD8<b+1+4*=" },    /* 0x1b */
00316   {  0, "LD16<c+1+4*=" },   /* 0x1c */
00317   {  1, "LD16<c+1+4*=" },   /* 0x1d */
00318   {  2, "LD16<c+1+4*=" },   /* 0x1e */
00319   {  0, "Ld1+=" },          /* 0x1f */
00320   /* R_ZEROES.  */
00321   {  0, "Lb1+4*=" },        /* 0x20 */
00322   {  1, "Ld1+=" },          /* 0x21 */
00323   /* R_UNINIT.  */
00324   {  0, "Lb1+4*=" },        /* 0x22 */
00325   {  1, "Ld1+=" },          /* 0x23 */
00326   /* R_RELOCATION.  */
00327   {  0, "L4=" },            /* 0x24 */
00328   /* R_DATA_ONE_SYMBOL.  */
00329   {  0, "L4=Sb=" },         /* 0x25 */
00330   {  1, "L4=Sd=" },         /* 0x26 */
00331   /* R_DATA_PLEBEL.  */
00332   {  0, "L4=Sb=" },         /* 0x27 */
00333   {  1, "L4=Sd=" },         /* 0x28 */
00334   /* R_SPACE_REF.  */
00335   {  0, "L4=" },            /* 0x29 */
00336   /* R_REPEATED_INIT.  */
00337   {  0, "L4=Mb1+4*=" },            /* 0x2a */
00338   {  1, "Lb4*=Mb1+L*=" },   /* 0x2b */
00339   {  2, "Lb4*=Md1+4*=" },   /* 0x2c */
00340   {  3, "Ld1+=Me1+=" },            /* 0x2d */
00341   {  0, "" },               /* 0x2e */
00342   {  0, "" },               /* 0x2f */
00343   /* R_PCREL_CALL.  */
00344   {  0, "L4=RD=Sb=" },             /* 0x30 */
00345   {  1, "L4=RD=Sb=" },             /* 0x31 */
00346   {  2, "L4=RD=Sb=" },             /* 0x32 */
00347   {  3, "L4=RD=Sb=" },             /* 0x33 */
00348   {  4, "L4=RD=Sb=" },             /* 0x34 */
00349   {  5, "L4=RD=Sb=" },             /* 0x35 */
00350   {  6, "L4=RD=Sb=" },             /* 0x36 */
00351   {  7, "L4=RD=Sb=" },             /* 0x37 */
00352   {  8, "L4=RD=Sb=" },             /* 0x38 */
00353   {  9, "L4=RD=Sb=" },             /* 0x39 */
00354   {  0, "L4=RD8<b+=Sb=" },  /* 0x3a */
00355   {  1, "L4=RD8<b+=Sb=" },  /* 0x3b */
00356   {  0, "L4=RD8<b+=Sd=" },  /* 0x3c */
00357   {  1, "L4=RD8<b+=Sd=" },  /* 0x3d */
00358   /* R_SHORT_PCREL_MODE.  */
00359   {  0, "" },               /* 0x3e */
00360   /* R_LONG_PCREL_MODE.  */
00361   {  0, "" },               /* 0x3f */
00362   /* R_ABS_CALL.  */
00363   {  0, "L4=RD=Sb=" },             /* 0x40 */
00364   {  1, "L4=RD=Sb=" },             /* 0x41 */
00365   {  2, "L4=RD=Sb=" },             /* 0x42 */
00366   {  3, "L4=RD=Sb=" },             /* 0x43 */
00367   {  4, "L4=RD=Sb=" },             /* 0x44 */
00368   {  5, "L4=RD=Sb=" },             /* 0x45 */
00369   {  6, "L4=RD=Sb=" },             /* 0x46 */
00370   {  7, "L4=RD=Sb=" },             /* 0x47 */
00371   {  8, "L4=RD=Sb=" },             /* 0x48 */
00372   {  9, "L4=RD=Sb=" },             /* 0x49 */
00373   {  0, "L4=RD8<b+=Sb=" },  /* 0x4a */
00374   {  1, "L4=RD8<b+=Sb=" },  /* 0x4b */
00375   {  0, "L4=RD8<b+=Sd=" },  /* 0x4c */
00376   {  1, "L4=RD8<b+=Sd=" },  /* 0x4d */
00377   /* R_RESERVED.  */
00378   {  0, "" },               /* 0x4e */
00379   {  0, "" },               /* 0x4f */
00380   /* R_DP_RELATIVE.  */
00381   {  0, "L4=SD=" },         /* 0x50 */
00382   {  1, "L4=SD=" },         /* 0x51 */
00383   {  2, "L4=SD=" },         /* 0x52 */
00384   {  3, "L4=SD=" },         /* 0x53 */
00385   {  4, "L4=SD=" },         /* 0x54 */
00386   {  5, "L4=SD=" },         /* 0x55 */
00387   {  6, "L4=SD=" },         /* 0x56 */
00388   {  7, "L4=SD=" },         /* 0x57 */
00389   {  8, "L4=SD=" },         /* 0x58 */
00390   {  9, "L4=SD=" },         /* 0x59 */
00391   { 10, "L4=SD=" },         /* 0x5a */
00392   { 11, "L4=SD=" },         /* 0x5b */
00393   { 12, "L4=SD=" },         /* 0x5c */
00394   { 13, "L4=SD=" },         /* 0x5d */
00395   { 14, "L4=SD=" },         /* 0x5e */
00396   { 15, "L4=SD=" },         /* 0x5f */
00397   { 16, "L4=SD=" },         /* 0x60 */
00398   { 17, "L4=SD=" },         /* 0x61 */
00399   { 18, "L4=SD=" },         /* 0x62 */
00400   { 19, "L4=SD=" },         /* 0x63 */
00401   { 20, "L4=SD=" },         /* 0x64 */
00402   { 21, "L4=SD=" },         /* 0x65 */
00403   { 22, "L4=SD=" },         /* 0x66 */
00404   { 23, "L4=SD=" },         /* 0x67 */
00405   { 24, "L4=SD=" },         /* 0x68 */
00406   { 25, "L4=SD=" },         /* 0x69 */
00407   { 26, "L4=SD=" },         /* 0x6a */
00408   { 27, "L4=SD=" },         /* 0x6b */
00409   { 28, "L4=SD=" },         /* 0x6c */
00410   { 29, "L4=SD=" },         /* 0x6d */
00411   { 30, "L4=SD=" },         /* 0x6e */
00412   { 31, "L4=SD=" },         /* 0x6f */
00413   { 32, "L4=Sb=" },         /* 0x70 */
00414   { 33, "L4=Sd=" },         /* 0x71 */
00415   /* R_RESERVED.  */
00416   {  0, "" },               /* 0x72 */
00417   {  0, "" },               /* 0x73 */
00418   {  0, "" },               /* 0x74 */
00419   {  0, "" },               /* 0x75 */
00420   {  0, "" },               /* 0x76 */
00421   {  0, "" },               /* 0x77 */
00422   /* R_DLT_REL.  */
00423   {  0, "L4=Sb=" },         /* 0x78 */
00424   {  1, "L4=Sd=" },         /* 0x79 */
00425   /* R_RESERVED.  */
00426   {  0, "" },               /* 0x7a */
00427   {  0, "" },               /* 0x7b */
00428   {  0, "" },               /* 0x7c */
00429   {  0, "" },               /* 0x7d */
00430   {  0, "" },               /* 0x7e */
00431   {  0, "" },               /* 0x7f */
00432   /* R_CODE_ONE_SYMBOL.  */
00433   {  0, "L4=SD=" },         /* 0x80 */
00434   {  1, "L4=SD=" },         /* 0x81 */
00435   {  2, "L4=SD=" },         /* 0x82 */
00436   {  3, "L4=SD=" },         /* 0x83 */
00437   {  4, "L4=SD=" },         /* 0x84 */
00438   {  5, "L4=SD=" },         /* 0x85 */
00439   {  6, "L4=SD=" },         /* 0x86 */
00440   {  7, "L4=SD=" },         /* 0x87 */
00441   {  8, "L4=SD=" },         /* 0x88 */
00442   {  9, "L4=SD=" },         /* 0x89 */
00443   { 10, "L4=SD=" },         /* 0x8q */
00444   { 11, "L4=SD=" },         /* 0x8b */
00445   { 12, "L4=SD=" },         /* 0x8c */
00446   { 13, "L4=SD=" },         /* 0x8d */
00447   { 14, "L4=SD=" },         /* 0x8e */
00448   { 15, "L4=SD=" },         /* 0x8f */
00449   { 16, "L4=SD=" },         /* 0x90 */
00450   { 17, "L4=SD=" },         /* 0x91 */
00451   { 18, "L4=SD=" },         /* 0x92 */
00452   { 19, "L4=SD=" },         /* 0x93 */
00453   { 20, "L4=SD=" },         /* 0x94 */
00454   { 21, "L4=SD=" },         /* 0x95 */
00455   { 22, "L4=SD=" },         /* 0x96 */
00456   { 23, "L4=SD=" },         /* 0x97 */
00457   { 24, "L4=SD=" },         /* 0x98 */
00458   { 25, "L4=SD=" },         /* 0x99 */
00459   { 26, "L4=SD=" },         /* 0x9a */
00460   { 27, "L4=SD=" },         /* 0x9b */
00461   { 28, "L4=SD=" },         /* 0x9c */
00462   { 29, "L4=SD=" },         /* 0x9d */
00463   { 30, "L4=SD=" },         /* 0x9e */
00464   { 31, "L4=SD=" },         /* 0x9f */
00465   { 32, "L4=Sb=" },         /* 0xa0 */
00466   { 33, "L4=Sd=" },         /* 0xa1 */
00467   /* R_RESERVED.  */
00468   {  0, "" },               /* 0xa2 */
00469   {  0, "" },               /* 0xa3 */
00470   {  0, "" },               /* 0xa4 */
00471   {  0, "" },               /* 0xa5 */
00472   {  0, "" },               /* 0xa6 */
00473   {  0, "" },               /* 0xa7 */
00474   {  0, "" },               /* 0xa8 */
00475   {  0, "" },               /* 0xa9 */
00476   {  0, "" },               /* 0xaa */
00477   {  0, "" },               /* 0xab */
00478   {  0, "" },               /* 0xac */
00479   {  0, "" },               /* 0xad */
00480   /* R_MILLI_REL.  */
00481   {  0, "L4=Sb=" },         /* 0xae */
00482   {  1, "L4=Sd=" },         /* 0xaf */
00483   /* R_CODE_PLABEL.  */
00484   {  0, "L4=Sb=" },         /* 0xb0 */
00485   {  1, "L4=Sd=" },         /* 0xb1 */
00486   /* R_BREAKPOINT.  */
00487   {  0, "L4=" },            /* 0xb2 */
00488   /* R_ENTRY.  */
00489   {  0, "Te=Ue=" },         /* 0xb3 */
00490   {  1, "Uf=" },            /* 0xb4 */
00491   /* R_ALT_ENTRY.  */
00492   {  0, "" },               /* 0xb5 */
00493   /* R_EXIT.  */
00494   {  0, "" },               /* 0xb6 */
00495   /* R_BEGIN_TRY.  */
00496   {  0, "" },               /* 0xb7 */
00497   /* R_END_TRY.  */
00498   {  0, "R0=" },            /* 0xb8 */
00499   {  1, "Rb4*=" },          /* 0xb9 */
00500   {  2, "Rd4*=" },          /* 0xba */
00501   /* R_BEGIN_BRTAB.  */
00502   {  0, "" },               /* 0xbb */
00503   /* R_END_BRTAB.  */
00504   {  0, "" },               /* 0xbc */
00505   /* R_STATEMENT.  */
00506   {  0, "Nb=" },            /* 0xbd */
00507   {  1, "Nc=" },            /* 0xbe */
00508   {  2, "Nd=" },            /* 0xbf */
00509   /* R_DATA_EXPR.  */
00510   {  0, "L4=" },            /* 0xc0 */
00511   /* R_CODE_EXPR.  */
00512   {  0, "L4=" },            /* 0xc1 */
00513   /* R_FSEL.  */
00514   {  0, "" },               /* 0xc2 */
00515   /* R_LSEL.  */
00516   {  0, "" },               /* 0xc3 */
00517   /* R_RSEL.  */
00518   {  0, "" },               /* 0xc4 */
00519   /* R_N_MODE.  */
00520   {  0, "" },               /* 0xc5 */
00521   /* R_S_MODE.  */
00522   {  0, "" },               /* 0xc6 */
00523   /* R_D_MODE.  */
00524   {  0, "" },               /* 0xc7 */
00525   /* R_R_MODE.  */
00526   {  0, "" },               /* 0xc8 */
00527   /* R_DATA_OVERRIDE.  */
00528   {  0, "V0=" },            /* 0xc9 */
00529   {  1, "Vb=" },            /* 0xca */
00530   {  2, "Vc=" },            /* 0xcb */
00531   {  3, "Vd=" },            /* 0xcc */
00532   {  4, "Ve=" },            /* 0xcd */
00533   /* R_TRANSLATED.  */
00534   {  0, "" },               /* 0xce */
00535   /* R_AUX_UNWIND.  */
00536   {  0,"Sd=Ve=Ee=" },              /* 0xcf */
00537   /* R_COMP1.  */
00538   {  0, "Ob=" },            /* 0xd0 */
00539   /* R_COMP2.  */
00540   {  0, "Ob=Sd=" },         /* 0xd1 */
00541   /* R_COMP3.  */
00542   {  0, "Ob=Ve=" },         /* 0xd2 */
00543   /* R_PREV_FIXUP.  */
00544   {  0, "P" },                     /* 0xd3 */
00545   {  1, "P" },                     /* 0xd4 */
00546   {  2, "P" },                     /* 0xd5 */
00547   {  3, "P" },                     /* 0xd6 */
00548   /* R_SEC_STMT.  */
00549   {  0, "" },               /* 0xd7 */
00550   /* R_N0SEL.  */
00551   {  0, "" },               /* 0xd8 */
00552   /* R_N1SEL.  */
00553   {  0, "" },               /* 0xd9 */
00554   /* R_LINETAB.  */
00555   {  0, "Eb=Sd=Ve=" },             /* 0xda */
00556   /* R_LINETAB_ESC.  */
00557   {  0, "Eb=Mb=" },         /* 0xdb */
00558   /* R_LTP_OVERRIDE.  */
00559   {  0, "" },               /* 0xdc */
00560   /* R_COMMENT.  */
00561   {  0, "Ob=Vf=" },         /* 0xdd */
00562   /* R_RESERVED.  */
00563   {  0, "" },               /* 0xde */
00564   {  0, "" },               /* 0xdf */
00565   {  0, "" },               /* 0xe0 */
00566   {  0, "" },               /* 0xe1 */
00567   {  0, "" },               /* 0xe2 */
00568   {  0, "" },               /* 0xe3 */
00569   {  0, "" },               /* 0xe4 */
00570   {  0, "" },               /* 0xe5 */
00571   {  0, "" },               /* 0xe6 */
00572   {  0, "" },               /* 0xe7 */
00573   {  0, "" },               /* 0xe8 */
00574   {  0, "" },               /* 0xe9 */
00575   {  0, "" },               /* 0xea */
00576   {  0, "" },               /* 0xeb */
00577   {  0, "" },               /* 0xec */
00578   {  0, "" },               /* 0xed */
00579   {  0, "" },               /* 0xee */
00580   {  0, "" },               /* 0xef */
00581   {  0, "" },               /* 0xf0 */
00582   {  0, "" },               /* 0xf1 */
00583   {  0, "" },               /* 0xf2 */
00584   {  0, "" },               /* 0xf3 */
00585   {  0, "" },               /* 0xf4 */
00586   {  0, "" },               /* 0xf5 */
00587   {  0, "" },               /* 0xf6 */
00588   {  0, "" },               /* 0xf7 */
00589   {  0, "" },               /* 0xf8 */
00590   {  0, "" },               /* 0xf9 */
00591   {  0, "" },               /* 0xfa */
00592   {  0, "" },               /* 0xfb */
00593   {  0, "" },               /* 0xfc */
00594   {  0, "" },               /* 0xfd */
00595   {  0, "" },               /* 0xfe */
00596   {  0, "" },               /* 0xff */
00597 };
00598 
00599 static const int comp1_opcodes[] =
00600 {
00601   0x00,
00602   0x40,
00603   0x41,
00604   0x42,
00605   0x43,
00606   0x44,
00607   0x45,
00608   0x46,
00609   0x47,
00610   0x48,
00611   0x49,
00612   0x4a,
00613   0x4b,
00614   0x60,
00615   0x80,
00616   0xa0,
00617   0xc0,
00618   -1
00619 };
00620 
00621 static const int comp2_opcodes[] =
00622 {
00623   0x00,
00624   0x80,
00625   0x82,
00626   0xc0,
00627   -1
00628 };
00629 
00630 static const int comp3_opcodes[] =
00631 {
00632   0x00,
00633   0x02,
00634   -1
00635 };
00636 
00637 /* These apparently are not in older versions of hpux reloc.h (hpux7).  */
00638 #ifndef R_DLT_REL
00639 #define R_DLT_REL 0x78
00640 #endif
00641 
00642 #ifndef R_AUX_UNWIND
00643 #define R_AUX_UNWIND 0xcf
00644 #endif
00645 
00646 #ifndef R_SEC_STMT
00647 #define R_SEC_STMT 0xd7
00648 #endif
00649 
00650 /* And these first appeared in hpux10.  */
00651 #ifndef R_SHORT_PCREL_MODE
00652 #define NO_PCREL_MODES
00653 #define R_SHORT_PCREL_MODE 0x3e
00654 #endif
00655 
00656 #ifndef R_LONG_PCREL_MODE
00657 #define R_LONG_PCREL_MODE 0x3f
00658 #endif
00659 
00660 #ifndef R_N0SEL
00661 #define R_N0SEL 0xd8
00662 #endif
00663 
00664 #ifndef R_N1SEL
00665 #define R_N1SEL 0xd9
00666 #endif
00667 
00668 #ifndef R_LINETAB
00669 #define R_LINETAB 0xda
00670 #endif
00671 
00672 #ifndef R_LINETAB_ESC
00673 #define R_LINETAB_ESC 0xdb
00674 #endif
00675 
00676 #ifndef R_LTP_OVERRIDE
00677 #define R_LTP_OVERRIDE 0xdc
00678 #endif
00679 
00680 #ifndef R_COMMENT
00681 #define R_COMMENT 0xdd
00682 #endif
00683 
00684 #define SOM_HOWTO(TYPE, NAME)      \
00685   HOWTO(TYPE, 0, 0, 32, FALSE, 0, 0, hppa_som_reloc, NAME, FALSE, 0, 0, FALSE)
00686 
00687 static reloc_howto_type som_hppa_howto_table[] =
00688 {
00689   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00690   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00691   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00692   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00693   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00694   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00695   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00696   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00697   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00698   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00699   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00700   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00701   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00702   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00703   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00704   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00705   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00706   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00707   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00708   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00709   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00710   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00711   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00712   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00713   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00714   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00715   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00716   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00717   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00718   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00719   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00720   SOM_HOWTO (R_NO_RELOCATION, "R_NO_RELOCATION"),
00721   SOM_HOWTO (R_ZEROES, "R_ZEROES"),
00722   SOM_HOWTO (R_ZEROES, "R_ZEROES"),
00723   SOM_HOWTO (R_UNINIT, "R_UNINIT"),
00724   SOM_HOWTO (R_UNINIT, "R_UNINIT"),
00725   SOM_HOWTO (R_RELOCATION, "R_RELOCATION"),
00726   SOM_HOWTO (R_DATA_ONE_SYMBOL, "R_DATA_ONE_SYMBOL"),
00727   SOM_HOWTO (R_DATA_ONE_SYMBOL, "R_DATA_ONE_SYMBOL"),
00728   SOM_HOWTO (R_DATA_PLABEL, "R_DATA_PLABEL"),
00729   SOM_HOWTO (R_DATA_PLABEL, "R_DATA_PLABEL"),
00730   SOM_HOWTO (R_SPACE_REF, "R_SPACE_REF"),
00731   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
00732   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
00733   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
00734   SOM_HOWTO (R_REPEATED_INIT, "REPEATED_INIT"),
00735   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00736   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00737   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00738   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00739   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00740   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00741   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00742   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00743   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00744   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00745   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00746   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00747   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00748   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00749   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00750   SOM_HOWTO (R_PCREL_CALL, "R_PCREL_CALL"),
00751   SOM_HOWTO (R_SHORT_PCREL_MODE, "R_SHORT_PCREL_MODE"),
00752   SOM_HOWTO (R_LONG_PCREL_MODE, "R_LONG_PCREL_MODE"),
00753   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00754   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00755   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00756   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00757   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00758   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00759   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00760   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00761   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00762   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00763   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00764   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00765   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00766   SOM_HOWTO (R_ABS_CALL, "R_ABS_CALL"),
00767   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00768   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00769   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00770   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00771   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00772   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00773   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00774   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00775   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00776   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00777   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00778   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00779   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00780   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00781   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00782   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00783   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00784   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00785   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00786   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00787   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00788   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00789   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00790   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00791   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00792   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00793   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00794   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00795   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00796   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00797   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00798   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00799   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00800   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00801   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00802   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00803   SOM_HOWTO (R_DP_RELATIVE, "R_DP_RELATIVE"),
00804   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00805   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00806   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00807   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00808   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00809   SOM_HOWTO (R_DLT_REL, "R_DLT_REL"),
00810   SOM_HOWTO (R_DLT_REL, "R_DLT_REL"),
00811   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00812   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00813   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00814   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00815   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00816   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00817   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00818   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00819   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00820   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00821   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00822   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00823   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00824   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00825   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00826   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00827   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00828   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00829   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00830   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00831   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00832   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00833   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00834   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00835   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00836   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00837   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00838   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00839   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00840   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00841   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00842   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00843   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00844   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00845   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00846   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00847   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00848   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00849   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00850   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00851   SOM_HOWTO (R_CODE_ONE_SYMBOL, "R_CODE_ONE_SYMBOL"),
00852   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00853   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00854   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00855   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00856   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00857   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00858   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00859   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00860   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00861   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00862   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00863   SOM_HOWTO (R_MILLI_REL, "R_MILLI_REL"),
00864   SOM_HOWTO (R_MILLI_REL, "R_MILLI_REL"),
00865   SOM_HOWTO (R_CODE_PLABEL, "R_CODE_PLABEL"),
00866   SOM_HOWTO (R_CODE_PLABEL, "R_CODE_PLABEL"),
00867   SOM_HOWTO (R_BREAKPOINT, "R_BREAKPOINT"),
00868   SOM_HOWTO (R_ENTRY, "R_ENTRY"),
00869   SOM_HOWTO (R_ENTRY, "R_ENTRY"),
00870   SOM_HOWTO (R_ALT_ENTRY, "R_ALT_ENTRY"),
00871   SOM_HOWTO (R_EXIT, "R_EXIT"),
00872   SOM_HOWTO (R_BEGIN_TRY, "R_BEGIN_TRY"),
00873   SOM_HOWTO (R_END_TRY, "R_END_TRY"),
00874   SOM_HOWTO (R_END_TRY, "R_END_TRY"),
00875   SOM_HOWTO (R_END_TRY, "R_END_TRY"),
00876   SOM_HOWTO (R_BEGIN_BRTAB, "R_BEGIN_BRTAB"),
00877   SOM_HOWTO (R_END_BRTAB, "R_END_BRTAB"),
00878   SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
00879   SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
00880   SOM_HOWTO (R_STATEMENT, "R_STATEMENT"),
00881   SOM_HOWTO (R_DATA_EXPR, "R_DATA_EXPR"),
00882   SOM_HOWTO (R_CODE_EXPR, "R_CODE_EXPR"),
00883   SOM_HOWTO (R_FSEL, "R_FSEL"),
00884   SOM_HOWTO (R_LSEL, "R_LSEL"),
00885   SOM_HOWTO (R_RSEL, "R_RSEL"),
00886   SOM_HOWTO (R_N_MODE, "R_N_MODE"),
00887   SOM_HOWTO (R_S_MODE, "R_S_MODE"),
00888   SOM_HOWTO (R_D_MODE, "R_D_MODE"),
00889   SOM_HOWTO (R_R_MODE, "R_R_MODE"),
00890   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
00891   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
00892   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
00893   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
00894   SOM_HOWTO (R_DATA_OVERRIDE, "R_DATA_OVERRIDE"),
00895   SOM_HOWTO (R_TRANSLATED, "R_TRANSLATED"),
00896   SOM_HOWTO (R_AUX_UNWIND, "R_AUX_UNWIND"),
00897   SOM_HOWTO (R_COMP1, "R_COMP1"),
00898   SOM_HOWTO (R_COMP2, "R_COMP2"),
00899   SOM_HOWTO (R_COMP3, "R_COMP3"),
00900   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
00901   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
00902   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
00903   SOM_HOWTO (R_PREV_FIXUP, "R_PREV_FIXUP"),
00904   SOM_HOWTO (R_SEC_STMT, "R_SEC_STMT"),
00905   SOM_HOWTO (R_N0SEL, "R_N0SEL"),
00906   SOM_HOWTO (R_N1SEL, "R_N1SEL"),
00907   SOM_HOWTO (R_LINETAB, "R_LINETAB"),
00908   SOM_HOWTO (R_LINETAB_ESC, "R_LINETAB_ESC"),
00909   SOM_HOWTO (R_LTP_OVERRIDE, "R_LTP_OVERRIDE"),
00910   SOM_HOWTO (R_COMMENT, "R_COMMENT"),
00911   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00912   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00913   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00914   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00915   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00916   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00917   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00918   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00919   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00920   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00921   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00922   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00923   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00924   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00925   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00926   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00927   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00928   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00929   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00930   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00931   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00932   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00933   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00934   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00935   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00936   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00937   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00938   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00939   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00940   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00941   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00942   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00943   SOM_HOWTO (R_RESERVED, "R_RESERVED"),
00944   SOM_HOWTO (R_RESERVED, "R_RESERVED")
00945 };
00946 
00947 /* Initialize the SOM relocation queue.  By definition the queue holds
00948    the last four multibyte fixups.  */
00949 
00950 static void
00951 som_initialize_reloc_queue (struct reloc_queue *queue)
00952 {
00953   queue[0].reloc = NULL;
00954   queue[0].size = 0;
00955   queue[1].reloc = NULL;
00956   queue[1].size = 0;
00957   queue[2].reloc = NULL;
00958   queue[2].size = 0;
00959   queue[3].reloc = NULL;
00960   queue[3].size = 0;
00961 }
00962 
00963 /* Insert a new relocation into the relocation queue.  */
00964 
00965 static void
00966 som_reloc_queue_insert (unsigned char *p,
00967                      unsigned int size,
00968                      struct reloc_queue *queue)
00969 {
00970   queue[3].reloc = queue[2].reloc;
00971   queue[3].size = queue[2].size;
00972   queue[2].reloc = queue[1].reloc;
00973   queue[2].size = queue[1].size;
00974   queue[1].reloc = queue[0].reloc;
00975   queue[1].size = queue[0].size;
00976   queue[0].reloc = p;
00977   queue[0].size = size;
00978 }
00979 
00980 /* When an entry in the relocation queue is reused, the entry moves
00981    to the front of the queue.  */
00982 
00983 static void
00984 som_reloc_queue_fix (struct reloc_queue *queue, unsigned int index)
00985 {
00986   if (index == 0)
00987     return;
00988 
00989   if (index == 1)
00990     {
00991       unsigned char *tmp1 = queue[0].reloc;
00992       unsigned int tmp2 = queue[0].size;
00993 
00994       queue[0].reloc = queue[1].reloc;
00995       queue[0].size = queue[1].size;
00996       queue[1].reloc = tmp1;
00997       queue[1].size = tmp2;
00998       return;
00999     }
01000 
01001   if (index == 2)
01002     {
01003       unsigned char *tmp1 = queue[0].reloc;
01004       unsigned int tmp2 = queue[0].size;
01005 
01006       queue[0].reloc = queue[2].reloc;
01007       queue[0].size = queue[2].size;
01008       queue[2].reloc = queue[1].reloc;
01009       queue[2].size = queue[1].size;
01010       queue[1].reloc = tmp1;
01011       queue[1].size = tmp2;
01012       return;
01013     }
01014 
01015   if (index == 3)
01016     {
01017       unsigned char *tmp1 = queue[0].reloc;
01018       unsigned int tmp2 = queue[0].size;
01019 
01020       queue[0].reloc = queue[3].reloc;
01021       queue[0].size = queue[3].size;
01022       queue[3].reloc = queue[2].reloc;
01023       queue[3].size = queue[2].size;
01024       queue[2].reloc = queue[1].reloc;
01025       queue[2].size = queue[1].size;
01026       queue[1].reloc = tmp1;
01027       queue[1].size = tmp2;
01028       return;
01029     }
01030   abort ();
01031 }
01032 
01033 /* Search for a particular relocation in the relocation queue.  */
01034 
01035 static int
01036 som_reloc_queue_find (unsigned char *p,
01037                     unsigned int size,
01038                     struct reloc_queue *queue)
01039 {
01040   if (queue[0].reloc && !memcmp (p, queue[0].reloc, size)
01041       && size == queue[0].size)
01042     return 0;
01043   if (queue[1].reloc && !memcmp (p, queue[1].reloc, size)
01044       && size == queue[1].size)
01045     return 1;
01046   if (queue[2].reloc && !memcmp (p, queue[2].reloc, size)
01047       && size == queue[2].size)
01048     return 2;
01049   if (queue[3].reloc && !memcmp (p, queue[3].reloc, size)
01050       && size == queue[3].size)
01051     return 3;
01052   return -1;
01053 }
01054 
01055 static unsigned char *
01056 try_prev_fixup (bfd *abfd ATTRIBUTE_UNUSED,
01057               unsigned int *subspace_reloc_sizep,
01058               unsigned char *p,
01059               unsigned int size,
01060               struct reloc_queue *queue)
01061 {
01062   int queue_index = som_reloc_queue_find (p, size, queue);
01063 
01064   if (queue_index != -1)
01065     {
01066       /* Found this in a previous fixup.  Undo the fixup we
01067         just built and use R_PREV_FIXUP instead.  We saved
01068         a total of size - 1 bytes in the fixup stream.  */
01069       bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
01070       p += 1;
01071       *subspace_reloc_sizep += 1;
01072       som_reloc_queue_fix (queue, queue_index);
01073     }
01074   else
01075     {
01076       som_reloc_queue_insert (p, size, queue);
01077       *subspace_reloc_sizep += size;
01078       p += size;
01079     }
01080   return p;
01081 }
01082 
01083 /* Emit the proper R_NO_RELOCATION fixups to map the next SKIP
01084    bytes without any relocation.  Update the size of the subspace
01085    relocation stream via SUBSPACE_RELOC_SIZE_P; also return the
01086    current pointer into the relocation stream.  */
01087 
01088 static unsigned char *
01089 som_reloc_skip (bfd *abfd,
01090               unsigned int skip,
01091               unsigned char *p,
01092               unsigned int *subspace_reloc_sizep,
01093               struct reloc_queue *queue)
01094 {
01095   /* Use a 4 byte R_NO_RELOCATION entry with a maximal value
01096      then R_PREV_FIXUPs to get the difference down to a
01097      reasonable size.  */
01098   if (skip >= 0x1000000)
01099     {
01100       skip -= 0x1000000;
01101       bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
01102       bfd_put_8 (abfd, 0xff, p + 1);
01103       bfd_put_16 (abfd, (bfd_vma) 0xffff, p + 2);
01104       p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
01105       while (skip >= 0x1000000)
01106        {
01107          skip -= 0x1000000;
01108          bfd_put_8 (abfd, R_PREV_FIXUP, p);
01109          p++;
01110          *subspace_reloc_sizep += 1;
01111          /* No need to adjust queue here since we are repeating the
01112             most recent fixup.  */
01113        }
01114     }
01115 
01116   /* The difference must be less than 0x1000000.  Use one
01117      more R_NO_RELOCATION entry to get to the right difference.  */
01118   if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
01119     {
01120       /* Difference can be handled in a simple single-byte
01121         R_NO_RELOCATION entry.  */
01122       if (skip <= 0x60)
01123        {
01124          bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
01125          *subspace_reloc_sizep += 1;
01126          p++;
01127        }
01128       /* Handle it with a two byte R_NO_RELOCATION entry.  */
01129       else if (skip <= 0x1000)
01130        {
01131          bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
01132          bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
01133          p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
01134        }
01135       /* Handle it with a three byte R_NO_RELOCATION entry.  */
01136       else
01137        {
01138          bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
01139          bfd_put_16 (abfd, (bfd_vma) (skip >> 2) - 1, p + 1);
01140          p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
01141        }
01142     }
01143   /* Ugh.  Punt and use a 4 byte entry.  */
01144   else if (skip > 0)
01145     {
01146       bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
01147       bfd_put_8 (abfd, (skip - 1) >> 16, p + 1);
01148       bfd_put_16 (abfd, (bfd_vma) skip - 1, p + 2);
01149       p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
01150     }
01151   return p;
01152 }
01153 
01154 /* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
01155    from a BFD relocation.  Update the size of the subspace relocation
01156    stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
01157    into the relocation stream.  */
01158 
01159 static unsigned char *
01160 som_reloc_addend (bfd *abfd,
01161                 bfd_vma addend,
01162                 unsigned char *p,
01163                 unsigned int *subspace_reloc_sizep,
01164                 struct reloc_queue *queue)
01165 {
01166   if (addend + 0x80 < 0x100)
01167     {
01168       bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
01169       bfd_put_8 (abfd, addend, p + 1);
01170       p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
01171     }
01172   else if (addend + 0x8000 < 0x10000)
01173     {
01174       bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
01175       bfd_put_16 (abfd, addend, p + 1);
01176       p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
01177     }
01178   else if (addend + 0x800000 < 0x1000000)
01179     {
01180       bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
01181       bfd_put_8 (abfd, addend >> 16, p + 1);
01182       bfd_put_16 (abfd, addend, p + 2);
01183       p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
01184     }
01185   else
01186     {
01187       bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
01188       bfd_put_32 (abfd, addend, p + 1);
01189       p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
01190     }
01191   return p;
01192 }
01193 
01194 /* Handle a single function call relocation.  */
01195 
01196 static unsigned char *
01197 som_reloc_call (bfd *abfd,
01198               unsigned char *p,
01199               unsigned int *subspace_reloc_sizep,
01200               arelent *bfd_reloc,
01201               int sym_num,
01202               struct reloc_queue *queue)
01203 {
01204   int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
01205   int rtn_bits = arg_bits & 0x3;
01206   int type, done = 0;
01207 
01208   /* You'll never believe all this is necessary to handle relocations
01209      for function calls.  Having to compute and pack the argument
01210      relocation bits is the real nightmare.
01211 
01212      If you're interested in how this works, just forget it.  You really
01213      do not want to know about this braindamage.  */
01214 
01215   /* First see if this can be done with a "simple" relocation.  Simple
01216      relocations have a symbol number < 0x100 and have simple encodings
01217      of argument relocations.  */
01218 
01219   if (sym_num < 0x100)
01220     {
01221       switch (arg_bits)
01222        {
01223        case 0:
01224        case 1:
01225          type = 0;
01226          break;
01227        case 1 << 8:
01228        case 1 << 8 | 1:
01229          type = 1;
01230          break;
01231        case 1 << 8 | 1 << 6:
01232        case 1 << 8 | 1 << 6 | 1:
01233          type = 2;
01234          break;
01235        case 1 << 8 | 1 << 6 | 1 << 4:
01236        case 1 << 8 | 1 << 6 | 1 << 4 | 1:
01237          type = 3;
01238          break;
01239        case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
01240        case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
01241          type = 4;
01242          break;
01243        default:
01244          /* Not one of the easy encodings.  This will have to be
01245             handled by the more complex code below.  */
01246          type = -1;
01247          break;
01248        }
01249       if (type != -1)
01250        {
01251          /* Account for the return value too.  */
01252          if (rtn_bits)
01253            type += 5;
01254 
01255          /* Emit a 2 byte relocation.  Then see if it can be handled
01256             with a relocation which is already in the relocation queue.  */
01257          bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
01258          bfd_put_8 (abfd, sym_num, p + 1);
01259          p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
01260          done = 1;
01261        }
01262     }
01263 
01264   /* If this could not be handled with a simple relocation, then do a hard
01265      one.  Hard relocations occur if the symbol number was too high or if
01266      the encoding of argument relocation bits is too complex.  */
01267   if (! done)
01268     {
01269       /* Don't ask about these magic sequences.  I took them straight
01270         from gas-1.36 which took them from the a.out man page.  */
01271       type = rtn_bits;
01272       if ((arg_bits >> 6 & 0xf) == 0xe)
01273        type += 9 * 40;
01274       else
01275        type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
01276       if ((arg_bits >> 2 & 0xf) == 0xe)
01277        type += 9 * 4;
01278       else
01279        type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
01280 
01281       /* Output the first two bytes of the relocation.  These describe
01282         the length of the relocation and encoding style.  */
01283       bfd_put_8 (abfd, bfd_reloc->howto->type + 10
01284                + 2 * (sym_num >= 0x100) + (type >= 0x100),
01285                p);
01286       bfd_put_8 (abfd, type, p + 1);
01287 
01288       /* Now output the symbol index and see if this bizarre relocation
01289         just happened to be in the relocation queue.  */
01290       if (sym_num < 0x100)
01291        {
01292          bfd_put_8 (abfd, sym_num, p + 2);
01293          p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
01294        }
01295       else
01296        {
01297          bfd_put_8 (abfd, sym_num >> 16, p + 2);
01298          bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
01299          p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
01300        }
01301     }
01302   return p;
01303 }
01304 
01305 /* Return the logarithm of X, base 2, considering X unsigned,
01306    if X is a power of 2.  Otherwise, returns -1.  */
01307 
01308 static int
01309 exact_log2 (unsigned int x)
01310 {
01311   int log = 0;
01312 
01313   /* Test for 0 or a power of 2.  */
01314   if (x == 0 || x != (x & -x))
01315     return -1;
01316 
01317   while ((x >>= 1) != 0)
01318     log++;
01319   return log;
01320 }
01321 
01322 static bfd_reloc_status_type
01323 hppa_som_reloc (bfd *abfd ATTRIBUTE_UNUSED,
01324               arelent *reloc_entry,
01325               asymbol *symbol_in ATTRIBUTE_UNUSED,
01326               void *data ATTRIBUTE_UNUSED,
01327               asection *input_section,
01328               bfd *output_bfd,
01329               char **error_message ATTRIBUTE_UNUSED)
01330 {
01331   if (output_bfd)
01332     reloc_entry->address += input_section->output_offset;
01333 
01334   return bfd_reloc_ok;
01335 }
01336 
01337 /* Given a generic HPPA relocation type, the instruction format,
01338    and a field selector, return one or more appropriate SOM relocations.  */
01339 
01340 int **
01341 hppa_som_gen_reloc_type (bfd *abfd,
01342                       int base_type,
01343                       int format,
01344                       enum hppa_reloc_field_selector_type_alt field,
01345                       int sym_diff,
01346                       asymbol *sym)
01347 {
01348   int *final_type, **final_types;
01349 
01350   final_types = bfd_alloc (abfd, (bfd_size_type) sizeof (int *) * 6);
01351   final_type = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01352   if (!final_types || !final_type)
01353     return NULL;
01354 
01355   /* The field selector may require additional relocations to be
01356      generated.  It's impossible to know at this moment if additional
01357      relocations will be needed, so we make them.  The code to actually
01358      write the relocation/fixup stream is responsible for removing
01359      any redundant relocations.  */
01360   switch (field)
01361     {
01362     case e_fsel:
01363     case e_psel:
01364     case e_lpsel:
01365     case e_rpsel:
01366       final_types[0] = final_type;
01367       final_types[1] = NULL;
01368       final_types[2] = NULL;
01369       *final_type = base_type;
01370       break;
01371 
01372     case e_tsel:
01373     case e_ltsel:
01374     case e_rtsel:
01375       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01376       if (!final_types[0])
01377        return NULL;
01378       if (field == e_tsel)
01379        *final_types[0] = R_FSEL;
01380       else if (field == e_ltsel)
01381        *final_types[0] = R_LSEL;
01382       else
01383        *final_types[0] = R_RSEL;
01384       final_types[1] = final_type;
01385       final_types[2] = NULL;
01386       *final_type = base_type;
01387       break;
01388 
01389     case e_lssel:
01390     case e_rssel:
01391       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01392       if (!final_types[0])
01393        return NULL;
01394       *final_types[0] = R_S_MODE;
01395       final_types[1] = final_type;
01396       final_types[2] = NULL;
01397       *final_type = base_type;
01398       break;
01399 
01400     case e_lsel:
01401     case e_rsel:
01402       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01403       if (!final_types[0])
01404        return NULL;
01405       *final_types[0] = R_N_MODE;
01406       final_types[1] = final_type;
01407       final_types[2] = NULL;
01408       *final_type = base_type;
01409       break;
01410 
01411     case e_ldsel:
01412     case e_rdsel:
01413       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01414       if (!final_types[0])
01415        return NULL;
01416       *final_types[0] = R_D_MODE;
01417       final_types[1] = final_type;
01418       final_types[2] = NULL;
01419       *final_type = base_type;
01420       break;
01421 
01422     case e_lrsel:
01423     case e_rrsel:
01424       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01425       if (!final_types[0])
01426        return NULL;
01427       *final_types[0] = R_R_MODE;
01428       final_types[1] = final_type;
01429       final_types[2] = NULL;
01430       *final_type = base_type;
01431       break;
01432 
01433     case e_nsel:
01434       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01435       if (!final_types[0])
01436        return NULL;
01437       *final_types[0] = R_N1SEL;
01438       final_types[1] = final_type;
01439       final_types[2] = NULL;
01440       *final_type = base_type;
01441       break;
01442 
01443     case e_nlsel:
01444     case e_nlrsel:
01445       final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01446       if (!final_types[0])
01447        return NULL;
01448       *final_types[0] = R_N0SEL;
01449       final_types[1] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
01450       if (!final_types[1])
01451        return NULL;
01452       if (field == e_nlsel)
01453        *final_types[1] = R_N_MODE;
01454       else
01455        *final_types[1] = R_R_MODE;
01456       final_types[2] = final_type;
01457       final_types[3] = NULL;
01458       *final_type = base_type;
01459       break;
01460 
01461     /* FIXME: These two field selectors are not currently supported.  */
01462     case e_ltpsel:
01463     case e_rtpsel:
01464       abort ();
01465     }
01466 
01467   switch (base_type)
01468     {
01469     case R_HPPA:
01470       /* The difference of two symbols needs *very* special handling.  */
01471       if (sym_diff)
01472        {
01473          bfd_size_type amt = sizeof (int);
01474 
01475          final_types[0] = bfd_alloc (abfd, amt);
01476          final_types[1] = bfd_alloc (abfd, amt);
01477          final_types[2] = bfd_alloc (abfd, amt);
01478          final_types[3] = bfd_alloc (abfd, amt);
01479          if (!final_types[0] || !final_types[1] || !final_types[2])
01480            return NULL;
01481          if (field == e_fsel)
01482            *final_types[0] = R_FSEL;
01483          else if (field == e_rsel)
01484            *final_types[0] = R_RSEL;
01485          else if (field == e_lsel)
01486            *final_types[0] = R_LSEL;
01487          *final_types[1] = R_COMP2;
01488          *final_types[2] = R_COMP2;
01489          *final_types[3] = R_COMP1;
01490          final_types[4] = final_type;
01491          if (format == 32)
01492            *final_types[4] = R_DATA_EXPR;
01493          else
01494            *final_types[4] = R_CODE_EXPR;
01495          final_types[5] = NULL;
01496          break;
01497        }
01498       /* PLABELs get their own relocation type.  */
01499       else if (field == e_psel
01500               || field == e_lpsel
01501               || field == e_rpsel)
01502        {
01503          /* A PLABEL relocation that has a size of 32 bits must
01504             be a R_DATA_PLABEL.  All others are R_CODE_PLABELs.  */
01505          if (format == 32)
01506            *final_type = R_DATA_PLABEL;
01507          else
01508            *final_type = R_CODE_PLABEL;
01509        }
01510       /* PIC stuff.  */
01511       else if (field == e_tsel
01512               || field == e_ltsel
01513               || field == e_rtsel)
01514        *final_type = R_DLT_REL;
01515       /* A relocation in the data space is always a full 32bits.  */
01516       else if (format == 32)
01517        {
01518          *final_type = R_DATA_ONE_SYMBOL;
01519 
01520          /* If there's no SOM symbol type associated with this BFD
01521             symbol, then set the symbol type to ST_DATA.
01522 
01523             Only do this if the type is going to default later when
01524             we write the object file.
01525 
01526             This is done so that the linker never encounters an
01527             R_DATA_ONE_SYMBOL reloc involving an ST_CODE symbol.
01528 
01529             This allows the compiler to generate exception handling
01530             tables.
01531 
01532             Note that one day we may need to also emit BEGIN_BRTAB and
01533             END_BRTAB to prevent the linker from optimizing away insns
01534             in exception handling regions.  */
01535          if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
01536              && (sym->flags & BSF_SECTION_SYM) == 0
01537              && (sym->flags & BSF_FUNCTION) == 0
01538              && ! bfd_is_com_section (sym->section))
01539            som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
01540        }
01541       break;
01542 
01543     case R_HPPA_GOTOFF:
01544       /* More PLABEL special cases.  */
01545       if (field == e_psel
01546          || field == e_lpsel
01547          || field == e_rpsel)
01548        *final_type = R_DATA_PLABEL;
01549       break;
01550 
01551     case R_HPPA_COMPLEX:
01552       /* The difference of two symbols needs *very* special handling.  */
01553       if (sym_diff)
01554        {
01555          bfd_size_type amt = sizeof (int);
01556 
01557          final_types[0] = bfd_alloc (abfd, amt);
01558          final_types[1] = bfd_alloc (abfd, amt);
01559          final_types[2] = bfd_alloc (abfd, amt);
01560          final_types[3] = bfd_alloc (abfd, amt);
01561          if (!final_types[0] || !final_types[1] || !final_types[2])
01562            return NULL;
01563          if (field == e_fsel)
01564            *final_types[0] = R_FSEL;
01565          else if (field == e_rsel)
01566            *final_types[0] = R_RSEL;
01567          else if (field == e_lsel)
01568            *final_types[0] = R_LSEL;
01569          *final_types[1] = R_COMP2;
01570          *final_types[2] = R_COMP2;
01571          *final_types[3] = R_COMP1;
01572          final_types[4] = final_type;
01573          if (format == 32)
01574            *final_types[4] = R_DATA_EXPR;
01575          else
01576            *final_types[4] = R_CODE_EXPR;
01577          final_types[5] = NULL;
01578          break;
01579        }
01580       else
01581        break;
01582 
01583     case R_HPPA_NONE:
01584     case R_HPPA_ABS_CALL:
01585       /* Right now we can default all these.  */
01586       break;
01587 
01588     case R_HPPA_PCREL_CALL:
01589       {
01590 #ifndef NO_PCREL_MODES
01591        /* If we have short and long pcrel modes, then generate the proper
01592           mode selector, then the pcrel relocation.  Redundant selectors
01593           will be eliminated as the relocs are sized and emitted.  */
01594        bfd_size_type amt = sizeof (int);
01595 
01596        final_types[0] = bfd_alloc (abfd, amt);
01597        if (!final_types[0])
01598          return NULL;
01599        if (format == 17)
01600          *final_types[0] = R_SHORT_PCREL_MODE;
01601        else
01602          *final_types[0] = R_LONG_PCREL_MODE;
01603        final_types[1] = final_type;
01604        final_types[2] = NULL;
01605        *final_type = base_type;
01606 #endif
01607        break;
01608       }
01609     }
01610   return final_types;
01611 }
01612 
01613 /* Return the address of the correct entry in the PA SOM relocation
01614    howto table.  */
01615 
01616 static reloc_howto_type *
01617 som_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
01618                         bfd_reloc_code_real_type code)
01619 {
01620   if ((int) code < (int) R_NO_RELOCATION + 255)
01621     {
01622       BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
01623       return &som_hppa_howto_table[(int) code];
01624     }
01625 
01626   return NULL;
01627 }
01628 
01629 static reloc_howto_type *
01630 som_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
01631                         const char *r_name)
01632 {
01633   unsigned int i;
01634 
01635   for (i = 0;
01636        i < sizeof (som_hppa_howto_table) / sizeof (som_hppa_howto_table[0]);
01637        i++)
01638     if (som_hppa_howto_table[i].name != NULL
01639        && strcasecmp (som_hppa_howto_table[i].name, r_name) == 0)
01640       return &som_hppa_howto_table[i];
01641 
01642   return NULL;
01643 }
01644 
01645 /* Perform some initialization for an object.  Save results of this
01646    initialization in the BFD.  */
01647 
01648 static const bfd_target *
01649 som_object_setup (bfd *abfd,
01650                 struct header *file_hdrp,
01651                 struct som_exec_auxhdr *aux_hdrp,
01652                 unsigned long current_offset)
01653 {
01654   asection *section;
01655 
01656   /* som_mkobject will set bfd_error if som_mkobject fails.  */
01657   if (! som_mkobject (abfd))
01658     return NULL;
01659 
01660   /* Set BFD flags based on what information is available in the SOM.  */
01661   abfd->flags = BFD_NO_FLAGS;
01662   if (file_hdrp->symbol_total)
01663     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
01664 
01665   switch (file_hdrp->a_magic)
01666     {
01667     case DEMAND_MAGIC:
01668       abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P);
01669       break;
01670     case SHARE_MAGIC:
01671       abfd->flags |= (WP_TEXT | EXEC_P);
01672       break;
01673     case EXEC_MAGIC:
01674       abfd->flags |= (EXEC_P);
01675       break;
01676     case RELOC_MAGIC:
01677       abfd->flags |= HAS_RELOC;
01678       break;
01679 #ifdef SHL_MAGIC
01680     case SHL_MAGIC:
01681 #endif
01682 #ifdef DL_MAGIC
01683     case DL_MAGIC:
01684 #endif
01685       abfd->flags |= DYNAMIC;
01686       break;
01687 
01688     default:
01689       break;
01690     }
01691 
01692   /* Save the auxiliary header.  */
01693   obj_som_exec_hdr (abfd) = aux_hdrp;
01694 
01695   /* Allocate space to hold the saved exec header information.  */
01696   obj_som_exec_data (abfd) = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_exec_data));
01697   if (obj_som_exec_data (abfd) == NULL)
01698     return NULL;
01699 
01700   /* The braindamaged OSF1 linker switched exec_flags and exec_entry!
01701 
01702      We used to identify OSF1 binaries based on NEW_VERSION_ID, but
01703      apparently the latest HPUX linker is using NEW_VERSION_ID now.
01704 
01705      It's about time, OSF has used the new id since at least 1992;
01706      HPUX didn't start till nearly 1995!.
01707 
01708      The new approach examines the entry field for an executable.  If
01709      it is not 4-byte aligned then it's not a proper code address and
01710      we guess it's really the executable flags.  For a main program,
01711      we also consider zero to be indicative of a buggy linker, since
01712      that is not a valid entry point.  The entry point for a shared
01713      library, however, can be zero so we do not consider that to be
01714      indicative of a buggy linker.  */
01715   if (aux_hdrp)
01716     {
01717       int found = 0;
01718 
01719       for (section = abfd->sections; section; section = section->next)
01720        {
01721          bfd_vma entry;
01722 
01723          if ((section->flags & SEC_CODE) == 0)
01724            continue;
01725          entry = aux_hdrp->exec_entry + aux_hdrp->exec_tmem;
01726          if (entry >= section->vma
01727              && entry < section->vma + section->size)
01728            found = 1;
01729        }
01730       if ((aux_hdrp->exec_entry == 0 && !(abfd->flags & DYNAMIC))
01731          || (aux_hdrp->exec_entry & 0x3) != 0
01732          || ! found)
01733        {
01734          bfd_get_start_address (abfd) = aux_hdrp->exec_flags;
01735          obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
01736        }
01737       else
01738        {
01739          bfd_get_start_address (abfd) = aux_hdrp->exec_entry + current_offset;
01740          obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
01741        }
01742     }
01743 
01744   obj_som_exec_data (abfd)->version_id = file_hdrp->version_id;
01745 
01746   bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
01747   bfd_get_symcount (abfd) = file_hdrp->symbol_total;
01748 
01749   /* Initialize the saved symbol table and string table to NULL.
01750      Save important offsets and sizes from the SOM header into
01751      the BFD.  */
01752   obj_som_stringtab (abfd) = NULL;
01753   obj_som_symtab (abfd) = NULL;
01754   obj_som_sorted_syms (abfd) = NULL;
01755   obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
01756   obj_som_sym_filepos (abfd) = file_hdrp->symbol_location + current_offset;
01757   obj_som_str_filepos (abfd) = (file_hdrp->symbol_strings_location
01758                             + current_offset);
01759   obj_som_reloc_filepos (abfd) = (file_hdrp->fixup_request_location
01760                               + current_offset);
01761   obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
01762 
01763   return abfd->xvec;
01764 }
01765 
01766 /* Convert all of the space and subspace info into BFD sections.  Each space
01767    contains a number of subspaces, which in turn describe the mapping between
01768    regions of the exec file, and the address space that the program runs in.
01769    BFD sections which correspond to spaces will overlap the sections for the
01770    associated subspaces.  */
01771 
01772 static bfd_boolean
01773 setup_sections (bfd *abfd,
01774               struct header *file_hdr,
01775               unsigned long current_offset)
01776 {
01777   char *space_strings;
01778   unsigned int space_index, i;
01779   unsigned int total_subspaces = 0;
01780   asection **subspace_sections = NULL;
01781   asection *section;
01782   bfd_size_type amt;
01783 
01784   /* First, read in space names.  */
01785   amt = file_hdr->space_strings_size;
01786   space_strings = bfd_malloc (amt);
01787   if (!space_strings && amt != 0)
01788     goto error_return;
01789 
01790   if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
01791               SEEK_SET) != 0)
01792     goto error_return;
01793   if (bfd_bread (space_strings, amt, abfd) != amt)
01794     goto error_return;
01795 
01796   /* Loop over all of the space dictionaries, building up sections.  */
01797   for (space_index = 0; space_index < file_hdr->space_total; space_index++)
01798     {
01799       struct space_dictionary_record space;
01800       struct som_subspace_dictionary_record subspace, save_subspace;
01801       unsigned int subspace_index;
01802       asection *space_asect;
01803       bfd_size_type space_size = 0;
01804       char *newname;
01805 
01806       /* Read the space dictionary element.  */
01807       if (bfd_seek (abfd,
01808                   (current_offset + file_hdr->space_location
01809                    + space_index * sizeof space),
01810                   SEEK_SET) != 0)
01811        goto error_return;
01812       amt = sizeof space;
01813       if (bfd_bread (&space, amt, abfd) != amt)
01814        goto error_return;
01815 
01816       /* Setup the space name string.  */
01817       space.name.n_name = space.name.n_strx + space_strings;
01818 
01819       /* Make a section out of it.  */
01820       amt = strlen (space.name.n_name) + 1;
01821       newname = bfd_alloc (abfd, amt);
01822       if (!newname)
01823        goto error_return;
01824       strcpy (newname, space.name.n_name);
01825 
01826       space_asect = bfd_make_section_anyway (abfd, newname);
01827       if (!space_asect)
01828        goto error_return;
01829 
01830       if (space.is_loadable == 0)
01831        space_asect->flags |= SEC_DEBUGGING;
01832 
01833       /* Set up all the attributes for the space.  */
01834       if (! bfd_som_set_section_attributes (space_asect, space.is_defined,
01835                                        space.is_private, space.sort_key,
01836                                        space.space_number))
01837        goto error_return;
01838 
01839       /* If the space has no subspaces, then we're done.  */
01840       if (space.subspace_quantity == 0)
01841        continue;
01842 
01843       /* Now, read in the first subspace for this space.  */
01844       if (bfd_seek (abfd,
01845                   (current_offset + file_hdr->subspace_location
01846                    + space.subspace_index * sizeof subspace),
01847                   SEEK_SET) != 0)
01848        goto error_return;
01849       amt = sizeof subspace;
01850       if (bfd_bread (&subspace, amt, abfd) != amt)
01851        goto error_return;
01852       /* Seek back to the start of the subspaces for loop below.  */
01853       if (bfd_seek (abfd,
01854                   (current_offset + file_hdr->subspace_location
01855                    + space.subspace_index * sizeof subspace),
01856                   SEEK_SET) != 0)
01857        goto error_return;
01858 
01859       /* Setup the start address and file loc from the first subspace
01860         record.  */
01861       space_asect->vma = subspace.subspace_start;
01862       space_asect->filepos = subspace.file_loc_init_value + current_offset;
01863       space_asect->alignment_power = exact_log2 (subspace.alignment);
01864       if (space_asect->alignment_power == (unsigned) -1)
01865        goto error_return;
01866 
01867       /* Initialize save_subspace so we can reliably determine if this
01868         loop placed any useful values into it.  */
01869       memset (&save_subspace, 0, sizeof (save_subspace));
01870 
01871       /* Loop over the rest of the subspaces, building up more sections.  */
01872       for (subspace_index = 0; subspace_index < space.subspace_quantity;
01873           subspace_index++)
01874        {
01875          asection *subspace_asect;
01876 
01877          /* Read in the next subspace.  */
01878          amt = sizeof subspace;
01879          if (bfd_bread (&subspace, amt, abfd) != amt)
01880            goto error_return;
01881 
01882          /* Setup the subspace name string.  */
01883          subspace.name.n_name = subspace.name.n_strx + space_strings;
01884 
01885          amt = strlen (subspace.name.n_name) + 1;
01886          newname = bfd_alloc (abfd, amt);
01887          if (!newname)
01888            goto error_return;
01889          strcpy (newname, subspace.name.n_name);
01890 
01891          /* Make a section out of this subspace.  */
01892          subspace_asect = bfd_make_section_anyway (abfd, newname);
01893          if (!subspace_asect)
01894            goto error_return;
01895 
01896          /* Store private information about the section.  */
01897          if (! bfd_som_set_subsection_attributes (subspace_asect, space_asect,
01898                                              subspace.access_control_bits,
01899                                              subspace.sort_key,
01900                                              subspace.quadrant,
01901                                              subspace.is_comdat,
01902                                              subspace.is_common,
01903                                              subspace.dup_common))
01904            goto error_return;
01905 
01906          /* Keep an easy mapping between subspaces and sections.
01907             Note we do not necessarily read the subspaces in the
01908             same order in which they appear in the object file.
01909 
01910             So to make the target index come out correctly, we
01911             store the location of the subspace header in target
01912             index, then sort using the location of the subspace
01913             header as the key.  Then we can assign correct
01914             subspace indices.  */
01915          total_subspaces++;
01916          subspace_asect->target_index = bfd_tell (abfd) - sizeof (subspace);
01917 
01918          /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
01919             by the access_control_bits in the subspace header.  */
01920          switch (subspace.access_control_bits >> 4)
01921            {
01922            /* Readonly data.  */
01923            case 0x0:
01924              subspace_asect->flags |= SEC_DATA | SEC_READONLY;
01925              break;
01926 
01927            /* Normal data.  */
01928            case 0x1:
01929              subspace_asect->flags |= SEC_DATA;
01930              break;
01931 
01932            /* Readonly code and the gateways.
01933               Gateways have other attributes which do not map
01934               into anything BFD knows about.  */
01935            case 0x2:
01936            case 0x4:
01937            case 0x5:
01938            case 0x6:
01939            case 0x7:
01940              subspace_asect->flags |= SEC_CODE | SEC_READONLY;
01941              break;
01942 
01943            /* dynamic (writable) code.  */
01944            case 0x3:
01945              subspace_asect->flags |= SEC_CODE;
01946              break;
01947            }
01948 
01949          if (subspace.is_comdat || subspace.is_common || subspace.dup_common)
01950            subspace_asect->flags |= SEC_LINK_ONCE;
01951 
01952          if (subspace.subspace_length > 0)
01953            subspace_asect->flags |= SEC_HAS_CONTENTS;
01954 
01955          if (subspace.is_loadable)
01956            subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
01957          else
01958            subspace_asect->flags |= SEC_DEBUGGING;
01959 
01960          if (subspace.code_only)
01961            subspace_asect->flags |= SEC_CODE;
01962 
01963          /* Both file_loc_init_value and initialization_length will
01964             be zero for a BSS like subspace.  */
01965          if (subspace.file_loc_init_value == 0
01966              && subspace.initialization_length == 0)
01967            subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD | SEC_HAS_CONTENTS);
01968 
01969          /* This subspace has relocations.
01970             The fixup_request_quantity is a byte count for the number of
01971             entries in the relocation stream; it is not the actual number
01972             of relocations in the subspace.  */
01973          if (subspace.fixup_request_quantity != 0)
01974            {
01975              subspace_asect->flags |= SEC_RELOC;
01976              subspace_asect->rel_filepos = subspace.fixup_request_index;
01977              som_section_data (subspace_asect)->reloc_size
01978               = subspace.fixup_request_quantity;
01979              /* We can not determine this yet.  When we read in the
01980                relocation table the correct value will be filled in.  */
01981              subspace_asect->reloc_count = (unsigned) -1;
01982            }
01983 
01984          /* Update save_subspace if appropriate.  */
01985          if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
01986            save_subspace = subspace;
01987 
01988          subspace_asect->vma = subspace.subspace_start;
01989          subspace_asect->size = subspace.subspace_length;
01990          subspace_asect->filepos = (subspace.file_loc_init_value
01991                                  + current_offset);
01992          subspace_asect->alignment_power = exact_log2 (subspace.alignment);
01993          if (subspace_asect->alignment_power == (unsigned) -1)
01994            goto error_return;
01995 
01996          /* Keep track of the accumulated sizes of the sections.  */
01997          space_size += subspace.subspace_length;
01998        }
01999 
02000       /* This can happen for a .o which defines symbols in otherwise
02001         empty subspaces.  */
02002       if (!save_subspace.file_loc_init_value)
02003        space_asect->size = 0;
02004       else
02005        {
02006          if (file_hdr->a_magic != RELOC_MAGIC)
02007            {
02008              /* Setup the size for the space section based upon the info
02009                in the last subspace of the space.  */
02010              space_asect->size = (save_subspace.subspace_start
02011                                - space_asect->vma
02012                                + save_subspace.subspace_length);
02013            }
02014          else
02015            {
02016              /* The subspace_start field is not initialised in relocatable
02017                 only objects, so it cannot be used for length calculations.
02018                Instead we use the space_size value which we have been
02019                accumulating.  This isn't an accurate estimate since it
02020                ignores alignment and ordering issues.  */
02021              space_asect->size = space_size;
02022            }
02023        }
02024     }
02025   /* Now that we've read in all the subspace records, we need to assign
02026      a target index to each subspace.  */
02027   amt = total_subspaces;
02028   amt *= sizeof (asection *);
02029   subspace_sections = bfd_malloc (amt);
02030   if (subspace_sections == NULL)
02031     goto error_return;
02032 
02033   for (i = 0, section = abfd->sections; section; section = section->next)
02034     {
02035       if (!som_is_subspace (section))
02036        continue;
02037 
02038       subspace_sections[i] = section;
02039       i++;
02040     }
02041   qsort (subspace_sections, total_subspaces,
02042         sizeof (asection *), compare_subspaces);
02043 
02044   /* subspace_sections is now sorted in the order in which the subspaces
02045      appear in the object file.  Assign an index to each one now.  */
02046   for (i = 0; i < total_subspaces; i++)
02047     subspace_sections[i]->target_index = i;
02048 
02049   if (space_strings != NULL)
02050     free (space_strings);
02051 
02052   if (subspace_sections != NULL)
02053     free (subspace_sections);
02054 
02055   return TRUE;
02056 
02057  error_return:
02058   if (space_strings != NULL)
02059     free (space_strings);
02060 
02061   if (subspace_sections != NULL)
02062     free (subspace_sections);
02063   return FALSE;
02064 }
02065 
02066 /* Read in a SOM object and make it into a BFD.  */
02067 
02068 static const bfd_target *
02069 som_object_p (bfd *abfd)
02070 {
02071   struct header file_hdr;
02072   struct som_exec_auxhdr *aux_hdr_ptr = NULL;
02073   unsigned long current_offset = 0;
02074   struct lst_header lst_header;
02075   struct som_entry som_entry;
02076   bfd_size_type amt;
02077 #define ENTRY_SIZE sizeof (struct som_entry)
02078 
02079   amt = FILE_HDR_SIZE;
02080   if (bfd_bread ((void *) &file_hdr, amt, abfd) != amt)
02081     {
02082       if (bfd_get_error () != bfd_error_system_call)
02083        bfd_set_error (bfd_error_wrong_format);
02084       return NULL;
02085     }
02086 
02087   if (!_PA_RISC_ID (file_hdr.system_id))
02088     {
02089       bfd_set_error (bfd_error_wrong_format);
02090       return NULL;
02091     }
02092 
02093   switch (file_hdr.a_magic)
02094     {
02095     case RELOC_MAGIC:
02096     case EXEC_MAGIC:
02097     case SHARE_MAGIC:
02098     case DEMAND_MAGIC:
02099 #ifdef DL_MAGIC
02100     case DL_MAGIC:
02101 #endif
02102 #ifdef SHL_MAGIC
02103     case SHL_MAGIC:
02104 #endif
02105 #ifdef SHARED_MAGIC_CNX
02106     case SHARED_MAGIC_CNX:
02107 #endif
02108       break;
02109 
02110 #ifdef EXECLIBMAGIC
02111     case EXECLIBMAGIC:
02112       /* Read the lst header and determine where the SOM directory begins.  */
02113 
02114       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
02115        {
02116          if (bfd_get_error () != bfd_error_system_call)
02117            bfd_set_error (bfd_error_wrong_format);
02118          return NULL;
02119        }
02120 
02121       amt = SLSTHDR;
02122       if (bfd_bread ((void *) &lst_header, amt, abfd) != amt)
02123        {
02124          if (bfd_get_error () != bfd_error_system_call)
02125            bfd_set_error (bfd_error_wrong_format);
02126          return NULL;
02127        }
02128 
02129       /* Position to and read the first directory entry.  */
02130 
02131       if (bfd_seek (abfd, lst_header.dir_loc, SEEK_SET) != 0)
02132        {
02133          if (bfd_get_error () != bfd_error_system_call)
02134            bfd_set_error (bfd_error_wrong_format);
02135          return NULL;
02136        }
02137 
02138       amt = ENTRY_SIZE;
02139       if (bfd_bread ((void *) &som_entry, amt, abfd) != amt)
02140        {
02141          if (bfd_get_error () != bfd_error_system_call)
02142            bfd_set_error (bfd_error_wrong_format);
02143          return NULL;
02144        }
02145 
02146       /* Now position to the first SOM.  */
02147 
02148       if (bfd_seek (abfd, som_entry.location, SEEK_SET) != 0)
02149        {
02150          if (bfd_get_error () != bfd_error_system_call)
02151            bfd_set_error (bfd_error_wrong_format);
02152          return NULL;
02153        }
02154 
02155       current_offset = som_entry.location;
02156 
02157       /* And finally, re-read the som header.  */
02158       amt = FILE_HDR_SIZE;
02159       if (bfd_bread ((void *) &file_hdr, amt, abfd) != amt)
02160        {
02161          if (bfd_get_error () != bfd_error_system_call)
02162            bfd_set_error (bfd_error_wrong_format);
02163          return NULL;
02164        }
02165 
02166       break;
02167 #endif
02168 
02169     default:
02170       bfd_set_error (bfd_error_wrong_format);
02171       return NULL;
02172     }
02173 
02174   if (file_hdr.version_id != VERSION_ID
02175       && file_hdr.version_id != NEW_VERSION_ID)
02176     {
02177       bfd_set_error (bfd_error_wrong_format);
02178       return NULL;
02179     }
02180 
02181   /* If the aux_header_size field in the file header is zero, then this
02182      object is an incomplete executable (a .o file).  Do not try to read
02183      a non-existant auxiliary header.  */
02184   if (file_hdr.aux_header_size != 0)
02185     {
02186       aux_hdr_ptr = bfd_zalloc (abfd, 
02187                             (bfd_size_type) sizeof (*aux_hdr_ptr));
02188       if (aux_hdr_ptr == NULL)
02189        return NULL;
02190       amt = AUX_HDR_SIZE;
02191       if (bfd_bread ((void *) aux_hdr_ptr, amt, abfd) != amt)
02192        {
02193          if (bfd_get_error () != bfd_error_system_call)
02194            bfd_set_error (bfd_error_wrong_format);
02195          return NULL;
02196        }
02197     }
02198 
02199   if (!setup_sections (abfd, &file_hdr, current_offset))
02200     {
02201       /* setup_sections does not bubble up a bfd error code.  */
02202       bfd_set_error (bfd_error_bad_value);
02203       return NULL;
02204     }
02205 
02206   /* This appears to be a valid SOM object.  Do some initialization.  */
02207   return som_object_setup (abfd, &file_hdr, aux_hdr_ptr, current_offset);
02208 }
02209 
02210 /* Create a SOM object.  */
02211 
02212 static bfd_boolean
02213 som_mkobject (bfd *abfd)
02214 {
02215   /* Allocate memory to hold backend information.  */
02216   abfd->tdata.som_data = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_data_struct));
02217   if (abfd->tdata.som_data == NULL)
02218     return FALSE;
02219   return TRUE;
02220 }
02221 
02222 /* Initialize some information in the file header.  This routine makes
02223    not attempt at doing the right thing for a full executable; it
02224    is only meant to handle relocatable objects.  */
02225 
02226 static bfd_boolean
02227 som_prep_headers (bfd *abfd)
02228 {
02229   struct header *file_hdr;
02230   asection *section;
02231   bfd_size_type amt = sizeof (struct header);
02232 
02233   /* Make and attach a file header to the BFD.  */
02234   file_hdr = bfd_zalloc (abfd, amt);
02235   if (file_hdr == NULL)
02236     return FALSE;
02237   obj_som_file_hdr (abfd) = file_hdr;
02238 
02239   if (abfd->flags & (EXEC_P | DYNAMIC))
02240     {
02241       /* Make and attach an exec header to the BFD.  */
02242       amt = sizeof (struct som_exec_auxhdr);
02243       obj_som_exec_hdr (abfd) = bfd_zalloc (abfd, amt);
02244       if (obj_som_exec_hdr (abfd) == NULL)
02245        return FALSE;
02246 
02247       if (abfd->flags & D_PAGED)
02248        file_hdr->a_magic = DEMAND_MAGIC;
02249       else if (abfd->flags & WP_TEXT)
02250        file_hdr->a_magic = SHARE_MAGIC;
02251 #ifdef SHL_MAGIC
02252       else if (abfd->flags & DYNAMIC)
02253        file_hdr->a_magic = SHL_MAGIC;
02254 #endif
02255       else
02256        file_hdr->a_magic = EXEC_MAGIC;
02257     }
02258   else
02259     file_hdr->a_magic = RELOC_MAGIC;
02260 
02261   /* These fields are optional, and embedding timestamps is not always
02262      a wise thing to do, it makes comparing objects during a multi-stage
02263      bootstrap difficult.  */
02264   file_hdr->file_time.secs = 0;
02265   file_hdr->file_time.nanosecs = 0;
02266 
02267   file_hdr->entry_space = 0;
02268   file_hdr->entry_subspace = 0;
02269   file_hdr->entry_offset = 0;
02270   file_hdr->presumed_dp = 0;
02271 
02272   /* Now iterate over the sections translating information from
02273      BFD sections to SOM spaces/subspaces.  */
02274   for (section = abfd->sections; section != NULL; section = section->next)
02275     {
02276       /* Ignore anything which has not been marked as a space or
02277         subspace.  */
02278       if (!som_is_space (section) && !som_is_subspace (section))
02279        continue;
02280 
02281       if (som_is_space (section))
02282        {
02283          /* Allocate space for the space dictionary.  */
02284          amt = sizeof (struct space_dictionary_record);
02285          som_section_data (section)->space_dict = bfd_zalloc (abfd, amt);
02286          if (som_section_data (section)->space_dict == NULL)
02287            return FALSE;
02288          /* Set space attributes.  Note most attributes of SOM spaces
02289             are set based on the subspaces it contains.  */
02290          som_section_data (section)->space_dict->loader_fix_index = -1;
02291          som_section_data (section)->space_dict->init_pointer_index = -1;
02292 
02293          /* Set more attributes that were stuffed away in private data.  */
02294          som_section_data (section)->space_dict->sort_key =
02295            som_section_data (section)->copy_data->sort_key;
02296          som_section_data (section)->space_dict->is_defined =
02297            som_section_data (section)->copy_data->is_defined;
02298          som_section_data (section)->space_dict->is_private =
02299            som_section_data (section)->copy_data->is_private;
02300          som_section_data (section)->space_dict->space_number =
02301            som_section_data (section)->copy_data->space_number;
02302        }
02303       else
02304        {
02305          /* Allocate space for the subspace dictionary.  */
02306          amt = sizeof (struct som_subspace_dictionary_record);
02307          som_section_data (section)->subspace_dict = bfd_zalloc (abfd, amt);
02308          if (som_section_data (section)->subspace_dict == NULL)
02309            return FALSE;
02310 
02311          /* Set subspace attributes.  Basic stuff is done here, additional
02312             attributes are filled in later as more information becomes
02313             available.  */
02314          if (section->flags & SEC_ALLOC)
02315            som_section_data (section)->subspace_dict->is_loadable = 1;
02316 
02317          if (section->flags & SEC_CODE)
02318            som_section_data (section)->subspace_dict->code_only = 1;
02319 
02320          som_section_data (section)->subspace_dict->subspace_start =
02321            section->vma;
02322          som_section_data (section)->subspace_dict->subspace_length =
02323            section->size;
02324          som_section_data (section)->subspace_dict->initialization_length =
02325            section->size;
02326          som_section_data (section)->subspace_dict->alignment =
02327            1 << section->alignment_power;
02328 
02329          /* Set more attributes that were stuffed away in private data.  */
02330          som_section_data (section)->subspace_dict->sort_key =
02331            som_section_data (section)->copy_data->sort_key;
02332          som_section_data (section)->subspace_dict->access_control_bits =
02333            som_section_data (section)->copy_data->access_control_bits;
02334          som_section_data (section)->subspace_dict->quadrant =
02335            som_section_data (section)->copy_data->quadrant;
02336          som_section_data (section)->subspace_dict->is_comdat =
02337            som_section_data (section)->copy_data->is_comdat;
02338          som_section_data (section)->subspace_dict->is_common =
02339            som_section_data (section)->copy_data->is_common;
02340          som_section_data (section)->subspace_dict->dup_common =
02341            som_section_data (section)->copy_data->dup_common;
02342        }
02343     }
02344   return TRUE;
02345 }
02346 
02347 /* Return TRUE if the given section is a SOM space, FALSE otherwise.  */
02348 
02349 static bfd_boolean
02350 som_is_space (asection *section)
02351 {
02352   /* If no copy data is available, then it's neither a space nor a
02353      subspace.  */
02354   if (som_section_data (section)->copy_data == NULL)
02355     return FALSE;
02356 
02357   /* If the containing space isn't the same as the given section,
02358      then this isn't a space.  */
02359   if (som_section_data (section)->copy_data->container != section
02360       && (som_section_data (section)->copy_data->container->output_section
02361          != section))
02362     return FALSE;
02363 
02364   /* OK.  Must be a space.  */
02365   return TRUE;
02366 }
02367 
02368 /* Return TRUE if the given section is a SOM subspace, FALSE otherwise.  */
02369 
02370 static bfd_boolean
02371 som_is_subspace (asection *section)
02372 {
02373   /* If no copy data is available, then it's neither a space nor a
02374      subspace.  */
02375   if (som_section_data (section)->copy_data == NULL)
02376     return FALSE;
02377 
02378   /* If the containing space is the same as the given section,
02379      then this isn't a subspace.  */
02380   if (som_section_data (section)->copy_data->container == section
02381       || (som_section_data (section)->copy_data->container->output_section
02382          == section))
02383     return FALSE;
02384 
02385   /* OK.  Must be a subspace.  */
02386   return TRUE;
02387 }
02388 
02389 /* Return TRUE if the given space contains the given subspace.  It
02390    is safe to assume space really is a space, and subspace really
02391    is a subspace.  */
02392 
02393 static bfd_boolean
02394 som_is_container (asection *space, asection *subspace)
02395 {
02396   return (som_section_data (subspace)->copy_data->container == space)
02397     || (som_section_data (subspace)->copy_data->container->output_section
02398        == space);
02399 }
02400 
02401 /* Count and return the number of spaces attached to the given BFD.  */
02402 
02403 static unsigned long
02404 som_count_spaces (bfd *abfd)
02405 {
02406   int count = 0;
02407   asection *section;
02408 
02409   for (section = abfd->sections; section != NULL; section = section->next)
02410     count += som_is_space (section);
02411 
02412   return count;
02413 }
02414 
02415 /* Count the number of subspaces attached to the given BFD.  */
02416 
02417 static unsigned long
02418 som_count_subspaces (bfd *abfd)
02419 {
02420   int count = 0;
02421   asection *section;
02422 
02423   for (section = abfd->sections; section != NULL; section = section->next)
02424     count += som_is_subspace (section);
02425 
02426   return count;
02427 }
02428 
02429 /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
02430 
02431    We desire symbols to be ordered starting with the symbol with the
02432    highest relocation count down to the symbol with the lowest relocation
02433    count.  Doing so compacts the relocation stream.  */
02434 
02435 static int
02436 compare_syms (const void *arg1, const void *arg2)
02437 {
02438   asymbol **sym1 = (asymbol **) arg1;
02439   asymbol **sym2 = (asymbol **) arg2;
02440   unsigned int count1, count2;
02441 
02442   /* Get relocation count for each symbol.  Note that the count
02443      is stored in the udata pointer for section symbols!  */
02444   if ((*sym1)->flags & BSF_SECTION_SYM)
02445     count1 = (*sym1)->udata.i;
02446   else
02447     count1 = som_symbol_data (*sym1)->reloc_count;
02448 
02449   if ((*sym2)->flags & BSF_SECTION_SYM)
02450     count2 = (*sym2)->udata.i;
02451   else
02452     count2 = som_symbol_data (*sym2)->reloc_count;
02453 
02454   /* Return the appropriate value.  */
02455   if (count1 < count2)
02456     return 1;
02457   else if (count1 > count2)
02458     return -1;
02459   return 0;
02460 }
02461 
02462 /* Return -1, 0, 1 indicating the relative ordering of subspace1
02463    and subspace.  */
02464 
02465 static int
02466 compare_subspaces (const void *arg1, const void *arg2)
02467 {
02468   asection **subspace1 = (asection **) arg1;
02469   asection **subspace2 = (asection **) arg2;
02470 
02471   if ((*subspace1)->target_index < (*subspace2)->target_index)
02472     return -1;
02473   else if ((*subspace2)->target_index < (*subspace1)->target_index)
02474     return 1;
02475   else
02476     return 0;
02477 }
02478 
02479 /* Perform various work in preparation for emitting the fixup stream.  */
02480 
02481 static void
02482 som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
02483 {
02484   unsigned long i;
02485   asection *section;
02486   asymbol **sorted_syms;
02487   bfd_size_type amt;
02488 
02489   /* Most SOM relocations involving a symbol have a length which is
02490      dependent on the index of the symbol.  So symbols which are
02491      used often in relocations should have a small index.  */
02492 
02493   /* First initialize the counters for each symbol.  */
02494   for (i = 0; i < num_syms; i++)
02495     {
02496       /* Handle a section symbol; these have no pointers back to the
02497         SOM symbol info.  So we just use the udata field to hold the
02498         relocation count.  */
02499       if (som_symbol_data (syms[i]) == NULL
02500          || syms[i]->flags & BSF_SECTION_SYM)
02501        {
02502          syms[i]->flags |= BSF_SECTION_SYM;
02503          syms[i]->udata.i = 0;
02504        }
02505       else
02506        som_symbol_data (syms[i])->reloc_count = 0;
02507     }
02508 
02509   /* Now that the counters are initialized, make a weighted count
02510      of how often a given symbol is used in a relocation.  */
02511   for (section = abfd->sections; section != NULL; section = section->next)
02512     {
02513       int j;
02514 
02515       /* Does this section have any relocations?  */
02516       if ((int) section->reloc_count <= 0)
02517        continue;
02518 
02519       /* Walk through each relocation for this section.  */
02520       for (j = 1; j < (int) section->reloc_count; j++)
02521        {
02522          arelent *reloc = section->orelocation[j];
02523          int scale;
02524 
02525          /* A relocation against a symbol in the *ABS* section really
02526             does not have a symbol.  Likewise if the symbol isn't associated
02527             with any section.  */
02528          if (reloc->sym_ptr_ptr == NULL
02529              || bfd_is_abs_section ((*reloc->sym_ptr_ptr)->section))
02530            continue;
02531 
02532          /* Scaling to encourage symbols involved in R_DP_RELATIVE
02533             and R_CODE_ONE_SYMBOL relocations to come first.  These
02534             two relocations have single byte versions if the symbol
02535             index is very small.  */
02536          if (reloc->howto->type == R_DP_RELATIVE
02537              || reloc->howto->type == R_CODE_ONE_SYMBOL)
02538            scale = 2;
02539          else
02540            scale = 1;
02541 
02542          /* Handle section symbols by storing the count in the udata
02543             field.  It will not be used and the count is very important
02544             for these symbols.  */
02545          if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
02546            {
02547              (*reloc->sym_ptr_ptr)->udata.i =
02548               (*reloc->sym_ptr_ptr)->udata.i + scale;
02549              continue;
02550            }
02551 
02552          /* A normal symbol.  Increment the count.  */
02553          som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
02554        }
02555     }
02556 
02557   /* Sort a copy of the symbol table, rather than the canonical
02558      output symbol table.  */
02559   amt = num_syms;
02560   amt *= sizeof (asymbol *);
02561   sorted_syms = bfd_zalloc (abfd, amt);
02562   memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
02563   qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms);
02564   obj_som_sorted_syms (abfd) = sorted_syms;
02565 
02566   /* Compute the symbol indexes, they will be needed by the relocation
02567      code.  */
02568   for (i = 0; i < num_syms; i++)
02569     {
02570       /* A section symbol.  Again, there is no pointer to backend symbol
02571         information, so we reuse the udata field again.  */
02572       if (sorted_syms[i]->flags & BSF_SECTION_SYM)
02573        sorted_syms[i]->udata.i = i;
02574       else
02575        som_symbol_data (sorted_syms[i])->index = i;
02576     }
02577 }
02578 
02579 static bfd_boolean
02580 som_write_fixups (bfd *abfd,
02581                 unsigned long current_offset,
02582                 unsigned int *total_reloc_sizep)
02583 {
02584   unsigned int i, j;
02585   /* Chunk of memory that we can use as buffer space, then throw
02586      away.  */
02587   unsigned char tmp_space[SOM_TMP_BUFSIZE];
02588   unsigned char *p;
02589   unsigned int total_reloc_size = 0;
02590   unsigned int subspace_reloc_size = 0;
02591   unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
02592   asection *section = abfd->sections;
02593   bfd_size_type amt;
02594 
02595   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
02596   p = tmp_space;
02597 
02598   /* All the fixups for a particular subspace are emitted in a single
02599      stream.  All the subspaces for a particular space are emitted
02600      as a single stream.
02601 
02602      So, to get all the locations correct one must iterate through all the
02603      spaces, for each space iterate through its subspaces and output a
02604      fixups stream.  */
02605   for (i = 0; i < num_spaces; i++)
02606     {
02607       asection *subsection;
02608 
02609       /* Find a space.  */
02610       while (!som_is_space (section))
02611        section = section->next;
02612 
02613       /* Now iterate through each of its subspaces.  */
02614       for (subsection = abfd->sections;
02615           subsection != NULL;
02616           subsection = subsection->next)
02617        {
02618          int reloc_offset;
02619          unsigned int current_rounding_mode;
02620 #ifndef NO_PCREL_MODES
02621          unsigned int current_call_mode;
02622 #endif
02623 
02624          /* Find a subspace of this space.  */
02625          if (!som_is_subspace (subsection)
02626              || !som_is_container (section, subsection))
02627            continue;
02628 
02629          /* If this subspace does not have real data, then we are
02630             finished with it.  */
02631          if ((subsection->flags & SEC_HAS_CONTENTS) == 0)
02632            {
02633              som_section_data (subsection)->subspace_dict->fixup_request_index
02634               = -1;
02635              continue;
02636            }
02637 
02638          /* This subspace has some relocations.  Put the relocation stream
02639             index into the subspace record.  */
02640          som_section_data (subsection)->subspace_dict->fixup_request_index
02641            = total_reloc_size;
02642 
02643          /* To make life easier start over with a clean slate for
02644             each subspace.  Seek to the start of the relocation stream
02645             for this subspace in preparation for writing out its fixup
02646             stream.  */
02647          if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
02648            return FALSE;
02649 
02650          /* Buffer space has already been allocated.  Just perform some
02651             initialization here.  */
02652          p = tmp_space;
02653          subspace_reloc_size = 0;
02654          reloc_offset = 0;
02655          som_initialize_reloc_queue (reloc_queue);
02656          current_rounding_mode = R_N_MODE;
02657 #ifndef NO_PCREL_MODES
02658          current_call_mode = R_SHORT_PCREL_MODE;
02659 #endif
02660 
02661          /* Translate each BFD relocation into one or more SOM
02662             relocations.  */
02663          for (j = 0; j < subsection->reloc_count; j++)
02664            {
02665              arelent *bfd_reloc = subsection->orelocation[j];
02666              unsigned int skip;
02667              int sym_num;
02668 
02669              /* Get the symbol number.  Remember it's stored in a
02670                special place for section symbols.  */
02671              if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
02672               sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i;
02673              else
02674               sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
02675 
02676              /* If there is not enough room for the next couple relocations,
02677                then dump the current buffer contents now.  Also reinitialize
02678                the relocation queue.
02679 
02680                No single BFD relocation could ever translate into more
02681                than 100 bytes of SOM relocations (20bytes is probably the
02682                upper limit, but leave lots of space for growth).  */
02683              if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
02684               {
02685                 amt = p - tmp_space;
02686                 if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
02687                   return FALSE;
02688 
02689                 p = tmp_space;
02690                 som_initialize_reloc_queue (reloc_queue);
02691               }
02692 
02693              /* Emit R_NO_RELOCATION fixups to map any bytes which were
02694                skipped.  */
02695              skip = bfd_reloc->address - reloc_offset;
02696              p = som_reloc_skip (abfd, skip, p,
02697                               &subspace_reloc_size, reloc_queue);
02698 
02699              /* Update reloc_offset for the next iteration.
02700 
02701                Many relocations do not consume input bytes.  They
02702                are markers, or set state necessary to perform some
02703                later relocation.  */
02704              switch (bfd_reloc->howto->type)
02705               {
02706               case R_ENTRY:
02707               case R_ALT_ENTRY:
02708               case R_EXIT:
02709               case R_N_MODE:
02710               case R_S_MODE:
02711               case R_D_MODE:
02712               case R_R_MODE:
02713               case R_FSEL:
02714               case R_LSEL:
02715               case R_RSEL:
02716               case R_COMP1:
02717               case R_COMP2:
02718               case R_BEGIN_BRTAB:
02719               case R_END_BRTAB:
02720               case R_BEGIN_TRY:
02721               case R_END_TRY:
02722               case R_N0SEL:
02723               case R_N1SEL:
02724 #ifndef NO_PCREL_MODES
02725               case R_SHORT_PCREL_MODE:
02726               case R_LONG_PCREL_MODE:
02727 #endif
02728                 reloc_offset = bfd_reloc->address;
02729                 break;
02730 
02731               default:
02732                 reloc_offset = bfd_reloc->address + 4;
02733                 break;
02734               }
02735 
02736              /* Now the actual relocation we care about.  */
02737              switch (bfd_reloc->howto->type)
02738               {
02739               case R_PCREL_CALL:
02740               case R_ABS_CALL:
02741                 p = som_reloc_call (abfd, p, &subspace_reloc_size,
02742                                   bfd_reloc, sym_num, reloc_queue);
02743                 break;
02744 
02745               case R_CODE_ONE_SYMBOL:
02746               case R_DP_RELATIVE:
02747                 /* Account for any addend.  */
02748                 if (bfd_reloc->addend)
02749                   p = som_reloc_addend (abfd, bfd_reloc->addend, p,
02750                                      &subspace_reloc_size, reloc_queue);
02751 
02752                 if (sym_num < 0x20)
02753                   {
02754                     bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
02755                     subspace_reloc_size += 1;
02756                     p += 1;
02757                   }
02758                 else if (sym_num < 0x100)
02759                   {
02760                     bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
02761                     bfd_put_8 (abfd, sym_num, p + 1);
02762                     p = try_prev_fixup (abfd, &subspace_reloc_size, p,
02763                                      2, reloc_queue);
02764                   }
02765                 else if (sym_num < 0x10000000)
02766                   {
02767                     bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
02768                     bfd_put_8 (abfd, sym_num >> 16, p + 1);
02769                     bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
02770                     p = try_prev_fixup (abfd, &subspace_reloc_size,
02771                                      p, 4, reloc_queue);
02772                   }
02773                 else
02774                   abort ();
02775                 break;
02776 
02777               case R_DATA_ONE_SYMBOL:
02778               case R_DATA_PLABEL:
02779               case R_CODE_PLABEL:
02780               case R_DLT_REL:
02781                 /* Account for any addend using R_DATA_OVERRIDE.  */
02782                 if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
02783                     && bfd_reloc->addend)
02784                   p = som_reloc_addend (abfd, bfd_reloc->addend, p,
02785                                      &subspace_reloc_size, reloc_queue);
02786 
02787                 if (sym_num < 0x100)
02788                   {
02789                     bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02790                     bfd_put_8 (abfd, sym_num, p + 1);
02791                     p = try_prev_fixup (abfd, &subspace_reloc_size, p,
02792                                      2, reloc_queue);
02793                   }
02794                 else if (sym_num < 0x10000000)
02795                   {
02796                     bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
02797                     bfd_put_8 (abfd, sym_num >> 16, p + 1);
02798                     bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
02799                     p = try_prev_fixup (abfd, &subspace_reloc_size,
02800                                      p, 4, reloc_queue);
02801                   }
02802                 else
02803                   abort ();
02804                 break;
02805 
02806               case R_ENTRY:
02807                 {
02808                   unsigned int tmp;
02809                   arelent *tmp_reloc = NULL;
02810                   bfd_put_8 (abfd, R_ENTRY, p);
02811 
02812                   /* R_ENTRY relocations have 64 bits of associated
02813                      data.  Unfortunately the addend field of a bfd
02814                      relocation is only 32 bits.  So, we split up
02815                      the 64bit unwind information and store part in
02816                      the R_ENTRY relocation, and the rest in the R_EXIT
02817                      relocation.  */
02818                   bfd_put_32 (abfd, bfd_reloc->addend, p + 1);
02819 
02820                   /* Find the next R_EXIT relocation.  */
02821                   for (tmp = j; tmp < subsection->reloc_count; tmp++)
02822                     {
02823                      tmp_reloc = subsection->orelocation[tmp];
02824                      if (tmp_reloc->howto->type == R_EXIT)
02825                        break;
02826                     }
02827 
02828                   if (tmp == subsection->reloc_count)
02829                     abort ();
02830 
02831                   bfd_put_32 (abfd, tmp_reloc->addend, p + 5);
02832                   p = try_prev_fixup (abfd, &subspace_reloc_size,
02833                                    p, 9, reloc_queue);
02834                   break;
02835                 }
02836 
02837               case R_N_MODE:
02838               case R_S_MODE:
02839               case R_D_MODE:
02840               case R_R_MODE:
02841                 /* If this relocation requests the current rounding
02842                    mode, then it is redundant.  */
02843                 if (bfd_reloc->howto->type != current_rounding_mode)
02844                   {
02845                     bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02846                     subspace_reloc_size += 1;
02847                     p += 1;
02848                     current_rounding_mode = bfd_reloc->howto->type;
02849                   }
02850                 break;
02851 
02852 #ifndef NO_PCREL_MODES
02853               case R_LONG_PCREL_MODE:
02854               case R_SHORT_PCREL_MODE:
02855                 if (bfd_reloc->howto->type != current_call_mode)
02856                   {
02857                     bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02858                     subspace_reloc_size += 1;
02859                     p += 1;
02860                     current_call_mode = bfd_reloc->howto->type;
02861                   }
02862                 break;
02863 #endif
02864 
02865               case R_EXIT:
02866               case R_ALT_ENTRY:
02867               case R_FSEL:
02868               case R_LSEL:
02869               case R_RSEL:
02870               case R_BEGIN_BRTAB:
02871               case R_END_BRTAB:
02872               case R_BEGIN_TRY:
02873               case R_N0SEL:
02874               case R_N1SEL:
02875                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02876                 subspace_reloc_size += 1;
02877                 p += 1;
02878                 break;
02879 
02880               case R_END_TRY:
02881                 /* The end of an exception handling region.  The reloc's
02882                    addend contains the offset of the exception handling
02883                    code.  */
02884                 if (bfd_reloc->addend == 0)
02885                   bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02886                 else if (bfd_reloc->addend < 1024)
02887                   {
02888                     bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
02889                     bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1);
02890                     p = try_prev_fixup (abfd, &subspace_reloc_size,
02891                                      p, 2, reloc_queue);
02892                   }
02893                 else
02894                   {
02895                     bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p);
02896                     bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1);
02897                     bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2);
02898                     p = try_prev_fixup (abfd, &subspace_reloc_size,
02899                                      p, 4, reloc_queue);
02900                   }
02901                 break;
02902 
02903               case R_COMP1:
02904                 /* The only time we generate R_COMP1, R_COMP2 and
02905                    R_CODE_EXPR relocs is for the difference of two
02906                    symbols.  Hence we can cheat here.  */
02907                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02908                 bfd_put_8 (abfd, 0x44, p + 1);
02909                 p = try_prev_fixup (abfd, &subspace_reloc_size,
02910                                   p, 2, reloc_queue);
02911                 break;
02912 
02913               case R_COMP2:
02914                 /* The only time we generate R_COMP1, R_COMP2 and
02915                    R_CODE_EXPR relocs is for the difference of two
02916                    symbols.  Hence we can cheat here.  */
02917                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02918                 bfd_put_8 (abfd, 0x80, p + 1);
02919                 bfd_put_8 (abfd, sym_num >> 16, p + 2);
02920                 bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
02921                 p = try_prev_fixup (abfd, &subspace_reloc_size,
02922                                   p, 5, reloc_queue);
02923                 break;
02924 
02925               case R_CODE_EXPR:
02926               case R_DATA_EXPR:
02927                 /* The only time we generate R_COMP1, R_COMP2 and
02928                    R_CODE_EXPR relocs is for the difference of two
02929                    symbols.  Hence we can cheat here.  */
02930                 bfd_put_8 (abfd, bfd_reloc->howto->type, p);
02931                 subspace_reloc_size += 1;
02932                 p += 1;
02933                 break;
02934 
02935               /* Put a "R_RESERVED" relocation in the stream if
02936                  we hit something we do not understand.  The linker
02937                  will complain loudly if this ever happens.  */
02938               default:
02939                 bfd_put_8 (abfd, 0xff, p);
02940                 subspace_reloc_size += 1;
02941                 p += 1;
02942                 break;
02943               }
02944            }
02945 
02946          /* Last BFD relocation for a subspace has been processed.
02947             Map the rest of the subspace with R_NO_RELOCATION fixups.  */
02948          p = som_reloc_skip (abfd, subsection->size - reloc_offset,
02949                            p, &subspace_reloc_size, reloc_queue);
02950 
02951          /* Scribble out the relocations.  */
02952          amt = p - tmp_space;
02953          if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
02954            return FALSE;
02955          p = tmp_space;
02956 
02957          total_reloc_size += subspace_reloc_size;
02958          som_section_data (subsection)->subspace_dict->fixup_request_quantity
02959            = subspace_reloc_size;
02960        }
02961       section = section->next;
02962     }
02963   *total_reloc_sizep = total_reloc_size;
02964   return TRUE;
02965 }
02966 
02967 /* Write out the space/subspace string table.  */
02968 
02969 static bfd_boolean
02970 som_write_space_strings (bfd *abfd,
02971                       unsigned long current_offset,
02972                       unsigned int *string_sizep)
02973 {
02974   /* Chunk of memory that we can use as buffer space, then throw
02975      away.  */
02976   size_t tmp_space_size = SOM_TMP_BUFSIZE;
02977   char *tmp_space = alloca (tmp_space_size);
02978   char *p = tmp_space;
02979   unsigned int strings_size = 0;
02980   asection *section;
02981   bfd_size_type amt;
02982 
02983   /* Seek to the start of the space strings in preparation for writing
02984      them out.  */
02985   if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
02986     return FALSE;
02987 
02988   /* Walk through all the spaces and subspaces (order is not important)
02989      building up and writing string table entries for their names.  */
02990   for (section = abfd->sections; section != NULL; section = section->next)
02991     {
02992       size_t length;
02993 
02994       /* Only work with space/subspaces; avoid any other sections
02995         which might have been made (.text for example).  */
02996       if (!som_is_space (section) && !som_is_subspace (section))
02997        continue;
02998 
02999       /* Get the length of the space/subspace name.  */
03000       length = strlen (section->name);
03001 
03002       /* If there is not enough room for the next entry, then dump the
03003         current buffer contents now and maybe allocate a larger
03004         buffer.  Each entry will take 4 bytes to hold the string
03005         length + the string itself + null terminator.  */
03006       if (p - tmp_space + 5 + length > tmp_space_size)
03007        {
03008          /* Flush buffer before refilling or reallocating.  */
03009          amt = p - tmp_space;
03010          if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
03011            return FALSE;
03012 
03013          /* Reallocate if now empty buffer still too small.  */
03014          if (5 + length > tmp_space_size)
03015            {
03016              /* Ensure a minimum growth factor to avoid O(n**2) space
03017                consumption for n strings.  The optimal minimum
03018                factor seems to be 2, as no other value can guarantee
03019                wasting less than 50% space.  (Note that we cannot
03020                deallocate space allocated by `alloca' without
03021                returning from this function.)  The same technique is
03022                used a few more times below when a buffer is
03023                reallocated.  */
03024              tmp_space_size = MAX (2 * tmp_space_size, 5 + length);
03025              tmp_space = alloca (tmp_space_size);
03026            }
03027 
03028          /* Reset to beginning of the (possibly new) buffer space.  */
03029          p = tmp_space;
03030        }
03031 
03032       /* First element in a string table entry is the length of the
03033         string.  Alignment issues are already handled.  */
03034       bfd_put_32 (abfd, (bfd_vma) length, p);
03035       p += 4;
03036       strings_size += 4;
03037 
03038       /* Record the index in the space/subspace records.  */
03039       if (som_is_space (section))
03040        som_section_data (section)->space_dict->name.n_strx = strings_size;
03041       else
03042        som_section_data (section)->subspace_dict->name.n_strx = strings_size;
03043 
03044       /* Next comes the string itself + a null terminator.  */
03045       strcpy (p, section->name);
03046       p += length + 1;
03047       strings_size += length + 1;
03048 
03049       /* Always align up to the next word boundary.  */
03050       while (strings_size % 4)
03051        {
03052          bfd_put_8 (abfd, 0, p);
03053          p++;
03054          strings_size++;
03055        }
03056     }
03057 
03058   /* Done with the space/subspace strings.  Write out any information
03059      contained in a partial block.  */
03060   amt = p - tmp_space;
03061   if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
03062     return FALSE;
03063   *string_sizep = strings_size;
03064   return TRUE;
03065 }
03066 
03067 /* Write out the symbol string table.  */
03068 
03069 static bfd_boolean
03070 som_write_symbol_strings (bfd *abfd,
03071                        unsigned long current_offset,
03072                        asymbol **syms,
03073                        unsigned int num_syms,
03074                        unsigned int *string_sizep,
03075                        COMPUNIT *compilation_unit)
03076 {
03077   unsigned int i;
03078 
03079   /* Chunk of memory that we can use as buffer space, then throw
03080      away.  */
03081   size_t tmp_space_size = SOM_TMP_BUFSIZE;
03082   char *tmp_space = alloca (tmp_space_size);
03083   char *p = tmp_space;
03084 
03085   unsigned int strings_size = 0;
03086   char *comp[4];
03087   bfd_size_type amt;
03088 
03089   /* This gets a bit gruesome because of the compilation unit.  The
03090      strings within the compilation unit are part of the symbol
03091      strings, but don't have symbol_dictionary entries.  So, manually
03092      write them and update the compilation unit header.  On input, the
03093      compilation unit header contains local copies of the strings.
03094      Move them aside.  */
03095   if (compilation_unit)
03096     {
03097       comp[0] = compilation_unit->name.n_name;
03098       comp[1] = compilation_unit->language_name.n_name;
03099       comp[2] = compilation_unit->product_id.n_name;
03100       comp[3] = compilation_unit->version_id.n_name;
03101     }
03102 
03103   /* Seek to the start of the space strings in preparation for writing
03104      them out.  */
03105   if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
03106     return FALSE;
03107 
03108   if (compilation_unit)
03109     {
03110       for (i = 0; i < 4; i++)
03111        {
03112          size_t length = strlen (comp[i]);
03113 
03114          /* If there is not enough room for the next entry, then dump
03115             the current buffer contents now and maybe allocate a
03116             larger buffer.  */
03117          if (p - tmp_space + 5 + length > tmp_space_size)
03118            {
03119              /* Flush buffer before refilling or reallocating.  */
03120              amt = p - tmp_space;
03121              if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
03122               return FALSE;
03123 
03124              /* Reallocate if now empty buffer still too small.  */
03125              if (5 + length > tmp_space_size)
03126               {
03127                 /* See alloca above for discussion of new size.  */
03128                 tmp_space_size = MAX (2 * tmp_space_size, 5 + length);
03129                 tmp_space = alloca (tmp_space_size);
03130               }
03131 
03132              /* Reset to beginning of the (possibly new) buffer
03133                space.  */
03134              p = tmp_space;
03135            }
03136 
03137          /* First element in a string table entry is the length of
03138             the string.  This must always be 4 byte aligned.  This is
03139             also an appropriate time to fill in the string index
03140             field in the symbol table entry.  */
03141          bfd_put_32 (abfd, (bfd_vma) length, p);
03142          strings_size += 4;
03143          p += 4;
03144 
03145          /* Next comes the string itself + a null terminator.  */
03146          strcpy (p, comp[i]);
03147 
03148          switch (i)
03149            {
03150            case 0:
03151              obj_som_compilation_unit (abfd)->name.n_strx = strings_size;
03152              break;
03153            case 1:
03154              obj_som_compilation_unit (abfd)->language_name.n_strx =
03155               strings_size;
03156              break;
03157            case 2:
03158              obj_som_compilation_unit (abfd)->product_id.n_strx =
03159               strings_size;
03160              break;
03161            case 3:
03162              obj_som_compilation_unit (abfd)->version_id.n_strx =
03163               strings_size;
03164              break;
03165            }
03166 
03167          p += length + 1;
03168          strings_size += length + 1;
03169 
03170          /* Always align up to the next word boundary.  */
03171          while (strings_size % 4)
03172            {
03173              bfd_put_8 (abfd, 0, p);
03174              strings_size++;
03175              p++;
03176            }
03177        }
03178     }
03179 
03180   for (i = 0; i < num_syms; i++)
03181     {
03182       size_t length = strlen (syms[i]->name);
03183 
03184       /* If there is not enough room for the next entry, then dump the
03185         current buffer contents now and maybe allocate a larger buffer.  */
03186      if (p - tmp_space + 5 + length > tmp_space_size)
03187        {
03188          /* Flush buffer before refilling or reallocating.  */
03189          amt = p - tmp_space;
03190          if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
03191            return FALSE;
03192 
03193          /* Reallocate if now empty buffer still too small.  */
03194          if (5 + length > tmp_space_size)
03195            {
03196              /* See alloca above for discussion of new size.  */
03197              tmp_space_size = MAX (2 * tmp_space_size, 5 + length);
03198              tmp_space = alloca (tmp_space_size);
03199            }
03200 
03201          /* Reset to beginning of the (possibly new) buffer space.  */
03202          p = tmp_space;
03203        }
03204 
03205       /* First element in a string table entry is the length of the
03206         string.  This must always be 4 byte aligned.  This is also
03207         an appropriate time to fill in the string index field in the
03208         symbol table entry.  */
03209       bfd_put_32 (abfd, (bfd_vma) length, p);
03210       strings_size += 4;
03211       p += 4;
03212 
03213       /* Next comes the string itself + a null terminator.  */
03214       strcpy (p, syms[i]->name);
03215 
03216       som_symbol_data (syms[i])->stringtab_offset = strings_size;
03217       p += length + 1;
03218       strings_size += length + 1;
03219 
03220       /* Always align up to the next word boundary.  */
03221       while (strings_size % 4)
03222        {
03223          bfd_put_8 (abfd, 0, p);
03224          strings_size++;
03225          p++;
03226        }
03227     }
03228 
03229   /* Scribble out any partial block.  */
03230   amt = p - tmp_space;
03231   if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
03232     return FALSE;
03233 
03234   *string_sizep = strings_size;
03235   return TRUE;
03236 }
03237 
03238 /* Compute variable information to be placed in the SOM headers,
03239    space/subspace dictionaries, relocation streams, etc.  Begin
03240    writing parts of the object file.  */
03241 
03242 static bfd_boolean
03243 som_begin_writing (bfd *abfd)
03244 {
03245   unsigned long current_offset = 0;
03246   unsigned int strings_size = 0;
03247   unsigned long num_spaces, num_subspaces, i;
03248   asection *section;
03249   unsigned int total_subspaces = 0;
03250   struct som_exec_auxhdr *exec_header = NULL;
03251 
03252   /* The file header will always be first in an object file,
03253      everything else can be in random locations.  To keep things
03254      "simple" BFD will lay out the object file in the manner suggested
03255      by the PRO ABI for PA-RISC Systems.  */
03256 
03257   /* Before any output can really begin offsets for all the major
03258      portions of the object file must be computed.  So, starting
03259      with the initial file header compute (and sometimes write)
03260      each portion of the object file.  */
03261 
03262   /* Make room for the file header, it's contents are not complete
03263      yet, so it can not be written at this time.  */
03264   current_offset += sizeof (struct header);
03265 
03266   /* Any auxiliary headers will follow the file header.  Right now
03267      we support only the copyright and version headers.  */
03268   obj_som_file_hdr (abfd)->aux_header_location = current_offset;
03269   obj_som_file_hdr (abfd)->aux_header_size = 0;
03270   if (abfd->flags & (EXEC_P | DYNAMIC))
03271     {
03272       /* Parts of the exec header will be filled in later, so
03273         delay writing the header itself.  Fill in the defaults,
03274         and write it later.  */
03275       current_offset += sizeof (struct som_exec_auxhdr);
03276       obj_som_file_hdr (abfd)->aux_header_size
03277        += sizeof (struct som_exec_auxhdr);
03278       exec_header = obj_som_exec_hdr (abfd);
03279       exec_header->som_auxhdr.type = EXEC_AUX_ID;
03280       exec_header->som_auxhdr.length = 40;
03281     }
03282   if (obj_som_version_hdr (abfd) != NULL)
03283     {
03284       bfd_size_type len;
03285 
03286       if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
03287        return FALSE;
03288 
03289       /* Write the aux_id structure and the string length.  */
03290       len = sizeof (struct aux_id) + sizeof (unsigned int);
03291       obj_som_file_hdr (abfd)->aux_header_size += len;
03292       current_offset += len;
03293       if (bfd_bwrite ((void *) obj_som_version_hdr (abfd), len, abfd) != len)
03294        return FALSE;
03295 
03296       /* Write the version string.  */
03297       len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
03298       obj_som_file_hdr (abfd)->aux_header_size += len;
03299       current_offset += len;
03300       if (bfd_bwrite ((void *) obj_som_version_hdr (abfd)->user_string, len, abfd)
03301          != len)
03302        return FALSE;
03303     }
03304 
03305   if (obj_som_copyright_hdr (abfd) != NULL)
03306     {
03307       bfd_size_type len;
03308 
03309       if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
03310        return FALSE;
03311 
03312       /* Write the aux_id structure and the string length.  */
03313       len = sizeof (struct aux_id) + sizeof (unsigned int);
03314       obj_som_file_hdr (abfd)->aux_header_size += len;
03315       current_offset += len;
03316       if (bfd_bwrite ((void *) obj_som_copyright_hdr (abfd), len, abfd) != len)
03317        return FALSE;
03318 
03319       /* Write the copyright string.  */
03320       len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
03321       obj_som_file_hdr (abfd)->aux_header_size += len;
03322       current_offset += len;
03323       if (bfd_bwrite ((void *) obj_som_copyright_hdr (abfd)->copyright, len, abfd)
03324          != len)
03325        return FALSE;
03326     }
03327 
03328   /* Next comes the initialization pointers; we have no initialization
03329      pointers, so current offset does not change.  */
03330   obj_som_file_hdr (abfd)->init_array_location = current_offset;
03331   obj_som_file_hdr (abfd)->init_array_total = 0;
03332 
03333   /* Next are the space records.  These are fixed length records.
03334 
03335      Count the number of spaces to determine how much room is needed
03336      in the object file for the space records.
03337 
03338      The names of the spaces are stored in a separate string table,
03339      and the index for each space into the string table is computed
03340      below.  Therefore, it is not possible to write the space headers
03341      at this time.  */
03342   num_spaces = som_count_spaces (abfd);
03343   obj_som_file_hdr (abfd)->space_location = current_offset;
03344   obj_som_file_hdr (abfd)->space_total = num_spaces;
03345   current_offset += num_spaces * sizeof (struct space_dictionary_record);
03346 
03347   /* Next are the subspace records.  These are fixed length records.
03348 
03349      Count the number of subspaes to determine how much room is needed
03350      in the object file for the subspace records.
03351 
03352      A variety if fields in the subspace record are still unknown at
03353      this time (index into string table, fixup stream location/size, etc).  */
03354   num_subspaces = som_count_subspaces (abfd);
03355   obj_som_file_hdr (abfd)->subspace_location = current_offset;
03356   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
03357   current_offset
03358     += num_subspaces * sizeof (struct som_subspace_dictionary_record);
03359 
03360   /* Next is the string table for the space/subspace names.  We will
03361      build and write the string table on the fly.  At the same time
03362      we will fill in the space/subspace name index fields.  */
03363 
03364   /* The string table needs to be aligned on a word boundary.  */
03365   if (current_offset % 4)
03366     current_offset += (4 - (current_offset % 4));
03367 
03368   /* Mark the offset of the space/subspace string table in the
03369      file header.  */
03370   obj_som_file_hdr (abfd)->space_strings_location = current_offset;
03371 
03372   /* Scribble out the space strings.  */
03373   if (! som_write_space_strings (abfd, current_offset, &strings_size))
03374     return FALSE;
03375 
03376   /* Record total string table size in the header and update the
03377      current offset.  */
03378   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
03379   current_offset += strings_size;
03380 
03381   /* Next is the compilation unit.  */
03382   obj_som_file_hdr (abfd)->compiler_location = current_offset;
03383   obj_som_file_hdr (abfd)->compiler_total = 0;
03384   if (obj_som_compilation_unit (abfd))
03385     {
03386       obj_som_file_hdr (abfd)->compiler_total = 1;
03387       current_offset += COMPUNITSZ;
03388     }
03389 
03390   /* Now compute the file positions for the loadable subspaces, taking
03391      care to make sure everything stays properly aligned.  */
03392 
03393   section = abfd->sections;
03394   for (i = 0; i < num_spaces; i++)
03395     {
03396       asection *subsection;
03397       int first_subspace;
03398       unsigned int subspace_offset = 0;
03399 
03400       /* Find a space.  */
03401       while (!som_is_space (section))
03402        section = section->next;
03403 
03404       first_subspace = 1;
03405       /* Now look for all its subspaces.  */
03406       for (subsection = abfd->sections;
03407           subsection != NULL;
03408           subsection = subsection->next)
03409        {
03410 
03411          if (!som_is_subspace (subsection)
03412              || !som_is_container (section, subsection)
03413              || (subsection->flags & SEC_ALLOC) == 0)
03414            continue;
03415 
03416          /* If this is the first subspace in the space, and we are
03417             building an executable, then take care to make sure all
03418             the alignments are correct and update the exec header.  */
03419          if (first_subspace
03420              && (abfd->flags & (EXEC_P | DYNAMIC)))
03421            {
03422              /* Demand paged executables have each space aligned to a
03423                page boundary.  Sharable executables (write-protected
03424                text) have just the private (aka data & bss) space aligned
03425                to a page boundary.  Ugh.  Not true for HPUX.
03426 
03427                The HPUX kernel requires the text to always be page aligned
03428                within the file regardless of the executable's type.  */
03429              if (abfd->flags & (D_PAGED | DYNAMIC)
03430                 || (subsection->flags & SEC_CODE)
03431                 || ((abfd->flags & WP_TEXT)
03432                     && (subsection->flags & SEC_DATA)))
03433               current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
03434 
03435              /* Update the exec header.  */
03436              if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
03437               {
03438                 exec_header->exec_tmem = section->vma;
03439                 exec_header->exec_tfile = current_offset;
03440               }
03441              if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
03442               {
03443                 exec_header->exec_dmem = section->vma;
03444                 exec_header->exec_dfile = current_offset;
03445               }
03446 
03447              /* Keep track of exactly where we are within a particular
03448                space.  This is necessary as the braindamaged HPUX
03449                loader will create holes between subspaces *and*
03450                subspace alignments are *NOT* preserved.  What a crock.  */
03451              subspace_offset = subsection->vma;
03452 
03453              /* Only do this for the first subspace within each space.  */
03454              first_subspace = 0;
03455            }
03456          else if (abfd->flags & (EXEC_P | DYNAMIC))
03457            {
03458              /* The braindamaged HPUX loader may have created a hole
03459                between two subspaces.  It is *not* sufficient to use
03460                the alignment specifications within the subspaces to
03461                account for these holes -- I've run into at least one
03462                case where the loader left one code subspace unaligned
03463                in a final executable.
03464 
03465                To combat this we keep a current offset within each space,
03466                and use the subspace vma fields to detect and preserve
03467                holes.  What a crock!
03468 
03469                ps.  This is not necessary for unloadable space/subspaces.  */
03470              current_offset += subsection->vma - subspace_offset;
03471              if (subsection->flags & SEC_CODE)
03472               exec_header->exec_tsize += subsection->vma - subspace_offset;
03473              else
03474               exec_header->exec_dsize += subsection->vma - subspace_offset;
03475              subspace_offset += subsection->vma - subspace_offset;
03476            }
03477 
03478          subsection->target_index = total_subspaces++;
03479          /* This is real data to be loaded from the file.  */
03480          if (subsection->flags & SEC_LOAD)
03481            {
03482              /* Update the size of the code & data.  */
03483              if (abfd->flags & (EXEC_P | DYNAMIC)
03484                 && subsection->flags & SEC_CODE)
03485               exec_header->exec_tsize += subsection->size;
03486              else if (abfd->flags & (EXEC_P | DYNAMIC)
03487                      && subsection->flags & SEC_DATA)
03488               exec_header->exec_dsize += subsection->size;
03489              som_section_data (subsection)->subspace_dict->file_loc_init_value
03490               = current_offset;
03491              subsection->filepos = current_offset;
03492              current_offset += subsection->size;
03493              subspace_offset += subsection->size;
03494            }
03495          /* Looks like uninitialized data.  */
03496          else
03497            {
03498              /* Update the size of the bss section.  */
03499              if (abfd->flags & (EXEC_P | DYNAMIC))
03500               exec_header->exec_bsize += subsection->size;
03501 
03502              som_section_data (subsection)->subspace_dict->file_loc_init_value
03503               = 0;
03504              som_section_data (subsection)->subspace_dict->
03505               initialization_length = 0;
03506            }
03507        }
03508       /* Goto the next section.  */
03509       section = section->next;
03510     }
03511 
03512   /* Finally compute the file positions for unloadable subspaces.
03513      If building an executable, start the unloadable stuff on its
03514      own page.  */
03515 
03516   if (abfd->flags & (EXEC_P | DYNAMIC))
03517     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
03518 
03519   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
03520   section = abfd->sections;
03521   for (i = 0; i < num_spaces; i++)
03522     {
03523       asection *subsection;
03524 
03525       /* Find a space.  */
03526       while (!som_is_space (section))
03527        section = section->next;
03528 
03529       if (abfd->flags & (EXEC_P | DYNAMIC))
03530        current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
03531 
03532       /* Now look for all its subspaces.  */
03533       for (subsection = abfd->sections;
03534           subsection != NULL;
03535           subsection = subsection->next)
03536        {
03537 
03538          if (!som_is_subspace (subsection)
03539              || !som_is_container (section, subsection)
03540              || (subsection->flags & SEC_ALLOC) != 0)
03541            continue;
03542 
03543          subsection->target_index = total_subspaces++;
03544          /* This is real data to be loaded from the file.  */
03545          if ((subsection->flags & SEC_LOAD) == 0)
03546            {
03547              som_section_data (subsection)->subspace_dict->file_loc_init_value
03548               = current_offset;
03549              subsection->filepos = current_offset;
03550              current_offset += subsection->size;
03551            }
03552          /* Looks like uninitialized data.  */
03553          else
03554            {
03555              som_section_data (subsection)->subspace_dict->file_loc_init_value
03556               = 0;
03557              som_section_data (subsection)->subspace_dict->
03558               initialization_length = subsection->size;
03559            }
03560        }
03561       /* Goto the next section.  */
03562       section = section->next;
03563     }
03564 
03565   /* If building an executable, then make sure to seek to and write
03566      one byte at the end of the file to make sure any necessary
03567      zeros are filled in.  Ugh.  */
03568   if (abfd->flags & (EXEC_P | DYNAMIC))
03569     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
03570   if (bfd_seek (abfd, (file_ptr) current_offset - 1, SEEK_SET) != 0)
03571     return FALSE;
03572   if (bfd_bwrite ((void *) "", (bfd_size_type) 1, abfd) != 1)
03573     return FALSE;
03574 
03575   obj_som_file_hdr (abfd)->unloadable_sp_size
03576     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
03577 
03578   /* Loader fixups are not supported in any way shape or form.  */
03579   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
03580   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
03581 
03582   /* Done.  Store the total size of the SOM so far.  */
03583   obj_som_file_hdr (abfd)->som_length = current_offset;
03584 
03585   return TRUE;
03586 }
03587 
03588 /* Finally, scribble out the various headers to the disk.  */
03589 
03590 static bfd_boolean
03591 som_finish_writing (bfd *abfd)
03592 {
03593   int num_spaces = som_count_spaces (abfd);
03594   asymbol **syms = bfd_get_outsymbols (abfd);
03595   int i, num_syms;
03596   int subspace_index = 0;
03597   file_ptr location;
03598   asection *section;
03599   unsigned long current_offset;
03600   unsigned int strings_size, total_reloc_size;
03601   bfd_size_type amt;
03602 
03603   /* We must set up the version identifier here as objcopy/strip copy
03604      private BFD data too late for us to handle this in som_begin_writing.  */
03605   if (obj_som_exec_data (abfd)
03606       && obj_som_exec_data (abfd)->version_id)
03607     obj_som_file_hdr (abfd)->version_id = obj_som_exec_data (abfd)->version_id;
03608   else
03609     obj_som_file_hdr (abfd)->version_id = NEW_VERSION_ID;
03610 
03611   /* Next is the symbol table.  These are fixed length records.
03612 
03613      Count the number of symbols to determine how much room is needed
03614      in the object file for the symbol table.
03615 
03616      The names of the symbols are stored in a separate string table,
03617      and the index for each symbol name into the string table is computed
03618      below.  Therefore, it is not possible to write the symbol table
03619      at this time.
03620 
03621      These used to be output before the subspace contents, but they
03622      were moved here to work around a stupid bug in the hpux linker
03623      (fixed in hpux10).  */
03624   current_offset = obj_som_file_hdr (abfd)->som_length;
03625 
03626   /* Make sure we're on a word boundary.  */
03627   if (current_offset % 4)
03628     current_offset += (4 - (current_offset % 4));
03629 
03630   num_syms = bfd_get_symcount (abfd);
03631   obj_som_file_hdr (abfd)->symbol_location = current_offset;
03632   obj_som_file_hdr (abfd)->symbol_total = num_syms;
03633   current_offset += num_syms * sizeof (struct symbol_dictionary_record);
03634 
03635   /* Next are the symbol strings.
03636      Align them to a word boundary.  */
03637   if (current_offset % 4)
03638     current_offset += (4 - (current_offset % 4));
03639   obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
03640 
03641   /* Scribble out the symbol strings.  */
03642   if (! som_write_symbol_strings (abfd, current_offset, syms,
03643                               num_syms, &strings_size,
03644                               obj_som_compilation_unit (abfd)))
03645     return FALSE;
03646 
03647   /* Record total string table size in header and update the
03648      current offset.  */
03649   obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
03650   current_offset += strings_size;
03651 
03652   /* Do prep work before handling fixups.  */
03653   som_prep_for_fixups (abfd,
03654                      bfd_get_outsymbols (abfd),
03655                      bfd_get_symcount (abfd));
03656 
03657   /* At the end of the file is the fixup stream which starts on a
03658      word boundary.  */
03659   if (current_offset % 4)
03660     current_offset += (4 - (current_offset % 4));
03661   obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
03662 
03663   /* Write the fixups and update fields in subspace headers which
03664      relate to the fixup stream.  */
03665   if (! som_write_fixups (abfd, current_offset, &total_reloc_size))
03666     return FALSE;
03667 
03668   /* Record the total size of the fixup stream in the file header.  */
03669   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
03670 
03671   /* Done.  Store the total size of the SOM.  */
03672   obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size;
03673 
03674   /* Now that the symbol table information is complete, build and
03675      write the symbol table.  */
03676   if (! som_build_and_write_symbol_table (abfd))
03677     return FALSE;
03678 
03679   /* Subspaces are written first so that we can set up information
03680      about them in their containing spaces as the subspace is written.  */
03681 
03682   /* Seek to the start of the subspace dictionary records.  */
03683   location = obj_som_file_hdr (abfd)->subspace_location;
03684   if (bfd_seek (abfd, location, SEEK_SET) != 0)
03685     return FALSE;
03686 
03687   section = abfd->sections;
03688   /* Now for each loadable space write out records for its subspaces.  */
03689   for (i = 0; i < num_spaces; i++)
03690     {
03691       asection *subsection;
03692 
03693       /* Find a space.  */
03694       while (!som_is_space (section))
03695        section = section->next;
03696 
03697       /* Now look for all its subspaces.  */
03698       for (subsection = abfd->sections;
03699           subsection != NULL;
03700           subsection = subsection->next)
03701        {
03702 
03703          /* Skip any section which does not correspond to a space
03704             or subspace.  Or does not have SEC_ALLOC set (and therefore
03705             has no real bits on the disk).  */
03706          if (!som_is_subspace (subsection)
03707              || !som_is_container (section, subsection)
03708              || (subsection->flags & SEC_ALLOC) == 0)
03709            continue;
03710 
03711          /* If this is the first subspace for this space, then save
03712             the index of the subspace in its containing space.  Also
03713             set "is_loadable" in the containing space.  */
03714 
03715          if (som_section_data (section)->space_dict->subspace_quantity == 0)
03716            {
03717              som_section_data (section)->space_dict->is_loadable = 1;
03718              som_section_data (section)->space_dict->subspace_index
03719               = subspace_index;
03720            }
03721 
03722          /* Increment the number of subspaces seen and the number of
03723             subspaces contained within the current space.  */
03724          subspace_index++;
03725          som_section_data (section)->space_dict->subspace_quantity++;
03726 
03727          /* Mark the index of the current space within the subspace's
03728             dictionary record.  */
03729          som_section_data (subsection)->subspace_dict->space_index = i;
03730 
03731          /* Dump the current subspace header.  */
03732          amt = sizeof (struct som_subspace_dictionary_record);
03733          if (bfd_bwrite ((void *) som_section_data (subsection)->subspace_dict,
03734                       amt, abfd) != amt)
03735            return FALSE;
03736        }
03737       /* Goto the next section.  */
03738       section = section->next;
03739     }
03740 
03741   /* Now repeat the process for unloadable subspaces.  */
03742   section = abfd->sections;
03743   /* Now for each space write out records for its subspaces.  */
03744   for (i = 0; i < num_spaces; i++)
03745     {
03746       asection *subsection;
03747 
03748       /* Find a space.  */
03749       while (!som_is_space (section))
03750        section = section->next;
03751 
03752       /* Now look for all its subspaces.  */
03753       for (subsection = abfd->sections;
03754           subsection != NULL;
03755           subsection = subsection->next)
03756        {
03757 
03758          /* Skip any section which does not correspond to a space or
03759             subspace, or which SEC_ALLOC set (and therefore handled
03760             in the loadable spaces/subspaces code above).  */
03761 
03762          if (!som_is_subspace (subsection)
03763              || !som_is_container (section, subsection)
03764              || (subsection->flags & SEC_ALLOC) != 0)
03765            continue;
03766 
03767          /* If this is the first subspace for this space, then save
03768             the index of the subspace in its containing space.  Clear
03769             "is_loadable".  */
03770 
03771          if (som_section_data (section)->space_dict->subspace_quantity == 0)
03772            {
03773              som_section_data (section)->space_dict->is_loadable = 0;
03774              som_section_data (section)->space_dict->subspace_index
03775               = subspace_index;
03776            }
03777 
03778          /* Increment the number of subspaces seen and the number of
03779             subspaces contained within the current space.  */
03780          som_section_data (section)->space_dict->subspace_quantity++;
03781          subspace_index++;
03782 
03783          /* Mark the index of the current space within the subspace's
03784             dictionary record.  */
03785          som_section_data (subsection)->subspace_dict->space_index = i;
03786 
03787          /* Dump this subspace header.  */
03788          amt = sizeof (struct som_subspace_dictionary_record);
03789          if (bfd_bwrite ((void *) som_section_data (subsection)->subspace_dict,
03790                       amt, abfd) != amt)
03791            return FALSE;
03792        }
03793       /* Goto the next section.  */
03794       section = section->next;
03795     }
03796 
03797   /* All the subspace dictionary records are written, and all the
03798      fields are set up in the space dictionary records.
03799 
03800      Seek to the right location and start writing the space
03801      dictionary records.  */
03802   location = obj_som_file_hdr (abfd)->space_location;
03803   if (bfd_seek (abfd, location, SEEK_SET) != 0)
03804     return FALSE;
03805 
03806   section = abfd->sections;
03807   for (i = 0; i < num_spaces; i++)
03808     {
03809       /* Find a space.  */
03810       while (!som_is_space (section))
03811        section = section->next;
03812 
03813       /* Dump its header.  */
03814       amt = sizeof (struct space_dictionary_record);
03815       if (bfd_bwrite ((void *) som_section_data (section)->space_dict,
03816                    amt, abfd) != amt)
03817        return FALSE;
03818 
03819       /* Goto the next section.  */
03820       section = section->next;
03821     }
03822 
03823   /* Write the compilation unit record if there is one.  */
03824   if (obj_som_compilation_unit (abfd))
03825     {
03826       location = obj_som_file_hdr (abfd)->compiler_location;
03827       if (bfd_seek (abfd, location, SEEK_SET) != 0)
03828        return FALSE;
03829 
03830       amt = COMPUNITSZ;
03831       if (bfd_bwrite ((void *) obj_som_compilation_unit (abfd), amt, abfd) != amt)
03832        return FALSE;
03833     }
03834 
03835   /* Setting of the system_id has to happen very late now that copying of
03836      BFD private data happens *after* section contents are set.  */
03837   if (abfd->flags & (EXEC_P | DYNAMIC))
03838     obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id;
03839   else if (bfd_get_mach (abfd) == pa20)
03840     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0;
03841   else if (bfd_get_mach (abfd) == pa11)
03842     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_1;
03843   else
03844     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_0;
03845 
03846   /* Compute the checksum for the file header just before writing
03847      the header to disk.  */
03848   obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
03849 
03850   /* Only thing left to do is write out the file header.  It is always
03851      at location zero.  Seek there and write it.  */
03852   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
03853     return FALSE;
03854   amt = sizeof (struct header);
03855   if (bfd_bwrite ((void *) obj_som_file_hdr (abfd), amt, abfd) != amt)
03856     return FALSE;
03857 
03858   /* Now write the exec header.  */
03859   if (abfd->flags & (EXEC_P | DYNAMIC))
03860     {
03861       long tmp, som_length;
03862       struct som_exec_auxhdr *exec_header;
03863 
03864       exec_header = obj_som_exec_hdr (abfd);
03865       exec_header->exec_entry = bfd_get_start_address (abfd);
03866       exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
03867 
03868       /* Oh joys.  Ram some of the BSS data into the DATA section
03869         to be compatible with how the hp linker makes objects
03870         (saves memory space).  */
03871       tmp = exec_header->exec_dsize;
03872       tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
03873       exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
03874       if (exec_header->exec_bsize < 0)
03875        exec_header->exec_bsize = 0;
03876       exec_header->exec_dsize = tmp;
03877 
03878       /* Now perform some sanity checks.  The idea is to catch bogons now and
03879         inform the user, instead of silently generating a bogus file.  */
03880       som_length = obj_som_file_hdr (abfd)->som_length;
03881       if (exec_header->exec_tfile + exec_header->exec_tsize > som_length
03882          || exec_header->exec_dfile + exec_header->exec_dsize > som_length)
03883        {
03884          bfd_set_error (bfd_error_bad_value);
03885          return FALSE;
03886        }
03887 
03888       if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
03889                   SEEK_SET) != 0)
03890        return FALSE;
03891 
03892       amt = AUX_HDR_SIZE;
03893       if (bfd_bwrite ((void *) exec_header, amt, abfd) != amt)
03894        return FALSE;
03895     }
03896   return TRUE;
03897 }
03898 
03899 /* Compute and return the checksum for a SOM file header.  */
03900 
03901 static unsigned long
03902 som_compute_checksum (bfd *abfd)
03903 {
03904   unsigned long checksum, count, i;
03905   unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
03906 
03907   checksum = 0;
03908   count = sizeof (struct header) / sizeof (unsigned long);
03909   for (i = 0; i < count; i++)
03910     checksum ^= *(buffer + i);
03911 
03912   return checksum;
03913 }
03914 
03915 static void
03916 som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
03917                              asymbol *sym,
03918                              struct som_misc_symbol_info *info)
03919 {
03920   /* Initialize.  */
03921   memset (info, 0, sizeof (struct som_misc_symbol_info));
03922 
03923   /* The HP SOM linker requires detailed type information about
03924      all symbols (including undefined symbols!).  Unfortunately,
03925      the type specified in an import/export statement does not
03926      always match what the linker wants.  Severe braindamage.  */
03927 
03928   /* Section symbols will not have a SOM symbol type assigned to
03929      them yet.  Assign all section symbols type ST_DATA.  */
03930   if (sym->flags & BSF_SECTION_SYM)
03931     info->symbol_type = ST_DATA;
03932   else
03933     {
03934       /* For BFD style common, the linker will choke unless we set the
03935         type and scope to ST_STORAGE and SS_UNSAT, respectively.  */
03936       if (bfd_is_com_section (sym->section))
03937        {
03938          info->symbol_type = ST_STORAGE;
03939          info->symbol_scope = SS_UNSAT;
03940        }
03941 
03942       /* It is possible to have a symbol without an associated
03943         type.  This happens if the user imported the symbol
03944         without a type and the symbol was never defined
03945         locally.  If BSF_FUNCTION is set for this symbol, then
03946         assign it type ST_CODE (the HP linker requires undefined
03947         external functions to have type ST_CODE rather than ST_ENTRY).  */
03948       else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
03949               || som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
03950               && bfd_is_und_section (sym->section)
03951               && sym->flags & BSF_FUNCTION)
03952        info->symbol_type = ST_CODE;
03953 
03954       /* Handle function symbols which were defined in this file.
03955         They should have type ST_ENTRY.  Also retrieve the argument
03956         relocation bits from the SOM backend information.  */
03957       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
03958               || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
03959                  && (sym->flags & BSF_FUNCTION))
03960               || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
03961                  && (sym->flags & BSF_FUNCTION)))
03962        {
03963          info->symbol_type = ST_ENTRY;
03964          info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc;
03965          info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level;
03966        }
03967 
03968       /* For unknown symbols set the symbol's type based on the symbol's
03969         section (ST_DATA for DATA sections, ST_CODE for CODE sections).  */
03970       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
03971        {
03972          if (sym->section->flags & SEC_CODE)
03973            info->symbol_type = ST_CODE;
03974          else
03975            info->symbol_type = ST_DATA;
03976        }
03977 
03978       /* From now on it's a very simple mapping.  */
03979       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
03980        info->symbol_type = ST_ABSOLUTE;
03981       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
03982        info->symbol_type = ST_CODE;
03983       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
03984        info->symbol_type = ST_DATA;
03985       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
03986        info->symbol_type = ST_MILLICODE;
03987       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
03988        info->symbol_type = ST_PLABEL;
03989       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
03990        info->symbol_type = ST_PRI_PROG;
03991       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
03992        info->symbol_type = ST_SEC_PROG;
03993     }
03994 
03995   /* Now handle the symbol's scope.  Exported data which is not
03996      in the common section has scope SS_UNIVERSAL.  Note scope
03997      of common symbols was handled earlier!  */
03998   if (bfd_is_com_section (sym->section))
03999     ;
04000   else if (bfd_is_und_section (sym->section))
04001     info->symbol_scope = SS_UNSAT;
04002   else if (sym->flags & (BSF_EXPORT | BSF_WEAK))
04003     info->symbol_scope = SS_UNIVERSAL;
04004   /* Anything else which is not in the common section has scope
04005      SS_LOCAL.  */
04006   else
04007     info->symbol_scope = SS_LOCAL;
04008 
04009   /* Now set the symbol_info field.  It has no real meaning
04010      for undefined or common symbols, but the HP linker will
04011      choke if it's not set to some "reasonable" value.  We
04012      use zero as a reasonable value.  */
04013   if (bfd_is_com_section (sym->section)
04014       || bfd_is_und_section (sym->section)
04015       || bfd_is_abs_section (sym->section))
04016     info->symbol_info = 0;
04017   /* For all other symbols, the symbol_info field contains the
04018      subspace index of the space this symbol is contained in.  */
04019   else
04020     info->symbol_info = sym->section->target_index;
04021 
04022   /* Set the symbol's value.  */
04023   info->symbol_value = sym->value + sym->section->vma;
04024 
04025   /* The secondary_def field is for "weak" symbols.  */
04026   if (sym->flags & BSF_WEAK)
04027     info->secondary_def = TRUE;
04028   else
04029     info->secondary_def = FALSE;
04030 
04031   /* The is_comdat, is_common and dup_common fields provide various
04032      flavors of common.
04033 
04034      For data symbols, setting IS_COMMON provides Fortran style common
04035      (duplicate definitions and overlapped initialization).  Setting both
04036      IS_COMMON and DUP_COMMON provides Cobol style common (duplicate
04037      definitions as long as they are all the same length).  In a shared
04038      link data symbols retain their IS_COMMON and DUP_COMMON flags.
04039      An IS_COMDAT data symbol is similar to a IS_COMMON | DUP_COMMON
04040      symbol except in that it loses its IS_COMDAT flag in a shared link.
04041 
04042      For code symbols, IS_COMDAT and DUP_COMMON have effect.  Universal
04043      DUP_COMMON code symbols are not exported from shared libraries.
04044      IS_COMDAT symbols are exported but they lose their IS_COMDAT flag.
04045 
04046      We take a simplified approach to setting the is_comdat, is_common
04047      and dup_common flags in symbols based on the flag settings of their
04048      subspace.  This avoids having to add directives like `.comdat' but
04049      the linker behavior is probably undefined if there is more than one
04050      universal symbol (comdat key sysmbol) in a subspace.
04051 
04052      The behavior of these flags is not well documentmented, so there
04053      may be bugs and some surprising interactions with other flags.  */
04054   if (som_section_data (sym->section)
04055       && som_section_data (sym->section)->subspace_dict
04056       && info->symbol_scope == SS_UNIVERSAL
04057       && (info->symbol_type == ST_ENTRY
04058          || info->symbol_type == ST_CODE
04059          || info->symbol_type == ST_DATA))
04060     {
04061       info->is_comdat
04062        = som_section_data (sym->section)->subspace_dict->is_comdat;
04063       info->is_common
04064        = som_section_data (sym->section)->subspace_dict->is_common;
04065       info->dup_common
04066        = som_section_data (sym->section)->subspace_dict->dup_common;
04067     }
04068 }
04069 
04070 /* Build and write, in one big chunk, the entire symbol table for
04071    this BFD.  */
04072 
04073 static bfd_boolean
04074 som_build_and_write_symbol_table (bfd *abfd)
04075 {
04076   unsigned int num_syms = bfd_get_symcount (abfd);
04077   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
04078   asymbol **bfd_syms = obj_som_sorted_syms (abfd);
04079   struct symbol_dictionary_record *som_symtab = NULL;
04080   unsigned int i;
04081   bfd_size_type symtab_size;
04082 
04083   /* Compute total symbol table size and allocate a chunk of memory
04084      to hold the symbol table as we build it.  */
04085   symtab_size = num_syms;
04086   symtab_size *= sizeof (struct symbol_dictionary_record);
04087   som_symtab = bfd_zmalloc (symtab_size);
04088   if (som_symtab == NULL && symtab_size != 0)
04089     goto error_return;
04090 
04091   /* Walk over each symbol.  */
04092   for (i = 0; i < num_syms; i++)
04093     {
04094       struct som_misc_symbol_info info;
04095 
04096       /* This is really an index into the symbol strings table.
04097         By the time we get here, the index has already been
04098         computed and stored into the name field in the BFD symbol.  */
04099       som_symtab[i].name.n_strx = som_symbol_data(bfd_syms[i])->stringtab_offset;
04100 
04101       /* Derive SOM information from the BFD symbol.  */
04102       som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
04103 
04104       /* Now use it.  */
04105       som_symtab[i].symbol_type = info.symbol_type;
04106       som_symtab[i].symbol_scope = info.symbol_scope;
04107       som_symtab[i].arg_reloc = info.arg_reloc;
04108       som_symtab[i].symbol_info = info.symbol_info;
04109       som_symtab[i].xleast = 3;
04110       som_symtab[i].symbol_value = info.symbol_value | info.priv_level;
04111       som_symtab[i].secondary_def = info.secondary_def;
04112       som_symtab[i].is_comdat = info.is_comdat;
04113       som_symtab[i].is_common = info.is_common;
04114       som_symtab[i].dup_common = info.dup_common;
04115     }
04116 
04117   /* Everything is ready, seek to the right location and
04118      scribble out the symbol table.  */
04119   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
04120     return FALSE;
04121 
04122   if (bfd_bwrite ((void *) som_symtab, symtab_size, abfd) != symtab_size)
04123     goto error_return;
04124 
04125   if (som_symtab != NULL)
04126     free (som_symtab);
04127   return TRUE;
04128  error_return:
04129   if (som_symtab != NULL)
04130     free (som_symtab);
04131   return FALSE;
04132 }
04133 
04134 /* Write an object in SOM format.  */
04135 
04136 static bfd_boolean
04137 som_write_object_contents (bfd *abfd)
04138 {
04139   if (! abfd->output_has_begun)
04140     {
04141       /* Set up fixed parts of the file, space, and subspace headers.
04142         Notify the world that output has begun.  */
04143       som_prep_headers (abfd);
04144       abfd->output_has_begun = TRUE;
04145       /* Start writing the object file.  This include all the string
04146         tables, fixup streams, and other portions of the object file.  */
04147       som_begin_writing (abfd);
04148     }
04149 
04150   return som_finish_writing (abfd);
04151 }
04152 
04153 /* Read and save the string table associated with the given BFD.  */
04154 
04155 static bfd_boolean
04156 som_slurp_string_table (bfd *abfd)
04157 {
04158   char *stringtab;
04159   bfd_size_type amt;
04160 
04161   /* Use the saved version if its available.  */
04162   if (obj_som_stringtab (abfd) != NULL)
04163     return TRUE;
04164 
04165   /* I don't think this can currently happen, and I'm not sure it should
04166      really be an error, but it's better than getting unpredictable results
04167      from the host's malloc when passed a size of zero.  */
04168   if (obj_som_stringtab_size (abfd) == 0)
04169     {
04170       bfd_set_error (bfd_error_no_symbols);
04171       return FALSE;
04172     }
04173 
04174   /* Allocate and read in the string table.  */
04175   amt = obj_som_stringtab_size (abfd);
04176   stringtab = bfd_zmalloc (amt);
04177   if (stringtab == NULL)
04178     return FALSE;
04179 
04180   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
04181     return FALSE;
04182 
04183   if (bfd_bread (stringtab, amt, abfd) != amt)
04184     return FALSE;
04185 
04186   /* Save our results and return success.  */
04187   obj_som_stringtab (abfd) = stringtab;
04188   return TRUE;
04189 }
04190 
04191 /* Return the amount of data (in bytes) required to hold the symbol
04192    table for this object.  */
04193 
04194 static long
04195 som_get_symtab_upper_bound (bfd *abfd)
04196 {
04197   if (!som_slurp_symbol_table (abfd))
04198     return -1;
04199 
04200   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
04201 }
04202 
04203 /* Convert from a SOM subspace index to a BFD section.  */
04204 
04205 static asection *
04206 bfd_section_from_som_symbol (bfd *abfd, struct symbol_dictionary_record *symbol)
04207 {
04208   asection *section;
04209 
04210   /* The meaning of the symbol_info field changes for functions
04211      within executables.  So only use the quick symbol_info mapping for
04212      incomplete objects and non-function symbols in executables.  */
04213   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
04214       || (symbol->symbol_type != ST_ENTRY
04215          && symbol->symbol_type != ST_PRI_PROG
04216          && symbol->symbol_type != ST_SEC_PROG
04217          && symbol->symbol_type != ST_MILLICODE))
04218     {
04219       int index = symbol->symbol_info;
04220 
04221       for (section = abfd->sections; section != NULL; section = section->next)
04222        if (section->target_index == index && som_is_subspace (section))
04223          return section;
04224     }
04225   else
04226     {
04227       unsigned int value = symbol->symbol_value;
04228 
04229       /* For executables we will have to use the symbol's address and
04230         find out what section would contain that address.   Yuk.  */
04231       for (section = abfd->sections; section; section = section->next)
04232        if (value >= section->vma
04233            && value <= section->vma + section->size
04234            && som_is_subspace (section))
04235          return section;
04236     }
04237 
04238   /* Could be a symbol from an external library (such as an OMOS
04239      shared library).  Don't abort.  */
04240   return bfd_abs_section_ptr;
04241 }
04242 
04243 /* Read and save the symbol table associated with the given BFD.  */
04244 
04245 static unsigned int
04246 som_slurp_symbol_table (bfd *abfd)
04247 {
04248   int symbol_count = bfd_get_symcount (abfd);
04249   int symsize = sizeof (struct symbol_dictionary_record);
04250   char *stringtab;
04251   struct symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
04252   som_symbol_type *sym, *symbase;
04253   bfd_size_type amt;
04254 
04255   /* Return saved value if it exists.  */
04256   if (obj_som_symtab (abfd) != NULL)
04257     goto successful_return;
04258 
04259   /* Special case.  This is *not* an error.  */
04260   if (symbol_count == 0)
04261     goto successful_return;
04262 
04263   if (!som_slurp_string_table (abfd))
04264     goto error_return;
04265 
04266   stringtab = obj_som_stringtab (abfd);
04267 
04268   amt = symbol_count;
04269   amt *= sizeof (som_symbol_type);
04270   symbase = bfd_zmalloc (amt);
04271   if (symbase == NULL)
04272     goto error_return;
04273 
04274   /* Read in the external SOM representation.  */
04275   amt = symbol_count;
04276   amt *= symsize;
04277   buf = bfd_malloc (amt);
04278   if (buf == NULL && amt != 0)
04279     goto error_return;
04280   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
04281     goto error_return;
04282   if (bfd_bread (buf, amt, abfd) != amt)
04283     goto error_return;
04284 
04285   /* Iterate over all the symbols and internalize them.  */
04286   endbufp = buf + symbol_count;
04287   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
04288     {
04289       /* I don't think we care about these.  */
04290       if (bufp->symbol_type == ST_SYM_EXT
04291          || bufp->symbol_type == ST_ARG_EXT)
04292        continue;
04293 
04294       /* Set some private data we care about.  */
04295       if (bufp->symbol_type == ST_NULL)
04296        som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
04297       else if (bufp->symbol_type == ST_ABSOLUTE)
04298        som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
04299       else if (bufp->symbol_type == ST_DATA)
04300        som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
04301       else if (bufp->symbol_type == ST_CODE)
04302        som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
04303       else if (bufp->symbol_type == ST_PRI_PROG)
04304        som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
04305       else if (bufp->symbol_type == ST_SEC_PROG)
04306        som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
04307       else if (bufp->symbol_type == ST_ENTRY)
04308        som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
04309       else if (bufp->symbol_type == ST_MILLICODE)
04310        som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
04311       else if (bufp->symbol_type == ST_PLABEL)
04312        som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
04313       else
04314        som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
04315       som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc = bufp->arg_reloc;
04316 
04317       /* Some reasonable defaults.  */
04318       sym->symbol.the_bfd = abfd;
04319       sym->symbol.name = bufp->name.n_strx + stringtab;
04320       sym->symbol.value = bufp->symbol_value;
04321       sym->symbol.section = 0;
04322       sym->symbol.flags = 0;
04323 
04324       switch (bufp->symbol_type)
04325        {
04326        case ST_ENTRY:
04327        case ST_MILLICODE:
04328          sym->symbol.flags |= BSF_FUNCTION;
04329          som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
04330            sym->symbol.value & 0x3;
04331          sym->symbol.value &= ~0x3;
04332          break;
04333 
04334        case ST_STUB:
04335        case ST_CODE:
04336        case ST_PRI_PROG:
04337        case ST_SEC_PROG:
04338          som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
04339            sym->symbol.value & 0x3;
04340          sym->symbol.value &= ~0x3;
04341          /* If the symbol's scope is SS_UNSAT, then these are
04342             undefined function symbols.  */
04343          if (bufp->symbol_scope == SS_UNSAT)
04344            sym->symbol.flags |= BSF_FUNCTION;
04345 
04346        default:
04347          break;
04348        }
04349 
04350       /* Handle scoping and section information.  */
04351       switch (bufp->symbol_scope)
04352        {
04353        /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
04354           so the section associated with this symbol can't be known.  */
04355        case SS_EXTERNAL:
04356          if (bufp->symbol_type != ST_STORAGE)
04357            sym->symbol.section = bfd_und_section_ptr;
04358          else
04359            sym->symbol.section = bfd_com_section_ptr;
04360          sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
04361          break;
04362 
04363        case SS_UNSAT:
04364          if (bufp->symbol_type != ST_STORAGE)
04365            sym->symbol.section = bfd_und_section_ptr;
04366          else
04367            sym->symbol.section = bfd_com_section_ptr;
04368          break;
04369 
04370        case SS_UNIVERSAL:
04371          sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
04372          sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
04373          sym->symbol.value -= sym->symbol.section->vma;
04374          break;
04375 
04376        case SS_LOCAL:
04377          sym->symbol.flags |= BSF_LOCAL;
04378          sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
04379          sym->symbol.value -= sym->symbol.section->vma;
04380          break;
04381        }
04382 
04383       /* Check for a weak symbol.  */
04384       if (bufp->secondary_def)
04385        sym->symbol.flags |= BSF_WEAK;
04386 
04387       /* Mark section symbols and symbols used by the debugger.
04388         Note $START$ is a magic code symbol, NOT a section symbol.  */
04389       if (sym->symbol.name[0] == '$'
04390          && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
04391          && !strcmp (sym->symbol.name, sym->symbol.section->name))
04392        sym->symbol.flags |= BSF_SECTION_SYM;
04393       else if (CONST_STRNEQ (sym->symbol.name, "L$0\002"))
04394        {
04395          sym->symbol.flags |= BSF_SECTION_SYM;
04396          sym->symbol.name = sym->symbol.section->name;
04397        }
04398       else if (CONST_STRNEQ (sym->symbol.name, "L$0\001"))
04399        sym->symbol.flags |= BSF_DEBUGGING;
04400 
04401       /* Note increment at bottom of loop, since we skip some symbols
04402         we can not include it as part of the for statement.  */
04403       sym++;
04404     }
04405 
04406   /* We modify the symbol count to record the number of BFD symbols we
04407      created.  */
04408   bfd_get_symcount (abfd) = sym - symbase;
04409 
04410   /* Save our results and return success.  */
04411   obj_som_symtab (abfd) = symbase;
04412  successful_return:
04413   if (buf != NULL)
04414     free (buf);
04415   return (TRUE);
04416 
04417  error_return:
04418   if (buf != NULL)
04419     free (buf);
04420   return FALSE;
04421 }
04422 
04423 /* Canonicalize a SOM symbol table.  Return the number of entries
04424    in the symbol table.  */
04425 
04426 static long
04427 som_canonicalize_symtab (bfd *abfd, asymbol **location)
04428 {
04429   int i;
04430   som_symbol_type *symbase;
04431 
04432   if (!som_slurp_symbol_table (abfd))
04433     return -1;
04434 
04435   i = bfd_get_symcount (abfd);
04436   symbase = obj_som_symtab (abfd);
04437 
04438   for (; i > 0; i--, location++, symbase++)
04439     *location = &symbase->symbol;
04440 
04441   /* Final null pointer.  */
04442   *location = 0;
04443   return (bfd_get_symcount (abfd));
04444 }
04445 
04446 /* Make a SOM symbol.  There is nothing special to do here.  */
04447 
04448 static asymbol *
04449 som_make_empty_symbol (bfd *abfd)
04450 {
04451   bfd_size_type amt = sizeof (som_symbol_type);
04452   som_symbol_type *new = bfd_zalloc (abfd, amt);
04453 
04454   if (new == NULL)
04455     return NULL;
04456   new->symbol.the_bfd = abfd;
04457 
04458   return &new->symbol;
04459 }
04460 
04461 /* Print symbol information.  */
04462 
04463 static void
04464 som_print_symbol (bfd *abfd,
04465                 void *afile,
04466                 asymbol *symbol,
04467                 bfd_print_symbol_type how)
04468 {
04469   FILE *file = (FILE *) afile;
04470 
04471   switch (how)
04472     {
04473     case bfd_print_symbol_name:
04474       fprintf (file, "%s", symbol->name);
04475       break;
04476     case bfd_print_symbol_more:
04477       fprintf (file, "som ");
04478       fprintf_vma (file, symbol->value);
04479       fprintf (file, " %lx", (long) symbol->flags);
04480       break;
04481     case bfd_print_symbol_all:
04482       {
04483        const char *section_name;
04484 
04485        section_name = symbol->section ? symbol->section->name : "(*none*)";
04486        bfd_print_symbol_vandf (abfd, (void *) file, symbol);
04487        fprintf (file, " %s\t%s", section_name, symbol->name);
04488        break;
04489       }
04490     }
04491 }
04492 
04493 static bfd_boolean
04494 som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
04495                           const char *name)
04496 {
04497   return name[0] == 'L' && name[1] == '$';
04498 }
04499 
04500 /* Count or process variable-length SOM fixup records.
04501 
04502    To avoid code duplication we use this code both to compute the number
04503    of relocations requested by a stream, and to internalize the stream.
04504 
04505    When computing the number of relocations requested by a stream the
04506    variables rptr, section, and symbols have no meaning.
04507 
04508    Return the number of relocations requested by the fixup stream.  When
04509    not just counting
04510 
04511    This needs at least two or three more passes to get it cleaned up.  */
04512 
04513 static unsigned int
04514 som_set_reloc_info (unsigned char *fixup,
04515                   unsigned int end,
04516                   arelent *internal_relocs,
04517                   asection *section,
04518                   asymbol **symbols,
04519                   bfd_boolean just_count)
04520 {
04521   unsigned int op, varname, deallocate_contents = 0;
04522   unsigned char *end_fixups = &fixup[end];
04523   const struct fixup_format *fp;
04524   const char *cp;
04525   unsigned char *save_fixup;
04526   int variables[26], stack[20], c, v, count, prev_fixup, *sp, saved_unwind_bits;
04527   const int *subop;
04528   arelent *rptr = internal_relocs;
04529   unsigned int offset = 0;
04530 
04531 #define       var(c)        variables[(c) - 'A']
04532 #define       push(v)              (*sp++ = (v))
04533 #define       pop()         (*--sp)
04534 #define       emptystack()  (sp == stack)
04535 
04536   som_initialize_reloc_queue (reloc_queue);
04537   memset (variables, 0, sizeof (variables));
04538   memset (stack, 0, sizeof (stack));
04539   count = 0;
04540   prev_fixup = 0;
04541   saved_unwind_bits = 0;
04542   sp = stack;
04543 
04544   while (fixup < end_fixups)
04545     {
04546       /* Save pointer to the start of this fixup.  We'll use
04547         it later to determine if it is necessary to put this fixup
04548         on the queue.  */
04549       save_fixup = fixup;
04550 
04551       /* Get the fixup code and its associated format.  */
04552       op = *fixup++;
04553       fp = &som_fixup_formats[op];
04554 
04555       /* Handle a request for a previous fixup.  */
04556       if (*fp->format == 'P')
04557        {
04558          /* Get pointer to the beginning of the prev fixup, move
04559             the repeated fixup to the head of the queue.  */
04560          fixup = reloc_queue[fp->D].reloc;
04561          som_reloc_queue_fix (reloc_queue, fp->D);
04562          prev_fixup = 1;
04563 
04564          /* Get the fixup code and its associated format.  */
04565          op = *fixup++;
04566          fp = &som_fixup_formats[op];
04567        }
04568 
04569       /* If this fixup will be passed to BFD, set some reasonable defaults.  */
04570       if (! just_count
04571          && som_hppa_howto_table[op].type != R_NO_RELOCATION
04572          && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
04573        {
04574          rptr->address = offset;
04575          rptr->howto = &som_hppa_howto_table[op];
04576          rptr->addend = 0;
04577          rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
04578        }
04579 
04580       /* Set default input length to 0.  Get the opcode class index
04581         into D.  */
04582       var ('L') = 0;
04583       var ('D') = fp->D;
04584       var ('U') = saved_unwind_bits;
04585 
04586       /* Get the opcode format.  */
04587       cp = fp->format;
04588 
04589       /* Process the format string.  Parsing happens in two phases,
04590         parse RHS, then assign to LHS.  Repeat until no more
04591         characters in the format string.  */
04592       while (*cp)
04593        {
04594          /* The variable this pass is going to compute a value for.  */
04595          varname = *cp++;
04596 
04597          /* Start processing RHS.  Continue until a NULL or '=' is found.  */
04598          do
04599            {
04600              c = *cp++;
04601 
04602              /* If this is a variable, push it on the stack.  */
04603              if (ISUPPER (c))
04604               push (var (c));
04605 
04606              /* If this is a lower case letter, then it represents
04607                additional data from the fixup stream to be pushed onto
04608                the stack.  */
04609              else if (ISLOWER (c))
04610               {
04611                 int bits = (c - 'a') * 8;
04612                 for (v = 0; c > 'a'; --c)
04613                   v = (v << 8) | *fixup++;
04614                 if (varname == 'V')
04615                   v = sign_extend (v, bits);
04616                 push (v);
04617               }
04618 
04619              /* A decimal constant.  Push it on the stack.  */
04620              else if (ISDIGIT (c))
04621               {
04622                 v = c - '0';
04623                 while (ISDIGIT (*cp))
04624                   v = (v * 10) + (*cp++ - '0');
04625                 push (v);
04626               }
04627              else
04628               /* An operator.  Pop two two values from the stack and
04629                  use them as operands to the given operation.  Push
04630                  the result of the operation back on the stack.  */
04631               switch (c)
04632                 {
04633                 case '+':
04634                   v = pop ();
04635                   v += pop ();
04636                   push (v);
04637                   break;
04638                 case '*':
04639                   v = pop ();
04640                   v *= pop ();
04641                   push (v);
04642                   break;
04643                 case '<':
04644                   v = pop ();
04645                   v = pop () << v;
04646                   push (v);
04647                   break;
04648                 default:
04649                   abort ();
04650                 }
04651            }
04652          while (*cp && *cp != '=');
04653 
04654          /* Move over the equal operator.  */
04655          cp++;
04656 
04657          /* Pop the RHS off the stack.  */
04658          c = pop ();
04659 
04660          /* Perform the assignment.  */
04661          var (varname) = c;
04662 
04663          /* Handle side effects. and special 'O' stack cases.  */
04664          switch (varname)
04665            {
04666            /* Consume some bytes from the input space.  */
04667            case 'L':
04668              offset += c;
04669              break;
04670            /* A symbol to use in the relocation.  Make a note
04671               of this if we are not just counting.  */
04672            case 'S':
04673              if (! just_count)
04674               rptr->sym_ptr_ptr = &symbols[c];
04675              break;
04676            /* Argument relocation bits for a function call.  */
04677            case 'R':
04678              if (! just_count)
04679               {
04680                 unsigned int tmp = var ('R');
04681                 rptr->addend = 0;
04682 
04683                 if ((som_hppa_howto_table[op].type == R_PCREL_CALL
04684                      && R_PCREL_CALL + 10 > op)
04685                     || (som_hppa_howto_table[op].type == R_ABS_CALL
04686                        && R_ABS_CALL + 10 > op))
04687                   {
04688                     /* Simple encoding.  */
04689                     if (tmp > 4)
04690                      {
04691                        tmp -= 5;
04692                        rptr->addend |= 1;
04693                      }
04694                     if (tmp == 4)
04695                      rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
04696                     else if (tmp == 3)
04697                      rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
04698                     else if (tmp == 2)
04699                      rptr->addend |= 1 << 8 | 1 << 6;
04700                     else if (tmp == 1)
04701                      rptr->addend |= 1 << 8;
04702                   }
04703                 else
04704                   {
04705                     unsigned int tmp1, tmp2;
04706 
04707                     /* First part is easy -- low order two bits are
04708                       directly copied, then shifted away.  */
04709                     rptr->addend = tmp & 0x3;
04710                     tmp >>= 2;
04711 
04712                     /* Diving the result by 10 gives us the second
04713                       part.  If it is 9, then the first two words
04714                       are a double precision paramater, else it is
04715                       3 * the first arg bits + the 2nd arg bits.  */
04716                     tmp1 = tmp / 10;
04717                     tmp -= tmp1 * 10;
04718                     if (tmp1 == 9)
04719                      rptr->addend += (0xe << 6);
04720                     else
04721                      {
04722                        /* Get the two pieces.  */
04723                        tmp2 = tmp1 / 3;
04724                        tmp1 -= tmp2 * 3;
04725                        /* Put them in the addend.  */
04726                        rptr->addend += (tmp2 << 8) + (tmp1 << 6);
04727                      }
04728 
04729                     /* What's left is the third part.  It's unpacked
04730                       just like the second.  */
04731                     if (tmp == 9)
04732                      rptr->addend += (0xe << 2);
04733                     else
04734                      {
04735                        tmp2 = tmp / 3;
04736                        tmp -= tmp2 * 3;
04737                        rptr->addend += (tmp2 << 4) + (tmp << 2);
04738                      }
04739                   }
04740                 rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
04741               }
04742              break;
04743            /* Handle the linker expression stack.  */
04744            case 'O':
04745              switch (op)
04746               {
04747               case R_COMP1:
04748                 subop = comp1_opcodes;
04749                 break;
04750               case R_COMP2:
04751                 subop = comp2_opcodes;
04752                 break;
04753               case R_COMP3:
04754                 subop = comp3_opcodes;
04755                 break;
04756               default:
04757                 abort ();
04758               }
04759              while (*subop <= (unsigned char) c)
04760               ++subop;
04761              --subop;
04762              break;
04763            /* The lower 32unwind bits must be persistent.  */
04764            case 'U':
04765              saved_unwind_bits = var ('U');
04766              break;
04767 
04768            default:
04769              break;
04770            }
04771        }
04772 
04773       /* If we used a previous fixup, clean up after it.  */
04774       if (prev_fixup)
04775        {
04776          fixup = save_fixup + 1;
04777          prev_fixup = 0;
04778        }
04779       /* Queue it.  */
04780       else if (fixup > save_fixup + 1)
04781        som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
04782 
04783       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
04784         fixups to BFD.  */
04785       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
04786          && som_hppa_howto_table[op].type != R_NO_RELOCATION)
04787        {
04788          /* Done with a single reloction. Loop back to the top.  */
04789          if (! just_count)
04790            {
04791              if (som_hppa_howto_table[op].type == R_ENTRY)
04792               rptr->addend = var ('T');
04793              else if (som_hppa_howto_table[op].type == R_EXIT)
04794               rptr->addend = var ('U');
04795              else if (som_hppa_howto_table[op].type == R_PCREL_CALL
04796                      || som_hppa_howto_table[op].type == R_ABS_CALL)
04797               ;
04798              else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
04799               {
04800                 /* Try what was specified in R_DATA_OVERRIDE first
04801                    (if anything).  Then the hard way using the
04802                    section contents.  */
04803                 rptr->addend = var ('V');
04804 
04805                 if (rptr->addend == 0 && !section->contents)
04806                   {
04807                     /* Got to read the damn contents first.  We don't
04808                       bother saving the contents (yet).  Add it one
04809                       day if the need arises.  */
04810                     bfd_byte *contents;
04811                     if (!bfd_malloc_and_get_section (section->owner, section,
04812                                                  &contents))
04813                      {
04814                        if (contents != NULL)
04815                          free (contents);
04816                        return (unsigned) -1;
04817                      }
04818                     section->contents = contents;
04819                     deallocate_contents = 1;
04820                   }
04821                 else if (rptr->addend == 0)
04822                   rptr->addend = bfd_get_32 (section->owner,
04823                                           (section->contents
04824                                           + offset - var ('L')));
04825 
04826               }
04827              else
04828               rptr->addend = var ('V');
04829              rptr++;
04830            }
04831          count++;
04832          /* Now that we've handled a "full" relocation, reset
04833             some state.  */
04834          memset (variables, 0, sizeof (variables));
04835          memset (stack, 0, sizeof (stack));
04836        }
04837     }
04838   if (deallocate_contents)
04839     free (section->contents);
04840 
04841   return count;
04842 
04843 #undef var
04844 #undef push
04845 #undef pop
04846 #undef emptystack
04847 }
04848 
04849 /* Read in the relocs (aka fixups in SOM terms) for a section.
04850 
04851    som_get_reloc_upper_bound calls this routine with JUST_COUNT
04852    set to TRUE to indicate it only needs a count of the number
04853    of actual relocations.  */
04854 
04855 static bfd_boolean
04856 som_slurp_reloc_table (bfd *abfd,
04857                      asection *section,
04858                      asymbol **symbols,
04859                      bfd_boolean just_count)
04860 {
04861   unsigned char *external_relocs;
04862   unsigned int fixup_stream_size;
04863   arelent *internal_relocs;
04864   unsigned int num_relocs;
04865   bfd_size_type amt;
04866 
04867   fixup_stream_size = som_section_data (section)->reloc_size;
04868   /* If there were no relocations, then there is nothing to do.  */
04869   if (section->reloc_count == 0)
04870     return TRUE;
04871 
04872   /* If reloc_count is -1, then the relocation stream has not been
04873      parsed.  We must do so now to know how many relocations exist.  */
04874   if (section->reloc_count == (unsigned) -1)
04875     {
04876       amt = fixup_stream_size;
04877       external_relocs = bfd_malloc (amt);
04878       if (external_relocs == NULL)
04879        return FALSE;
04880       /* Read in the external forms.  */
04881       if (bfd_seek (abfd,
04882                   obj_som_reloc_filepos (abfd) + section->rel_filepos,
04883                   SEEK_SET)
04884          != 0)
04885        return FALSE;
04886       if (bfd_bread (external_relocs, amt, abfd) != amt)
04887        return FALSE;
04888 
04889       /* Let callers know how many relocations found.
04890         also save the relocation stream as we will
04891         need it again.  */
04892       section->reloc_count = som_set_reloc_info (external_relocs,
04893                                            fixup_stream_size,
04894                                            NULL, NULL, NULL, TRUE);
04895 
04896       som_section_data (section)->reloc_stream = external_relocs;
04897     }
04898 
04899   /* If the caller only wanted a count, then return now.  */
04900   if (just_count)
04901     return TRUE;
04902 
04903   num_relocs = section->reloc_count;
04904   external_relocs = som_section_data (section)->reloc_stream;
04905   /* Return saved information about the relocations if it is available.  */
04906   if (section->relocation != NULL)
04907     return TRUE;
04908 
04909   amt = num_relocs;
04910   amt *= sizeof (arelent);
04911   internal_relocs = bfd_zalloc (abfd, (amt));
04912   if (internal_relocs == NULL)
04913     return FALSE;
04914 
04915   /* Process and internalize the relocations.  */
04916   som_set_reloc_info (external_relocs, fixup_stream_size,
04917                     internal_relocs, section, symbols, FALSE);
04918 
04919   /* We're done with the external relocations.  Free them.  */
04920   free (external_relocs);
04921   som_section_data (section)->reloc_stream = NULL;
04922 
04923   /* Save our results and return success.  */
04924   section->relocation = internal_relocs;
04925   return TRUE;
04926 }
04927 
04928 /* Return the number of bytes required to store the relocation
04929    information associated with the given section.  */
04930 
04931 static long
04932 som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
04933 {
04934   /* If section has relocations, then read in the relocation stream
04935      and parse it to determine how many relocations exist.  */
04936   if (asect->flags & SEC_RELOC)
04937     {
04938       if (! som_slurp_reloc_table (abfd, asect, NULL, TRUE))
04939        return -1;
04940       return (asect->reloc_count + 1) * sizeof (arelent *);
04941     }
04942   /* There are no relocations.  */
04943   return 0;
04944 }
04945 
04946 /* Convert relocations from SOM (external) form into BFD internal
04947    form.  Return the number of relocations.  */
04948 
04949 static long
04950 som_canonicalize_reloc (bfd *abfd,
04951                      sec_ptr section,
04952                      arelent **relptr,
04953                      asymbol **symbols)
04954 {
04955   arelent *tblptr;
04956   int count;
04957 
04958   if (! som_slurp_reloc_table (abfd, section, symbols, FALSE))
04959     return -1;
04960 
04961   count = section->reloc_count;
04962   tblptr = section->relocation;
04963 
04964   while (count--)
04965     *relptr++ = tblptr++;
04966 
04967   *relptr = NULL;
04968   return section->reloc_count;
04969 }
04970 
04971 extern const bfd_target som_vec;
04972 
04973 /* A hook to set up object file dependent section information.  */
04974 
04975 static bfd_boolean
04976 som_new_section_hook (bfd *abfd, asection *newsect)
04977 {
04978   if (!newsect->used_by_bfd)
04979     {
04980       bfd_size_type amt = sizeof (struct som_section_data_struct);
04981 
04982       newsect->used_by_bfd = bfd_zalloc (abfd, amt);
04983       if (!newsect->used_by_bfd)
04984        return FALSE;
04985     }
04986   newsect->alignment_power = 3;
04987 
04988   /* We allow more than three sections internally.  */
04989   return _bfd_generic_new_section_hook (abfd, newsect);
04990 }
04991 
04992 /* Copy any private info we understand from the input symbol
04993    to the output symbol.  */
04994 
04995 static bfd_boolean
04996 som_bfd_copy_private_symbol_data (bfd *ibfd,
04997                               asymbol *isymbol,
04998                               bfd *obfd,
04999                               asymbol *osymbol)
05000 {
05001   struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
05002   struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
05003 
05004   /* One day we may try to grok other private data.  */
05005   if (ibfd->xvec->flavour != bfd_target_som_flavour
05006       || obfd->xvec->flavour != bfd_target_som_flavour)
05007     return FALSE;
05008 
05009   /* The only private information we need to copy is the argument relocation
05010      bits.  */
05011   output_symbol->tc_data.ap.hppa_arg_reloc =
05012     input_symbol->tc_data.ap.hppa_arg_reloc;
05013 
05014   return TRUE;
05015 }
05016 
05017 /* Copy any private info we understand from the input section
05018    to the output section.  */
05019 
05020 static bfd_boolean
05021 som_bfd_copy_private_section_data (bfd *ibfd,
05022                                asection *isection,
05023                                bfd *obfd,
05024                                asection *osection)
05025 {
05026   bfd_size_type amt;
05027 
05028   /* One day we may try to grok other private data.  */
05029   if (ibfd->xvec->flavour != bfd_target_som_flavour
05030       || obfd->xvec->flavour != bfd_target_som_flavour
05031       || (!som_is_space (isection) && !som_is_subspace (isection)))
05032     return TRUE;
05033 
05034   amt = sizeof (struct som_copyable_section_data_struct);
05035   som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
05036   if (som_section_data (osection)->copy_data == NULL)
05037     return FALSE;
05038 
05039   memcpy (som_section_data (osection)->copy_data,
05040          som_section_data (isection)->copy_data,
05041          sizeof (struct som_copyable_section_data_struct));
05042 
05043   /* Reparent if necessary.  */
05044   if (som_section_data (osection)->copy_data->container)
05045     som_section_data (osection)->copy_data->container =
05046       som_section_data (osection)->copy_data->container->output_section;
05047 
05048   return TRUE;
05049 }
05050 
05051 /* Copy any private info we understand from the input bfd
05052    to the output bfd.  */
05053 
05054 static bfd_boolean
05055 som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
05056 {
05057   /* One day we may try to grok other private data.  */
05058   if (ibfd->xvec->flavour != bfd_target_som_flavour
05059       || obfd->xvec->flavour != bfd_target_som_flavour)
05060     return TRUE;
05061 
05062   /* Allocate some memory to hold the data we need.  */
05063   obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
05064   if (obj_som_exec_data (obfd) == NULL)
05065     return FALSE;
05066 
05067   /* Now copy the data.  */
05068   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
05069          sizeof (struct som_exec_data));
05070 
05071   return TRUE;
05072 }
05073 
05074 /* Display the SOM header.  */
05075 
05076 static bfd_boolean
05077 som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
05078 {
05079   struct som_exec_auxhdr *exec_header;
05080   struct aux_id* auxhdr;
05081   FILE *f;
05082 
05083   f = (FILE *) farg;
05084 
05085   exec_header = obj_som_exec_hdr (abfd);
05086   if (exec_header)
05087     {
05088       fprintf (f, _("\nExec Auxiliary Header\n"));
05089       fprintf (f, "  flags              ");
05090       auxhdr = &exec_header->som_auxhdr;
05091       if (auxhdr->mandatory)
05092        fprintf (f, "mandatory ");
05093       if (auxhdr->copy)
05094        fprintf (f, "copy ");
05095       if (auxhdr->append)
05096        fprintf (f, "append ");
05097       if (auxhdr->ignore)
05098        fprintf (f, "ignore ");
05099       fprintf (f, "\n");
05100       fprintf (f, "  type               %#x\n", auxhdr->type);
05101       fprintf (f, "  length             %#x\n", auxhdr->length);
05102 
05103       /* Note that, depending on the HP-UX version, the following fields can be
05104          either ints, or longs.  */
05105 
05106       fprintf (f, "  text size          %#lx\n", (long) exec_header->exec_tsize);
05107       fprintf (f, "  text memory offset %#lx\n", (long) exec_header->exec_tmem);
05108       fprintf (f, "  text file offset   %#lx\n", (long) exec_header->exec_tfile);
05109       fprintf (f, "  data size          %#lx\n", (long) exec_header->exec_dsize);
05110       fprintf (f, "  data memory offset %#lx\n", (long) exec_header->exec_dmem);
05111       fprintf (f, "  data file offset   %#lx\n", (long) exec_header->exec_dfile);
05112       fprintf (f, "  bss size           %#lx\n", (long) exec_header->exec_bsize);
05113       fprintf (f, "  entry point        %#lx\n", (long) exec_header->exec_entry);
05114       fprintf (f, "  loader flags       %#lx\n", (long) exec_header->exec_flags);
05115       fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
05116     }
05117 
05118   return TRUE;
05119 }
05120 
05121 /* Set backend info for sections which can not be described
05122    in the BFD data structures.  */
05123 
05124 bfd_boolean
05125 bfd_som_set_section_attributes (asection *section,
05126                             int defined,
05127                             int private,
05128                             unsigned int sort_key,
05129                             int spnum)
05130 {
05131   /* Allocate memory to hold the magic information.  */
05132   if (som_section_data (section)->copy_data == NULL)
05133     {
05134       bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
05135 
05136       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
05137       if (som_section_data (section)->copy_data == NULL)
05138        return FALSE;
05139     }
05140   som_section_data (section)->copy_data->sort_key = sort_key;
05141   som_section_data (section)->copy_data->is_defined = defined;
05142   som_section_data (section)->copy_data->is_private = private;
05143   som_section_data (section)->copy_data->container = section;
05144   som_section_data (section)->copy_data->space_number = spnum;
05145   return TRUE;
05146 }
05147 
05148 /* Set backend info for subsections which can not be described
05149    in the BFD data structures.  */
05150 
05151 bfd_boolean
05152 bfd_som_set_subsection_attributes (asection *section,
05153                                asection *container,
05154                                int access,
05155                                unsigned int sort_key,
05156                                int quadrant,
05157                                int comdat,
05158                                int common,
05159                                int dup_common)
05160 {
05161   /* Allocate memory to hold the magic information.  */
05162   if (som_section_data (section)->copy_data == NULL)
05163     {
05164       bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
05165 
05166       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
05167       if (som_section_data (section)->copy_data == NULL)
05168        return FALSE;
05169     }
05170   som_section_data (section)->copy_data->sort_key = sort_key;
05171   som_section_data (section)->copy_data->access_control_bits = access;
05172   som_section_data (section)->copy_data->quadrant = quadrant;
05173   som_section_data (section)->copy_data->container = container;
05174   som_section_data (section)->copy_data->is_comdat = comdat;
05175   som_section_data (section)->copy_data->is_common = common;
05176   som_section_data (section)->copy_data->dup_common = dup_common;
05177   return TRUE;
05178 }
05179 
05180 /* Set the full SOM symbol type.  SOM needs far more symbol information
05181    than any other object file format I'm aware of.  It is mandatory
05182    to be able to know if a symbol is an entry point, millicode, data,
05183    code, absolute, storage request, or procedure label.  If you get
05184    the symbol type wrong your program will not link.  */
05185 
05186 void
05187 bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
05188 {
05189   som_symbol_data (symbol)->som_type = type;
05190 }
05191 
05192 /* Attach an auxiliary header to the BFD backend so that it may be
05193    written into the object file.  */
05194 
05195 bfd_boolean
05196 bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
05197 {
05198   bfd_size_type amt;
05199 
05200   if (type == VERSION_AUX_ID)
05201     {
05202       size_t len = strlen (string);
05203       int pad = 0;
05204 
05205       if (len % 4)
05206        pad = (4 - (len % 4));
05207       amt = sizeof (struct aux_id) + sizeof (unsigned int) + len + pad;
05208       obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
05209       if (!obj_som_version_hdr (abfd))
05210        return FALSE;
05211       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
05212       obj_som_version_hdr (abfd)->header_id.length = len + pad;
05213       obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
05214       obj_som_version_hdr (abfd)->string_length = len;
05215       strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
05216     }
05217   else if (type == COPYRIGHT_AUX_ID)
05218     {
05219       int len = strlen (string);
05220       int pad = 0;
05221 
05222       if (len % 4)
05223        pad = (4 - (len % 4));
05224       amt = sizeof (struct aux_id) + sizeof (unsigned int) + len + pad;
05225       obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
05226       if (!obj_som_copyright_hdr (abfd))
05227        return FALSE;
05228       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
05229       obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
05230       obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
05231       obj_som_copyright_hdr (abfd)->string_length = len;
05232       strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
05233     }
05234   return TRUE;
05235 }
05236 
05237 /* Attach a compilation unit header to the BFD backend so that it may be
05238    written into the object file.  */
05239 
05240 bfd_boolean
05241 bfd_som_attach_compilation_unit (bfd *abfd,
05242                              const char *name,
05243                              const char *language_name,
05244                              const char *product_id,
05245                              const char *version_id)
05246 {
05247   COMPUNIT *n = (COMPUNIT *) bfd_zalloc (abfd, (bfd_size_type) COMPUNITSZ);
05248 
05249   if (n == NULL)
05250     return FALSE;
05251 
05252 #define STRDUP(f) \
05253   if (f != NULL) \
05254     { \
05255       n->f.n_name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
05256       if (n->f.n_name == NULL) \
05257        return FALSE; \
05258       strcpy (n->f.n_name, f); \
05259     }
05260 
05261   STRDUP (name);
05262   STRDUP (language_name);
05263   STRDUP (product_id);
05264   STRDUP (version_id);
05265 
05266 #undef STRDUP
05267 
05268   obj_som_compilation_unit (abfd) = n;
05269 
05270   return TRUE;
05271 }
05272 
05273 static bfd_boolean
05274 som_get_section_contents (bfd *abfd,
05275                        sec_ptr section,
05276                        void *location,
05277                        file_ptr offset,
05278                        bfd_size_type count)
05279 {
05280   if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
05281     return TRUE;
05282   if ((bfd_size_type) (offset+count) > section->size
05283       || bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
05284       || bfd_bread (location, count, abfd) != count)
05285     return FALSE; /* On error.  */
05286   return TRUE;
05287 }
05288 
05289 static bfd_boolean
05290 som_set_section_contents (bfd *abfd,
05291                        sec_ptr section,
05292                        const void *location,
05293                        file_ptr offset,
05294                        bfd_size_type count)
05295 {
05296   if (! abfd->output_has_begun)
05297     {
05298       /* Set up fixed parts of the file, space, and subspace headers.
05299         Notify the world that output has begun.  */
05300       som_prep_headers (abfd);
05301       abfd->output_has_begun = TRUE;
05302       /* Start writing the object file.  This include all the string
05303         tables, fixup streams, and other portions of the object file.  */
05304       som_begin_writing (abfd);
05305     }
05306 
05307   /* Only write subspaces which have "real" contents (eg. the contents
05308      are not generated at run time by the OS).  */
05309   if (!som_is_subspace (section)
05310       || ((section->flags & SEC_HAS_CONTENTS) == 0))
05311     return TRUE;
05312 
05313   /* Seek to the proper offset within the object file and write the
05314      data.  */
05315   offset += som_section_data (section)->subspace_dict->file_loc_init_value;
05316   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
05317     return FALSE;
05318 
05319   if (bfd_bwrite (location, count, abfd) != count)
05320     return FALSE;
05321   return TRUE;
05322 }
05323 
05324 static bfd_boolean
05325 som_set_arch_mach (bfd *abfd,
05326                  enum bfd_architecture arch,
05327                  unsigned long machine)
05328 {
05329   /* Allow any architecture to be supported by the SOM backend.  */
05330   return bfd_default_set_arch_mach (abfd, arch, machine);
05331 }
05332 
05333 static bfd_boolean
05334 som_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
05335                      asection *section ATTRIBUTE_UNUSED,
05336                      asymbol **symbols ATTRIBUTE_UNUSED,
05337                      bfd_vma offset ATTRIBUTE_UNUSED,
05338                      const char **filename_ptr ATTRIBUTE_UNUSED,
05339                      const char **functionname_ptr ATTRIBUTE_UNUSED,
05340                      unsigned int *line_ptr ATTRIBUTE_UNUSED)
05341 {
05342   return FALSE;
05343 }
05344 
05345 static int
05346 som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
05347                   struct bfd_link_info *info ATTRIBUTE_UNUSED)
05348 {
05349   (*_bfd_error_handler) (_("som_sizeof_headers unimplemented"));
05350   fflush (stderr);
05351   abort ();
05352   return 0;
05353 }
05354 
05355 /* Return the single-character symbol type corresponding to
05356    SOM section S, or '?' for an unknown SOM section.  */
05357 
05358 static char
05359 som_section_type (const char *s)
05360 {
05361   const struct section_to_type *t;
05362 
05363   for (t = &stt[0]; t->section; t++)
05364     if (!strcmp (s, t->section))
05365       return t->type;
05366   return '?';
05367 }
05368 
05369 static int
05370 som_decode_symclass (asymbol *symbol)
05371 {
05372   char c;
05373 
05374   if (bfd_is_com_section (symbol->section))
05375     return 'C';
05376   if (bfd_is_und_section (symbol->section))
05377     {
05378       if (symbol->flags & BSF_WEAK)
05379        {
05380          /* If weak, determine if it's specifically an object
05381             or non-object weak.  */
05382          if (symbol->flags & BSF_OBJECT)
05383            return 'v';
05384          else
05385            return 'w';
05386        }
05387       else
05388         return 'U';
05389     }
05390   if (bfd_is_ind_section (symbol->section))
05391     return 'I';
05392   if (symbol->flags & BSF_WEAK)
05393     {
05394       /* If weak, determine if it's specifically an object
05395         or non-object weak.  */
05396       if (symbol->flags & BSF_OBJECT)
05397        return 'V';
05398       else
05399        return 'W';
05400     }
05401   if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
05402     return '?';
05403 
05404   if (bfd_is_abs_section (symbol->section)
05405       || (som_symbol_data (symbol) != NULL
05406          && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
05407     c = 'a';
05408   else if (symbol->section)
05409     c = som_section_type (symbol->section->name);
05410   else
05411     return '?';
05412   if (symbol->flags & BSF_GLOBAL)
05413     c = TOUPPER (c);
05414   return c;
05415 }
05416 
05417 /* Return information about SOM symbol SYMBOL in RET.  */
05418 
05419 static void
05420 som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
05421                    asymbol *symbol,
05422                    symbol_info *ret)
05423 {
05424   ret->type = som_decode_symclass (symbol);
05425   if (ret->type != 'U')
05426     ret->value = symbol->value + symbol->section->vma;
05427   else
05428     ret->value = 0;
05429   ret->name = symbol->name;
05430 }
05431 
05432 /* Count the number of symbols in the archive symbol table.  Necessary
05433    so that we can allocate space for all the carsyms at once.  */
05434 
05435 static bfd_boolean
05436 som_bfd_count_ar_symbols (bfd *abfd,
05437                        struct lst_header *lst_header,
05438                        symindex *count)
05439 {
05440   unsigned int i;
05441   unsigned int *hash_table = NULL;
05442   bfd_size_type amt;
05443   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
05444 
05445   amt = lst_header->hash_size;
05446   amt *= sizeof (unsigned int);
05447   hash_table = bfd_malloc (amt);
05448   if (hash_table == NULL && lst_header->hash_size != 0)
05449     goto error_return;
05450 
05451   /* Don't forget to initialize the counter!  */
05452   *count = 0;
05453 
05454   /* Read in the hash table.  The has table is an array of 32bit file offsets
05455      which point to the hash chains.  */
05456   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
05457     goto error_return;
05458 
05459   /* Walk each chain counting the number of symbols found on that particular
05460      chain.  */
05461   for (i = 0; i < lst_header->hash_size; i++)
05462     {
05463       struct lst_symbol_record lst_symbol;
05464 
05465       /* An empty chain has zero as it's file offset.  */
05466       if (hash_table[i] == 0)
05467        continue;
05468 
05469       /* Seek to the first symbol in this hash chain.  */
05470       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) != 0)
05471        goto error_return;
05472 
05473       /* Read in this symbol and update the counter.  */
05474       amt = sizeof (lst_symbol);
05475       if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
05476        goto error_return;
05477 
05478       (*count)++;
05479 
05480       /* Now iterate through the rest of the symbols on this chain.  */
05481       while (lst_symbol.next_entry)
05482        {
05483 
05484          /* Seek to the next symbol.  */
05485          if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
05486              != 0)
05487            goto error_return;
05488 
05489          /* Read the symbol in and update the counter.  */
05490          amt = sizeof (lst_symbol);
05491          if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
05492            goto error_return;
05493 
05494          (*count)++;
05495        }
05496     }
05497   if (hash_table != NULL)
05498     free (hash_table);
05499   return TRUE;
05500 
05501  error_return:
05502   if (hash_table != NULL)
05503     free (hash_table);
05504   return FALSE;
05505 }
05506 
05507 /* Fill in the canonical archive symbols (SYMS) from the archive described
05508    by ABFD and LST_HEADER.  */
05509 
05510 static bfd_boolean
05511 som_bfd_fill_in_ar_symbols (bfd *abfd,
05512                          struct lst_header *lst_header,
05513                          carsym **syms)
05514 {
05515   unsigned int i, len;
05516   carsym *set = syms[0];
05517   unsigned int *hash_table = NULL;
05518   struct som_entry *som_dict = NULL;
05519   bfd_size_type amt;
05520   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
05521 
05522   amt = lst_header->hash_size;
05523   amt *= sizeof (unsigned int);
05524   hash_table = bfd_malloc (amt);
05525   if (hash_table == NULL && lst_header->hash_size != 0)
05526     goto error_return;
05527 
05528   /* Read in the hash table.  The has table is an array of 32bit file offsets
05529      which point to the hash chains.  */
05530   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
05531     goto error_return;
05532 
05533   /* Seek to and read in the SOM dictionary.  We will need this to fill
05534      in the carsym's filepos field.  */
05535   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
05536     goto error_return;
05537 
05538   amt = lst_header->module_count;
05539   amt *= sizeof (struct som_entry);
05540   som_dict = bfd_malloc (amt);
05541   if (som_dict == NULL && lst_header->module_count != 0)
05542     goto error_return;
05543 
05544   if (bfd_bread ((void *) som_dict, amt, abfd) != amt)
05545     goto error_return;
05546 
05547   /* Walk each chain filling in the carsyms as we go along.  */
05548   for (i = 0; i < lst_header->hash_size; i++)
05549     {
05550       struct lst_symbol_record lst_symbol;
05551 
05552       /* An empty chain has zero as it's file offset.  */
05553       if (hash_table[i] == 0)
05554        continue;
05555 
05556       /* Seek to and read the first symbol on the chain.  */
05557       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) != 0)
05558        goto error_return;
05559 
05560       amt = sizeof (lst_symbol);
05561       if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
05562        goto error_return;
05563 
05564       /* Get the name of the symbol, first get the length which is stored
05565         as a 32bit integer just before the symbol.
05566 
05567         One might ask why we don't just read in the entire string table
05568         and index into it.  Well, according to the SOM ABI the string
05569         index can point *anywhere* in the archive to save space, so just
05570         using the string table would not be safe.  */
05571       if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
05572                          + lst_symbol.name.n_strx - 4, SEEK_SET) != 0)
05573        goto error_return;
05574 
05575       if (bfd_bread (&len, (bfd_size_type) 4, abfd) != 4)
05576        goto error_return;
05577 
05578       /* Allocate space for the name and null terminate it too.  */
05579       set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
05580       if (!set->name)
05581        goto error_return;
05582       if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
05583        goto error_return;
05584 
05585       set->name[len] = 0;
05586 
05587       /* Fill in the file offset.  Note that the "location" field points
05588         to the SOM itself, not the ar_hdr in front of it.  */
05589       set->file_offset = som_dict[lst_symbol.som_index].location
05590                        - sizeof (struct ar_hdr);
05591 
05592       /* Go to the next symbol.  */
05593       set++;
05594 
05595       /* Iterate through the rest of the chain.  */
05596       while (lst_symbol.next_entry)
05597        {
05598          /* Seek to the next symbol and read it in.  */
05599          if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
05600              != 0)
05601            goto error_return;
05602 
05603          amt = sizeof (lst_symbol);
05604          if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
05605            goto error_return;
05606 
05607          /* Seek to the name length & string and read them in.  */
05608          if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
05609                             + lst_symbol.name.n_strx - 4, SEEK_SET) != 0)
05610            goto error_return;
05611 
05612          if (bfd_bread (&len, (bfd_size_type) 4, abfd) != 4)
05613            goto error_return;
05614 
05615          /* Allocate space for the name and null terminate it too.  */
05616          set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
05617          if (!set->name)
05618            goto error_return;
05619 
05620          if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
05621            goto error_return;
05622          set->name[len] = 0;
05623 
05624          /* Fill in the file offset.  Note that the "location" field points
05625             to the SOM itself, not the ar_hdr in front of it.  */
05626          set->file_offset = som_dict[lst_symbol.som_index].location
05627                             - sizeof (struct ar_hdr);
05628 
05629          /* Go on to the next symbol.  */
05630          set++;
05631        }
05632     }
05633   /* If we haven't died by now, then we successfully read the entire
05634      archive symbol table.  */
05635   if (hash_table != NULL)
05636     free (hash_table);
05637   if (som_dict != NULL)
05638     free (som_dict);
05639   return TRUE;
05640 
05641  error_return:
05642   if (hash_table != NULL)
05643     free (hash_table);
05644   if (som_dict != NULL)
05645     free (som_dict);
05646   return FALSE;
05647 }
05648 
05649 /* Read in the LST from the archive.  */
05650 
05651 static bfd_boolean
05652 som_slurp_armap (bfd *abfd)
05653 {
05654   struct lst_header lst_header;
05655   struct ar_hdr ar_header;
05656   unsigned int parsed_size;
05657   struct artdata *ardata = bfd_ardata (abfd);
05658   char nextname[17];
05659   bfd_size_type amt = 16;
05660   int i = bfd_bread ((void *) nextname, amt, abfd);
05661 
05662   /* Special cases.  */
05663   if (i == 0)
05664     return TRUE;
05665   if (i != 16)
05666     return FALSE;
05667 
05668   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
05669     return FALSE;
05670 
05671   /* For archives without .o files there is no symbol table.  */
05672   if (! CONST_STRNEQ (nextname, "/               "))
05673     {
05674       bfd_has_map (abfd) = FALSE;
05675       return TRUE;
05676     }
05677 
05678   /* Read in and sanity check the archive header.  */
05679   amt = sizeof (struct ar_hdr);
05680   if (bfd_bread ((void *) &ar_header, amt, abfd) != amt)
05681     return FALSE;
05682 
05683   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
05684     {
05685       bfd_set_error (bfd_error_malformed_archive);
05686       return FALSE;
05687     }
05688 
05689   /* How big is the archive symbol table entry?  */
05690   errno = 0;
05691   parsed_size = strtol (ar_header.ar_size, NULL, 10);
05692   if (errno != 0)
05693     {
05694       bfd_set_error (bfd_error_malformed_archive);
05695       return FALSE;
05696     }
05697 
05698   /* Save off the file offset of the first real user data.  */
05699   ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
05700 
05701   /* Read in the library symbol table.  We'll make heavy use of this
05702      in just a minute.  */
05703   amt = sizeof (struct lst_header);
05704   if (bfd_bread ((void *) &lst_header, amt, abfd) != amt)
05705     return FALSE;
05706 
05707   /* Sanity check.  */
05708   if (lst_header.a_magic != LIBMAGIC)
05709     {
05710       bfd_set_error (bfd_error_malformed_archive);
05711       return FALSE;
05712     }
05713 
05714   /* Count the number of symbols in the library symbol table.  */
05715   if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
05716     return FALSE;
05717 
05718   /* Get back to the start of the library symbol table.  */
05719   if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
05720                      + sizeof (struct lst_header)), SEEK_SET) != 0)
05721     return FALSE;
05722 
05723   /* Initialize the cache and allocate space for the library symbols.  */
05724   ardata->cache = 0;
05725   amt = ardata->symdef_count;
05726   amt *= sizeof (carsym);
05727   ardata->symdefs = bfd_alloc (abfd, amt);
05728   if (!ardata->symdefs)
05729     return FALSE;
05730 
05731   /* Now fill in the canonical archive symbols.  */
05732   if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
05733     return FALSE;
05734 
05735   /* Seek back to the "first" file in the archive.  Note the "first"
05736      file may be the extended name table.  */
05737   if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
05738     return FALSE;
05739 
05740   /* Notify the generic archive code that we have a symbol map.  */
05741   bfd_has_map (abfd) = TRUE;
05742   return TRUE;
05743 }
05744 
05745 /* Begin preparing to write a SOM library symbol table.
05746 
05747    As part of the prep work we need to determine the number of symbols
05748    and the size of the associated string section.  */
05749 
05750 static bfd_boolean
05751 som_bfd_prep_for_ar_write (bfd *abfd,
05752                         unsigned int *num_syms,
05753                         unsigned int *stringsize)
05754 {
05755   bfd *curr_bfd = abfd->archive_head;
05756 
05757   /* Some initialization.  */
05758   *num_syms = 0;
05759   *stringsize = 0;
05760 
05761   /* Iterate over each BFD within this archive.  */
05762   while (curr_bfd != NULL)
05763     {
05764       unsigned int curr_count, i;
05765       som_symbol_type *sym;
05766 
05767       /* Don't bother for non-SOM objects.  */
05768       if (curr_bfd->format != bfd_object
05769          || curr_bfd->xvec->flavour != bfd_target_som_flavour)
05770        {
05771          curr_bfd = curr_bfd->next;
05772          continue;
05773        }
05774 
05775       /* Make sure the symbol table has been read, then snag a pointer
05776         to it.  It's a little slimey to grab the symbols via obj_som_symtab,
05777         but doing so avoids allocating lots of extra memory.  */
05778       if (! som_slurp_symbol_table (curr_bfd))
05779        return FALSE;
05780 
05781       sym = obj_som_symtab (curr_bfd);
05782       curr_count = bfd_get_symcount (curr_bfd);
05783 
05784       /* Examine each symbol to determine if it belongs in the
05785         library symbol table.  */
05786       for (i = 0; i < curr_count; i++, sym++)
05787        {
05788          struct som_misc_symbol_info info;
05789 
05790          /* Derive SOM information from the BFD symbol.  */
05791          som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
05792 
05793          /* Should we include this symbol?  */
05794          if (info.symbol_type == ST_NULL
05795              || info.symbol_type == ST_SYM_EXT
05796              || info.symbol_type == ST_ARG_EXT)
05797            continue;
05798 
05799          /* Only global symbols and unsatisfied commons.  */
05800          if (info.symbol_scope != SS_UNIVERSAL
05801              && info.symbol_type != ST_STORAGE)
05802            continue;
05803 
05804          /* Do no include undefined symbols.  */
05805          if (bfd_is_und_section (sym->symbol.section))
05806            continue;
05807 
05808          /* Bump the various counters, being careful to honor
05809             alignment considerations in the string table.  */
05810          (*num_syms)++;
05811          *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
05812          while (*stringsize % 4)
05813            (*stringsize)++;
05814        }
05815 
05816       curr_bfd = curr_bfd->next;
05817     }
05818   return TRUE;
05819 }
05820 
05821 /* Hash a symbol name based on the hashing algorithm presented in the
05822    SOM ABI.  */
05823 
05824 static unsigned int
05825 som_bfd_ar_symbol_hash (asymbol *symbol)
05826 {
05827   unsigned int len = strlen (symbol->name);
05828 
05829   /* Names with length 1 are special.  */
05830   if (len == 1)
05831     return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
05832 
05833   return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
05834          | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
05835 }
05836 
05837 /* Do the bulk of the work required to write the SOM library
05838    symbol table.  */
05839 
05840 static bfd_boolean
05841 som_bfd_ar_write_symbol_stuff (bfd *abfd,
05842                             unsigned int nsyms,
05843                             unsigned int string_size,
05844                             struct lst_header lst,
05845                             unsigned elength)
05846 {
05847   file_ptr lst_filepos;
05848   char *strings = NULL, *p;
05849   struct lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
05850   bfd *curr_bfd;
05851   unsigned int *hash_table = NULL;
05852   struct som_entry *som_dict = NULL;
05853   struct lst_symbol_record **last_hash_entry = NULL;
05854   unsigned int curr_som_offset, som_index = 0;
05855   bfd_size_type amt;
05856 
05857   amt = lst.hash_size;
05858   amt *= sizeof (unsigned int);
05859   hash_table = bfd_zmalloc (amt);
05860   if (hash_table == NULL && lst.hash_size != 0)
05861     goto error_return;
05862 
05863   amt = lst.module_count;
05864   amt *= sizeof (struct som_entry);
05865   som_dict = bfd_zmalloc (amt);
05866   if (som_dict == NULL && lst.module_count != 0)
05867     goto error_return;
05868 
05869   amt = lst.hash_size;
05870   amt *= sizeof (struct lst_symbol_record *);
05871   last_hash_entry = bfd_zmalloc (amt);
05872   if (last_hash_entry == NULL && lst.hash_size != 0)
05873     goto error_return;
05874 
05875   /* Lots of fields are file positions relative to the start
05876      of the lst record.  So save its location.  */
05877   lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
05878 
05879   /* Symbols have som_index fields, so we have to keep track of the
05880      index of each SOM in the archive.
05881 
05882      The SOM dictionary has (among other things) the absolute file
05883      position for the SOM which a particular dictionary entry
05884      describes.  We have to compute that information as we iterate
05885      through the SOMs/symbols.  */
05886   som_index = 0;
05887 
05888   /* We add in the size of the archive header twice as the location
05889      in the SOM dictionary is the actual offset of the SOM, not the
05890      archive header before the SOM.  */
05891   curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
05892 
05893   /* Make room for the archive header and the contents of the
05894      extended string table.  Note that elength includes the size
05895      of the archive header for the extended name table!  */
05896   if (elength)
05897     curr_som_offset += elength;
05898 
05899   /* Make sure we're properly aligned.  */
05900   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
05901 
05902   /* FIXME should be done with buffers just like everything else...  */
05903   amt = nsyms;
05904   amt *= sizeof (struct lst_symbol_record);
05905   lst_syms = bfd_malloc (amt);
05906   if (lst_syms == NULL && nsyms != 0)
05907     goto error_return;
05908   strings = bfd_malloc ((bfd_size_type) string_size);
05909   if (strings == NULL && string_size != 0)
05910     goto error_return;
05911 
05912   p = strings;
05913   curr_lst_sym = lst_syms;
05914 
05915   curr_bfd = abfd->archive_head;
05916   while (curr_bfd != NULL)
05917     {
05918       unsigned int curr_count, i;
05919       som_symbol_type *sym;
05920 
05921       /* Don't bother for non-SOM objects.  */
05922       if (curr_bfd->format != bfd_object
05923          || curr_bfd->xvec->flavour != bfd_target_som_flavour)
05924        {
05925          curr_bfd = curr_bfd->next;
05926          continue;
05927        }
05928 
05929       /* Make sure the symbol table has been read, then snag a pointer
05930         to it.  It's a little slimey to grab the symbols via obj_som_symtab,
05931         but doing so avoids allocating lots of extra memory.  */
05932       if (! som_slurp_symbol_table (curr_bfd))
05933        goto error_return;
05934 
05935       sym = obj_som_symtab (curr_bfd);
05936       curr_count = bfd_get_symcount (curr_bfd);
05937 
05938       for (i = 0; i < curr_count; i++, sym++)
05939        {
05940          struct som_misc_symbol_info info;
05941 
05942          /* Derive SOM information from the BFD symbol.  */
05943          som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
05944 
05945          /* Should we include this symbol?  */
05946          if (info.symbol_type == ST_NULL
05947              || info.symbol_type == ST_SYM_EXT
05948              || info.symbol_type == ST_ARG_EXT)
05949            continue;
05950 
05951          /* Only global symbols and unsatisfied commons.  */
05952          if (info.symbol_scope != SS_UNIVERSAL
05953              && info.symbol_type != ST_STORAGE)
05954            continue;
05955 
05956          /* Do no include undefined symbols.  */
05957          if (bfd_is_und_section (sym->symbol.section))
05958            continue;
05959 
05960          /* If this is the first symbol from this SOM, then update
05961             the SOM dictionary too.  */
05962          if (som_dict[som_index].location == 0)
05963            {
05964              som_dict[som_index].location = curr_som_offset;
05965              som_dict[som_index].length = arelt_size (curr_bfd);
05966            }
05967 
05968          /* Fill in the lst symbol record.  */
05969          curr_lst_sym->hidden = 0;
05970          curr_lst_sym->secondary_def = info.secondary_def;
05971          curr_lst_sym->symbol_type = info.symbol_type;
05972          curr_lst_sym->symbol_scope = info.symbol_scope;
05973          curr_lst_sym->check_level = 0;
05974          curr_lst_sym->must_qualify = 0;
05975          curr_lst_sym->initially_frozen = 0;
05976          curr_lst_sym->memory_resident = 0;
05977          curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
05978          curr_lst_sym->dup_common = info.dup_common;
05979          curr_lst_sym->xleast = 3;
05980          curr_lst_sym->arg_reloc = info.arg_reloc;
05981          curr_lst_sym->name.n_strx = p - strings + 4;
05982          curr_lst_sym->qualifier_name.n_strx = 0;
05983          curr_lst_sym->symbol_info = info.symbol_info;
05984          curr_lst_sym->symbol_value = info.symbol_value | info.priv_level;
05985          curr_lst_sym->symbol_descriptor = 0;
05986          curr_lst_sym->reserved = 0;
05987          curr_lst_sym->som_index = som_index;
05988          curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
05989          curr_lst_sym->next_entry = 0;
05990 
05991          /* Insert into the hash table.  */
05992          if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
05993            {
05994              struct lst_symbol_record *tmp;
05995 
05996              /* There is already something at the head of this hash chain,
05997                so tack this symbol onto the end of the chain.  */
05998              tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
05999              tmp->next_entry
06000               = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
06001                 + lst.hash_size * 4
06002                 + lst.module_count * sizeof (struct som_entry)
06003                 + sizeof (struct lst_header);
06004            }
06005          else
06006            /* First entry in this hash chain.  */
06007            hash_table[curr_lst_sym->symbol_key % lst.hash_size]
06008              = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
06009              + lst.hash_size * 4
06010              + lst.module_count * sizeof (struct som_entry)
06011              + sizeof (struct lst_header);
06012 
06013          /* Keep track of the last symbol we added to this chain so we can
06014             easily update its next_entry pointer.  */
06015          last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
06016            = curr_lst_sym;
06017 
06018          /* Update the string table.  */
06019          bfd_put_32 (abfd, strlen (sym->symbol.name), p);
06020          p += 4;
06021          strcpy (p, sym->symbol.name);
06022          p += strlen (sym->symbol.name) + 1;
06023          while ((int) p % 4)
06024            {
06025              bfd_put_8 (abfd, 0, p);
06026              p++;
06027            }
06028 
06029          /* Head to the next symbol.  */
06030          curr_lst_sym++;
06031        }
06032 
06033       /* Keep track of where each SOM will finally reside; then look
06034         at the next BFD.  */
06035       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
06036 
06037       /* A particular object in the archive may have an odd length; the
06038         linker requires objects begin on an even boundary.  So round
06039         up the current offset as necessary.  */
06040       curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
06041       curr_bfd = curr_bfd->next;
06042       som_index++;
06043     }
06044 
06045   /* Now scribble out the hash table.  */
06046   amt = lst.hash_size * 4;
06047   if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
06048     goto error_return;
06049 
06050   /* Then the SOM dictionary.  */
06051   amt = lst.module_count * sizeof (struct som_entry);
06052   if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
06053     goto error_return;
06054 
06055   /* The library symbols.  */
06056   amt = nsyms * sizeof (struct lst_symbol_record);
06057   if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
06058     goto error_return;
06059 
06060   /* And finally the strings.  */
06061   amt = string_size;
06062   if (bfd_bwrite ((void *) strings, amt, abfd) != amt)
06063     goto error_return;
06064 
06065   if (hash_table != NULL)
06066     free (hash_table);
06067   if (som_dict != NULL)
06068     free (som_dict);
06069   if (last_hash_entry != NULL)
06070     free (last_hash_entry);
06071   if (lst_syms != NULL)
06072     free (lst_syms);
06073   if (strings != NULL)
06074     free (strings);
06075   return TRUE;
06076 
06077  error_return:
06078   if (hash_table != NULL)
06079     free (hash_table);
06080   if (som_dict != NULL)
06081     free (som_dict);
06082   if (last_hash_entry != NULL)
06083     free (last_hash_entry);
06084   if (lst_syms != NULL)
06085     free (lst_syms);
06086   if (strings != NULL)
06087     free (strings);
06088 
06089   return FALSE;
06090 }
06091 
06092 /* Write out the LST for the archive.
06093 
06094    You'll never believe this is really how armaps are handled in SOM...  */
06095 
06096 static bfd_boolean
06097 som_write_armap (bfd *abfd,
06098                unsigned int elength,
06099                struct orl *map ATTRIBUTE_UNUSED,
06100                unsigned int orl_count ATTRIBUTE_UNUSED,
06101                int stridx ATTRIBUTE_UNUSED)
06102 {
06103   bfd *curr_bfd;
06104   struct stat statbuf;
06105   unsigned int i, lst_size, nsyms, stringsize;
06106   struct ar_hdr hdr;
06107   struct lst_header lst;
06108   int *p;
06109   bfd_size_type amt;
06110 
06111   /* We'll use this for the archive's date and mode later.  */
06112   if (stat (abfd->filename, &statbuf) != 0)
06113     {
06114       bfd_set_error (bfd_error_system_call);
06115       return FALSE;
06116     }
06117   /* Fudge factor.  */
06118   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
06119 
06120   /* Account for the lst header first.  */
06121   lst_size = sizeof (struct lst_header);
06122 
06123   /* Start building the LST header.  */
06124   /* FIXME:  Do we need to examine each element to determine the
06125      largest id number?  */
06126   lst.system_id = CPU_PA_RISC1_0;
06127   lst.a_magic = LIBMAGIC;
06128   lst.version_id = VERSION_ID;
06129   lst.file_time.secs = 0;
06130   lst.file_time.nanosecs = 0;
06131 
06132   lst.hash_loc = lst_size;
06133   lst.hash_size = SOM_LST_HASH_SIZE;
06134 
06135   /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
06136   lst_size += 4 * SOM_LST_HASH_SIZE;
06137 
06138   /* We need to count the number of SOMs in this archive.  */
06139   curr_bfd = abfd->archive_head;
06140   lst.module_count = 0;
06141   while (curr_bfd != NULL)
06142     {
06143       /* Only true SOM objects count.  */
06144       if (curr_bfd->format == bfd_object
06145          && curr_bfd->xvec->flavour == bfd_target_som_flavour)
06146        lst.module_count++;
06147       curr_bfd = curr_bfd->next;
06148     }
06149   lst.module_limit = lst.module_count;
06150   lst.dir_loc = lst_size;
06151   lst_size += sizeof (struct som_entry) * lst.module_count;
06152 
06153   /* We don't support import/export tables, auxiliary headers,
06154      or free lists yet.  Make the linker work a little harder
06155      to make our life easier.  */
06156 
06157   lst.export_loc = 0;
06158   lst.export_count = 0;
06159   lst.import_loc = 0;
06160   lst.aux_loc = 0;
06161   lst.aux_size = 0;
06162 
06163   /* Count how many symbols we will have on the hash chains and the
06164      size of the associated string table.  */
06165   if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
06166     return FALSE;
06167 
06168   lst_size += sizeof (struct lst_symbol_record) * nsyms;
06169 
06170   /* For the string table.  One day we might actually use this info
06171      to avoid small seeks/reads when reading archives.  */
06172   lst.string_loc = lst_size;
06173   lst.string_size = stringsize;
06174   lst_size += stringsize;
06175 
06176   /* SOM ABI says this must be zero.  */
06177   lst.free_list = 0;
06178   lst.file_end = lst_size;
06179 
06180   /* Compute the checksum.  Must happen after the entire lst header
06181      has filled in.  */
06182   p = (int *) &lst;
06183   lst.checksum = 0;
06184   for (i = 0; i < sizeof (struct lst_header) / sizeof (int) - 1; i++)
06185     lst.checksum ^= *p++;
06186 
06187   sprintf (hdr.ar_name, "/               ");
06188   sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
06189   sprintf (hdr.ar_uid, "%ld", (long) getuid ());
06190   sprintf (hdr.ar_gid, "%ld", (long) getgid ());
06191   sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
06192   sprintf (hdr.ar_size, "%-10d", (int) lst_size);
06193   hdr.ar_fmag[0] = '`';
06194   hdr.ar_fmag[1] = '\012';
06195 
06196   /* Turn any nulls into spaces.  */
06197   for (i = 0; i < sizeof (struct ar_hdr); i++)
06198     if (((char *) (&hdr))[i] == '\0')
06199       (((char *) (&hdr))[i]) = ' ';
06200 
06201   /* Scribble out the ar header.  */
06202   amt = sizeof (struct ar_hdr);
06203   if (bfd_bwrite ((void *) &hdr, amt, abfd) != amt)
06204     return FALSE;
06205 
06206   /* Now scribble out the lst header.  */
06207   amt = sizeof (struct lst_header);
06208   if (bfd_bwrite ((void *) &lst, amt, abfd) != amt)
06209     return FALSE;
06210 
06211   /* Build and write the armap.  */
06212   if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
06213     return FALSE;
06214 
06215   /* Done.  */
06216   return TRUE;
06217 }
06218 
06219 /* Free all information we have cached for this BFD.  We can always
06220    read it again later if we need it.  */
06221 
06222 static bfd_boolean
06223 som_bfd_free_cached_info (bfd *abfd)
06224 {
06225   asection *o;
06226 
06227   if (bfd_get_format (abfd) != bfd_object)
06228     return TRUE;
06229 
06230 #define FREE(x) if (x != NULL) { free (x); x = NULL; }
06231   /* Free the native string and symbol tables.  */
06232   FREE (obj_som_symtab (abfd));
06233   FREE (obj_som_stringtab (abfd));
06234   for (o = abfd->sections; o != NULL; o = o->next)
06235     {
06236       /* Free the native relocations.  */
06237       o->reloc_count = (unsigned) -1;
06238       FREE (som_section_data (o)->reloc_stream);
06239       /* Free the generic relocations.  */
06240       FREE (o->relocation);
06241     }
06242 #undef FREE
06243 
06244   return TRUE;
06245 }
06246 
06247 /* End of miscellaneous support functions.  */
06248 
06249 /* Linker support functions.  */
06250 
06251 static bfd_boolean
06252 som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
06253 {
06254   return som_is_subspace (sec) && sec->size > 240000;
06255 }
06256 
06257 #define       som_close_and_cleanup                      som_bfd_free_cached_info
06258 #define som_read_ar_hdr                           _bfd_generic_read_ar_hdr
06259 #define som_openr_next_archived_file              bfd_generic_openr_next_archived_file
06260 #define som_get_elt_at_index                      _bfd_generic_get_elt_at_index
06261 #define som_generic_stat_arch_elt          bfd_generic_stat_arch_elt
06262 #define som_truncate_arname                bfd_bsd_truncate_arname
06263 #define som_slurp_extended_name_table             _bfd_slurp_extended_name_table
06264 #define som_construct_extended_name_table       _bfd_archive_coff_construct_extended_name_table
06265 #define som_update_armap_timestamp         bfd_true
06266 #define som_bfd_is_target_special_symbol   ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
06267 #define som_get_lineno                            _bfd_nosymbols_get_lineno
06268 #define som_bfd_make_debug_symbol          _bfd_nosymbols_bfd_make_debug_symbol
06269 #define som_read_minisymbols                      _bfd_generic_read_minisymbols
06270 #define som_minisymbol_to_symbol           _bfd_generic_minisymbol_to_symbol
06271 #define som_get_section_contents_in_window      _bfd_generic_get_section_contents_in_window
06272 #define som_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
06273 #define som_bfd_relax_section                   bfd_generic_relax_section
06274 #define som_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
06275 #define som_bfd_link_hash_table_free            _bfd_generic_link_hash_table_free
06276 #define som_bfd_link_add_symbols                _bfd_generic_link_add_symbols
06277 #define som_bfd_link_just_syms                  _bfd_generic_link_just_syms
06278 #define som_bfd_final_link                      _bfd_generic_final_link
06279 #define som_bfd_gc_sections                bfd_generic_gc_sections
06280 #define som_bfd_merge_sections                    bfd_generic_merge_sections
06281 #define som_bfd_is_group_section           bfd_generic_is_group_section
06282 #define som_bfd_discard_group                     bfd_generic_discard_group
06283 #define som_section_already_linked              _bfd_generic_section_already_linked
06284 #define som_bfd_merge_private_bfd_data           _bfd_generic_bfd_merge_private_bfd_data
06285 #define som_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
06286 #define som_bfd_set_private_flags         _bfd_generic_bfd_set_private_flags
06287 #define som_find_inliner_info                    _bfd_nosymbols_find_inliner_info
06288 
06289 const bfd_target som_vec =
06290 {
06291   "som",                    /* Name.  */
06292   bfd_target_som_flavour,
06293   BFD_ENDIAN_BIG,           /* Target byte order.  */
06294   BFD_ENDIAN_BIG,           /* Target headers byte order.  */
06295   (HAS_RELOC | EXEC_P |            /* Object flags.  */
06296    HAS_LINENO | HAS_DEBUG |
06297    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
06298   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
06299    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),          /* Section flags.  */
06300 
06301   /* Leading_symbol_char: is the first char of a user symbol
06302      predictable, and if so what is it.  */
06303   0,
06304   '/',                      /* AR_pad_char.  */
06305   14,                       /* AR_max_namelen.  */
06306   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
06307   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
06308   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* Data.  */
06309   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
06310   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
06311   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* Headers.  */
06312   {_bfd_dummy_target,
06313    som_object_p,            /* bfd_check_format.  */
06314    bfd_generic_archive_p,
06315    _bfd_dummy_target
06316   },
06317   {
06318     bfd_false,
06319     som_mkobject,
06320     _bfd_generic_mkarchive,
06321     bfd_false
06322   },
06323   {
06324     bfd_false,
06325     som_write_object_contents,
06326     _bfd_write_archive_contents,
06327     bfd_false,
06328   },
06329 #undef som
06330 
06331   BFD_JUMP_TABLE_GENERIC (som),
06332   BFD_JUMP_TABLE_COPY (som),
06333   BFD_JUMP_TABLE_CORE (_bfd_nocore),
06334   BFD_JUMP_TABLE_ARCHIVE (som),
06335   BFD_JUMP_TABLE_SYMBOLS (som),
06336   BFD_JUMP_TABLE_RELOCS (som),
06337   BFD_JUMP_TABLE_WRITE (som),
06338   BFD_JUMP_TABLE_LINK (som),
06339   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
06340 
06341   NULL,
06342 
06343   NULL
06344 };
06345 
06346 #endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */