1 1.1 christos /* bfd back-end for HP PA-RISC SOM objects. 2 1.11 christos Copyright (C) 1990-2024 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos Contributed by the Center for Software Science at the 5 1.1 christos University of Utah. 6 1.1 christos 7 1.1 christos This file is part of BFD, the Binary File Descriptor library. 8 1.1 christos 9 1.1 christos This program is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 3 of the License, or 12 1.1 christos (at your option) any later version. 13 1.1 christos 14 1.1 christos This program is distributed in the hope that it will be useful, 15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 1.1 christos GNU General Public License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program; if not, write to the Free Software 21 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 22 1.1 christos 02110-1301, USA. */ 23 1.1 christos 24 1.1 christos #include "sysdep.h" 25 1.1 christos #include "bfd.h" 26 1.6 christos #include "libiberty.h" 27 1.1 christos #include "libbfd.h" 28 1.1 christos #include "som.h" 29 1.1 christos #include "safe-ctype.h" 30 1.1 christos #include "som/reloc.h" 31 1.1 christos #include "aout/ar.h" 32 1.1 christos 33 1.1 christos static bfd_reloc_status_type hppa_som_reloc 34 1.1 christos (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 35 1.10 christos static bool som_mkobject (bfd *); 36 1.10 christos static bool som_is_space (asection *); 37 1.10 christos static bool som_is_subspace (asection *); 38 1.1 christos static int compare_subspaces (const void *, const void *); 39 1.9 christos static uint32_t som_compute_checksum (struct som_external_header *); 40 1.10 christos static bool som_build_and_write_symbol_table (bfd *); 41 1.1 christos static unsigned int som_slurp_symbol_table (bfd *); 42 1.1 christos 43 1.1 christos /* Magic not defined in standard HP-UX header files until 8.0. */ 44 1.1 christos 45 1.1 christos #ifndef CPU_PA_RISC1_0 46 1.1 christos #define CPU_PA_RISC1_0 0x20B 47 1.1 christos #endif /* CPU_PA_RISC1_0 */ 48 1.1 christos 49 1.1 christos #ifndef CPU_PA_RISC1_1 50 1.1 christos #define CPU_PA_RISC1_1 0x210 51 1.1 christos #endif /* CPU_PA_RISC1_1 */ 52 1.1 christos 53 1.1 christos #ifndef CPU_PA_RISC2_0 54 1.1 christos #define CPU_PA_RISC2_0 0x214 55 1.1 christos #endif /* CPU_PA_RISC2_0 */ 56 1.1 christos 57 1.1 christos #ifndef _PA_RISC1_0_ID 58 1.1 christos #define _PA_RISC1_0_ID CPU_PA_RISC1_0 59 1.1 christos #endif /* _PA_RISC1_0_ID */ 60 1.1 christos 61 1.1 christos #ifndef _PA_RISC1_1_ID 62 1.1 christos #define _PA_RISC1_1_ID CPU_PA_RISC1_1 63 1.1 christos #endif /* _PA_RISC1_1_ID */ 64 1.1 christos 65 1.1 christos #ifndef _PA_RISC2_0_ID 66 1.1 christos #define _PA_RISC2_0_ID CPU_PA_RISC2_0 67 1.1 christos #endif /* _PA_RISC2_0_ID */ 68 1.1 christos 69 1.1 christos #ifndef _PA_RISC_MAXID 70 1.1 christos #define _PA_RISC_MAXID 0x2FF 71 1.1 christos #endif /* _PA_RISC_MAXID */ 72 1.1 christos 73 1.1 christos #ifndef _PA_RISC_ID 74 1.1 christos #define _PA_RISC_ID(__m_num) \ 75 1.1 christos (((__m_num) == _PA_RISC1_0_ID) || \ 76 1.1 christos ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID)) 77 1.1 christos #endif /* _PA_RISC_ID */ 78 1.1 christos 79 1.1 christos /* HIUX in it's infinite stupidity changed the names for several "well 80 1.1 christos known" constants. Work around such braindamage. Try the HPUX version 81 1.1 christos first, then the HIUX version, and finally provide a default. */ 82 1.1 christos #ifdef HPUX_AUX_ID 83 1.1 christos #define EXEC_AUX_ID HPUX_AUX_ID 84 1.1 christos #endif 85 1.1 christos 86 1.1 christos #if !defined (EXEC_AUX_ID) && defined (HIUX_AUX_ID) 87 1.1 christos #define EXEC_AUX_ID HIUX_AUX_ID 88 1.1 christos #endif 89 1.1 christos 90 1.1 christos #ifndef EXEC_AUX_ID 91 1.1 christos #define EXEC_AUX_ID 0 92 1.1 christos #endif 93 1.1 christos 94 1.1 christos /* Size (in chars) of the temporary buffers used during fixup and string 95 1.1 christos table writes. */ 96 1.1 christos 97 1.1 christos #define SOM_TMP_BUFSIZE 8192 98 1.1 christos 99 1.1 christos /* Size of the hash table in archives. */ 100 1.1 christos #define SOM_LST_HASH_SIZE 31 101 1.1 christos 102 1.1 christos /* Max number of SOMs to be found in an archive. */ 103 1.1 christos #define SOM_LST_MODULE_LIMIT 1024 104 1.1 christos 105 1.1 christos /* Generic alignment macro. */ 106 1.1 christos #define SOM_ALIGN(val, alignment) \ 107 1.1 christos (((val) + (alignment) - 1) &~ ((unsigned long) (alignment) - 1)) 108 1.1 christos 109 1.1 christos /* SOM allows any one of the four previous relocations to be reused 110 1.1 christos with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP 111 1.1 christos relocations are always a single byte, using a R_PREV_FIXUP instead 112 1.1 christos of some multi-byte relocation makes object files smaller. 113 1.1 christos 114 1.1 christos Note one side effect of using a R_PREV_FIXUP is the relocation that 115 1.1 christos is being repeated moves to the front of the queue. */ 116 1.10 christos static struct reloc_queue 117 1.1 christos { 118 1.1 christos unsigned char *reloc; 119 1.1 christos unsigned int size; 120 1.1 christos } reloc_queue[4]; 121 1.1 christos 122 1.1 christos /* This fully describes the symbol types which may be attached to 123 1.1 christos an EXPORT or IMPORT directive. Only SOM uses this formation 124 1.1 christos (ELF has no need for it). */ 125 1.1 christos typedef enum 126 1.1 christos { 127 1.1 christos SYMBOL_TYPE_UNKNOWN, 128 1.1 christos SYMBOL_TYPE_ABSOLUTE, 129 1.1 christos SYMBOL_TYPE_CODE, 130 1.1 christos SYMBOL_TYPE_DATA, 131 1.1 christos SYMBOL_TYPE_ENTRY, 132 1.1 christos SYMBOL_TYPE_MILLICODE, 133 1.1 christos SYMBOL_TYPE_PLABEL, 134 1.1 christos SYMBOL_TYPE_PRI_PROG, 135 1.1 christos SYMBOL_TYPE_SEC_PROG, 136 1.1 christos } pa_symbol_type; 137 1.1 christos 138 1.1 christos struct section_to_type 139 1.1 christos { 140 1.1 christos const char *section; 141 1.1 christos char type; 142 1.1 christos }; 143 1.1 christos 144 1.1 christos /* Assorted symbol information that needs to be derived from the BFD symbol 145 1.1 christos and/or the BFD backend private symbol data. */ 146 1.1 christos struct som_misc_symbol_info 147 1.1 christos { 148 1.1 christos unsigned int symbol_type; 149 1.1 christos unsigned int symbol_scope; 150 1.1 christos unsigned int arg_reloc; 151 1.1 christos unsigned int symbol_info; 152 1.1 christos unsigned int symbol_value; 153 1.1 christos unsigned int priv_level; 154 1.1 christos unsigned int secondary_def; 155 1.1 christos unsigned int is_comdat; 156 1.1 christos unsigned int is_common; 157 1.1 christos unsigned int dup_common; 158 1.1 christos }; 159 1.1 christos 160 1.1 christos /* Map SOM section names to POSIX/BSD single-character symbol types. 161 1.1 christos 162 1.1 christos This table includes all the standard subspaces as defined in the 163 1.1 christos current "PRO ABI for PA-RISC Systems", $UNWIND$ which for 164 1.1 christos some reason was left out, and sections specific to embedded stabs. */ 165 1.1 christos 166 1.1 christos static const struct section_to_type stt[] = 167 1.1 christos { 168 1.1 christos {"$TEXT$", 't'}, 169 1.1 christos {"$SHLIB_INFO$", 't'}, 170 1.1 christos {"$MILLICODE$", 't'}, 171 1.1 christos {"$LIT$", 't'}, 172 1.1 christos {"$CODE$", 't'}, 173 1.1 christos {"$UNWIND_START$", 't'}, 174 1.1 christos {"$UNWIND$", 't'}, 175 1.1 christos {"$PRIVATE$", 'd'}, 176 1.1 christos {"$PLT$", 'd'}, 177 1.1 christos {"$SHLIB_DATA$", 'd'}, 178 1.1 christos {"$DATA$", 'd'}, 179 1.1 christos {"$SHORTDATA$", 'g'}, 180 1.1 christos {"$DLT$", 'd'}, 181 1.1 christos {"$GLOBAL$", 'g'}, 182 1.1 christos {"$SHORTBSS$", 's'}, 183 1.1 christos {"$BSS$", 'b'}, 184 1.1 christos {"$GDB_STRINGS$", 'N'}, 185 1.1 christos {"$GDB_SYMBOLS$", 'N'}, 186 1.1 christos {0, 0} 187 1.1 christos }; 188 1.1 christos 189 1.1 christos /* About the relocation formatting table... 190 1.1 christos 191 1.1 christos There are 256 entries in the table, one for each possible 192 1.1 christos relocation opcode available in SOM. We index the table by 193 1.1 christos the relocation opcode. The names and operations are those 194 1.1 christos defined by a.out_800 (4). 195 1.1 christos 196 1.1 christos Right now this table is only used to count and perform minimal 197 1.1 christos processing on relocation streams so that they can be internalized 198 1.1 christos into BFD and symbolically printed by utilities. To make actual use 199 1.1 christos of them would be much more difficult, BFD's concept of relocations 200 1.1 christos is far too simple to handle SOM relocations. The basic assumption 201 1.1 christos that a relocation can be completely processed independent of other 202 1.1 christos relocations before an object file is written is invalid for SOM. 203 1.1 christos 204 1.1 christos The SOM relocations are meant to be processed as a stream, they 205 1.1 christos specify copying of data from the input section to the output section 206 1.1 christos while possibly modifying the data in some manner. They also can 207 1.1 christos specify that a variable number of zeros or uninitialized data be 208 1.1 christos inserted on in the output segment at the current offset. Some 209 1.1 christos relocations specify that some previous relocation be re-applied at 210 1.1 christos the current location in the input/output sections. And finally a number 211 1.1 christos of relocations have effects on other sections (R_ENTRY, R_EXIT, 212 1.1 christos R_UNWIND_AUX and a variety of others). There isn't even enough room 213 1.1 christos in the BFD relocation data structure to store enough information to 214 1.1 christos perform all the relocations. 215 1.1 christos 216 1.1 christos Each entry in the table has three fields. 217 1.1 christos 218 1.1 christos The first entry is an index into this "class" of relocations. This 219 1.1 christos index can then be used as a variable within the relocation itself. 220 1.1 christos 221 1.1 christos The second field is a format string which actually controls processing 222 1.1 christos of the relocation. It uses a simple postfix machine to do calculations 223 1.1 christos based on variables/constants found in the string and the relocation 224 1.1 christos stream. 225 1.1 christos 226 1.1 christos The third field specifys whether or not this relocation may use 227 1.1 christos a constant (V) from the previous R_DATA_OVERRIDE rather than a constant 228 1.1 christos stored in the instruction. 229 1.1 christos 230 1.1 christos Variables: 231 1.1 christos 232 1.1 christos L = input space byte count 233 1.1 christos D = index into class of relocations 234 1.1 christos M = output space byte count 235 1.1 christos N = statement number (unused?) 236 1.1 christos O = stack operation 237 1.1 christos R = parameter relocation bits 238 1.1 christos S = symbol index 239 1.1 christos T = first 32 bits of stack unwind information 240 1.1 christos U = second 32 bits of stack unwind information 241 1.1 christos V = a literal constant (usually used in the next relocation) 242 1.1 christos P = a previous relocation 243 1.1 christos 244 1.1 christos Lower case letters (starting with 'b') refer to following 245 1.1 christos bytes in the relocation stream. 'b' is the next 1 byte, 246 1.1 christos c is the next 2 bytes, d is the next 3 bytes, etc... 247 1.1 christos This is the variable part of the relocation entries that 248 1.1 christos makes our life a living hell. 249 1.1 christos 250 1.1 christos numerical constants are also used in the format string. Note 251 1.1 christos the constants are represented in decimal. 252 1.1 christos 253 1.1 christos '+', "*" and "=" represents the obvious postfix operators. 254 1.1 christos '<' represents a left shift. 255 1.1 christos 256 1.1 christos Stack Operations: 257 1.1 christos 258 1.1 christos Parameter Relocation Bits: 259 1.1 christos 260 1.1 christos Unwind Entries: 261 1.1 christos 262 1.1 christos Previous Relocations: The index field represents which in the queue 263 1.1 christos of 4 previous fixups should be re-applied. 264 1.1 christos 265 1.1 christos Literal Constants: These are generally used to represent addend 266 1.1 christos parts of relocations when these constants are not stored in the 267 1.1 christos fields of the instructions themselves. For example the instruction 268 1.1 christos addil foo-$global$-0x1234 would use an override for "0x1234" rather 269 1.1 christos than storing it into the addil itself. */ 270 1.1 christos 271 1.1 christos struct fixup_format 272 1.1 christos { 273 1.1 christos int D; 274 1.1 christos const char *format; 275 1.1 christos }; 276 1.1 christos 277 1.1 christos static const struct fixup_format som_fixup_formats[256] = 278 1.1 christos { 279 1.1 christos /* R_NO_RELOCATION. */ 280 1.1 christos { 0, "LD1+4*=" }, /* 0x00 */ 281 1.1 christos { 1, "LD1+4*=" }, /* 0x01 */ 282 1.1 christos { 2, "LD1+4*=" }, /* 0x02 */ 283 1.1 christos { 3, "LD1+4*=" }, /* 0x03 */ 284 1.1 christos { 4, "LD1+4*=" }, /* 0x04 */ 285 1.1 christos { 5, "LD1+4*=" }, /* 0x05 */ 286 1.1 christos { 6, "LD1+4*=" }, /* 0x06 */ 287 1.1 christos { 7, "LD1+4*=" }, /* 0x07 */ 288 1.1 christos { 8, "LD1+4*=" }, /* 0x08 */ 289 1.1 christos { 9, "LD1+4*=" }, /* 0x09 */ 290 1.1 christos { 10, "LD1+4*=" }, /* 0x0a */ 291 1.1 christos { 11, "LD1+4*=" }, /* 0x0b */ 292 1.1 christos { 12, "LD1+4*=" }, /* 0x0c */ 293 1.1 christos { 13, "LD1+4*=" }, /* 0x0d */ 294 1.1 christos { 14, "LD1+4*=" }, /* 0x0e */ 295 1.1 christos { 15, "LD1+4*=" }, /* 0x0f */ 296 1.1 christos { 16, "LD1+4*=" }, /* 0x10 */ 297 1.1 christos { 17, "LD1+4*=" }, /* 0x11 */ 298 1.1 christos { 18, "LD1+4*=" }, /* 0x12 */ 299 1.1 christos { 19, "LD1+4*=" }, /* 0x13 */ 300 1.1 christos { 20, "LD1+4*=" }, /* 0x14 */ 301 1.1 christos { 21, "LD1+4*=" }, /* 0x15 */ 302 1.1 christos { 22, "LD1+4*=" }, /* 0x16 */ 303 1.1 christos { 23, "LD1+4*=" }, /* 0x17 */ 304 1.1 christos { 0, "LD8<b+1+4*=" }, /* 0x18 */ 305 1.1 christos { 1, "LD8<b+1+4*=" }, /* 0x19 */ 306 1.1 christos { 2, "LD8<b+1+4*=" }, /* 0x1a */ 307 1.1 christos { 3, "LD8<b+1+4*=" }, /* 0x1b */ 308 1.1 christos { 0, "LD16<c+1+4*=" }, /* 0x1c */ 309 1.1 christos { 1, "LD16<c+1+4*=" }, /* 0x1d */ 310 1.1 christos { 2, "LD16<c+1+4*=" }, /* 0x1e */ 311 1.1 christos { 0, "Ld1+=" }, /* 0x1f */ 312 1.1 christos /* R_ZEROES. */ 313 1.1 christos { 0, "Lb1+4*=" }, /* 0x20 */ 314 1.1 christos { 1, "Ld1+=" }, /* 0x21 */ 315 1.1 christos /* R_UNINIT. */ 316 1.1 christos { 0, "Lb1+4*=" }, /* 0x22 */ 317 1.1 christos { 1, "Ld1+=" }, /* 0x23 */ 318 1.1 christos /* R_RELOCATION. */ 319 1.1 christos { 0, "L4=" }, /* 0x24 */ 320 1.1 christos /* R_DATA_ONE_SYMBOL. */ 321 1.1 christos { 0, "L4=Sb=" }, /* 0x25 */ 322 1.1 christos { 1, "L4=Sd=" }, /* 0x26 */ 323 1.1 christos /* R_DATA_PLABEL. */ 324 1.1 christos { 0, "L4=Sb=" }, /* 0x27 */ 325 1.1 christos { 1, "L4=Sd=" }, /* 0x28 */ 326 1.1 christos /* R_SPACE_REF. */ 327 1.1 christos { 0, "L4=" }, /* 0x29 */ 328 1.1 christos /* R_REPEATED_INIT. */ 329 1.1 christos { 0, "L4=Mb1+4*=" }, /* 0x2a */ 330 1.1 christos { 1, "Lb4*=Mb1+L*=" }, /* 0x2b */ 331 1.1 christos { 2, "Lb4*=Md1+4*=" }, /* 0x2c */ 332 1.1 christos { 3, "Ld1+=Me1+=" }, /* 0x2d */ 333 1.1 christos { 0, "" }, /* 0x2e */ 334 1.1 christos { 0, "" }, /* 0x2f */ 335 1.1 christos /* R_PCREL_CALL. */ 336 1.1 christos { 0, "L4=RD=Sb=" }, /* 0x30 */ 337 1.1 christos { 1, "L4=RD=Sb=" }, /* 0x31 */ 338 1.1 christos { 2, "L4=RD=Sb=" }, /* 0x32 */ 339 1.1 christos { 3, "L4=RD=Sb=" }, /* 0x33 */ 340 1.1 christos { 4, "L4=RD=Sb=" }, /* 0x34 */ 341 1.1 christos { 5, "L4=RD=Sb=" }, /* 0x35 */ 342 1.1 christos { 6, "L4=RD=Sb=" }, /* 0x36 */ 343 1.1 christos { 7, "L4=RD=Sb=" }, /* 0x37 */ 344 1.1 christos { 8, "L4=RD=Sb=" }, /* 0x38 */ 345 1.1 christos { 9, "L4=RD=Sb=" }, /* 0x39 */ 346 1.1 christos { 0, "L4=RD8<b+=Sb=" }, /* 0x3a */ 347 1.1 christos { 1, "L4=RD8<b+=Sb=" }, /* 0x3b */ 348 1.1 christos { 0, "L4=RD8<b+=Sd=" }, /* 0x3c */ 349 1.1 christos { 1, "L4=RD8<b+=Sd=" }, /* 0x3d */ 350 1.1 christos /* R_SHORT_PCREL_MODE. */ 351 1.1 christos { 0, "" }, /* 0x3e */ 352 1.1 christos /* R_LONG_PCREL_MODE. */ 353 1.1 christos { 0, "" }, /* 0x3f */ 354 1.1 christos /* R_ABS_CALL. */ 355 1.1 christos { 0, "L4=RD=Sb=" }, /* 0x40 */ 356 1.1 christos { 1, "L4=RD=Sb=" }, /* 0x41 */ 357 1.1 christos { 2, "L4=RD=Sb=" }, /* 0x42 */ 358 1.1 christos { 3, "L4=RD=Sb=" }, /* 0x43 */ 359 1.1 christos { 4, "L4=RD=Sb=" }, /* 0x44 */ 360 1.1 christos { 5, "L4=RD=Sb=" }, /* 0x45 */ 361 1.1 christos { 6, "L4=RD=Sb=" }, /* 0x46 */ 362 1.1 christos { 7, "L4=RD=Sb=" }, /* 0x47 */ 363 1.1 christos { 8, "L4=RD=Sb=" }, /* 0x48 */ 364 1.1 christos { 9, "L4=RD=Sb=" }, /* 0x49 */ 365 1.1 christos { 0, "L4=RD8<b+=Sb=" }, /* 0x4a */ 366 1.1 christos { 1, "L4=RD8<b+=Sb=" }, /* 0x4b */ 367 1.1 christos { 0, "L4=RD8<b+=Sd=" }, /* 0x4c */ 368 1.1 christos { 1, "L4=RD8<b+=Sd=" }, /* 0x4d */ 369 1.1 christos /* R_RESERVED. */ 370 1.1 christos { 0, "" }, /* 0x4e */ 371 1.1 christos { 0, "" }, /* 0x4f */ 372 1.1 christos /* R_DP_RELATIVE. */ 373 1.1 christos { 0, "L4=SD=" }, /* 0x50 */ 374 1.1 christos { 1, "L4=SD=" }, /* 0x51 */ 375 1.1 christos { 2, "L4=SD=" }, /* 0x52 */ 376 1.1 christos { 3, "L4=SD=" }, /* 0x53 */ 377 1.1 christos { 4, "L4=SD=" }, /* 0x54 */ 378 1.1 christos { 5, "L4=SD=" }, /* 0x55 */ 379 1.1 christos { 6, "L4=SD=" }, /* 0x56 */ 380 1.1 christos { 7, "L4=SD=" }, /* 0x57 */ 381 1.1 christos { 8, "L4=SD=" }, /* 0x58 */ 382 1.1 christos { 9, "L4=SD=" }, /* 0x59 */ 383 1.1 christos { 10, "L4=SD=" }, /* 0x5a */ 384 1.1 christos { 11, "L4=SD=" }, /* 0x5b */ 385 1.1 christos { 12, "L4=SD=" }, /* 0x5c */ 386 1.1 christos { 13, "L4=SD=" }, /* 0x5d */ 387 1.1 christos { 14, "L4=SD=" }, /* 0x5e */ 388 1.1 christos { 15, "L4=SD=" }, /* 0x5f */ 389 1.1 christos { 16, "L4=SD=" }, /* 0x60 */ 390 1.1 christos { 17, "L4=SD=" }, /* 0x61 */ 391 1.1 christos { 18, "L4=SD=" }, /* 0x62 */ 392 1.1 christos { 19, "L4=SD=" }, /* 0x63 */ 393 1.1 christos { 20, "L4=SD=" }, /* 0x64 */ 394 1.1 christos { 21, "L4=SD=" }, /* 0x65 */ 395 1.1 christos { 22, "L4=SD=" }, /* 0x66 */ 396 1.1 christos { 23, "L4=SD=" }, /* 0x67 */ 397 1.1 christos { 24, "L4=SD=" }, /* 0x68 */ 398 1.1 christos { 25, "L4=SD=" }, /* 0x69 */ 399 1.1 christos { 26, "L4=SD=" }, /* 0x6a */ 400 1.1 christos { 27, "L4=SD=" }, /* 0x6b */ 401 1.1 christos { 28, "L4=SD=" }, /* 0x6c */ 402 1.1 christos { 29, "L4=SD=" }, /* 0x6d */ 403 1.1 christos { 30, "L4=SD=" }, /* 0x6e */ 404 1.1 christos { 31, "L4=SD=" }, /* 0x6f */ 405 1.1 christos { 32, "L4=Sb=" }, /* 0x70 */ 406 1.1 christos { 33, "L4=Sd=" }, /* 0x71 */ 407 1.1 christos /* R_DATA_GPREL. */ 408 1.1 christos { 0, "L4=Sd=" }, /* 0x72 */ 409 1.1 christos /* R_RESERVED. */ 410 1.1 christos { 0, "" }, /* 0x73 */ 411 1.1 christos { 0, "" }, /* 0x74 */ 412 1.1 christos { 0, "" }, /* 0x75 */ 413 1.1 christos { 0, "" }, /* 0x76 */ 414 1.1 christos { 0, "" }, /* 0x77 */ 415 1.1 christos /* R_DLT_REL. */ 416 1.1 christos { 0, "L4=Sb=" }, /* 0x78 */ 417 1.1 christos { 1, "L4=Sd=" }, /* 0x79 */ 418 1.1 christos /* R_RESERVED. */ 419 1.1 christos { 0, "" }, /* 0x7a */ 420 1.1 christos { 0, "" }, /* 0x7b */ 421 1.1 christos { 0, "" }, /* 0x7c */ 422 1.1 christos { 0, "" }, /* 0x7d */ 423 1.1 christos { 0, "" }, /* 0x7e */ 424 1.1 christos { 0, "" }, /* 0x7f */ 425 1.1 christos /* R_CODE_ONE_SYMBOL. */ 426 1.1 christos { 0, "L4=SD=" }, /* 0x80 */ 427 1.1 christos { 1, "L4=SD=" }, /* 0x81 */ 428 1.1 christos { 2, "L4=SD=" }, /* 0x82 */ 429 1.1 christos { 3, "L4=SD=" }, /* 0x83 */ 430 1.1 christos { 4, "L4=SD=" }, /* 0x84 */ 431 1.1 christos { 5, "L4=SD=" }, /* 0x85 */ 432 1.1 christos { 6, "L4=SD=" }, /* 0x86 */ 433 1.1 christos { 7, "L4=SD=" }, /* 0x87 */ 434 1.1 christos { 8, "L4=SD=" }, /* 0x88 */ 435 1.1 christos { 9, "L4=SD=" }, /* 0x89 */ 436 1.1 christos { 10, "L4=SD=" }, /* 0x8q */ 437 1.1 christos { 11, "L4=SD=" }, /* 0x8b */ 438 1.1 christos { 12, "L4=SD=" }, /* 0x8c */ 439 1.1 christos { 13, "L4=SD=" }, /* 0x8d */ 440 1.1 christos { 14, "L4=SD=" }, /* 0x8e */ 441 1.1 christos { 15, "L4=SD=" }, /* 0x8f */ 442 1.1 christos { 16, "L4=SD=" }, /* 0x90 */ 443 1.1 christos { 17, "L4=SD=" }, /* 0x91 */ 444 1.1 christos { 18, "L4=SD=" }, /* 0x92 */ 445 1.1 christos { 19, "L4=SD=" }, /* 0x93 */ 446 1.1 christos { 20, "L4=SD=" }, /* 0x94 */ 447 1.1 christos { 21, "L4=SD=" }, /* 0x95 */ 448 1.1 christos { 22, "L4=SD=" }, /* 0x96 */ 449 1.1 christos { 23, "L4=SD=" }, /* 0x97 */ 450 1.1 christos { 24, "L4=SD=" }, /* 0x98 */ 451 1.1 christos { 25, "L4=SD=" }, /* 0x99 */ 452 1.1 christos { 26, "L4=SD=" }, /* 0x9a */ 453 1.1 christos { 27, "L4=SD=" }, /* 0x9b */ 454 1.1 christos { 28, "L4=SD=" }, /* 0x9c */ 455 1.1 christos { 29, "L4=SD=" }, /* 0x9d */ 456 1.1 christos { 30, "L4=SD=" }, /* 0x9e */ 457 1.1 christos { 31, "L4=SD=" }, /* 0x9f */ 458 1.1 christos { 32, "L4=Sb=" }, /* 0xa0 */ 459 1.1 christos { 33, "L4=Sd=" }, /* 0xa1 */ 460 1.1 christos /* R_RESERVED. */ 461 1.1 christos { 0, "" }, /* 0xa2 */ 462 1.1 christos { 0, "" }, /* 0xa3 */ 463 1.1 christos { 0, "" }, /* 0xa4 */ 464 1.1 christos { 0, "" }, /* 0xa5 */ 465 1.1 christos { 0, "" }, /* 0xa6 */ 466 1.1 christos { 0, "" }, /* 0xa7 */ 467 1.1 christos { 0, "" }, /* 0xa8 */ 468 1.1 christos { 0, "" }, /* 0xa9 */ 469 1.1 christos { 0, "" }, /* 0xaa */ 470 1.1 christos { 0, "" }, /* 0xab */ 471 1.1 christos { 0, "" }, /* 0xac */ 472 1.1 christos { 0, "" }, /* 0xad */ 473 1.1 christos /* R_MILLI_REL. */ 474 1.1 christos { 0, "L4=Sb=" }, /* 0xae */ 475 1.1 christos { 1, "L4=Sd=" }, /* 0xaf */ 476 1.1 christos /* R_CODE_PLABEL. */ 477 1.1 christos { 0, "L4=Sb=" }, /* 0xb0 */ 478 1.1 christos { 1, "L4=Sd=" }, /* 0xb1 */ 479 1.1 christos /* R_BREAKPOINT. */ 480 1.1 christos { 0, "L4=" }, /* 0xb2 */ 481 1.1 christos /* R_ENTRY. */ 482 1.1 christos { 0, "Te=Ue=" }, /* 0xb3 */ 483 1.1 christos { 1, "Uf=" }, /* 0xb4 */ 484 1.1 christos /* R_ALT_ENTRY. */ 485 1.1 christos { 0, "" }, /* 0xb5 */ 486 1.1 christos /* R_EXIT. */ 487 1.1 christos { 0, "" }, /* 0xb6 */ 488 1.1 christos /* R_BEGIN_TRY. */ 489 1.1 christos { 0, "" }, /* 0xb7 */ 490 1.1 christos /* R_END_TRY. */ 491 1.1 christos { 0, "R0=" }, /* 0xb8 */ 492 1.1 christos { 1, "Rb4*=" }, /* 0xb9 */ 493 1.1 christos { 2, "Rd4*=" }, /* 0xba */ 494 1.1 christos /* R_BEGIN_BRTAB. */ 495 1.1 christos { 0, "" }, /* 0xbb */ 496 1.1 christos /* R_END_BRTAB. */ 497 1.1 christos { 0, "" }, /* 0xbc */ 498 1.1 christos /* R_STATEMENT. */ 499 1.1 christos { 0, "Nb=" }, /* 0xbd */ 500 1.1 christos { 1, "Nc=" }, /* 0xbe */ 501 1.1 christos { 2, "Nd=" }, /* 0xbf */ 502 1.1 christos /* R_DATA_EXPR. */ 503 1.1 christos { 0, "L4=" }, /* 0xc0 */ 504 1.1 christos /* R_CODE_EXPR. */ 505 1.1 christos { 0, "L4=" }, /* 0xc1 */ 506 1.1 christos /* R_FSEL. */ 507 1.1 christos { 0, "" }, /* 0xc2 */ 508 1.1 christos /* R_LSEL. */ 509 1.1 christos { 0, "" }, /* 0xc3 */ 510 1.1 christos /* R_RSEL. */ 511 1.1 christos { 0, "" }, /* 0xc4 */ 512 1.1 christos /* R_N_MODE. */ 513 1.1 christos { 0, "" }, /* 0xc5 */ 514 1.1 christos /* R_S_MODE. */ 515 1.1 christos { 0, "" }, /* 0xc6 */ 516 1.1 christos /* R_D_MODE. */ 517 1.1 christos { 0, "" }, /* 0xc7 */ 518 1.1 christos /* R_R_MODE. */ 519 1.1 christos { 0, "" }, /* 0xc8 */ 520 1.1 christos /* R_DATA_OVERRIDE. */ 521 1.1 christos { 0, "V0=" }, /* 0xc9 */ 522 1.1 christos { 1, "Vb=" }, /* 0xca */ 523 1.1 christos { 2, "Vc=" }, /* 0xcb */ 524 1.1 christos { 3, "Vd=" }, /* 0xcc */ 525 1.1 christos { 4, "Ve=" }, /* 0xcd */ 526 1.1 christos /* R_TRANSLATED. */ 527 1.1 christos { 0, "" }, /* 0xce */ 528 1.1 christos /* R_AUX_UNWIND. */ 529 1.1 christos { 0,"Sd=Ve=Ee=" }, /* 0xcf */ 530 1.1 christos /* R_COMP1. */ 531 1.1 christos { 0, "Ob=" }, /* 0xd0 */ 532 1.1 christos /* R_COMP2. */ 533 1.1 christos { 0, "Ob=Sd=" }, /* 0xd1 */ 534 1.1 christos /* R_COMP3. */ 535 1.1 christos { 0, "Ob=Ve=" }, /* 0xd2 */ 536 1.1 christos /* R_PREV_FIXUP. */ 537 1.1 christos { 0, "P" }, /* 0xd3 */ 538 1.1 christos { 1, "P" }, /* 0xd4 */ 539 1.1 christos { 2, "P" }, /* 0xd5 */ 540 1.1 christos { 3, "P" }, /* 0xd6 */ 541 1.1 christos /* R_SEC_STMT. */ 542 1.1 christos { 0, "" }, /* 0xd7 */ 543 1.1 christos /* R_N0SEL. */ 544 1.1 christos { 0, "" }, /* 0xd8 */ 545 1.1 christos /* R_N1SEL. */ 546 1.1 christos { 0, "" }, /* 0xd9 */ 547 1.1 christos /* R_LINETAB. */ 548 1.1 christos { 0, "Eb=Sd=Ve=" }, /* 0xda */ 549 1.1 christos /* R_LINETAB_ESC. */ 550 1.1 christos { 0, "Eb=Mb=" }, /* 0xdb */ 551 1.1 christos /* R_LTP_OVERRIDE. */ 552 1.1 christos { 0, "" }, /* 0xdc */ 553 1.1 christos /* R_COMMENT. */ 554 1.1 christos { 0, "Ob=Vf=" }, /* 0xdd */ 555 1.1 christos /* R_RESERVED. */ 556 1.1 christos { 0, "" }, /* 0xde */ 557 1.1 christos { 0, "" }, /* 0xdf */ 558 1.1 christos { 0, "" }, /* 0xe0 */ 559 1.1 christos { 0, "" }, /* 0xe1 */ 560 1.1 christos { 0, "" }, /* 0xe2 */ 561 1.1 christos { 0, "" }, /* 0xe3 */ 562 1.1 christos { 0, "" }, /* 0xe4 */ 563 1.1 christos { 0, "" }, /* 0xe5 */ 564 1.1 christos { 0, "" }, /* 0xe6 */ 565 1.1 christos { 0, "" }, /* 0xe7 */ 566 1.1 christos { 0, "" }, /* 0xe8 */ 567 1.1 christos { 0, "" }, /* 0xe9 */ 568 1.1 christos { 0, "" }, /* 0xea */ 569 1.1 christos { 0, "" }, /* 0xeb */ 570 1.1 christos { 0, "" }, /* 0xec */ 571 1.1 christos { 0, "" }, /* 0xed */ 572 1.1 christos { 0, "" }, /* 0xee */ 573 1.1 christos { 0, "" }, /* 0xef */ 574 1.1 christos { 0, "" }, /* 0xf0 */ 575 1.1 christos { 0, "" }, /* 0xf1 */ 576 1.1 christos { 0, "" }, /* 0xf2 */ 577 1.1 christos { 0, "" }, /* 0xf3 */ 578 1.1 christos { 0, "" }, /* 0xf4 */ 579 1.1 christos { 0, "" }, /* 0xf5 */ 580 1.1 christos { 0, "" }, /* 0xf6 */ 581 1.1 christos { 0, "" }, /* 0xf7 */ 582 1.1 christos { 0, "" }, /* 0xf8 */ 583 1.1 christos { 0, "" }, /* 0xf9 */ 584 1.1 christos { 0, "" }, /* 0xfa */ 585 1.1 christos { 0, "" }, /* 0xfb */ 586 1.1 christos { 0, "" }, /* 0xfc */ 587 1.1 christos { 0, "" }, /* 0xfd */ 588 1.1 christos { 0, "" }, /* 0xfe */ 589 1.1 christos { 0, "" }, /* 0xff */ 590 1.1 christos }; 591 1.1 christos 592 1.1 christos static const int comp1_opcodes[] = 593 1.1 christos { 594 1.1 christos 0x00, 595 1.1 christos 0x40, 596 1.1 christos 0x41, 597 1.1 christos 0x42, 598 1.1 christos 0x43, 599 1.1 christos 0x44, 600 1.1 christos 0x45, 601 1.1 christos 0x46, 602 1.1 christos 0x47, 603 1.1 christos 0x48, 604 1.1 christos 0x49, 605 1.1 christos 0x4a, 606 1.1 christos 0x4b, 607 1.1 christos 0x60, 608 1.1 christos 0x80, 609 1.1 christos 0xa0, 610 1.1 christos 0xc0, 611 1.1 christos -1 612 1.1 christos }; 613 1.1 christos 614 1.1 christos static const int comp2_opcodes[] = 615 1.1 christos { 616 1.1 christos 0x00, 617 1.1 christos 0x80, 618 1.1 christos 0x82, 619 1.1 christos 0xc0, 620 1.1 christos -1 621 1.1 christos }; 622 1.1 christos 623 1.1 christos static const int comp3_opcodes[] = 624 1.1 christos { 625 1.1 christos 0x00, 626 1.1 christos 0x02, 627 1.1 christos -1 628 1.1 christos }; 629 1.1 christos 630 1.1 christos /* These apparently are not in older versions of hpux reloc.h (hpux7). */ 631 1.1 christos 632 1.1 christos /* And these first appeared in hpux10. */ 633 1.1 christos #ifndef R_SHORT_PCREL_MODE 634 1.1 christos #define NO_PCREL_MODES 635 1.1 christos #define R_SHORT_PCREL_MODE 0x3e 636 1.1 christos #endif 637 1.1 christos 638 1.10 christos #define SOM_HOWTO(SIZE, TYPE) \ 639 1.10 christos HOWTO(TYPE, 0, SIZE, 32, false, 0, 0, hppa_som_reloc, \ 640 1.10 christos #TYPE, false, 0, 0, false) 641 1.1 christos 642 1.1 christos static reloc_howto_type som_hppa_howto_table[] = 643 1.1 christos { 644 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 645 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 646 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 647 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 648 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 649 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 650 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 651 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 652 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 653 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 654 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 655 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 656 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 657 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 658 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 659 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 660 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 661 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 662 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 663 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 664 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 665 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 666 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 667 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 668 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 669 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 670 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 671 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 672 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 673 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 674 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 675 1.10 christos SOM_HOWTO (0, R_NO_RELOCATION), 676 1.10 christos SOM_HOWTO (0, R_ZEROES), 677 1.10 christos SOM_HOWTO (0, R_ZEROES), 678 1.10 christos SOM_HOWTO (0, R_UNINIT), 679 1.10 christos SOM_HOWTO (0, R_UNINIT), 680 1.10 christos SOM_HOWTO (4, R_RELOCATION), 681 1.10 christos SOM_HOWTO (4, R_DATA_ONE_SYMBOL), 682 1.10 christos SOM_HOWTO (4, R_DATA_ONE_SYMBOL), 683 1.10 christos SOM_HOWTO (4, R_DATA_PLABEL), 684 1.10 christos SOM_HOWTO (4, R_DATA_PLABEL), 685 1.10 christos SOM_HOWTO (4, R_SPACE_REF), 686 1.10 christos SOM_HOWTO (0, R_REPEATED_INIT), 687 1.10 christos SOM_HOWTO (0, R_REPEATED_INIT), 688 1.10 christos SOM_HOWTO (0, R_REPEATED_INIT), 689 1.10 christos SOM_HOWTO (0, R_REPEATED_INIT), 690 1.10 christos SOM_HOWTO (0, R_RESERVED), 691 1.10 christos SOM_HOWTO (0, R_RESERVED), 692 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 693 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 694 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 695 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 696 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 697 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 698 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 699 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 700 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 701 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 702 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 703 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 704 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 705 1.10 christos SOM_HOWTO (4, R_PCREL_CALL), 706 1.10 christos SOM_HOWTO (0, R_SHORT_PCREL_MODE), 707 1.10 christos SOM_HOWTO (0, R_LONG_PCREL_MODE), 708 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 709 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 710 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 711 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 712 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 713 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 714 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 715 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 716 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 717 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 718 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 719 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 720 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 721 1.10 christos SOM_HOWTO (4, R_ABS_CALL), 722 1.10 christos SOM_HOWTO (0, R_RESERVED), 723 1.10 christos SOM_HOWTO (0, R_RESERVED), 724 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 725 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 726 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 727 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 728 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 729 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 730 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 731 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 732 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 733 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 734 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 735 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 736 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 737 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 738 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 739 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 740 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 741 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 742 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 743 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 744 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 745 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 746 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 747 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 748 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 749 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 750 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 751 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 752 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 753 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 754 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 755 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 756 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 757 1.10 christos SOM_HOWTO (4, R_DP_RELATIVE), 758 1.10 christos SOM_HOWTO (4, R_DATA_GPREL), 759 1.10 christos SOM_HOWTO (0, R_RESERVED), 760 1.10 christos SOM_HOWTO (0, R_RESERVED), 761 1.10 christos SOM_HOWTO (0, R_RESERVED), 762 1.10 christos SOM_HOWTO (0, R_RESERVED), 763 1.10 christos SOM_HOWTO (0, R_RESERVED), 764 1.10 christos SOM_HOWTO (4, R_DLT_REL), 765 1.10 christos SOM_HOWTO (4, R_DLT_REL), 766 1.10 christos SOM_HOWTO (0, R_RESERVED), 767 1.10 christos SOM_HOWTO (0, R_RESERVED), 768 1.10 christos SOM_HOWTO (0, R_RESERVED), 769 1.10 christos SOM_HOWTO (0, R_RESERVED), 770 1.10 christos SOM_HOWTO (0, R_RESERVED), 771 1.10 christos SOM_HOWTO (0, R_RESERVED), 772 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 773 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 774 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 775 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 776 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 777 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 778 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 779 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 780 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 781 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 782 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 783 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 784 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 785 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 786 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 787 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 788 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 789 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 790 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 791 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 792 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 793 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 794 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 795 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 796 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 797 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 798 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 799 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 800 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 801 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 802 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 803 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 804 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 805 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 806 1.10 christos SOM_HOWTO (4, R_CODE_ONE_SYMBOL), 807 1.10 christos SOM_HOWTO (0, R_RESERVED), 808 1.10 christos SOM_HOWTO (0, R_RESERVED), 809 1.10 christos SOM_HOWTO (0, R_RESERVED), 810 1.10 christos SOM_HOWTO (0, R_RESERVED), 811 1.10 christos SOM_HOWTO (0, R_RESERVED), 812 1.10 christos SOM_HOWTO (0, R_RESERVED), 813 1.10 christos SOM_HOWTO (0, R_RESERVED), 814 1.10 christos SOM_HOWTO (0, R_RESERVED), 815 1.10 christos SOM_HOWTO (0, R_RESERVED), 816 1.10 christos SOM_HOWTO (0, R_RESERVED), 817 1.10 christos SOM_HOWTO (0, R_RESERVED), 818 1.10 christos SOM_HOWTO (4, R_MILLI_REL), 819 1.10 christos SOM_HOWTO (4, R_MILLI_REL), 820 1.10 christos SOM_HOWTO (4, R_CODE_PLABEL), 821 1.10 christos SOM_HOWTO (4, R_CODE_PLABEL), 822 1.10 christos SOM_HOWTO (4, R_BREAKPOINT), 823 1.10 christos SOM_HOWTO (0, R_ENTRY), 824 1.10 christos SOM_HOWTO (0, R_ENTRY), 825 1.10 christos SOM_HOWTO (0, R_ALT_ENTRY), 826 1.10 christos SOM_HOWTO (0, R_EXIT), 827 1.10 christos SOM_HOWTO (0, R_BEGIN_TRY), 828 1.10 christos SOM_HOWTO (0, R_END_TRY), 829 1.10 christos SOM_HOWTO (0, R_END_TRY), 830 1.10 christos SOM_HOWTO (0, R_END_TRY), 831 1.10 christos SOM_HOWTO (0, R_BEGIN_BRTAB), 832 1.10 christos SOM_HOWTO (0, R_END_BRTAB), 833 1.10 christos SOM_HOWTO (0, R_STATEMENT), 834 1.10 christos SOM_HOWTO (0, R_STATEMENT), 835 1.10 christos SOM_HOWTO (0, R_STATEMENT), 836 1.10 christos SOM_HOWTO (4, R_DATA_EXPR), 837 1.10 christos SOM_HOWTO (4, R_CODE_EXPR), 838 1.10 christos SOM_HOWTO (0, R_FSEL), 839 1.10 christos SOM_HOWTO (0, R_LSEL), 840 1.10 christos SOM_HOWTO (0, R_RSEL), 841 1.10 christos SOM_HOWTO (0, R_N_MODE), 842 1.10 christos SOM_HOWTO (0, R_S_MODE), 843 1.10 christos SOM_HOWTO (0, R_D_MODE), 844 1.10 christos SOM_HOWTO (0, R_R_MODE), 845 1.10 christos SOM_HOWTO (0, R_DATA_OVERRIDE), 846 1.10 christos SOM_HOWTO (0, R_DATA_OVERRIDE), 847 1.10 christos SOM_HOWTO (0, R_DATA_OVERRIDE), 848 1.10 christos SOM_HOWTO (0, R_DATA_OVERRIDE), 849 1.10 christos SOM_HOWTO (0, R_DATA_OVERRIDE), 850 1.10 christos SOM_HOWTO (0, R_TRANSLATED), 851 1.10 christos SOM_HOWTO (0, R_AUX_UNWIND), 852 1.10 christos SOM_HOWTO (0, R_COMP1), 853 1.10 christos SOM_HOWTO (0, R_COMP2), 854 1.10 christos SOM_HOWTO (0, R_COMP3), 855 1.10 christos SOM_HOWTO (0, R_PREV_FIXUP), 856 1.10 christos SOM_HOWTO (0, R_PREV_FIXUP), 857 1.10 christos SOM_HOWTO (0, R_PREV_FIXUP), 858 1.10 christos SOM_HOWTO (0, R_PREV_FIXUP), 859 1.10 christos SOM_HOWTO (0, R_SEC_STMT), 860 1.10 christos SOM_HOWTO (0, R_N0SEL), 861 1.10 christos SOM_HOWTO (0, R_N1SEL), 862 1.10 christos SOM_HOWTO (0, R_LINETAB), 863 1.10 christos SOM_HOWTO (0, R_LINETAB_ESC), 864 1.10 christos SOM_HOWTO (0, R_LTP_OVERRIDE), 865 1.10 christos SOM_HOWTO (0, R_COMMENT), 866 1.10 christos SOM_HOWTO (0, R_RESERVED), 867 1.10 christos SOM_HOWTO (0, R_RESERVED), 868 1.10 christos SOM_HOWTO (0, R_RESERVED), 869 1.10 christos SOM_HOWTO (0, R_RESERVED), 870 1.10 christos SOM_HOWTO (0, R_RESERVED), 871 1.10 christos SOM_HOWTO (0, R_RESERVED), 872 1.10 christos SOM_HOWTO (0, R_RESERVED), 873 1.10 christos SOM_HOWTO (0, R_RESERVED), 874 1.10 christos SOM_HOWTO (0, R_RESERVED), 875 1.10 christos SOM_HOWTO (0, R_RESERVED), 876 1.10 christos SOM_HOWTO (0, R_RESERVED), 877 1.10 christos SOM_HOWTO (0, R_RESERVED), 878 1.10 christos SOM_HOWTO (0, R_RESERVED), 879 1.10 christos SOM_HOWTO (0, R_RESERVED), 880 1.10 christos SOM_HOWTO (0, R_RESERVED), 881 1.10 christos SOM_HOWTO (0, R_RESERVED), 882 1.10 christos SOM_HOWTO (0, R_RESERVED), 883 1.10 christos SOM_HOWTO (0, R_RESERVED), 884 1.10 christos SOM_HOWTO (0, R_RESERVED), 885 1.10 christos SOM_HOWTO (0, R_RESERVED), 886 1.10 christos SOM_HOWTO (0, R_RESERVED), 887 1.10 christos SOM_HOWTO (0, R_RESERVED), 888 1.10 christos SOM_HOWTO (0, R_RESERVED), 889 1.10 christos SOM_HOWTO (0, R_RESERVED), 890 1.10 christos SOM_HOWTO (0, R_RESERVED), 891 1.10 christos SOM_HOWTO (0, R_RESERVED), 892 1.10 christos SOM_HOWTO (0, R_RESERVED), 893 1.10 christos SOM_HOWTO (0, R_RESERVED), 894 1.10 christos SOM_HOWTO (0, R_RESERVED), 895 1.10 christos SOM_HOWTO (0, R_RESERVED), 896 1.10 christos SOM_HOWTO (0, R_RESERVED), 897 1.10 christos SOM_HOWTO (0, R_RESERVED), 898 1.10 christos SOM_HOWTO (0, R_RESERVED), 899 1.10 christos SOM_HOWTO (0, R_RESERVED) 900 1.1 christos }; 901 1.1 christos 902 1.1 christos /* Initialize the SOM relocation queue. By definition the queue holds 903 1.1 christos the last four multibyte fixups. */ 904 1.1 christos 905 1.1 christos static void 906 1.1 christos som_initialize_reloc_queue (struct reloc_queue *queue) 907 1.1 christos { 908 1.1 christos queue[0].reloc = NULL; 909 1.1 christos queue[0].size = 0; 910 1.1 christos queue[1].reloc = NULL; 911 1.1 christos queue[1].size = 0; 912 1.1 christos queue[2].reloc = NULL; 913 1.1 christos queue[2].size = 0; 914 1.1 christos queue[3].reloc = NULL; 915 1.1 christos queue[3].size = 0; 916 1.1 christos } 917 1.1 christos 918 1.1 christos /* Insert a new relocation into the relocation queue. */ 919 1.1 christos 920 1.1 christos static void 921 1.1 christos som_reloc_queue_insert (unsigned char *p, 922 1.1 christos unsigned int size, 923 1.1 christos struct reloc_queue *queue) 924 1.1 christos { 925 1.1 christos queue[3].reloc = queue[2].reloc; 926 1.1 christos queue[3].size = queue[2].size; 927 1.1 christos queue[2].reloc = queue[1].reloc; 928 1.1 christos queue[2].size = queue[1].size; 929 1.1 christos queue[1].reloc = queue[0].reloc; 930 1.1 christos queue[1].size = queue[0].size; 931 1.1 christos queue[0].reloc = p; 932 1.1 christos queue[0].size = size; 933 1.1 christos } 934 1.1 christos 935 1.1 christos /* When an entry in the relocation queue is reused, the entry moves 936 1.1 christos to the front of the queue. */ 937 1.1 christos 938 1.1 christos static void 939 1.1 christos som_reloc_queue_fix (struct reloc_queue *queue, unsigned int idx) 940 1.1 christos { 941 1.1 christos if (idx == 0) 942 1.1 christos return; 943 1.1 christos 944 1.1 christos if (idx == 1) 945 1.1 christos { 946 1.1 christos unsigned char *tmp1 = queue[0].reloc; 947 1.1 christos unsigned int tmp2 = queue[0].size; 948 1.1 christos 949 1.1 christos queue[0].reloc = queue[1].reloc; 950 1.1 christos queue[0].size = queue[1].size; 951 1.1 christos queue[1].reloc = tmp1; 952 1.1 christos queue[1].size = tmp2; 953 1.1 christos return; 954 1.1 christos } 955 1.1 christos 956 1.1 christos if (idx == 2) 957 1.1 christos { 958 1.1 christos unsigned char *tmp1 = queue[0].reloc; 959 1.1 christos unsigned int tmp2 = queue[0].size; 960 1.1 christos 961 1.1 christos queue[0].reloc = queue[2].reloc; 962 1.1 christos queue[0].size = queue[2].size; 963 1.1 christos queue[2].reloc = queue[1].reloc; 964 1.1 christos queue[2].size = queue[1].size; 965 1.1 christos queue[1].reloc = tmp1; 966 1.1 christos queue[1].size = tmp2; 967 1.1 christos return; 968 1.1 christos } 969 1.1 christos 970 1.1 christos if (idx == 3) 971 1.1 christos { 972 1.1 christos unsigned char *tmp1 = queue[0].reloc; 973 1.1 christos unsigned int tmp2 = queue[0].size; 974 1.1 christos 975 1.1 christos queue[0].reloc = queue[3].reloc; 976 1.1 christos queue[0].size = queue[3].size; 977 1.1 christos queue[3].reloc = queue[2].reloc; 978 1.1 christos queue[3].size = queue[2].size; 979 1.1 christos queue[2].reloc = queue[1].reloc; 980 1.1 christos queue[2].size = queue[1].size; 981 1.1 christos queue[1].reloc = tmp1; 982 1.1 christos queue[1].size = tmp2; 983 1.1 christos return; 984 1.1 christos } 985 1.1 christos abort (); 986 1.1 christos } 987 1.1 christos 988 1.1 christos /* Search for a particular relocation in the relocation queue. */ 989 1.1 christos 990 1.1 christos static int 991 1.1 christos som_reloc_queue_find (unsigned char *p, 992 1.1 christos unsigned int size, 993 1.1 christos struct reloc_queue *queue) 994 1.1 christos { 995 1.1 christos if (queue[0].reloc && !memcmp (p, queue[0].reloc, size) 996 1.1 christos && size == queue[0].size) 997 1.1 christos return 0; 998 1.1 christos if (queue[1].reloc && !memcmp (p, queue[1].reloc, size) 999 1.1 christos && size == queue[1].size) 1000 1.1 christos return 1; 1001 1.1 christos if (queue[2].reloc && !memcmp (p, queue[2].reloc, size) 1002 1.1 christos && size == queue[2].size) 1003 1.1 christos return 2; 1004 1.1 christos if (queue[3].reloc && !memcmp (p, queue[3].reloc, size) 1005 1.1 christos && size == queue[3].size) 1006 1.1 christos return 3; 1007 1.1 christos return -1; 1008 1.1 christos } 1009 1.1 christos 1010 1.1 christos static unsigned char * 1011 1.1 christos try_prev_fixup (bfd *abfd ATTRIBUTE_UNUSED, 1012 1.1 christos unsigned int *subspace_reloc_sizep, 1013 1.1 christos unsigned char *p, 1014 1.1 christos unsigned int size, 1015 1.1 christos struct reloc_queue *queue) 1016 1.1 christos { 1017 1.1 christos int queue_index = som_reloc_queue_find (p, size, queue); 1018 1.1 christos 1019 1.1 christos if (queue_index != -1) 1020 1.1 christos { 1021 1.1 christos /* Found this in a previous fixup. Undo the fixup we 1022 1.1 christos just built and use R_PREV_FIXUP instead. We saved 1023 1.1 christos a total of size - 1 bytes in the fixup stream. */ 1024 1.1 christos bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p); 1025 1.1 christos p += 1; 1026 1.1 christos *subspace_reloc_sizep += 1; 1027 1.1 christos som_reloc_queue_fix (queue, queue_index); 1028 1.1 christos } 1029 1.1 christos else 1030 1.1 christos { 1031 1.1 christos som_reloc_queue_insert (p, size, queue); 1032 1.1 christos *subspace_reloc_sizep += size; 1033 1.1 christos p += size; 1034 1.1 christos } 1035 1.1 christos return p; 1036 1.1 christos } 1037 1.1 christos 1038 1.1 christos /* Emit the proper R_NO_RELOCATION fixups to map the next SKIP 1039 1.1 christos bytes without any relocation. Update the size of the subspace 1040 1.1 christos relocation stream via SUBSPACE_RELOC_SIZE_P; also return the 1041 1.1 christos current pointer into the relocation stream. */ 1042 1.1 christos 1043 1.1 christos static unsigned char * 1044 1.1 christos som_reloc_skip (bfd *abfd, 1045 1.1 christos unsigned int skip, 1046 1.1 christos unsigned char *p, 1047 1.1 christos unsigned int *subspace_reloc_sizep, 1048 1.1 christos struct reloc_queue *queue) 1049 1.1 christos { 1050 1.1 christos /* Use a 4 byte R_NO_RELOCATION entry with a maximal value 1051 1.1 christos then R_PREV_FIXUPs to get the difference down to a 1052 1.1 christos reasonable size. */ 1053 1.1 christos if (skip >= 0x1000000) 1054 1.1 christos { 1055 1.1 christos skip -= 0x1000000; 1056 1.1 christos bfd_put_8 (abfd, R_NO_RELOCATION + 31, p); 1057 1.1 christos bfd_put_8 (abfd, 0xff, p + 1); 1058 1.1 christos bfd_put_16 (abfd, (bfd_vma) 0xffff, p + 2); 1059 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue); 1060 1.1 christos while (skip >= 0x1000000) 1061 1.1 christos { 1062 1.1 christos skip -= 0x1000000; 1063 1.1 christos bfd_put_8 (abfd, R_PREV_FIXUP, p); 1064 1.1 christos p++; 1065 1.1 christos *subspace_reloc_sizep += 1; 1066 1.1 christos /* No need to adjust queue here since we are repeating the 1067 1.1 christos most recent fixup. */ 1068 1.1 christos } 1069 1.1 christos } 1070 1.1 christos 1071 1.1 christos /* The difference must be less than 0x1000000. Use one 1072 1.1 christos more R_NO_RELOCATION entry to get to the right difference. */ 1073 1.1 christos if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0) 1074 1.1 christos { 1075 1.1 christos /* Difference can be handled in a simple single-byte 1076 1.1 christos R_NO_RELOCATION entry. */ 1077 1.1 christos if (skip <= 0x60) 1078 1.1 christos { 1079 1.1 christos bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p); 1080 1.1 christos *subspace_reloc_sizep += 1; 1081 1.1 christos p++; 1082 1.1 christos } 1083 1.1 christos /* Handle it with a two byte R_NO_RELOCATION entry. */ 1084 1.1 christos else if (skip <= 0x1000) 1085 1.1 christos { 1086 1.1 christos bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p); 1087 1.1 christos bfd_put_8 (abfd, (skip >> 2) - 1, p + 1); 1088 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue); 1089 1.1 christos } 1090 1.1 christos /* Handle it with a three byte R_NO_RELOCATION entry. */ 1091 1.1 christos else 1092 1.1 christos { 1093 1.1 christos bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p); 1094 1.1 christos bfd_put_16 (abfd, (bfd_vma) (skip >> 2) - 1, p + 1); 1095 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue); 1096 1.1 christos } 1097 1.1 christos } 1098 1.1 christos /* Ugh. Punt and use a 4 byte entry. */ 1099 1.1 christos else if (skip > 0) 1100 1.1 christos { 1101 1.1 christos bfd_put_8 (abfd, R_NO_RELOCATION + 31, p); 1102 1.1 christos bfd_put_8 (abfd, (skip - 1) >> 16, p + 1); 1103 1.1 christos bfd_put_16 (abfd, (bfd_vma) skip - 1, p + 2); 1104 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue); 1105 1.1 christos } 1106 1.1 christos return p; 1107 1.1 christos } 1108 1.1 christos 1109 1.1 christos /* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend 1110 1.1 christos from a BFD relocation. Update the size of the subspace relocation 1111 1.1 christos stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer 1112 1.1 christos into the relocation stream. */ 1113 1.1 christos 1114 1.1 christos static unsigned char * 1115 1.1 christos som_reloc_addend (bfd *abfd, 1116 1.1 christos bfd_vma addend, 1117 1.1 christos unsigned char *p, 1118 1.1 christos unsigned int *subspace_reloc_sizep, 1119 1.1 christos struct reloc_queue *queue) 1120 1.1 christos { 1121 1.1 christos if (addend + 0x80 < 0x100) 1122 1.1 christos { 1123 1.1 christos bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p); 1124 1.1 christos bfd_put_8 (abfd, addend, p + 1); 1125 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue); 1126 1.1 christos } 1127 1.1 christos else if (addend + 0x8000 < 0x10000) 1128 1.1 christos { 1129 1.1 christos bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p); 1130 1.1 christos bfd_put_16 (abfd, addend, p + 1); 1131 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue); 1132 1.1 christos } 1133 1.1 christos else if (addend + 0x800000 < 0x1000000) 1134 1.1 christos { 1135 1.1 christos bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p); 1136 1.1 christos bfd_put_8 (abfd, addend >> 16, p + 1); 1137 1.1 christos bfd_put_16 (abfd, addend, p + 2); 1138 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue); 1139 1.1 christos } 1140 1.1 christos else 1141 1.1 christos { 1142 1.1 christos bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p); 1143 1.1 christos bfd_put_32 (abfd, addend, p + 1); 1144 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue); 1145 1.1 christos } 1146 1.1 christos return p; 1147 1.1 christos } 1148 1.1 christos 1149 1.1 christos /* Handle a single function call relocation. */ 1150 1.1 christos 1151 1.1 christos static unsigned char * 1152 1.1 christos som_reloc_call (bfd *abfd, 1153 1.1 christos unsigned char *p, 1154 1.1 christos unsigned int *subspace_reloc_sizep, 1155 1.1 christos arelent *bfd_reloc, 1156 1.1 christos int sym_num, 1157 1.1 christos struct reloc_queue *queue) 1158 1.1 christos { 1159 1.1 christos int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend); 1160 1.1 christos int rtn_bits = arg_bits & 0x3; 1161 1.1 christos int type, done = 0; 1162 1.1 christos 1163 1.1 christos /* You'll never believe all this is necessary to handle relocations 1164 1.1 christos for function calls. Having to compute and pack the argument 1165 1.1 christos relocation bits is the real nightmare. 1166 1.1 christos 1167 1.1 christos If you're interested in how this works, just forget it. You really 1168 1.1 christos do not want to know about this braindamage. */ 1169 1.1 christos 1170 1.1 christos /* First see if this can be done with a "simple" relocation. Simple 1171 1.1 christos relocations have a symbol number < 0x100 and have simple encodings 1172 1.1 christos of argument relocations. */ 1173 1.1 christos 1174 1.1 christos if (sym_num < 0x100) 1175 1.1 christos { 1176 1.1 christos switch (arg_bits) 1177 1.1 christos { 1178 1.1 christos case 0: 1179 1.1 christos case 1: 1180 1.1 christos type = 0; 1181 1.1 christos break; 1182 1.1 christos case 1 << 8: 1183 1.1 christos case 1 << 8 | 1: 1184 1.1 christos type = 1; 1185 1.1 christos break; 1186 1.1 christos case 1 << 8 | 1 << 6: 1187 1.1 christos case 1 << 8 | 1 << 6 | 1: 1188 1.1 christos type = 2; 1189 1.1 christos break; 1190 1.1 christos case 1 << 8 | 1 << 6 | 1 << 4: 1191 1.1 christos case 1 << 8 | 1 << 6 | 1 << 4 | 1: 1192 1.1 christos type = 3; 1193 1.1 christos break; 1194 1.1 christos case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2: 1195 1.1 christos case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1: 1196 1.1 christos type = 4; 1197 1.1 christos break; 1198 1.1 christos default: 1199 1.1 christos /* Not one of the easy encodings. This will have to be 1200 1.1 christos handled by the more complex code below. */ 1201 1.1 christos type = -1; 1202 1.1 christos break; 1203 1.1 christos } 1204 1.1 christos if (type != -1) 1205 1.1 christos { 1206 1.1 christos /* Account for the return value too. */ 1207 1.1 christos if (rtn_bits) 1208 1.1 christos type += 5; 1209 1.1 christos 1210 1.1 christos /* Emit a 2 byte relocation. Then see if it can be handled 1211 1.1 christos with a relocation which is already in the relocation queue. */ 1212 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + type, p); 1213 1.1 christos bfd_put_8 (abfd, sym_num, p + 1); 1214 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue); 1215 1.1 christos done = 1; 1216 1.1 christos } 1217 1.1 christos } 1218 1.1 christos 1219 1.1 christos /* If this could not be handled with a simple relocation, then do a hard 1220 1.1 christos one. Hard relocations occur if the symbol number was too high or if 1221 1.1 christos the encoding of argument relocation bits is too complex. */ 1222 1.1 christos if (! done) 1223 1.1 christos { 1224 1.1 christos /* Don't ask about these magic sequences. I took them straight 1225 1.1 christos from gas-1.36 which took them from the a.out man page. */ 1226 1.1 christos type = rtn_bits; 1227 1.1 christos if ((arg_bits >> 6 & 0xf) == 0xe) 1228 1.1 christos type += 9 * 40; 1229 1.1 christos else 1230 1.1 christos type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40; 1231 1.1 christos if ((arg_bits >> 2 & 0xf) == 0xe) 1232 1.1 christos type += 9 * 4; 1233 1.1 christos else 1234 1.1 christos type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4; 1235 1.1 christos 1236 1.1 christos /* Output the first two bytes of the relocation. These describe 1237 1.1 christos the length of the relocation and encoding style. */ 1238 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + 10 1239 1.1 christos + 2 * (sym_num >= 0x100) + (type >= 0x100), 1240 1.1 christos p); 1241 1.1 christos bfd_put_8 (abfd, type, p + 1); 1242 1.1 christos 1243 1.1 christos /* Now output the symbol index and see if this bizarre relocation 1244 1.1 christos just happened to be in the relocation queue. */ 1245 1.1 christos if (sym_num < 0x100) 1246 1.1 christos { 1247 1.1 christos bfd_put_8 (abfd, sym_num, p + 2); 1248 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue); 1249 1.1 christos } 1250 1.1 christos else 1251 1.1 christos { 1252 1.1 christos bfd_put_8 (abfd, sym_num >> 16, p + 2); 1253 1.1 christos bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3); 1254 1.1 christos p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue); 1255 1.1 christos } 1256 1.1 christos } 1257 1.1 christos return p; 1258 1.1 christos } 1259 1.1 christos 1260 1.1 christos /* Return the logarithm of X, base 2, considering X unsigned, 1261 1.1 christos if X is a power of 2. Otherwise, returns -1. */ 1262 1.1 christos 1263 1.1 christos static int 1264 1.1 christos exact_log2 (unsigned int x) 1265 1.1 christos { 1266 1.1 christos int log = 0; 1267 1.1 christos 1268 1.1 christos /* Test for 0 or a power of 2. */ 1269 1.1 christos if (x == 0 || x != (x & -x)) 1270 1.1 christos return -1; 1271 1.1 christos 1272 1.1 christos while ((x >>= 1) != 0) 1273 1.1 christos log++; 1274 1.1 christos return log; 1275 1.1 christos } 1276 1.1 christos 1277 1.1 christos static bfd_reloc_status_type 1278 1.1 christos hppa_som_reloc (bfd *abfd ATTRIBUTE_UNUSED, 1279 1.1 christos arelent *reloc_entry, 1280 1.1 christos asymbol *symbol_in ATTRIBUTE_UNUSED, 1281 1.1 christos void *data ATTRIBUTE_UNUSED, 1282 1.1 christos asection *input_section, 1283 1.1 christos bfd *output_bfd, 1284 1.1 christos char **error_message ATTRIBUTE_UNUSED) 1285 1.1 christos { 1286 1.1 christos if (output_bfd) 1287 1.1 christos reloc_entry->address += input_section->output_offset; 1288 1.1 christos 1289 1.1 christos return bfd_reloc_ok; 1290 1.1 christos } 1291 1.1 christos 1292 1.1 christos /* Given a generic HPPA relocation type, the instruction format, 1293 1.1 christos and a field selector, return one or more appropriate SOM relocations. */ 1294 1.1 christos 1295 1.1 christos int ** 1296 1.1 christos hppa_som_gen_reloc_type (bfd *abfd, 1297 1.1 christos int base_type, 1298 1.1 christos int format, 1299 1.1 christos enum hppa_reloc_field_selector_type_alt field, 1300 1.1 christos int sym_diff, 1301 1.1 christos asymbol *sym) 1302 1.1 christos { 1303 1.1 christos int *final_type, **final_types; 1304 1.1 christos 1305 1.1 christos final_types = bfd_alloc (abfd, (bfd_size_type) sizeof (int *) * 6); 1306 1.1 christos final_type = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1307 1.1 christos if (!final_types || !final_type) 1308 1.1 christos return NULL; 1309 1.1 christos 1310 1.1 christos /* The field selector may require additional relocations to be 1311 1.1 christos generated. It's impossible to know at this moment if additional 1312 1.1 christos relocations will be needed, so we make them. The code to actually 1313 1.1 christos write the relocation/fixup stream is responsible for removing 1314 1.1 christos any redundant relocations. */ 1315 1.1 christos switch (field) 1316 1.1 christos { 1317 1.1 christos case e_fsel: 1318 1.1 christos case e_psel: 1319 1.1 christos case e_lpsel: 1320 1.1 christos case e_rpsel: 1321 1.1 christos final_types[0] = final_type; 1322 1.1 christos final_types[1] = NULL; 1323 1.1 christos final_types[2] = NULL; 1324 1.1 christos *final_type = base_type; 1325 1.1 christos break; 1326 1.1 christos 1327 1.1 christos case e_tsel: 1328 1.1 christos case e_ltsel: 1329 1.1 christos case e_rtsel: 1330 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1331 1.1 christos if (!final_types[0]) 1332 1.1 christos return NULL; 1333 1.1 christos if (field == e_tsel) 1334 1.1 christos *final_types[0] = R_FSEL; 1335 1.1 christos else if (field == e_ltsel) 1336 1.1 christos *final_types[0] = R_LSEL; 1337 1.1 christos else 1338 1.1 christos *final_types[0] = R_RSEL; 1339 1.1 christos final_types[1] = final_type; 1340 1.1 christos final_types[2] = NULL; 1341 1.1 christos *final_type = base_type; 1342 1.1 christos break; 1343 1.1 christos 1344 1.1 christos case e_lssel: 1345 1.1 christos case e_rssel: 1346 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1347 1.1 christos if (!final_types[0]) 1348 1.1 christos return NULL; 1349 1.1 christos *final_types[0] = R_S_MODE; 1350 1.1 christos final_types[1] = final_type; 1351 1.1 christos final_types[2] = NULL; 1352 1.1 christos *final_type = base_type; 1353 1.1 christos break; 1354 1.1 christos 1355 1.1 christos case e_lsel: 1356 1.1 christos case e_rsel: 1357 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1358 1.1 christos if (!final_types[0]) 1359 1.1 christos return NULL; 1360 1.1 christos *final_types[0] = R_N_MODE; 1361 1.1 christos final_types[1] = final_type; 1362 1.1 christos final_types[2] = NULL; 1363 1.1 christos *final_type = base_type; 1364 1.1 christos break; 1365 1.1 christos 1366 1.1 christos case e_ldsel: 1367 1.1 christos case e_rdsel: 1368 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1369 1.1 christos if (!final_types[0]) 1370 1.1 christos return NULL; 1371 1.1 christos *final_types[0] = R_D_MODE; 1372 1.1 christos final_types[1] = final_type; 1373 1.1 christos final_types[2] = NULL; 1374 1.1 christos *final_type = base_type; 1375 1.1 christos break; 1376 1.1 christos 1377 1.1 christos case e_lrsel: 1378 1.1 christos case e_rrsel: 1379 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1380 1.1 christos if (!final_types[0]) 1381 1.1 christos return NULL; 1382 1.1 christos *final_types[0] = R_R_MODE; 1383 1.1 christos final_types[1] = final_type; 1384 1.1 christos final_types[2] = NULL; 1385 1.1 christos *final_type = base_type; 1386 1.1 christos break; 1387 1.1 christos 1388 1.1 christos case e_nsel: 1389 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1390 1.1 christos if (!final_types[0]) 1391 1.1 christos return NULL; 1392 1.1 christos *final_types[0] = R_N1SEL; 1393 1.1 christos final_types[1] = final_type; 1394 1.1 christos final_types[2] = NULL; 1395 1.1 christos *final_type = base_type; 1396 1.1 christos break; 1397 1.1 christos 1398 1.1 christos case e_nlsel: 1399 1.1 christos case e_nlrsel: 1400 1.1 christos final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1401 1.1 christos if (!final_types[0]) 1402 1.1 christos return NULL; 1403 1.1 christos *final_types[0] = R_N0SEL; 1404 1.1 christos final_types[1] = bfd_alloc (abfd, (bfd_size_type) sizeof (int)); 1405 1.1 christos if (!final_types[1]) 1406 1.1 christos return NULL; 1407 1.1 christos if (field == e_nlsel) 1408 1.1 christos *final_types[1] = R_N_MODE; 1409 1.1 christos else 1410 1.1 christos *final_types[1] = R_R_MODE; 1411 1.1 christos final_types[2] = final_type; 1412 1.1 christos final_types[3] = NULL; 1413 1.1 christos *final_type = base_type; 1414 1.1 christos break; 1415 1.1 christos 1416 1.1 christos /* FIXME: These two field selectors are not currently supported. */ 1417 1.1 christos case e_ltpsel: 1418 1.1 christos case e_rtpsel: 1419 1.1 christos abort (); 1420 1.1 christos } 1421 1.1 christos 1422 1.1 christos switch (base_type) 1423 1.1 christos { 1424 1.1 christos case R_HPPA: 1425 1.1 christos /* The difference of two symbols needs *very* special handling. */ 1426 1.1 christos if (sym_diff) 1427 1.1 christos { 1428 1.9 christos size_t amt = sizeof (int); 1429 1.1 christos 1430 1.1 christos final_types[0] = bfd_alloc (abfd, amt); 1431 1.1 christos final_types[1] = bfd_alloc (abfd, amt); 1432 1.1 christos final_types[2] = bfd_alloc (abfd, amt); 1433 1.1 christos final_types[3] = bfd_alloc (abfd, amt); 1434 1.1 christos if (!final_types[0] || !final_types[1] || !final_types[2]) 1435 1.1 christos return NULL; 1436 1.1 christos if (field == e_fsel) 1437 1.1 christos *final_types[0] = R_FSEL; 1438 1.1 christos else if (field == e_rsel) 1439 1.1 christos *final_types[0] = R_RSEL; 1440 1.1 christos else if (field == e_lsel) 1441 1.1 christos *final_types[0] = R_LSEL; 1442 1.1 christos *final_types[1] = R_COMP2; 1443 1.1 christos *final_types[2] = R_COMP2; 1444 1.1 christos *final_types[3] = R_COMP1; 1445 1.1 christos final_types[4] = final_type; 1446 1.1 christos if (format == 32) 1447 1.1 christos *final_types[4] = R_DATA_EXPR; 1448 1.1 christos else 1449 1.1 christos *final_types[4] = R_CODE_EXPR; 1450 1.1 christos final_types[5] = NULL; 1451 1.1 christos break; 1452 1.1 christos } 1453 1.1 christos /* PLABELs get their own relocation type. */ 1454 1.1 christos else if (field == e_psel 1455 1.1 christos || field == e_lpsel 1456 1.1 christos || field == e_rpsel) 1457 1.1 christos { 1458 1.1 christos /* A PLABEL relocation that has a size of 32 bits must 1459 1.1 christos be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */ 1460 1.1 christos if (format == 32) 1461 1.1 christos *final_type = R_DATA_PLABEL; 1462 1.1 christos else 1463 1.1 christos *final_type = R_CODE_PLABEL; 1464 1.1 christos } 1465 1.1 christos /* PIC stuff. */ 1466 1.1 christos else if (field == e_tsel 1467 1.1 christos || field == e_ltsel 1468 1.1 christos || field == e_rtsel) 1469 1.1 christos *final_type = R_DLT_REL; 1470 1.1 christos /* A relocation in the data space is always a full 32bits. */ 1471 1.1 christos else if (format == 32) 1472 1.1 christos { 1473 1.1 christos *final_type = R_DATA_ONE_SYMBOL; 1474 1.1 christos 1475 1.1 christos /* If there's no SOM symbol type associated with this BFD 1476 1.1 christos symbol, then set the symbol type to ST_DATA. 1477 1.1 christos 1478 1.1 christos Only do this if the type is going to default later when 1479 1.1 christos we write the object file. 1480 1.1 christos 1481 1.1 christos This is done so that the linker never encounters an 1482 1.1 christos R_DATA_ONE_SYMBOL reloc involving an ST_CODE symbol. 1483 1.1 christos 1484 1.1 christos This allows the compiler to generate exception handling 1485 1.1 christos tables. 1486 1.1 christos 1487 1.1 christos Note that one day we may need to also emit BEGIN_BRTAB and 1488 1.1 christos END_BRTAB to prevent the linker from optimizing away insns 1489 1.1 christos in exception handling regions. */ 1490 1.1 christos if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN 1491 1.1 christos && (sym->flags & BSF_SECTION_SYM) == 0 1492 1.1 christos && (sym->flags & BSF_FUNCTION) == 0 1493 1.1 christos && ! bfd_is_com_section (sym->section)) 1494 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA; 1495 1.1 christos } 1496 1.1 christos break; 1497 1.1 christos 1498 1.1 christos case R_HPPA_GOTOFF: 1499 1.1 christos /* More PLABEL special cases. */ 1500 1.1 christos if (field == e_psel 1501 1.1 christos || field == e_lpsel 1502 1.1 christos || field == e_rpsel) 1503 1.1 christos *final_type = R_DATA_PLABEL; 1504 1.1 christos else if (field == e_fsel && format == 32) 1505 1.1 christos *final_type = R_DATA_GPREL; 1506 1.1 christos break; 1507 1.1 christos 1508 1.1 christos case R_HPPA_COMPLEX: 1509 1.1 christos /* The difference of two symbols needs *very* special handling. */ 1510 1.1 christos if (sym_diff) 1511 1.1 christos { 1512 1.9 christos size_t amt = sizeof (int); 1513 1.1 christos 1514 1.1 christos final_types[0] = bfd_alloc (abfd, amt); 1515 1.1 christos final_types[1] = bfd_alloc (abfd, amt); 1516 1.1 christos final_types[2] = bfd_alloc (abfd, amt); 1517 1.1 christos final_types[3] = bfd_alloc (abfd, amt); 1518 1.1 christos if (!final_types[0] || !final_types[1] || !final_types[2]) 1519 1.1 christos return NULL; 1520 1.1 christos if (field == e_fsel) 1521 1.1 christos *final_types[0] = R_FSEL; 1522 1.1 christos else if (field == e_rsel) 1523 1.1 christos *final_types[0] = R_RSEL; 1524 1.1 christos else if (field == e_lsel) 1525 1.1 christos *final_types[0] = R_LSEL; 1526 1.1 christos *final_types[1] = R_COMP2; 1527 1.1 christos *final_types[2] = R_COMP2; 1528 1.1 christos *final_types[3] = R_COMP1; 1529 1.1 christos final_types[4] = final_type; 1530 1.1 christos if (format == 32) 1531 1.1 christos *final_types[4] = R_DATA_EXPR; 1532 1.1 christos else 1533 1.1 christos *final_types[4] = R_CODE_EXPR; 1534 1.1 christos final_types[5] = NULL; 1535 1.1 christos break; 1536 1.1 christos } 1537 1.1 christos else 1538 1.1 christos break; 1539 1.1 christos 1540 1.1 christos case R_HPPA_NONE: 1541 1.1 christos case R_HPPA_ABS_CALL: 1542 1.1 christos /* Right now we can default all these. */ 1543 1.1 christos break; 1544 1.1 christos 1545 1.1 christos case R_HPPA_PCREL_CALL: 1546 1.1 christos { 1547 1.1 christos #ifndef NO_PCREL_MODES 1548 1.1 christos /* If we have short and long pcrel modes, then generate the proper 1549 1.1 christos mode selector, then the pcrel relocation. Redundant selectors 1550 1.1 christos will be eliminated as the relocs are sized and emitted. */ 1551 1.9 christos size_t amt = sizeof (int); 1552 1.1 christos 1553 1.1 christos final_types[0] = bfd_alloc (abfd, amt); 1554 1.1 christos if (!final_types[0]) 1555 1.1 christos return NULL; 1556 1.1 christos if (format == 17) 1557 1.1 christos *final_types[0] = R_SHORT_PCREL_MODE; 1558 1.1 christos else 1559 1.1 christos *final_types[0] = R_LONG_PCREL_MODE; 1560 1.1 christos final_types[1] = final_type; 1561 1.1 christos final_types[2] = NULL; 1562 1.1 christos *final_type = base_type; 1563 1.1 christos #endif 1564 1.1 christos break; 1565 1.1 christos } 1566 1.1 christos } 1567 1.1 christos return final_types; 1568 1.1 christos } 1569 1.1 christos 1570 1.1 christos /* Return the address of the correct entry in the PA SOM relocation 1571 1.1 christos howto table. */ 1572 1.1 christos 1573 1.1 christos static reloc_howto_type * 1574 1.1 christos som_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1575 1.1 christos bfd_reloc_code_real_type code) 1576 1.1 christos { 1577 1.1 christos if ((int) code < (int) R_NO_RELOCATION + 255) 1578 1.1 christos { 1579 1.1 christos BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code); 1580 1.1 christos return &som_hppa_howto_table[(int) code]; 1581 1.1 christos } 1582 1.1 christos 1583 1.1 christos return NULL; 1584 1.1 christos } 1585 1.1 christos 1586 1.1 christos static reloc_howto_type * 1587 1.1 christos som_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1588 1.1 christos const char *r_name) 1589 1.1 christos { 1590 1.1 christos unsigned int i; 1591 1.1 christos 1592 1.1 christos for (i = 0; 1593 1.1 christos i < sizeof (som_hppa_howto_table) / sizeof (som_hppa_howto_table[0]); 1594 1.1 christos i++) 1595 1.1 christos if (som_hppa_howto_table[i].name != NULL 1596 1.1 christos && strcasecmp (som_hppa_howto_table[i].name, r_name) == 0) 1597 1.1 christos return &som_hppa_howto_table[i]; 1598 1.1 christos 1599 1.1 christos return NULL; 1600 1.1 christos } 1601 1.1 christos 1602 1.1 christos static void 1603 1.1 christos som_swap_clock_in (struct som_external_clock *src, 1604 1.8 christos struct som_clock *dst) 1605 1.1 christos { 1606 1.1 christos dst->secs = bfd_getb32 (src->secs); 1607 1.1 christos dst->nanosecs = bfd_getb32 (src->nanosecs); 1608 1.1 christos } 1609 1.1 christos 1610 1.1 christos static void 1611 1.1 christos som_swap_clock_out (struct som_clock *src, 1612 1.8 christos struct som_external_clock *dst) 1613 1.1 christos { 1614 1.1 christos bfd_putb32 (src->secs, dst->secs); 1615 1.1 christos bfd_putb32 (src->nanosecs, dst->nanosecs); 1616 1.1 christos } 1617 1.1 christos 1618 1.1 christos static void 1619 1.1 christos som_swap_header_in (struct som_external_header *src, 1620 1.8 christos struct som_header *dst) 1621 1.1 christos { 1622 1.1 christos dst->system_id = bfd_getb16 (src->system_id); 1623 1.1 christos dst->a_magic = bfd_getb16 (src->a_magic); 1624 1.1 christos dst->version_id = bfd_getb32 (src->version_id); 1625 1.1 christos som_swap_clock_in (&src->file_time, &dst->file_time); 1626 1.1 christos dst->entry_space = bfd_getb32 (src->entry_space); 1627 1.1 christos dst->entry_subspace = bfd_getb32 (src->entry_subspace); 1628 1.1 christos dst->entry_offset = bfd_getb32 (src->entry_offset); 1629 1.1 christos dst->aux_header_location = bfd_getb32 (src->aux_header_location); 1630 1.1 christos dst->aux_header_size = bfd_getb32 (src->aux_header_size); 1631 1.1 christos dst->som_length = bfd_getb32 (src->som_length); 1632 1.1 christos dst->presumed_dp = bfd_getb32 (src->presumed_dp); 1633 1.1 christos dst->space_location = bfd_getb32 (src->space_location); 1634 1.1 christos dst->space_total = bfd_getb32 (src->space_total); 1635 1.1 christos dst->subspace_location = bfd_getb32 (src->subspace_location); 1636 1.1 christos dst->subspace_total = bfd_getb32 (src->subspace_total); 1637 1.1 christos dst->loader_fixup_location = bfd_getb32 (src->loader_fixup_location); 1638 1.1 christos dst->loader_fixup_total = bfd_getb32 (src->loader_fixup_total); 1639 1.1 christos dst->space_strings_location = bfd_getb32 (src->space_strings_location); 1640 1.1 christos dst->space_strings_size = bfd_getb32 (src->space_strings_size); 1641 1.1 christos dst->init_array_location = bfd_getb32 (src->init_array_location); 1642 1.1 christos dst->init_array_total = bfd_getb32 (src->init_array_total); 1643 1.1 christos dst->compiler_location = bfd_getb32 (src->compiler_location); 1644 1.1 christos dst->compiler_total = bfd_getb32 (src->compiler_total); 1645 1.1 christos dst->symbol_location = bfd_getb32 (src->symbol_location); 1646 1.1 christos dst->symbol_total = bfd_getb32 (src->symbol_total); 1647 1.1 christos dst->fixup_request_location = bfd_getb32 (src->fixup_request_location); 1648 1.1 christos dst->fixup_request_total = bfd_getb32 (src->fixup_request_total); 1649 1.1 christos dst->symbol_strings_location = bfd_getb32 (src->symbol_strings_location); 1650 1.1 christos dst->symbol_strings_size = bfd_getb32 (src->symbol_strings_size); 1651 1.1 christos dst->unloadable_sp_location = bfd_getb32 (src->unloadable_sp_location); 1652 1.1 christos dst->unloadable_sp_size = bfd_getb32 (src->unloadable_sp_size); 1653 1.1 christos dst->checksum = bfd_getb32 (src->checksum); 1654 1.1 christos } 1655 1.1 christos 1656 1.1 christos static void 1657 1.1 christos som_swap_header_out (struct som_header *src, 1658 1.8 christos struct som_external_header *dst) 1659 1.1 christos { 1660 1.1 christos bfd_putb16 (src->system_id, dst->system_id); 1661 1.1 christos bfd_putb16 (src->a_magic, dst->a_magic); 1662 1.1 christos bfd_putb32 (src->version_id, dst->version_id); 1663 1.1 christos som_swap_clock_out (&src->file_time, &dst->file_time); 1664 1.1 christos bfd_putb32 (src->entry_space, dst->entry_space); 1665 1.1 christos bfd_putb32 (src->entry_subspace, dst->entry_subspace); 1666 1.1 christos bfd_putb32 (src->entry_offset, dst->entry_offset); 1667 1.1 christos bfd_putb32 (src->aux_header_location, dst->aux_header_location); 1668 1.1 christos bfd_putb32 (src->aux_header_size, dst->aux_header_size); 1669 1.1 christos bfd_putb32 (src->som_length, dst->som_length); 1670 1.1 christos bfd_putb32 (src->presumed_dp, dst->presumed_dp); 1671 1.1 christos bfd_putb32 (src->space_location, dst->space_location); 1672 1.1 christos bfd_putb32 (src->space_total, dst->space_total); 1673 1.1 christos bfd_putb32 (src->subspace_location, dst->subspace_location); 1674 1.1 christos bfd_putb32 (src->subspace_total, dst->subspace_total); 1675 1.1 christos bfd_putb32 (src->loader_fixup_location, dst->loader_fixup_location); 1676 1.1 christos bfd_putb32 (src->loader_fixup_total, dst->loader_fixup_total); 1677 1.1 christos bfd_putb32 (src->space_strings_location, dst->space_strings_location); 1678 1.1 christos bfd_putb32 (src->space_strings_size, dst->space_strings_size); 1679 1.1 christos bfd_putb32 (src->init_array_location, dst->init_array_location); 1680 1.1 christos bfd_putb32 (src->init_array_total, dst->init_array_total); 1681 1.1 christos bfd_putb32 (src->compiler_location, dst->compiler_location); 1682 1.1 christos bfd_putb32 (src->compiler_total, dst->compiler_total); 1683 1.1 christos bfd_putb32 (src->symbol_location, dst->symbol_location); 1684 1.1 christos bfd_putb32 (src->symbol_total, dst->symbol_total); 1685 1.1 christos bfd_putb32 (src->fixup_request_location, dst->fixup_request_location); 1686 1.1 christos bfd_putb32 (src->fixup_request_total, dst->fixup_request_total); 1687 1.1 christos bfd_putb32 (src->symbol_strings_location, dst->symbol_strings_location); 1688 1.1 christos bfd_putb32 (src->symbol_strings_size, dst->symbol_strings_size); 1689 1.1 christos bfd_putb32 (src->unloadable_sp_location, dst->unloadable_sp_location); 1690 1.1 christos bfd_putb32 (src->unloadable_sp_size, dst->unloadable_sp_size); 1691 1.1 christos bfd_putb32 (src->checksum, dst->checksum); 1692 1.1 christos } 1693 1.1 christos 1694 1.1 christos static void 1695 1.1 christos som_swap_space_dictionary_in (struct som_external_space_dictionary_record *src, 1696 1.8 christos struct som_space_dictionary_record *dst) 1697 1.1 christos { 1698 1.1 christos unsigned int flags; 1699 1.1 christos 1700 1.1 christos dst->name = bfd_getb32 (src->name); 1701 1.1 christos flags = bfd_getb32 (src->flags); 1702 1.1 christos dst->is_loadable = (flags & SOM_SPACE_IS_LOADABLE) != 0; 1703 1.1 christos dst->is_defined = (flags & SOM_SPACE_IS_DEFINED) != 0; 1704 1.1 christos dst->is_private = (flags & SOM_SPACE_IS_PRIVATE) != 0; 1705 1.1 christos dst->has_intermediate_code = (flags & SOM_SPACE_HAS_INTERMEDIATE_CODE) != 0; 1706 1.1 christos dst->is_tspecific = (flags & SOM_SPACE_IS_TSPECIFIC) != 0; 1707 1.1 christos dst->reserved = 0; 1708 1.1 christos dst->sort_key = (flags >> SOM_SPACE_SORT_KEY_SH) & SOM_SPACE_SORT_KEY_MASK; 1709 1.1 christos dst->reserved2 = 0; 1710 1.1 christos dst->space_number = bfd_getb32 (src->space_number); 1711 1.1 christos dst->subspace_index = bfd_getb32 (src->subspace_index); 1712 1.1 christos dst->subspace_quantity = bfd_getb32 (src->subspace_quantity); 1713 1.1 christos dst->loader_fix_index = bfd_getb32 (src->loader_fix_index); 1714 1.1 christos dst->loader_fix_quantity = bfd_getb32 (src->loader_fix_quantity); 1715 1.1 christos dst->init_pointer_index = bfd_getb32 (src->init_pointer_index); 1716 1.1 christos dst->init_pointer_quantity = bfd_getb32 (src->init_pointer_quantity); 1717 1.1 christos } 1718 1.1 christos 1719 1.1 christos static void 1720 1.1 christos som_swap_space_dictionary_out (struct som_space_dictionary_record *src, 1721 1.8 christos struct som_external_space_dictionary_record *dst) 1722 1.1 christos { 1723 1.1 christos unsigned int flags; 1724 1.1 christos 1725 1.1 christos bfd_putb32 (src->name, dst->name); 1726 1.1 christos 1727 1.1 christos flags = 0; 1728 1.1 christos if (src->is_loadable) 1729 1.1 christos flags |= SOM_SPACE_IS_LOADABLE; 1730 1.1 christos if (src->is_defined) 1731 1.1 christos flags |= SOM_SPACE_IS_DEFINED; 1732 1.1 christos if (src->is_private) 1733 1.1 christos flags |= SOM_SPACE_IS_PRIVATE; 1734 1.1 christos if (src->has_intermediate_code) 1735 1.1 christos flags |= SOM_SPACE_HAS_INTERMEDIATE_CODE; 1736 1.1 christos if (src->is_tspecific) 1737 1.1 christos flags |= SOM_SPACE_IS_TSPECIFIC; 1738 1.1 christos flags |= (src->sort_key & SOM_SPACE_SORT_KEY_MASK) << SOM_SPACE_SORT_KEY_SH; 1739 1.1 christos bfd_putb32 (flags, dst->flags); 1740 1.1 christos bfd_putb32 (src->space_number, dst->space_number); 1741 1.1 christos bfd_putb32 (src->subspace_index, dst->subspace_index); 1742 1.1 christos bfd_putb32 (src->subspace_quantity, dst->subspace_quantity); 1743 1.1 christos bfd_putb32 (src->loader_fix_index, dst->loader_fix_index); 1744 1.1 christos bfd_putb32 (src->loader_fix_quantity, dst->loader_fix_quantity); 1745 1.1 christos bfd_putb32 (src->init_pointer_index, dst->init_pointer_index); 1746 1.1 christos bfd_putb32 (src->init_pointer_quantity, dst->init_pointer_quantity); 1747 1.1 christos } 1748 1.1 christos 1749 1.1 christos static void 1750 1.1 christos som_swap_subspace_dictionary_in 1751 1.1 christos (struct som_external_subspace_dictionary_record *src, 1752 1.1 christos struct som_subspace_dictionary_record *dst) 1753 1.1 christos { 1754 1.1 christos unsigned int flags; 1755 1.1 christos dst->space_index = bfd_getb32 (src->space_index); 1756 1.1 christos flags = bfd_getb32 (src->flags); 1757 1.1 christos dst->access_control_bits = (flags >> SOM_SUBSPACE_ACCESS_CONTROL_BITS_SH) 1758 1.1 christos & SOM_SUBSPACE_ACCESS_CONTROL_BITS_MASK; 1759 1.1 christos dst->memory_resident = (flags & SOM_SUBSPACE_MEMORY_RESIDENT) != 0; 1760 1.1 christos dst->dup_common = (flags & SOM_SUBSPACE_DUP_COMMON) != 0; 1761 1.1 christos dst->is_common = (flags & SOM_SUBSPACE_IS_COMMON) != 0; 1762 1.1 christos dst->is_loadable = (flags & SOM_SUBSPACE_IS_LOADABLE) != 0; 1763 1.1 christos dst->quadrant = (flags >> SOM_SUBSPACE_QUADRANT_SH) 1764 1.1 christos & SOM_SUBSPACE_QUADRANT_MASK; 1765 1.1 christos dst->initially_frozen = (flags & SOM_SUBSPACE_INITIALLY_FROZEN) != 0; 1766 1.1 christos dst->is_first = (flags & SOM_SUBSPACE_IS_FIRST) != 0; 1767 1.1 christos dst->code_only = (flags & SOM_SUBSPACE_CODE_ONLY) != 0; 1768 1.1 christos dst->sort_key = (flags >> SOM_SUBSPACE_SORT_KEY_SH) 1769 1.1 christos & SOM_SUBSPACE_SORT_KEY_MASK; 1770 1.1 christos dst->replicate_init = (flags & SOM_SUBSPACE_REPLICATE_INIT) != 0; 1771 1.1 christos dst->continuation = (flags & SOM_SUBSPACE_CONTINUATION) != 0; 1772 1.1 christos dst->is_tspecific = (flags & SOM_SUBSPACE_IS_TSPECIFIC) != 0; 1773 1.1 christos dst->is_comdat = (flags & SOM_SUBSPACE_IS_COMDAT) != 0; 1774 1.1 christos dst->reserved = 0; 1775 1.1 christos dst->file_loc_init_value = bfd_getb32 (src->file_loc_init_value); 1776 1.1 christos dst->initialization_length = bfd_getb32 (src->initialization_length); 1777 1.1 christos dst->subspace_start = bfd_getb32 (src->subspace_start); 1778 1.1 christos dst->subspace_length = bfd_getb32 (src->subspace_length); 1779 1.1 christos dst->alignment = bfd_getb32 (src->alignment); 1780 1.1 christos dst->name = bfd_getb32 (src->name); 1781 1.1 christos dst->fixup_request_index = bfd_getb32 (src->fixup_request_index); 1782 1.1 christos dst->fixup_request_quantity = bfd_getb32 (src->fixup_request_quantity); 1783 1.1 christos } 1784 1.1 christos 1785 1.1 christos static void 1786 1.1 christos som_swap_subspace_dictionary_record_out 1787 1.1 christos (struct som_subspace_dictionary_record *src, 1788 1.1 christos struct som_external_subspace_dictionary_record *dst) 1789 1.1 christos { 1790 1.1 christos unsigned int flags; 1791 1.1 christos 1792 1.1 christos bfd_putb32 (src->space_index, dst->space_index); 1793 1.1 christos flags = (src->access_control_bits & SOM_SUBSPACE_ACCESS_CONTROL_BITS_MASK) 1794 1.1 christos << SOM_SUBSPACE_ACCESS_CONTROL_BITS_SH; 1795 1.1 christos if (src->memory_resident) 1796 1.1 christos flags |= SOM_SUBSPACE_MEMORY_RESIDENT; 1797 1.1 christos if (src->dup_common) 1798 1.1 christos flags |= SOM_SUBSPACE_DUP_COMMON; 1799 1.1 christos if (src->is_common) 1800 1.1 christos flags |= SOM_SUBSPACE_IS_COMMON; 1801 1.1 christos if (src->is_loadable) 1802 1.1 christos flags |= SOM_SUBSPACE_IS_LOADABLE; 1803 1.1 christos flags |= (src->quadrant & SOM_SUBSPACE_QUADRANT_MASK) 1804 1.1 christos << SOM_SUBSPACE_QUADRANT_SH; 1805 1.1 christos if (src->initially_frozen) 1806 1.1 christos flags |= SOM_SUBSPACE_INITIALLY_FROZEN; 1807 1.1 christos if (src->is_first) 1808 1.1 christos flags |= SOM_SUBSPACE_IS_FIRST; 1809 1.1 christos if (src->code_only) 1810 1.1 christos flags |= SOM_SUBSPACE_CODE_ONLY; 1811 1.1 christos flags |= (src->sort_key & SOM_SUBSPACE_SORT_KEY_MASK) 1812 1.1 christos << SOM_SUBSPACE_SORT_KEY_SH; 1813 1.1 christos if (src->replicate_init) 1814 1.1 christos flags |= SOM_SUBSPACE_REPLICATE_INIT; 1815 1.1 christos if (src->continuation) 1816 1.1 christos flags |= SOM_SUBSPACE_CONTINUATION; 1817 1.1 christos if (src->is_tspecific) 1818 1.1 christos flags |= SOM_SUBSPACE_IS_TSPECIFIC; 1819 1.1 christos if (src->is_comdat) 1820 1.1 christos flags |= SOM_SUBSPACE_IS_COMDAT; 1821 1.1 christos bfd_putb32 (flags, dst->flags); 1822 1.1 christos bfd_putb32 (src->file_loc_init_value, dst->file_loc_init_value); 1823 1.1 christos bfd_putb32 (src->initialization_length, dst->initialization_length); 1824 1.1 christos bfd_putb32 (src->subspace_start, dst->subspace_start); 1825 1.1 christos bfd_putb32 (src->subspace_length, dst->subspace_length); 1826 1.1 christos bfd_putb32 (src->alignment, dst->alignment); 1827 1.1 christos bfd_putb32 (src->name, dst->name); 1828 1.1 christos bfd_putb32 (src->fixup_request_index, dst->fixup_request_index); 1829 1.1 christos bfd_putb32 (src->fixup_request_quantity, dst->fixup_request_quantity); 1830 1.1 christos } 1831 1.1 christos 1832 1.1 christos static void 1833 1.1 christos som_swap_aux_id_in (struct som_external_aux_id *src, 1834 1.8 christos struct som_aux_id *dst) 1835 1.1 christos { 1836 1.1 christos unsigned int flags = bfd_getb32 (src->flags); 1837 1.1 christos 1838 1.1 christos dst->mandatory = (flags & SOM_AUX_ID_MANDATORY) != 0; 1839 1.1 christos dst->copy = (flags & SOM_AUX_ID_COPY) != 0; 1840 1.1 christos dst->append = (flags & SOM_AUX_ID_APPEND) != 0; 1841 1.1 christos dst->ignore = (flags & SOM_AUX_ID_IGNORE) != 0; 1842 1.1 christos dst->type = (flags >> SOM_AUX_ID_TYPE_SH) & SOM_AUX_ID_TYPE_MASK; 1843 1.1 christos dst->length = bfd_getb32 (src->length); 1844 1.1 christos } 1845 1.1 christos 1846 1.1 christos static void 1847 1.1 christos som_swap_aux_id_out (struct som_aux_id *src, 1848 1.8 christos struct som_external_aux_id *dst) 1849 1.1 christos { 1850 1.1 christos unsigned int flags = 0; 1851 1.1 christos 1852 1.1 christos if (src->mandatory) 1853 1.1 christos flags |= SOM_AUX_ID_MANDATORY; 1854 1.1 christos if (src->copy) 1855 1.1 christos flags |= SOM_AUX_ID_COPY; 1856 1.1 christos if (src->append) 1857 1.1 christos flags |= SOM_AUX_ID_APPEND; 1858 1.1 christos if (src->ignore) 1859 1.1 christos flags |= SOM_AUX_ID_IGNORE; 1860 1.1 christos flags |= (src->type & SOM_AUX_ID_TYPE_MASK) << SOM_AUX_ID_TYPE_SH; 1861 1.1 christos bfd_putb32 (flags, dst->flags); 1862 1.1 christos bfd_putb32 (src->length, dst->length); 1863 1.1 christos } 1864 1.1 christos 1865 1.1 christos static void 1866 1.1 christos som_swap_string_auxhdr_out (struct som_string_auxhdr *src, 1867 1.8 christos struct som_external_string_auxhdr *dst) 1868 1.1 christos { 1869 1.1 christos som_swap_aux_id_out (&src->header_id, &dst->header_id); 1870 1.1 christos bfd_putb32 (src->string_length, dst->string_length); 1871 1.1 christos } 1872 1.1 christos 1873 1.1 christos static void 1874 1.1 christos som_swap_compilation_unit_out (struct som_compilation_unit *src, 1875 1.8 christos struct som_external_compilation_unit *dst) 1876 1.1 christos { 1877 1.1 christos bfd_putb32 (src->name.strx, dst->name); 1878 1.1 christos bfd_putb32 (src->language_name.strx, dst->language_name); 1879 1.1 christos bfd_putb32 (src->product_id.strx, dst->product_id); 1880 1.1 christos bfd_putb32 (src->version_id.strx, dst->version_id); 1881 1.1 christos bfd_putb32 (src->flags, dst->flags); 1882 1.1 christos som_swap_clock_out (&src->compile_time, &dst->compile_time); 1883 1.1 christos som_swap_clock_out (&src->source_time, &dst->source_time); 1884 1.1 christos } 1885 1.1 christos 1886 1.1 christos static void 1887 1.1 christos som_swap_exec_auxhdr_in (struct som_external_exec_auxhdr *src, 1888 1.8 christos struct som_exec_auxhdr *dst) 1889 1.1 christos { 1890 1.1 christos som_swap_aux_id_in (&src->som_auxhdr, &dst->som_auxhdr); 1891 1.1 christos dst->exec_tsize = bfd_getb32 (src->exec_tsize); 1892 1.1 christos dst->exec_tmem = bfd_getb32 (src->exec_tmem); 1893 1.1 christos dst->exec_tfile = bfd_getb32 (src->exec_tfile); 1894 1.1 christos dst->exec_dsize = bfd_getb32 (src->exec_dsize); 1895 1.1 christos dst->exec_dmem = bfd_getb32 (src->exec_dmem); 1896 1.1 christos dst->exec_dfile = bfd_getb32 (src->exec_dfile); 1897 1.1 christos dst->exec_bsize = bfd_getb32 (src->exec_bsize); 1898 1.1 christos dst->exec_entry = bfd_getb32 (src->exec_entry); 1899 1.1 christos dst->exec_flags = bfd_getb32 (src->exec_flags); 1900 1.1 christos dst->exec_bfill = bfd_getb32 (src->exec_bfill); 1901 1.1 christos } 1902 1.1 christos 1903 1.1 christos static void 1904 1.1 christos som_swap_exec_auxhdr_out (struct som_exec_auxhdr *src, 1905 1.8 christos struct som_external_exec_auxhdr *dst) 1906 1.1 christos { 1907 1.1 christos som_swap_aux_id_out (&src->som_auxhdr, &dst->som_auxhdr); 1908 1.1 christos bfd_putb32 (src->exec_tsize, dst->exec_tsize); 1909 1.1 christos bfd_putb32 (src->exec_tmem, dst->exec_tmem); 1910 1.1 christos bfd_putb32 (src->exec_tfile, dst->exec_tfile); 1911 1.1 christos bfd_putb32 (src->exec_dsize, dst->exec_dsize); 1912 1.1 christos bfd_putb32 (src->exec_dmem, dst->exec_dmem); 1913 1.1 christos bfd_putb32 (src->exec_dfile, dst->exec_dfile); 1914 1.1 christos bfd_putb32 (src->exec_bsize, dst->exec_bsize); 1915 1.1 christos bfd_putb32 (src->exec_entry, dst->exec_entry); 1916 1.1 christos bfd_putb32 (src->exec_flags, dst->exec_flags); 1917 1.1 christos bfd_putb32 (src->exec_bfill, dst->exec_bfill); 1918 1.1 christos } 1919 1.1 christos 1920 1.1 christos static void 1921 1.1 christos som_swap_lst_header_in (struct som_external_lst_header *src, 1922 1.8 christos struct som_lst_header *dst) 1923 1.1 christos { 1924 1.1 christos dst->system_id = bfd_getb16 (src->system_id); 1925 1.1 christos dst->a_magic = bfd_getb16 (src->a_magic); 1926 1.1 christos dst->version_id = bfd_getb32 (src->version_id); 1927 1.1 christos som_swap_clock_in (&src->file_time, &dst->file_time); 1928 1.1 christos dst->hash_loc = bfd_getb32 (src->hash_loc); 1929 1.1 christos dst->hash_size = bfd_getb32 (src->hash_size); 1930 1.1 christos dst->module_count = bfd_getb32 (src->module_count); 1931 1.1 christos dst->module_limit = bfd_getb32 (src->module_limit); 1932 1.1 christos dst->dir_loc = bfd_getb32 (src->dir_loc); 1933 1.1 christos dst->export_loc = bfd_getb32 (src->export_loc); 1934 1.1 christos dst->export_count = bfd_getb32 (src->export_count); 1935 1.1 christos dst->import_loc = bfd_getb32 (src->import_loc); 1936 1.1 christos dst->aux_loc = bfd_getb32 (src->aux_loc); 1937 1.1 christos dst->aux_size = bfd_getb32 (src->aux_size); 1938 1.1 christos dst->string_loc = bfd_getb32 (src->string_loc); 1939 1.1 christos dst->string_size = bfd_getb32 (src->string_size); 1940 1.1 christos dst->free_list = bfd_getb32 (src->free_list); 1941 1.1 christos dst->file_end = bfd_getb32 (src->file_end); 1942 1.1 christos dst->checksum = bfd_getb32 (src->checksum); 1943 1.1 christos } 1944 1.1 christos 1945 1.1 christos /* Perform some initialization for an object. Save results of this 1946 1.1 christos initialization in the BFD. */ 1947 1.1 christos 1948 1.9 christos static bfd_cleanup 1949 1.1 christos som_object_setup (bfd *abfd, 1950 1.1 christos struct som_header *file_hdrp, 1951 1.1 christos struct som_exec_auxhdr *aux_hdrp, 1952 1.1 christos unsigned long current_offset) 1953 1.1 christos { 1954 1.1 christos asection *section; 1955 1.1 christos 1956 1.1 christos /* som_mkobject will set bfd_error if som_mkobject fails. */ 1957 1.1 christos if (! som_mkobject (abfd)) 1958 1.1 christos return NULL; 1959 1.1 christos 1960 1.1 christos /* Set BFD flags based on what information is available in the SOM. */ 1961 1.1 christos abfd->flags = BFD_NO_FLAGS; 1962 1.1 christos if (file_hdrp->symbol_total) 1963 1.1 christos abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; 1964 1.1 christos 1965 1.1 christos switch (file_hdrp->a_magic) 1966 1.1 christos { 1967 1.1 christos case DEMAND_MAGIC: 1968 1.1 christos abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P); 1969 1.1 christos break; 1970 1.1 christos case SHARE_MAGIC: 1971 1.1 christos abfd->flags |= (WP_TEXT | EXEC_P); 1972 1.1 christos break; 1973 1.1 christos case EXEC_MAGIC: 1974 1.1 christos abfd->flags |= (EXEC_P); 1975 1.1 christos break; 1976 1.1 christos case RELOC_MAGIC: 1977 1.1 christos abfd->flags |= HAS_RELOC; 1978 1.1 christos break; 1979 1.1 christos #ifdef SHL_MAGIC 1980 1.1 christos case SHL_MAGIC: 1981 1.1 christos #endif 1982 1.1 christos #ifdef DL_MAGIC 1983 1.1 christos case DL_MAGIC: 1984 1.1 christos #endif 1985 1.1 christos abfd->flags |= DYNAMIC; 1986 1.1 christos break; 1987 1.1 christos 1988 1.1 christos default: 1989 1.1 christos break; 1990 1.1 christos } 1991 1.1 christos 1992 1.1 christos /* Save the auxiliary header. */ 1993 1.1 christos obj_som_exec_hdr (abfd) = aux_hdrp; 1994 1.1 christos 1995 1.1 christos /* Allocate space to hold the saved exec header information. */ 1996 1.1 christos obj_som_exec_data (abfd) = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_exec_data)); 1997 1.1 christos if (obj_som_exec_data (abfd) == NULL) 1998 1.1 christos return NULL; 1999 1.1 christos 2000 1.1 christos /* The braindamaged OSF1 linker switched exec_flags and exec_entry! 2001 1.1 christos 2002 1.1 christos We used to identify OSF1 binaries based on NEW_VERSION_ID, but 2003 1.1 christos apparently the latest HPUX linker is using NEW_VERSION_ID now. 2004 1.1 christos 2005 1.1 christos It's about time, OSF has used the new id since at least 1992; 2006 1.1 christos HPUX didn't start till nearly 1995!. 2007 1.1 christos 2008 1.1 christos The new approach examines the entry field for an executable. If 2009 1.1 christos it is not 4-byte aligned then it's not a proper code address and 2010 1.1 christos we guess it's really the executable flags. For a main program, 2011 1.1 christos we also consider zero to be indicative of a buggy linker, since 2012 1.1 christos that is not a valid entry point. The entry point for a shared 2013 1.1 christos library, however, can be zero so we do not consider that to be 2014 1.1 christos indicative of a buggy linker. */ 2015 1.1 christos if (aux_hdrp) 2016 1.1 christos { 2017 1.1 christos int found = 0; 2018 1.1 christos 2019 1.1 christos for (section = abfd->sections; section; section = section->next) 2020 1.1 christos { 2021 1.1 christos bfd_vma entry; 2022 1.1 christos 2023 1.1 christos if ((section->flags & SEC_CODE) == 0) 2024 1.1 christos continue; 2025 1.1 christos entry = aux_hdrp->exec_entry + aux_hdrp->exec_tmem; 2026 1.1 christos if (entry >= section->vma 2027 1.1 christos && entry < section->vma + section->size) 2028 1.1 christos found = 1; 2029 1.1 christos } 2030 1.1 christos if ((aux_hdrp->exec_entry == 0 && !(abfd->flags & DYNAMIC)) 2031 1.1 christos || (aux_hdrp->exec_entry & 0x3) != 0 2032 1.1 christos || ! found) 2033 1.1 christos { 2034 1.9 christos abfd->start_address = aux_hdrp->exec_flags; 2035 1.1 christos obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry; 2036 1.1 christos } 2037 1.1 christos else 2038 1.1 christos { 2039 1.9 christos abfd->start_address = aux_hdrp->exec_entry + current_offset; 2040 1.1 christos obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags; 2041 1.1 christos } 2042 1.1 christos } 2043 1.1 christos 2044 1.1 christos obj_som_exec_data (abfd)->version_id = file_hdrp->version_id; 2045 1.1 christos 2046 1.1 christos bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10); 2047 1.9 christos abfd->symcount = file_hdrp->symbol_total; 2048 1.1 christos 2049 1.1 christos /* Initialize the saved symbol table and string table to NULL. 2050 1.1 christos Save important offsets and sizes from the SOM header into 2051 1.1 christos the BFD. */ 2052 1.1 christos obj_som_stringtab (abfd) = NULL; 2053 1.1 christos obj_som_symtab (abfd) = NULL; 2054 1.1 christos obj_som_sorted_syms (abfd) = NULL; 2055 1.1 christos obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size; 2056 1.1 christos obj_som_sym_filepos (abfd) = file_hdrp->symbol_location + current_offset; 2057 1.1 christos obj_som_str_filepos (abfd) = (file_hdrp->symbol_strings_location 2058 1.1 christos + current_offset); 2059 1.1 christos obj_som_reloc_filepos (abfd) = (file_hdrp->fixup_request_location 2060 1.1 christos + current_offset); 2061 1.1 christos obj_som_exec_data (abfd)->system_id = file_hdrp->system_id; 2062 1.1 christos 2063 1.9 christos return _bfd_no_cleanup; 2064 1.1 christos } 2065 1.1 christos 2066 1.1 christos /* Convert all of the space and subspace info into BFD sections. Each space 2067 1.1 christos contains a number of subspaces, which in turn describe the mapping between 2068 1.1 christos regions of the exec file, and the address space that the program runs in. 2069 1.1 christos BFD sections which correspond to spaces will overlap the sections for the 2070 1.1 christos associated subspaces. */ 2071 1.1 christos 2072 1.10 christos static bool 2073 1.1 christos setup_sections (bfd *abfd, 2074 1.1 christos struct som_header *file_hdr, 2075 1.1 christos unsigned long current_offset) 2076 1.1 christos { 2077 1.9 christos char *space_strings = NULL; 2078 1.1 christos unsigned int space_index, i; 2079 1.1 christos unsigned int total_subspaces = 0; 2080 1.1 christos asection **subspace_sections = NULL; 2081 1.1 christos asection *section; 2082 1.9 christos size_t amt; 2083 1.1 christos 2084 1.1 christos /* First, read in space names. */ 2085 1.1 christos amt = file_hdr->space_strings_size; 2086 1.9 christos if (amt == (size_t) -1) 2087 1.9 christos { 2088 1.9 christos bfd_set_error (bfd_error_no_memory); 2089 1.9 christos goto error_return; 2090 1.9 christos } 2091 1.1 christos if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location, 2092 1.1 christos SEEK_SET) != 0) 2093 1.1 christos goto error_return; 2094 1.9 christos space_strings = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt); 2095 1.9 christos if (space_strings == NULL) 2096 1.1 christos goto error_return; 2097 1.8 christos /* Make sure that the string table is NUL terminated. */ 2098 1.8 christos space_strings[amt] = 0; 2099 1.1 christos 2100 1.1 christos /* Loop over all of the space dictionaries, building up sections. */ 2101 1.1 christos for (space_index = 0; space_index < file_hdr->space_total; space_index++) 2102 1.1 christos { 2103 1.1 christos struct som_space_dictionary_record space; 2104 1.1 christos struct som_external_space_dictionary_record ext_space; 2105 1.1 christos char *space_name; 2106 1.1 christos struct som_external_subspace_dictionary_record ext_subspace; 2107 1.1 christos struct som_subspace_dictionary_record subspace, save_subspace; 2108 1.1 christos unsigned int subspace_index; 2109 1.1 christos asection *space_asect; 2110 1.1 christos bfd_size_type space_size = 0; 2111 1.1 christos char *newname; 2112 1.1 christos 2113 1.1 christos /* Read the space dictionary element. */ 2114 1.1 christos if (bfd_seek (abfd, 2115 1.1 christos (current_offset + file_hdr->space_location 2116 1.1 christos + space_index * sizeof (ext_space)), 2117 1.1 christos SEEK_SET) != 0) 2118 1.1 christos goto error_return; 2119 1.1 christos amt = sizeof ext_space; 2120 1.11 christos if (bfd_read (&ext_space, amt, abfd) != amt) 2121 1.1 christos goto error_return; 2122 1.1 christos 2123 1.1 christos som_swap_space_dictionary_in (&ext_space, &space); 2124 1.1 christos 2125 1.1 christos /* Setup the space name string. */ 2126 1.8 christos if (space.name >= file_hdr->space_strings_size) 2127 1.8 christos goto error_return; 2128 1.8 christos 2129 1.1 christos space_name = space.name + space_strings; 2130 1.1 christos 2131 1.1 christos /* Make a section out of it. */ 2132 1.1 christos amt = strlen (space_name) + 1; 2133 1.1 christos newname = bfd_alloc (abfd, amt); 2134 1.1 christos if (!newname) 2135 1.1 christos goto error_return; 2136 1.1 christos strcpy (newname, space_name); 2137 1.1 christos 2138 1.1 christos space_asect = bfd_make_section_anyway (abfd, newname); 2139 1.1 christos if (!space_asect) 2140 1.1 christos goto error_return; 2141 1.1 christos 2142 1.1 christos if (space.is_loadable == 0) 2143 1.1 christos space_asect->flags |= SEC_DEBUGGING; 2144 1.1 christos 2145 1.1 christos /* Set up all the attributes for the space. */ 2146 1.1 christos if (! bfd_som_set_section_attributes (space_asect, space.is_defined, 2147 1.1 christos space.is_private, space.sort_key, 2148 1.1 christos space.space_number)) 2149 1.1 christos goto error_return; 2150 1.1 christos 2151 1.1 christos /* If the space has no subspaces, then we're done. */ 2152 1.1 christos if (space.subspace_quantity == 0) 2153 1.1 christos continue; 2154 1.1 christos 2155 1.1 christos /* Now, read in the first subspace for this space. */ 2156 1.1 christos if (bfd_seek (abfd, 2157 1.1 christos (current_offset + file_hdr->subspace_location 2158 1.1 christos + space.subspace_index * sizeof ext_subspace), 2159 1.1 christos SEEK_SET) != 0) 2160 1.1 christos goto error_return; 2161 1.1 christos amt = sizeof ext_subspace; 2162 1.11 christos if (bfd_read (&ext_subspace, amt, abfd) != amt) 2163 1.1 christos goto error_return; 2164 1.1 christos /* Seek back to the start of the subspaces for loop below. */ 2165 1.1 christos if (bfd_seek (abfd, 2166 1.1 christos (current_offset + file_hdr->subspace_location 2167 1.1 christos + space.subspace_index * sizeof ext_subspace), 2168 1.1 christos SEEK_SET) != 0) 2169 1.1 christos goto error_return; 2170 1.1 christos 2171 1.1 christos som_swap_subspace_dictionary_in (&ext_subspace, &subspace); 2172 1.1 christos 2173 1.1 christos /* Setup the start address and file loc from the first subspace 2174 1.1 christos record. */ 2175 1.1 christos space_asect->vma = subspace.subspace_start; 2176 1.1 christos space_asect->filepos = subspace.file_loc_init_value + current_offset; 2177 1.1 christos space_asect->alignment_power = exact_log2 (subspace.alignment); 2178 1.1 christos if (space_asect->alignment_power == (unsigned) -1) 2179 1.1 christos goto error_return; 2180 1.1 christos 2181 1.1 christos /* Initialize save_subspace so we can reliably determine if this 2182 1.1 christos loop placed any useful values into it. */ 2183 1.1 christos memset (&save_subspace, 0, sizeof (save_subspace)); 2184 1.1 christos 2185 1.1 christos /* Loop over the rest of the subspaces, building up more sections. */ 2186 1.1 christos for (subspace_index = 0; subspace_index < space.subspace_quantity; 2187 1.1 christos subspace_index++) 2188 1.1 christos { 2189 1.1 christos asection *subspace_asect; 2190 1.8 christos char *subspace_name; 2191 1.1 christos 2192 1.1 christos /* Read in the next subspace. */ 2193 1.1 christos amt = sizeof ext_subspace; 2194 1.11 christos if (bfd_read (&ext_subspace, amt, abfd) != amt) 2195 1.1 christos goto error_return; 2196 1.1 christos 2197 1.8 christos som_swap_subspace_dictionary_in (&ext_subspace, &subspace); 2198 1.1 christos 2199 1.1 christos /* Setup the subspace name string. */ 2200 1.9 christos if (subspace.name >= file_hdr->space_strings_size) 2201 1.9 christos goto error_return; 2202 1.9 christos 2203 1.1 christos subspace_name = subspace.name + space_strings; 2204 1.1 christos 2205 1.1 christos amt = strlen (subspace_name) + 1; 2206 1.1 christos newname = bfd_alloc (abfd, amt); 2207 1.1 christos if (!newname) 2208 1.1 christos goto error_return; 2209 1.1 christos strcpy (newname, subspace_name); 2210 1.1 christos 2211 1.1 christos /* Make a section out of this subspace. */ 2212 1.1 christos subspace_asect = bfd_make_section_anyway (abfd, newname); 2213 1.1 christos if (!subspace_asect) 2214 1.1 christos goto error_return; 2215 1.1 christos 2216 1.1 christos /* Store private information about the section. */ 2217 1.1 christos if (! bfd_som_set_subsection_attributes (subspace_asect, space_asect, 2218 1.1 christos subspace.access_control_bits, 2219 1.1 christos subspace.sort_key, 2220 1.1 christos subspace.quadrant, 2221 1.1 christos subspace.is_comdat, 2222 1.1 christos subspace.is_common, 2223 1.1 christos subspace.dup_common)) 2224 1.1 christos goto error_return; 2225 1.1 christos 2226 1.1 christos /* Keep an easy mapping between subspaces and sections. 2227 1.1 christos Note we do not necessarily read the subspaces in the 2228 1.1 christos same order in which they appear in the object file. 2229 1.1 christos 2230 1.1 christos So to make the target index come out correctly, we 2231 1.1 christos store the location of the subspace header in target 2232 1.1 christos index, then sort using the location of the subspace 2233 1.1 christos header as the key. Then we can assign correct 2234 1.1 christos subspace indices. */ 2235 1.1 christos total_subspaces++; 2236 1.1 christos subspace_asect->target_index = bfd_tell (abfd) - sizeof (subspace); 2237 1.1 christos 2238 1.1 christos /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified 2239 1.1 christos by the access_control_bits in the subspace header. */ 2240 1.1 christos switch (subspace.access_control_bits >> 4) 2241 1.1 christos { 2242 1.1 christos /* Readonly data. */ 2243 1.1 christos case 0x0: 2244 1.1 christos subspace_asect->flags |= SEC_DATA | SEC_READONLY; 2245 1.1 christos break; 2246 1.1 christos 2247 1.1 christos /* Normal data. */ 2248 1.1 christos case 0x1: 2249 1.1 christos subspace_asect->flags |= SEC_DATA; 2250 1.1 christos break; 2251 1.1 christos 2252 1.1 christos /* Readonly code and the gateways. 2253 1.1 christos Gateways have other attributes which do not map 2254 1.1 christos into anything BFD knows about. */ 2255 1.1 christos case 0x2: 2256 1.1 christos case 0x4: 2257 1.1 christos case 0x5: 2258 1.1 christos case 0x6: 2259 1.1 christos case 0x7: 2260 1.1 christos subspace_asect->flags |= SEC_CODE | SEC_READONLY; 2261 1.1 christos break; 2262 1.1 christos 2263 1.1 christos /* dynamic (writable) code. */ 2264 1.1 christos case 0x3: 2265 1.1 christos subspace_asect->flags |= SEC_CODE; 2266 1.1 christos break; 2267 1.1 christos } 2268 1.1 christos 2269 1.1 christos if (subspace.is_comdat || subspace.is_common || subspace.dup_common) 2270 1.1 christos subspace_asect->flags |= SEC_LINK_ONCE; 2271 1.1 christos 2272 1.1 christos if (subspace.subspace_length > 0) 2273 1.1 christos subspace_asect->flags |= SEC_HAS_CONTENTS; 2274 1.1 christos 2275 1.1 christos if (subspace.is_loadable) 2276 1.1 christos subspace_asect->flags |= SEC_ALLOC | SEC_LOAD; 2277 1.1 christos else 2278 1.1 christos subspace_asect->flags |= SEC_DEBUGGING; 2279 1.1 christos 2280 1.1 christos if (subspace.code_only) 2281 1.1 christos subspace_asect->flags |= SEC_CODE; 2282 1.1 christos 2283 1.1 christos /* Both file_loc_init_value and initialization_length will 2284 1.1 christos be zero for a BSS like subspace. */ 2285 1.1 christos if (subspace.file_loc_init_value == 0 2286 1.1 christos && subspace.initialization_length == 0) 2287 1.1 christos subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD | SEC_HAS_CONTENTS); 2288 1.1 christos 2289 1.1 christos /* This subspace has relocations. 2290 1.1 christos The fixup_request_quantity is a byte count for the number of 2291 1.1 christos entries in the relocation stream; it is not the actual number 2292 1.1 christos of relocations in the subspace. */ 2293 1.1 christos if (subspace.fixup_request_quantity != 0) 2294 1.1 christos { 2295 1.1 christos subspace_asect->flags |= SEC_RELOC; 2296 1.1 christos subspace_asect->rel_filepos = subspace.fixup_request_index; 2297 1.1 christos som_section_data (subspace_asect)->reloc_size 2298 1.1 christos = subspace.fixup_request_quantity; 2299 1.1 christos /* We can not determine this yet. When we read in the 2300 1.1 christos relocation table the correct value will be filled in. */ 2301 1.1 christos subspace_asect->reloc_count = (unsigned) -1; 2302 1.1 christos } 2303 1.1 christos 2304 1.1 christos /* Update save_subspace if appropriate. */ 2305 1.1 christos if (subspace.file_loc_init_value > save_subspace.file_loc_init_value) 2306 1.1 christos save_subspace = subspace; 2307 1.1 christos 2308 1.1 christos subspace_asect->vma = subspace.subspace_start; 2309 1.1 christos subspace_asect->size = subspace.subspace_length; 2310 1.1 christos subspace_asect->filepos = (subspace.file_loc_init_value 2311 1.1 christos + current_offset); 2312 1.1 christos subspace_asect->alignment_power = exact_log2 (subspace.alignment); 2313 1.1 christos if (subspace_asect->alignment_power == (unsigned) -1) 2314 1.1 christos goto error_return; 2315 1.1 christos 2316 1.1 christos /* Keep track of the accumulated sizes of the sections. */ 2317 1.1 christos space_size += subspace.subspace_length; 2318 1.1 christos } 2319 1.1 christos 2320 1.1 christos /* This can happen for a .o which defines symbols in otherwise 2321 1.1 christos empty subspaces. */ 2322 1.1 christos if (!save_subspace.file_loc_init_value) 2323 1.1 christos space_asect->size = 0; 2324 1.1 christos else 2325 1.1 christos { 2326 1.1 christos if (file_hdr->a_magic != RELOC_MAGIC) 2327 1.1 christos { 2328 1.1 christos /* Setup the size for the space section based upon the info 2329 1.1 christos in the last subspace of the space. */ 2330 1.1 christos space_asect->size = (save_subspace.subspace_start 2331 1.1 christos - space_asect->vma 2332 1.1 christos + save_subspace.subspace_length); 2333 1.1 christos } 2334 1.1 christos else 2335 1.1 christos { 2336 1.1 christos /* The subspace_start field is not initialised in relocatable 2337 1.8 christos only objects, so it cannot be used for length calculations. 2338 1.1 christos Instead we use the space_size value which we have been 2339 1.1 christos accumulating. This isn't an accurate estimate since it 2340 1.1 christos ignores alignment and ordering issues. */ 2341 1.1 christos space_asect->size = space_size; 2342 1.1 christos } 2343 1.1 christos } 2344 1.1 christos } 2345 1.1 christos /* Now that we've read in all the subspace records, we need to assign 2346 1.1 christos a target index to each subspace. */ 2347 1.9 christos if (_bfd_mul_overflow (total_subspaces, sizeof (asection *), &amt)) 2348 1.9 christos { 2349 1.9 christos bfd_set_error (bfd_error_file_too_big); 2350 1.9 christos goto error_return; 2351 1.9 christos } 2352 1.1 christos subspace_sections = bfd_malloc (amt); 2353 1.1 christos if (subspace_sections == NULL) 2354 1.1 christos goto error_return; 2355 1.1 christos 2356 1.1 christos for (i = 0, section = abfd->sections; section; section = section->next) 2357 1.1 christos { 2358 1.1 christos if (!som_is_subspace (section)) 2359 1.1 christos continue; 2360 1.1 christos 2361 1.1 christos subspace_sections[i] = section; 2362 1.1 christos i++; 2363 1.1 christos } 2364 1.1 christos qsort (subspace_sections, total_subspaces, 2365 1.1 christos sizeof (asection *), compare_subspaces); 2366 1.1 christos 2367 1.1 christos /* subspace_sections is now sorted in the order in which the subspaces 2368 1.1 christos appear in the object file. Assign an index to each one now. */ 2369 1.1 christos for (i = 0; i < total_subspaces; i++) 2370 1.1 christos subspace_sections[i]->target_index = i; 2371 1.1 christos 2372 1.9 christos free (space_strings); 2373 1.9 christos free (subspace_sections); 2374 1.10 christos return true; 2375 1.1 christos 2376 1.1 christos error_return: 2377 1.9 christos free (space_strings); 2378 1.9 christos free (subspace_sections); 2379 1.10 christos return false; 2380 1.1 christos } 2381 1.1 christos 2382 1.1 christos 2383 1.1 christos /* Read in a SOM object and make it into a BFD. */ 2384 1.1 christos 2385 1.9 christos static bfd_cleanup 2386 1.1 christos som_object_p (bfd *abfd) 2387 1.1 christos { 2388 1.1 christos struct som_external_header ext_file_hdr; 2389 1.1 christos struct som_header file_hdr; 2390 1.1 christos struct som_exec_auxhdr *aux_hdr_ptr = NULL; 2391 1.1 christos unsigned long current_offset = 0; 2392 1.1 christos struct som_external_lst_header ext_lst_header; 2393 1.1 christos struct som_external_som_entry ext_som_entry; 2394 1.9 christos size_t amt; 2395 1.1 christos unsigned int loc; 2396 1.1 christos #define ENTRY_SIZE sizeof (struct som_external_som_entry) 2397 1.1 christos 2398 1.1 christos amt = sizeof (struct som_external_header); 2399 1.11 christos if (bfd_read (&ext_file_hdr, amt, abfd) != amt) 2400 1.1 christos { 2401 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2402 1.1 christos bfd_set_error (bfd_error_wrong_format); 2403 1.1 christos return NULL; 2404 1.1 christos } 2405 1.1 christos 2406 1.1 christos som_swap_header_in (&ext_file_hdr, &file_hdr); 2407 1.1 christos 2408 1.1 christos if (!_PA_RISC_ID (file_hdr.system_id)) 2409 1.1 christos { 2410 1.1 christos bfd_set_error (bfd_error_wrong_format); 2411 1.1 christos return NULL; 2412 1.1 christos } 2413 1.1 christos 2414 1.1 christos switch (file_hdr.a_magic) 2415 1.1 christos { 2416 1.1 christos case RELOC_MAGIC: 2417 1.1 christos case EXEC_MAGIC: 2418 1.1 christos case SHARE_MAGIC: 2419 1.1 christos case DEMAND_MAGIC: 2420 1.1 christos case DL_MAGIC: 2421 1.1 christos case SHL_MAGIC: 2422 1.1 christos #ifdef SHARED_MAGIC_CNX 2423 1.1 christos case SHARED_MAGIC_CNX: 2424 1.1 christos #endif 2425 1.1 christos break; 2426 1.1 christos 2427 1.1 christos case EXECLIBMAGIC: 2428 1.1 christos /* Read the lst header and determine where the SOM directory begins. */ 2429 1.1 christos 2430 1.11 christos if (bfd_seek (abfd, 0, SEEK_SET) != 0) 2431 1.1 christos { 2432 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2433 1.1 christos bfd_set_error (bfd_error_wrong_format); 2434 1.1 christos return NULL; 2435 1.1 christos } 2436 1.1 christos 2437 1.1 christos amt = sizeof (struct som_external_lst_header); 2438 1.11 christos if (bfd_read (&ext_lst_header, amt, abfd) != amt) 2439 1.1 christos { 2440 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2441 1.1 christos bfd_set_error (bfd_error_wrong_format); 2442 1.1 christos return NULL; 2443 1.1 christos } 2444 1.1 christos 2445 1.1 christos /* Position to and read the first directory entry. */ 2446 1.1 christos loc = bfd_getb32 (ext_lst_header.dir_loc); 2447 1.1 christos if (bfd_seek (abfd, loc, SEEK_SET) != 0) 2448 1.1 christos { 2449 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2450 1.1 christos bfd_set_error (bfd_error_wrong_format); 2451 1.1 christos return NULL; 2452 1.1 christos } 2453 1.1 christos 2454 1.1 christos amt = ENTRY_SIZE; 2455 1.11 christos if (bfd_read (&ext_som_entry, amt, abfd) != amt) 2456 1.1 christos { 2457 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2458 1.1 christos bfd_set_error (bfd_error_wrong_format); 2459 1.1 christos return NULL; 2460 1.1 christos } 2461 1.1 christos 2462 1.1 christos /* Now position to the first SOM. */ 2463 1.1 christos current_offset = bfd_getb32 (ext_som_entry.location); 2464 1.1 christos if (bfd_seek (abfd, current_offset, SEEK_SET) != 0) 2465 1.1 christos { 2466 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2467 1.1 christos bfd_set_error (bfd_error_wrong_format); 2468 1.1 christos return NULL; 2469 1.1 christos } 2470 1.1 christos 2471 1.1 christos /* And finally, re-read the som header. */ 2472 1.1 christos amt = sizeof (struct som_external_header); 2473 1.11 christos if (bfd_read (&ext_file_hdr, amt, abfd) != amt) 2474 1.1 christos { 2475 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2476 1.1 christos bfd_set_error (bfd_error_wrong_format); 2477 1.1 christos return NULL; 2478 1.1 christos } 2479 1.1 christos 2480 1.1 christos som_swap_header_in (&ext_file_hdr, &file_hdr); 2481 1.1 christos 2482 1.1 christos break; 2483 1.1 christos 2484 1.1 christos default: 2485 1.1 christos bfd_set_error (bfd_error_wrong_format); 2486 1.1 christos return NULL; 2487 1.1 christos } 2488 1.1 christos 2489 1.1 christos if (file_hdr.version_id != OLD_VERSION_ID 2490 1.1 christos && file_hdr.version_id != NEW_VERSION_ID) 2491 1.1 christos { 2492 1.1 christos bfd_set_error (bfd_error_wrong_format); 2493 1.1 christos return NULL; 2494 1.1 christos } 2495 1.1 christos 2496 1.1 christos /* If the aux_header_size field in the file header is zero, then this 2497 1.1 christos object is an incomplete executable (a .o file). Do not try to read 2498 1.1 christos a non-existant auxiliary header. */ 2499 1.1 christos if (file_hdr.aux_header_size != 0) 2500 1.1 christos { 2501 1.1 christos struct som_external_exec_auxhdr ext_exec_auxhdr; 2502 1.1 christos 2503 1.1 christos aux_hdr_ptr = bfd_zalloc (abfd, 2504 1.1 christos (bfd_size_type) sizeof (*aux_hdr_ptr)); 2505 1.1 christos if (aux_hdr_ptr == NULL) 2506 1.1 christos return NULL; 2507 1.1 christos amt = sizeof (struct som_external_exec_auxhdr); 2508 1.11 christos if (bfd_read (&ext_exec_auxhdr, amt, abfd) != amt) 2509 1.1 christos { 2510 1.1 christos if (bfd_get_error () != bfd_error_system_call) 2511 1.1 christos bfd_set_error (bfd_error_wrong_format); 2512 1.1 christos return NULL; 2513 1.1 christos } 2514 1.1 christos som_swap_exec_auxhdr_in (&ext_exec_auxhdr, aux_hdr_ptr); 2515 1.1 christos } 2516 1.1 christos 2517 1.1 christos if (!setup_sections (abfd, &file_hdr, current_offset)) 2518 1.1 christos { 2519 1.1 christos /* setup_sections does not bubble up a bfd error code. */ 2520 1.1 christos bfd_set_error (bfd_error_bad_value); 2521 1.1 christos return NULL; 2522 1.1 christos } 2523 1.1 christos 2524 1.1 christos /* This appears to be a valid SOM object. Do some initialization. */ 2525 1.1 christos return som_object_setup (abfd, &file_hdr, aux_hdr_ptr, current_offset); 2526 1.1 christos } 2527 1.1 christos 2528 1.1 christos /* Create a SOM object. */ 2529 1.1 christos 2530 1.10 christos static bool 2531 1.1 christos som_mkobject (bfd *abfd) 2532 1.1 christos { 2533 1.1 christos /* Allocate memory to hold backend information. */ 2534 1.1 christos abfd->tdata.som_data = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_data_struct)); 2535 1.1 christos if (abfd->tdata.som_data == NULL) 2536 1.10 christos return false; 2537 1.10 christos return true; 2538 1.1 christos } 2539 1.1 christos 2540 1.1 christos /* Initialize some information in the file header. This routine makes 2541 1.1 christos not attempt at doing the right thing for a full executable; it 2542 1.1 christos is only meant to handle relocatable objects. */ 2543 1.1 christos 2544 1.10 christos static bool 2545 1.1 christos som_prep_headers (bfd *abfd) 2546 1.1 christos { 2547 1.1 christos struct som_header *file_hdr; 2548 1.1 christos asection *section; 2549 1.9 christos size_t amt = sizeof (struct som_header); 2550 1.1 christos 2551 1.1 christos /* Make and attach a file header to the BFD. */ 2552 1.1 christos file_hdr = bfd_zalloc (abfd, amt); 2553 1.1 christos if (file_hdr == NULL) 2554 1.10 christos return false; 2555 1.1 christos obj_som_file_hdr (abfd) = file_hdr; 2556 1.1 christos 2557 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 2558 1.1 christos { 2559 1.1 christos /* Make and attach an exec header to the BFD. */ 2560 1.1 christos amt = sizeof (struct som_exec_auxhdr); 2561 1.1 christos obj_som_exec_hdr (abfd) = bfd_zalloc (abfd, amt); 2562 1.1 christos if (obj_som_exec_hdr (abfd) == NULL) 2563 1.10 christos return false; 2564 1.1 christos 2565 1.1 christos if (abfd->flags & D_PAGED) 2566 1.1 christos file_hdr->a_magic = DEMAND_MAGIC; 2567 1.1 christos else if (abfd->flags & WP_TEXT) 2568 1.1 christos file_hdr->a_magic = SHARE_MAGIC; 2569 1.1 christos #ifdef SHL_MAGIC 2570 1.1 christos else if (abfd->flags & DYNAMIC) 2571 1.1 christos file_hdr->a_magic = SHL_MAGIC; 2572 1.1 christos #endif 2573 1.1 christos else 2574 1.1 christos file_hdr->a_magic = EXEC_MAGIC; 2575 1.1 christos } 2576 1.1 christos else 2577 1.1 christos file_hdr->a_magic = RELOC_MAGIC; 2578 1.1 christos 2579 1.1 christos /* These fields are optional, and embedding timestamps is not always 2580 1.1 christos a wise thing to do, it makes comparing objects during a multi-stage 2581 1.1 christos bootstrap difficult. */ 2582 1.1 christos file_hdr->file_time.secs = 0; 2583 1.1 christos file_hdr->file_time.nanosecs = 0; 2584 1.1 christos 2585 1.1 christos file_hdr->entry_space = 0; 2586 1.1 christos file_hdr->entry_subspace = 0; 2587 1.1 christos file_hdr->entry_offset = 0; 2588 1.1 christos file_hdr->presumed_dp = 0; 2589 1.1 christos 2590 1.1 christos /* Now iterate over the sections translating information from 2591 1.1 christos BFD sections to SOM spaces/subspaces. */ 2592 1.1 christos for (section = abfd->sections; section != NULL; section = section->next) 2593 1.1 christos { 2594 1.1 christos /* Ignore anything which has not been marked as a space or 2595 1.1 christos subspace. */ 2596 1.1 christos if (!som_is_space (section) && !som_is_subspace (section)) 2597 1.1 christos continue; 2598 1.1 christos 2599 1.1 christos if (som_is_space (section)) 2600 1.1 christos { 2601 1.1 christos /* Allocate space for the space dictionary. */ 2602 1.1 christos amt = sizeof (struct som_space_dictionary_record); 2603 1.1 christos som_section_data (section)->space_dict = bfd_zalloc (abfd, amt); 2604 1.1 christos if (som_section_data (section)->space_dict == NULL) 2605 1.10 christos return false; 2606 1.1 christos /* Set space attributes. Note most attributes of SOM spaces 2607 1.1 christos are set based on the subspaces it contains. */ 2608 1.1 christos som_section_data (section)->space_dict->loader_fix_index = -1; 2609 1.1 christos som_section_data (section)->space_dict->init_pointer_index = -1; 2610 1.1 christos 2611 1.1 christos /* Set more attributes that were stuffed away in private data. */ 2612 1.1 christos som_section_data (section)->space_dict->sort_key = 2613 1.1 christos som_section_data (section)->copy_data->sort_key; 2614 1.1 christos som_section_data (section)->space_dict->is_defined = 2615 1.1 christos som_section_data (section)->copy_data->is_defined; 2616 1.1 christos som_section_data (section)->space_dict->is_private = 2617 1.1 christos som_section_data (section)->copy_data->is_private; 2618 1.1 christos som_section_data (section)->space_dict->space_number = 2619 1.1 christos som_section_data (section)->copy_data->space_number; 2620 1.1 christos } 2621 1.1 christos else 2622 1.1 christos { 2623 1.1 christos /* Allocate space for the subspace dictionary. */ 2624 1.1 christos amt = sizeof (struct som_subspace_dictionary_record); 2625 1.1 christos som_section_data (section)->subspace_dict = bfd_zalloc (abfd, amt); 2626 1.1 christos if (som_section_data (section)->subspace_dict == NULL) 2627 1.10 christos return false; 2628 1.1 christos 2629 1.1 christos /* Set subspace attributes. Basic stuff is done here, additional 2630 1.1 christos attributes are filled in later as more information becomes 2631 1.1 christos available. */ 2632 1.1 christos if (section->flags & SEC_ALLOC) 2633 1.1 christos som_section_data (section)->subspace_dict->is_loadable = 1; 2634 1.1 christos 2635 1.1 christos if (section->flags & SEC_CODE) 2636 1.1 christos som_section_data (section)->subspace_dict->code_only = 1; 2637 1.1 christos 2638 1.1 christos som_section_data (section)->subspace_dict->subspace_start = 2639 1.1 christos section->vma; 2640 1.1 christos som_section_data (section)->subspace_dict->subspace_length = 2641 1.1 christos section->size; 2642 1.1 christos som_section_data (section)->subspace_dict->initialization_length = 2643 1.1 christos section->size; 2644 1.1 christos som_section_data (section)->subspace_dict->alignment = 2645 1.1 christos 1 << section->alignment_power; 2646 1.1 christos 2647 1.1 christos /* Set more attributes that were stuffed away in private data. */ 2648 1.1 christos som_section_data (section)->subspace_dict->sort_key = 2649 1.1 christos som_section_data (section)->copy_data->sort_key; 2650 1.1 christos som_section_data (section)->subspace_dict->access_control_bits = 2651 1.1 christos som_section_data (section)->copy_data->access_control_bits; 2652 1.1 christos som_section_data (section)->subspace_dict->quadrant = 2653 1.1 christos som_section_data (section)->copy_data->quadrant; 2654 1.1 christos som_section_data (section)->subspace_dict->is_comdat = 2655 1.1 christos som_section_data (section)->copy_data->is_comdat; 2656 1.1 christos som_section_data (section)->subspace_dict->is_common = 2657 1.1 christos som_section_data (section)->copy_data->is_common; 2658 1.1 christos som_section_data (section)->subspace_dict->dup_common = 2659 1.1 christos som_section_data (section)->copy_data->dup_common; 2660 1.1 christos } 2661 1.1 christos } 2662 1.10 christos return true; 2663 1.1 christos } 2664 1.1 christos 2665 1.1 christos /* Return TRUE if the given section is a SOM space, FALSE otherwise. */ 2666 1.1 christos 2667 1.10 christos static bool 2668 1.1 christos som_is_space (asection *section) 2669 1.1 christos { 2670 1.1 christos /* If no copy data is available, then it's neither a space nor a 2671 1.1 christos subspace. */ 2672 1.1 christos if (som_section_data (section)->copy_data == NULL) 2673 1.10 christos return false; 2674 1.1 christos 2675 1.1 christos /* If the containing space isn't the same as the given section, 2676 1.1 christos then this isn't a space. */ 2677 1.1 christos if (som_section_data (section)->copy_data->container != section 2678 1.1 christos && (som_section_data (section)->copy_data->container->output_section 2679 1.1 christos != section)) 2680 1.10 christos return false; 2681 1.1 christos 2682 1.1 christos /* OK. Must be a space. */ 2683 1.10 christos return true; 2684 1.1 christos } 2685 1.1 christos 2686 1.1 christos /* Return TRUE if the given section is a SOM subspace, FALSE otherwise. */ 2687 1.1 christos 2688 1.10 christos static bool 2689 1.1 christos som_is_subspace (asection *section) 2690 1.1 christos { 2691 1.1 christos /* If no copy data is available, then it's neither a space nor a 2692 1.1 christos subspace. */ 2693 1.1 christos if (som_section_data (section)->copy_data == NULL) 2694 1.10 christos return false; 2695 1.1 christos 2696 1.1 christos /* If the containing space is the same as the given section, 2697 1.1 christos then this isn't a subspace. */ 2698 1.1 christos if (som_section_data (section)->copy_data->container == section 2699 1.1 christos || (som_section_data (section)->copy_data->container->output_section 2700 1.1 christos == section)) 2701 1.10 christos return false; 2702 1.1 christos 2703 1.1 christos /* OK. Must be a subspace. */ 2704 1.10 christos return true; 2705 1.1 christos } 2706 1.1 christos 2707 1.1 christos /* Return TRUE if the given space contains the given subspace. It 2708 1.1 christos is safe to assume space really is a space, and subspace really 2709 1.1 christos is a subspace. */ 2710 1.1 christos 2711 1.10 christos static bool 2712 1.1 christos som_is_container (asection *space, asection *subspace) 2713 1.1 christos { 2714 1.1 christos return (som_section_data (subspace)->copy_data->container == space) 2715 1.1 christos || (som_section_data (subspace)->copy_data->container->output_section 2716 1.1 christos == space); 2717 1.1 christos } 2718 1.1 christos 2719 1.1 christos /* Count and return the number of spaces attached to the given BFD. */ 2720 1.1 christos 2721 1.1 christos static unsigned long 2722 1.1 christos som_count_spaces (bfd *abfd) 2723 1.1 christos { 2724 1.1 christos int count = 0; 2725 1.1 christos asection *section; 2726 1.1 christos 2727 1.1 christos for (section = abfd->sections; section != NULL; section = section->next) 2728 1.1 christos count += som_is_space (section); 2729 1.1 christos 2730 1.1 christos return count; 2731 1.1 christos } 2732 1.1 christos 2733 1.1 christos /* Count the number of subspaces attached to the given BFD. */ 2734 1.1 christos 2735 1.1 christos static unsigned long 2736 1.1 christos som_count_subspaces (bfd *abfd) 2737 1.1 christos { 2738 1.1 christos int count = 0; 2739 1.1 christos asection *section; 2740 1.1 christos 2741 1.1 christos for (section = abfd->sections; section != NULL; section = section->next) 2742 1.1 christos count += som_is_subspace (section); 2743 1.1 christos 2744 1.1 christos return count; 2745 1.1 christos } 2746 1.1 christos 2747 1.1 christos /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2. 2748 1.1 christos 2749 1.1 christos We desire symbols to be ordered starting with the symbol with the 2750 1.1 christos highest relocation count down to the symbol with the lowest relocation 2751 1.1 christos count. Doing so compacts the relocation stream. */ 2752 1.1 christos 2753 1.1 christos static int 2754 1.1 christos compare_syms (const void *arg1, const void *arg2) 2755 1.1 christos { 2756 1.1 christos asymbol **sym1 = (asymbol **) arg1; 2757 1.1 christos asymbol **sym2 = (asymbol **) arg2; 2758 1.1 christos unsigned int count1, count2; 2759 1.1 christos 2760 1.1 christos /* Get relocation count for each symbol. Note that the count 2761 1.1 christos is stored in the udata pointer for section symbols! */ 2762 1.1 christos if ((*sym1)->flags & BSF_SECTION_SYM) 2763 1.1 christos count1 = (*sym1)->udata.i; 2764 1.1 christos else 2765 1.1 christos count1 = som_symbol_data (*sym1)->reloc_count; 2766 1.1 christos 2767 1.1 christos if ((*sym2)->flags & BSF_SECTION_SYM) 2768 1.1 christos count2 = (*sym2)->udata.i; 2769 1.1 christos else 2770 1.1 christos count2 = som_symbol_data (*sym2)->reloc_count; 2771 1.1 christos 2772 1.1 christos /* Return the appropriate value. */ 2773 1.1 christos if (count1 < count2) 2774 1.1 christos return 1; 2775 1.1 christos else if (count1 > count2) 2776 1.1 christos return -1; 2777 1.1 christos return 0; 2778 1.1 christos } 2779 1.1 christos 2780 1.1 christos /* Return -1, 0, 1 indicating the relative ordering of subspace1 2781 1.1 christos and subspace. */ 2782 1.1 christos 2783 1.1 christos static int 2784 1.1 christos compare_subspaces (const void *arg1, const void *arg2) 2785 1.1 christos { 2786 1.1 christos asection **subspace1 = (asection **) arg1; 2787 1.1 christos asection **subspace2 = (asection **) arg2; 2788 1.1 christos 2789 1.1 christos if ((*subspace1)->target_index < (*subspace2)->target_index) 2790 1.1 christos return -1; 2791 1.1 christos else if ((*subspace2)->target_index < (*subspace1)->target_index) 2792 1.1 christos return 1; 2793 1.1 christos else 2794 1.1 christos return 0; 2795 1.1 christos } 2796 1.1 christos 2797 1.1 christos /* Perform various work in preparation for emitting the fixup stream. */ 2798 1.1 christos 2799 1.10 christos static bool 2800 1.1 christos som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms) 2801 1.1 christos { 2802 1.1 christos unsigned long i; 2803 1.1 christos asection *section; 2804 1.1 christos asymbol **sorted_syms; 2805 1.9 christos size_t amt; 2806 1.9 christos 2807 1.9 christos if (num_syms == 0) 2808 1.10 christos return true; 2809 1.1 christos 2810 1.1 christos /* Most SOM relocations involving a symbol have a length which is 2811 1.1 christos dependent on the index of the symbol. So symbols which are 2812 1.1 christos used often in relocations should have a small index. */ 2813 1.1 christos 2814 1.1 christos /* First initialize the counters for each symbol. */ 2815 1.1 christos for (i = 0; i < num_syms; i++) 2816 1.1 christos { 2817 1.1 christos /* Handle a section symbol; these have no pointers back to the 2818 1.1 christos SOM symbol info. So we just use the udata field to hold the 2819 1.1 christos relocation count. */ 2820 1.1 christos if (som_symbol_data (syms[i]) == NULL 2821 1.1 christos || syms[i]->flags & BSF_SECTION_SYM) 2822 1.1 christos { 2823 1.1 christos syms[i]->flags |= BSF_SECTION_SYM; 2824 1.1 christos syms[i]->udata.i = 0; 2825 1.1 christos } 2826 1.1 christos else 2827 1.1 christos som_symbol_data (syms[i])->reloc_count = 0; 2828 1.1 christos } 2829 1.1 christos 2830 1.1 christos /* Now that the counters are initialized, make a weighted count 2831 1.1 christos of how often a given symbol is used in a relocation. */ 2832 1.1 christos for (section = abfd->sections; section != NULL; section = section->next) 2833 1.1 christos { 2834 1.1 christos int j; 2835 1.1 christos 2836 1.1 christos /* Does this section have any relocations? */ 2837 1.1 christos if ((int) section->reloc_count <= 0) 2838 1.1 christos continue; 2839 1.1 christos 2840 1.1 christos /* Walk through each relocation for this section. */ 2841 1.1 christos for (j = 1; j < (int) section->reloc_count; j++) 2842 1.1 christos { 2843 1.1 christos arelent *reloc = section->orelocation[j]; 2844 1.1 christos int scale; 2845 1.1 christos 2846 1.1 christos /* A relocation against a symbol in the *ABS* section really 2847 1.1 christos does not have a symbol. Likewise if the symbol isn't associated 2848 1.1 christos with any section. */ 2849 1.1 christos if (reloc->sym_ptr_ptr == NULL 2850 1.1 christos || bfd_is_abs_section ((*reloc->sym_ptr_ptr)->section)) 2851 1.1 christos continue; 2852 1.1 christos 2853 1.1 christos /* Scaling to encourage symbols involved in R_DP_RELATIVE 2854 1.1 christos and R_CODE_ONE_SYMBOL relocations to come first. These 2855 1.1 christos two relocations have single byte versions if the symbol 2856 1.1 christos index is very small. */ 2857 1.1 christos if (reloc->howto->type == R_DP_RELATIVE 2858 1.1 christos || reloc->howto->type == R_CODE_ONE_SYMBOL) 2859 1.1 christos scale = 2; 2860 1.1 christos else 2861 1.1 christos scale = 1; 2862 1.1 christos 2863 1.1 christos /* Handle section symbols by storing the count in the udata 2864 1.1 christos field. It will not be used and the count is very important 2865 1.1 christos for these symbols. */ 2866 1.1 christos if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM) 2867 1.1 christos { 2868 1.1 christos (*reloc->sym_ptr_ptr)->udata.i = 2869 1.1 christos (*reloc->sym_ptr_ptr)->udata.i + scale; 2870 1.1 christos continue; 2871 1.1 christos } 2872 1.1 christos 2873 1.1 christos /* A normal symbol. Increment the count. */ 2874 1.1 christos som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale; 2875 1.1 christos } 2876 1.1 christos } 2877 1.1 christos 2878 1.1 christos /* Sort a copy of the symbol table, rather than the canonical 2879 1.1 christos output symbol table. */ 2880 1.9 christos if (_bfd_mul_overflow (num_syms, sizeof (asymbol *), &amt)) 2881 1.9 christos { 2882 1.9 christos bfd_set_error (bfd_error_no_memory); 2883 1.10 christos return false; 2884 1.9 christos } 2885 1.1 christos sorted_syms = bfd_zalloc (abfd, amt); 2886 1.9 christos if (sorted_syms == NULL) 2887 1.10 christos return false; 2888 1.1 christos memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *)); 2889 1.1 christos qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms); 2890 1.1 christos obj_som_sorted_syms (abfd) = sorted_syms; 2891 1.1 christos 2892 1.1 christos /* Compute the symbol indexes, they will be needed by the relocation 2893 1.1 christos code. */ 2894 1.1 christos for (i = 0; i < num_syms; i++) 2895 1.1 christos { 2896 1.1 christos /* A section symbol. Again, there is no pointer to backend symbol 2897 1.1 christos information, so we reuse the udata field again. */ 2898 1.1 christos if (sorted_syms[i]->flags & BSF_SECTION_SYM) 2899 1.1 christos sorted_syms[i]->udata.i = i; 2900 1.1 christos else 2901 1.1 christos som_symbol_data (sorted_syms[i])->index = i; 2902 1.1 christos } 2903 1.10 christos return true; 2904 1.1 christos } 2905 1.1 christos 2906 1.10 christos static bool 2907 1.1 christos som_write_fixups (bfd *abfd, 2908 1.1 christos unsigned long current_offset, 2909 1.1 christos unsigned int *total_reloc_sizep) 2910 1.1 christos { 2911 1.1 christos unsigned int i, j; 2912 1.1 christos /* Chunk of memory that we can use as buffer space, then throw 2913 1.1 christos away. */ 2914 1.1 christos unsigned char tmp_space[SOM_TMP_BUFSIZE]; 2915 1.1 christos unsigned char *p; 2916 1.1 christos unsigned int total_reloc_size = 0; 2917 1.1 christos unsigned int subspace_reloc_size = 0; 2918 1.1 christos unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total; 2919 1.1 christos asection *section = abfd->sections; 2920 1.9 christos size_t amt; 2921 1.1 christos 2922 1.1 christos memset (tmp_space, 0, SOM_TMP_BUFSIZE); 2923 1.1 christos p = tmp_space; 2924 1.1 christos 2925 1.1 christos /* All the fixups for a particular subspace are emitted in a single 2926 1.1 christos stream. All the subspaces for a particular space are emitted 2927 1.1 christos as a single stream. 2928 1.1 christos 2929 1.1 christos So, to get all the locations correct one must iterate through all the 2930 1.1 christos spaces, for each space iterate through its subspaces and output a 2931 1.1 christos fixups stream. */ 2932 1.1 christos for (i = 0; i < num_spaces; i++) 2933 1.1 christos { 2934 1.1 christos asection *subsection; 2935 1.1 christos 2936 1.1 christos /* Find a space. */ 2937 1.10 christos while (section && !som_is_space (section)) 2938 1.1 christos section = section->next; 2939 1.10 christos if (!section) 2940 1.10 christos break; 2941 1.1 christos 2942 1.1 christos /* Now iterate through each of its subspaces. */ 2943 1.1 christos for (subsection = abfd->sections; 2944 1.1 christos subsection != NULL; 2945 1.1 christos subsection = subsection->next) 2946 1.1 christos { 2947 1.10 christos unsigned int reloc_offset; 2948 1.1 christos unsigned int current_rounding_mode; 2949 1.1 christos #ifndef NO_PCREL_MODES 2950 1.1 christos unsigned int current_call_mode; 2951 1.1 christos #endif 2952 1.1 christos 2953 1.1 christos /* Find a subspace of this space. */ 2954 1.1 christos if (!som_is_subspace (subsection) 2955 1.1 christos || !som_is_container (section, subsection)) 2956 1.1 christos continue; 2957 1.1 christos 2958 1.1 christos /* If this subspace does not have real data, then we are 2959 1.1 christos finished with it. */ 2960 1.1 christos if ((subsection->flags & SEC_HAS_CONTENTS) == 0) 2961 1.1 christos { 2962 1.1 christos som_section_data (subsection)->subspace_dict->fixup_request_index 2963 1.1 christos = -1; 2964 1.1 christos continue; 2965 1.1 christos } 2966 1.1 christos 2967 1.1 christos /* This subspace has some relocations. Put the relocation stream 2968 1.1 christos index into the subspace record. */ 2969 1.1 christos som_section_data (subsection)->subspace_dict->fixup_request_index 2970 1.1 christos = total_reloc_size; 2971 1.1 christos 2972 1.1 christos /* To make life easier start over with a clean slate for 2973 1.1 christos each subspace. Seek to the start of the relocation stream 2974 1.1 christos for this subspace in preparation for writing out its fixup 2975 1.1 christos stream. */ 2976 1.1 christos if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0) 2977 1.10 christos return false; 2978 1.1 christos 2979 1.1 christos /* Buffer space has already been allocated. Just perform some 2980 1.1 christos initialization here. */ 2981 1.1 christos p = tmp_space; 2982 1.1 christos subspace_reloc_size = 0; 2983 1.1 christos reloc_offset = 0; 2984 1.1 christos som_initialize_reloc_queue (reloc_queue); 2985 1.1 christos current_rounding_mode = R_N_MODE; 2986 1.1 christos #ifndef NO_PCREL_MODES 2987 1.1 christos current_call_mode = R_SHORT_PCREL_MODE; 2988 1.1 christos #endif 2989 1.1 christos 2990 1.1 christos /* Translate each BFD relocation into one or more SOM 2991 1.1 christos relocations. */ 2992 1.1 christos for (j = 0; j < subsection->reloc_count; j++) 2993 1.1 christos { 2994 1.1 christos arelent *bfd_reloc = subsection->orelocation[j]; 2995 1.1 christos unsigned int skip; 2996 1.1 christos int sym_num; 2997 1.1 christos 2998 1.10 christos if (bfd_reloc->address < reloc_offset) 2999 1.10 christos { 3000 1.10 christos _bfd_error_handler 3001 1.10 christos /* xgettext:c-format */ 3002 1.10 christos (_("%pB(%pA+%#" PRIx64 "): " 3003 1.10 christos "%s relocation offset out of order"), 3004 1.10 christos abfd, subsection, (uint64_t) bfd_reloc->address, 3005 1.10 christos bfd_reloc->howto->name); 3006 1.10 christos bfd_set_error (bfd_error_bad_value); 3007 1.10 christos return false; 3008 1.10 christos } 3009 1.10 christos if (!bfd_reloc_offset_in_range (bfd_reloc->howto, 3010 1.10 christos abfd, subsection, 3011 1.10 christos bfd_reloc->address)) 3012 1.10 christos { 3013 1.10 christos _bfd_error_handler 3014 1.10 christos /* xgettext:c-format */ 3015 1.10 christos (_("%pB(%pA+%#" PRIx64 "): " 3016 1.10 christos "%s relocation offset out of range"), 3017 1.10 christos abfd, subsection, (uint64_t) bfd_reloc->address, 3018 1.10 christos bfd_reloc->howto->name); 3019 1.10 christos bfd_set_error (bfd_error_bad_value); 3020 1.10 christos return false; 3021 1.10 christos } 3022 1.10 christos 3023 1.1 christos /* Get the symbol number. Remember it's stored in a 3024 1.1 christos special place for section symbols. */ 3025 1.1 christos if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM) 3026 1.1 christos sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i; 3027 1.1 christos else 3028 1.1 christos sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index; 3029 1.1 christos 3030 1.1 christos /* If there is not enough room for the next couple relocations, 3031 1.1 christos then dump the current buffer contents now. Also reinitialize 3032 1.1 christos the relocation queue. 3033 1.1 christos 3034 1.10 christos A single BFD relocation would probably only ever 3035 1.10 christos translate into at most 20 bytes of SOM relocations. 3036 1.10 christos However with fuzzed object files and resulting silly 3037 1.10 christos values for "skip" below, som_reloc_skip can emit 262 3038 1.10 christos bytes. Leave lots of space for growth. */ 3039 1.10 christos if (p - tmp_space + 512 > SOM_TMP_BUFSIZE) 3040 1.1 christos { 3041 1.1 christos amt = p - tmp_space; 3042 1.11 christos if (bfd_write (tmp_space, amt, abfd) != amt) 3043 1.10 christos return false; 3044 1.1 christos 3045 1.1 christos p = tmp_space; 3046 1.1 christos som_initialize_reloc_queue (reloc_queue); 3047 1.1 christos } 3048 1.1 christos 3049 1.1 christos /* Emit R_NO_RELOCATION fixups to map any bytes which were 3050 1.1 christos skipped. */ 3051 1.1 christos skip = bfd_reloc->address - reloc_offset; 3052 1.1 christos p = som_reloc_skip (abfd, skip, p, 3053 1.1 christos &subspace_reloc_size, reloc_queue); 3054 1.1 christos 3055 1.10 christos /* Update reloc_offset for the next iteration. */ 3056 1.10 christos reloc_offset = bfd_reloc->address + bfd_reloc->howto->size; 3057 1.1 christos 3058 1.1 christos /* Now the actual relocation we care about. */ 3059 1.1 christos switch (bfd_reloc->howto->type) 3060 1.1 christos { 3061 1.1 christos case R_PCREL_CALL: 3062 1.1 christos case R_ABS_CALL: 3063 1.1 christos p = som_reloc_call (abfd, p, &subspace_reloc_size, 3064 1.1 christos bfd_reloc, sym_num, reloc_queue); 3065 1.1 christos break; 3066 1.1 christos 3067 1.1 christos case R_CODE_ONE_SYMBOL: 3068 1.1 christos case R_DP_RELATIVE: 3069 1.1 christos /* Account for any addend. */ 3070 1.1 christos if (bfd_reloc->addend) 3071 1.1 christos p = som_reloc_addend (abfd, bfd_reloc->addend, p, 3072 1.1 christos &subspace_reloc_size, reloc_queue); 3073 1.1 christos 3074 1.1 christos if (sym_num < 0x20) 3075 1.1 christos { 3076 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p); 3077 1.1 christos subspace_reloc_size += 1; 3078 1.1 christos p += 1; 3079 1.1 christos } 3080 1.1 christos else if (sym_num < 0x100) 3081 1.1 christos { 3082 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p); 3083 1.1 christos bfd_put_8 (abfd, sym_num, p + 1); 3084 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, p, 3085 1.1 christos 2, reloc_queue); 3086 1.1 christos } 3087 1.1 christos else if (sym_num < 0x10000000) 3088 1.1 christos { 3089 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p); 3090 1.1 christos bfd_put_8 (abfd, sym_num >> 16, p + 1); 3091 1.1 christos bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2); 3092 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3093 1.1 christos p, 4, reloc_queue); 3094 1.1 christos } 3095 1.1 christos else 3096 1.1 christos abort (); 3097 1.1 christos break; 3098 1.1 christos 3099 1.1 christos case R_DATA_GPREL: 3100 1.1 christos /* Account for any addend. */ 3101 1.1 christos if (bfd_reloc->addend) 3102 1.1 christos p = som_reloc_addend (abfd, bfd_reloc->addend, p, 3103 1.1 christos &subspace_reloc_size, reloc_queue); 3104 1.1 christos 3105 1.1 christos if (sym_num < 0x10000000) 3106 1.1 christos { 3107 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3108 1.1 christos bfd_put_8 (abfd, sym_num >> 16, p + 1); 3109 1.1 christos bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2); 3110 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3111 1.1 christos p, 4, reloc_queue); 3112 1.1 christos } 3113 1.1 christos else 3114 1.1 christos abort (); 3115 1.1 christos break; 3116 1.1 christos 3117 1.1 christos case R_DATA_ONE_SYMBOL: 3118 1.1 christos case R_DATA_PLABEL: 3119 1.1 christos case R_CODE_PLABEL: 3120 1.1 christos case R_DLT_REL: 3121 1.1 christos /* Account for any addend using R_DATA_OVERRIDE. */ 3122 1.1 christos if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL 3123 1.1 christos && bfd_reloc->addend) 3124 1.1 christos p = som_reloc_addend (abfd, bfd_reloc->addend, p, 3125 1.1 christos &subspace_reloc_size, reloc_queue); 3126 1.1 christos 3127 1.1 christos if (sym_num < 0x100) 3128 1.1 christos { 3129 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3130 1.1 christos bfd_put_8 (abfd, sym_num, p + 1); 3131 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, p, 3132 1.1 christos 2, reloc_queue); 3133 1.1 christos } 3134 1.1 christos else if (sym_num < 0x10000000) 3135 1.1 christos { 3136 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p); 3137 1.1 christos bfd_put_8 (abfd, sym_num >> 16, p + 1); 3138 1.1 christos bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2); 3139 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3140 1.1 christos p, 4, reloc_queue); 3141 1.1 christos } 3142 1.1 christos else 3143 1.1 christos abort (); 3144 1.1 christos break; 3145 1.1 christos 3146 1.1 christos case R_ENTRY: 3147 1.1 christos { 3148 1.1 christos unsigned int tmp; 3149 1.1 christos arelent *tmp_reloc = NULL; 3150 1.1 christos bfd_put_8 (abfd, R_ENTRY, p); 3151 1.1 christos 3152 1.1 christos /* R_ENTRY relocations have 64 bits of associated 3153 1.1 christos data. Unfortunately the addend field of a bfd 3154 1.1 christos relocation is only 32 bits. So, we split up 3155 1.1 christos the 64bit unwind information and store part in 3156 1.1 christos the R_ENTRY relocation, and the rest in the R_EXIT 3157 1.1 christos relocation. */ 3158 1.1 christos bfd_put_32 (abfd, bfd_reloc->addend, p + 1); 3159 1.1 christos 3160 1.1 christos /* Find the next R_EXIT relocation. */ 3161 1.1 christos for (tmp = j; tmp < subsection->reloc_count; tmp++) 3162 1.1 christos { 3163 1.1 christos tmp_reloc = subsection->orelocation[tmp]; 3164 1.1 christos if (tmp_reloc->howto->type == R_EXIT) 3165 1.1 christos break; 3166 1.1 christos } 3167 1.1 christos 3168 1.1 christos if (tmp == subsection->reloc_count) 3169 1.1 christos abort (); 3170 1.1 christos 3171 1.1 christos bfd_put_32 (abfd, tmp_reloc->addend, p + 5); 3172 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3173 1.1 christos p, 9, reloc_queue); 3174 1.1 christos break; 3175 1.1 christos } 3176 1.1 christos 3177 1.1 christos case R_N_MODE: 3178 1.1 christos case R_S_MODE: 3179 1.1 christos case R_D_MODE: 3180 1.1 christos case R_R_MODE: 3181 1.1 christos /* If this relocation requests the current rounding 3182 1.1 christos mode, then it is redundant. */ 3183 1.1 christos if (bfd_reloc->howto->type != current_rounding_mode) 3184 1.1 christos { 3185 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3186 1.1 christos subspace_reloc_size += 1; 3187 1.1 christos p += 1; 3188 1.1 christos current_rounding_mode = bfd_reloc->howto->type; 3189 1.1 christos } 3190 1.1 christos break; 3191 1.1 christos 3192 1.1 christos #ifndef NO_PCREL_MODES 3193 1.1 christos case R_LONG_PCREL_MODE: 3194 1.1 christos case R_SHORT_PCREL_MODE: 3195 1.1 christos if (bfd_reloc->howto->type != current_call_mode) 3196 1.1 christos { 3197 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3198 1.1 christos subspace_reloc_size += 1; 3199 1.1 christos p += 1; 3200 1.1 christos current_call_mode = bfd_reloc->howto->type; 3201 1.1 christos } 3202 1.1 christos break; 3203 1.1 christos #endif 3204 1.1 christos 3205 1.1 christos case R_EXIT: 3206 1.1 christos case R_ALT_ENTRY: 3207 1.1 christos case R_FSEL: 3208 1.1 christos case R_LSEL: 3209 1.1 christos case R_RSEL: 3210 1.1 christos case R_BEGIN_BRTAB: 3211 1.1 christos case R_END_BRTAB: 3212 1.1 christos case R_BEGIN_TRY: 3213 1.1 christos case R_N0SEL: 3214 1.1 christos case R_N1SEL: 3215 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3216 1.1 christos subspace_reloc_size += 1; 3217 1.1 christos p += 1; 3218 1.1 christos break; 3219 1.1 christos 3220 1.1 christos case R_END_TRY: 3221 1.1 christos /* The end of an exception handling region. The reloc's 3222 1.1 christos addend contains the offset of the exception handling 3223 1.1 christos code. */ 3224 1.1 christos if (bfd_reloc->addend == 0) 3225 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3226 1.1 christos else if (bfd_reloc->addend < 1024) 3227 1.1 christos { 3228 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p); 3229 1.1 christos bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1); 3230 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3231 1.1 christos p, 2, reloc_queue); 3232 1.1 christos } 3233 1.1 christos else 3234 1.1 christos { 3235 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p); 3236 1.1 christos bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1); 3237 1.1 christos bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2); 3238 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3239 1.1 christos p, 4, reloc_queue); 3240 1.1 christos } 3241 1.1 christos break; 3242 1.1 christos 3243 1.1 christos case R_COMP1: 3244 1.1 christos /* The only time we generate R_COMP1, R_COMP2 and 3245 1.1 christos R_CODE_EXPR relocs is for the difference of two 3246 1.1 christos symbols. Hence we can cheat here. */ 3247 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3248 1.1 christos bfd_put_8 (abfd, 0x44, p + 1); 3249 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3250 1.1 christos p, 2, reloc_queue); 3251 1.1 christos break; 3252 1.1 christos 3253 1.1 christos case R_COMP2: 3254 1.1 christos /* The only time we generate R_COMP1, R_COMP2 and 3255 1.1 christos R_CODE_EXPR relocs is for the difference of two 3256 1.1 christos symbols. Hence we can cheat here. */ 3257 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3258 1.1 christos bfd_put_8 (abfd, 0x80, p + 1); 3259 1.1 christos bfd_put_8 (abfd, sym_num >> 16, p + 2); 3260 1.1 christos bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3); 3261 1.1 christos p = try_prev_fixup (abfd, &subspace_reloc_size, 3262 1.1 christos p, 5, reloc_queue); 3263 1.1 christos break; 3264 1.1 christos 3265 1.1 christos case R_CODE_EXPR: 3266 1.1 christos case R_DATA_EXPR: 3267 1.1 christos /* The only time we generate R_COMP1, R_COMP2 and 3268 1.1 christos R_CODE_EXPR relocs is for the difference of two 3269 1.1 christos symbols. Hence we can cheat here. */ 3270 1.1 christos bfd_put_8 (abfd, bfd_reloc->howto->type, p); 3271 1.1 christos subspace_reloc_size += 1; 3272 1.1 christos p += 1; 3273 1.1 christos break; 3274 1.1 christos 3275 1.1 christos /* Put a "R_RESERVED" relocation in the stream if 3276 1.1 christos we hit something we do not understand. The linker 3277 1.1 christos will complain loudly if this ever happens. */ 3278 1.1 christos default: 3279 1.1 christos bfd_put_8 (abfd, 0xff, p); 3280 1.1 christos subspace_reloc_size += 1; 3281 1.1 christos p += 1; 3282 1.1 christos break; 3283 1.1 christos } 3284 1.1 christos } 3285 1.1 christos 3286 1.1 christos /* Last BFD relocation for a subspace has been processed. 3287 1.1 christos Map the rest of the subspace with R_NO_RELOCATION fixups. */ 3288 1.1 christos p = som_reloc_skip (abfd, subsection->size - reloc_offset, 3289 1.1 christos p, &subspace_reloc_size, reloc_queue); 3290 1.1 christos 3291 1.1 christos /* Scribble out the relocations. */ 3292 1.1 christos amt = p - tmp_space; 3293 1.11 christos if (bfd_write (tmp_space, amt, abfd) != amt) 3294 1.10 christos return false; 3295 1.1 christos p = tmp_space; 3296 1.1 christos 3297 1.1 christos total_reloc_size += subspace_reloc_size; 3298 1.1 christos som_section_data (subsection)->subspace_dict->fixup_request_quantity 3299 1.1 christos = subspace_reloc_size; 3300 1.1 christos } 3301 1.1 christos section = section->next; 3302 1.1 christos } 3303 1.1 christos *total_reloc_sizep = total_reloc_size; 3304 1.10 christos return true; 3305 1.1 christos } 3306 1.1 christos 3307 1.11 christos /* Write the length of STR followed by STR to P which points into 3308 1.11 christos *BUF, a buffer of *BUFLEN size. Track total size in *STRINGS_SIZE, 3309 1.11 christos setting *STRX to the current offset for STR. When STR can't fit in 3310 1.11 christos *BUF, flush the buffer to ABFD, possibly reallocating. Return the 3311 1.11 christos next available location in *BUF, or NULL on error. */ 3312 1.11 christos 3313 1.11 christos static char * 3314 1.11 christos add_string (char *p, const char *str, bfd *abfd, char **buf, size_t *buflen, 3315 1.11 christos unsigned int *strings_size, unsigned int *strx) 3316 1.11 christos { 3317 1.11 christos size_t length = strlen (str) + 1; 3318 1.11 christos /* Each entry will take 4 bytes to hold the string length + the 3319 1.11 christos string itself + null terminator + padding to a 4 byte boundary. */ 3320 1.11 christos size_t needed = (4 + length + 3) & ~3; 3321 1.11 christos 3322 1.11 christos /* If there is not enough room for the next entry, then dump the 3323 1.11 christos current buffer contents now and maybe allocate a larger buffer. */ 3324 1.11 christos if (p - *buf + needed > *buflen) 3325 1.11 christos { 3326 1.11 christos /* Flush buffer before refilling or reallocating. */ 3327 1.11 christos size_t amt = p - *buf; 3328 1.11 christos if (bfd_write (*buf, amt, abfd) != amt) 3329 1.11 christos return NULL; 3330 1.11 christos 3331 1.11 christos /* Reallocate if now empty buffer still too small. */ 3332 1.11 christos if (needed > *buflen) 3333 1.11 christos { 3334 1.11 christos /* Ensure a minimum growth factor to avoid O(n**2) space 3335 1.11 christos consumption for n strings. The optimal minimum factor 3336 1.11 christos seems to be 2. */ 3337 1.11 christos if (*buflen * 2 < needed) 3338 1.11 christos *buflen = needed; 3339 1.11 christos else 3340 1.11 christos *buflen = *buflen * 2; 3341 1.11 christos free (*buf); 3342 1.11 christos *buf = bfd_malloc (*buflen); 3343 1.11 christos if (*buf == NULL) 3344 1.11 christos return NULL; 3345 1.11 christos } 3346 1.11 christos 3347 1.11 christos /* Reset to beginning of the (possibly new) buffer space. */ 3348 1.11 christos p = *buf; 3349 1.11 christos } 3350 1.11 christos 3351 1.11 christos /* First element in a string table entry is the length of 3352 1.11 christos the string. This must always be 4 byte aligned. This is 3353 1.11 christos also an appropriate time to fill in the string index 3354 1.11 christos field in the symbol table entry. */ 3355 1.11 christos bfd_put_32 (abfd, length - 1, p); 3356 1.11 christos *strings_size += 4; 3357 1.11 christos p += 4; 3358 1.11 christos 3359 1.11 christos *strx = *strings_size; 3360 1.11 christos 3361 1.11 christos /* Next comes the string itself + a null terminator. */ 3362 1.11 christos memcpy (p, str, length); 3363 1.11 christos p += length; 3364 1.11 christos *strings_size += length; 3365 1.11 christos 3366 1.11 christos /* Always align up to the next word boundary. */ 3367 1.11 christos if (length & 3) 3368 1.11 christos { 3369 1.11 christos length = 4 - (length & 3); 3370 1.11 christos memset (p, 0, length); 3371 1.11 christos *strings_size += length; 3372 1.11 christos p += length; 3373 1.11 christos } 3374 1.11 christos return p; 3375 1.11 christos } 3376 1.11 christos 3377 1.1 christos /* Write out the space/subspace string table. */ 3378 1.1 christos 3379 1.10 christos static bool 3380 1.1 christos som_write_space_strings (bfd *abfd, 3381 1.1 christos unsigned long current_offset, 3382 1.11 christos unsigned int *strings_size) 3383 1.1 christos { 3384 1.1 christos /* Chunk of memory that we can use as buffer space, then throw 3385 1.1 christos away. */ 3386 1.1 christos size_t tmp_space_size = SOM_TMP_BUFSIZE; 3387 1.9 christos char *tmp_space = bfd_malloc (tmp_space_size); 3388 1.1 christos char *p = tmp_space; 3389 1.1 christos asection *section; 3390 1.1 christos 3391 1.9 christos if (tmp_space == NULL) 3392 1.10 christos return false; 3393 1.9 christos 3394 1.1 christos /* Seek to the start of the space strings in preparation for writing 3395 1.1 christos them out. */ 3396 1.11 christos if (bfd_seek (abfd, current_offset, SEEK_SET) != 0) 3397 1.10 christos return false; 3398 1.1 christos 3399 1.1 christos /* Walk through all the spaces and subspaces (order is not important) 3400 1.1 christos building up and writing string table entries for their names. */ 3401 1.11 christos *strings_size = 0; 3402 1.1 christos for (section = abfd->sections; section != NULL; section = section->next) 3403 1.1 christos { 3404 1.11 christos unsigned int *strx; 3405 1.1 christos 3406 1.1 christos /* Only work with space/subspaces; avoid any other sections 3407 1.1 christos which might have been made (.text for example). */ 3408 1.1 christos if (som_is_space (section)) 3409 1.11 christos strx = &som_section_data (section)->space_dict->name; 3410 1.11 christos else if (som_is_subspace (section)) 3411 1.11 christos strx = &som_section_data (section)->subspace_dict->name; 3412 1.1 christos else 3413 1.11 christos continue; 3414 1.1 christos 3415 1.11 christos p = add_string (p, section->name, abfd, &tmp_space, &tmp_space_size, 3416 1.11 christos strings_size, strx); 3417 1.11 christos if (p == NULL) 3418 1.11 christos return false; 3419 1.1 christos } 3420 1.1 christos 3421 1.1 christos /* Done with the space/subspace strings. Write out any information 3422 1.1 christos contained in a partial block. */ 3423 1.11 christos size_t amt = p - tmp_space; 3424 1.11 christos bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true; 3425 1.6 christos free (tmp_space); 3426 1.11 christos return ok; 3427 1.1 christos } 3428 1.1 christos 3429 1.1 christos /* Write out the symbol string table. */ 3430 1.1 christos 3431 1.10 christos static bool 3432 1.1 christos som_write_symbol_strings (bfd *abfd, 3433 1.1 christos unsigned long current_offset, 3434 1.1 christos asymbol **syms, 3435 1.1 christos unsigned int num_syms, 3436 1.11 christos unsigned int *strings_size, 3437 1.1 christos struct som_compilation_unit *compilation_unit) 3438 1.1 christos { 3439 1.1 christos unsigned int i; 3440 1.1 christos /* Chunk of memory that we can use as buffer space, then throw 3441 1.1 christos away. */ 3442 1.1 christos size_t tmp_space_size = SOM_TMP_BUFSIZE; 3443 1.9 christos char *tmp_space = bfd_malloc (tmp_space_size); 3444 1.1 christos char *p = tmp_space; 3445 1.1 christos 3446 1.9 christos if (tmp_space == NULL) 3447 1.10 christos return false; 3448 1.9 christos 3449 1.1 christos /* This gets a bit gruesome because of the compilation unit. The 3450 1.1 christos strings within the compilation unit are part of the symbol 3451 1.1 christos strings, but don't have symbol_dictionary entries. So, manually 3452 1.1 christos write them and update the compilation unit header. On input, the 3453 1.1 christos compilation unit header contains local copies of the strings. 3454 1.1 christos Move them aside. */ 3455 1.1 christos 3456 1.1 christos /* Seek to the start of the space strings in preparation for writing 3457 1.1 christos them out. */ 3458 1.11 christos if (bfd_seek (abfd, current_offset, SEEK_SET) != 0) 3459 1.10 christos return false; 3460 1.1 christos 3461 1.11 christos *strings_size = 0; 3462 1.1 christos if (compilation_unit) 3463 1.1 christos { 3464 1.1 christos for (i = 0; i < 4; i++) 3465 1.1 christos { 3466 1.8 christos struct som_name_pt *name; 3467 1.1 christos 3468 1.1 christos switch (i) 3469 1.1 christos { 3470 1.1 christos case 0: 3471 1.1 christos name = &compilation_unit->name; 3472 1.1 christos break; 3473 1.1 christos case 1: 3474 1.1 christos name = &compilation_unit->language_name; 3475 1.1 christos break; 3476 1.1 christos case 2: 3477 1.1 christos name = &compilation_unit->product_id; 3478 1.1 christos break; 3479 1.1 christos case 3: 3480 1.1 christos name = &compilation_unit->version_id; 3481 1.1 christos break; 3482 1.8 christos default: 3483 1.8 christos abort (); 3484 1.1 christos } 3485 1.1 christos 3486 1.11 christos p = add_string (p, name->name, abfd, &tmp_space, &tmp_space_size, 3487 1.11 christos strings_size, &name->strx); 3488 1.1 christos 3489 1.11 christos if (p == NULL) 3490 1.11 christos return false; 3491 1.1 christos } 3492 1.1 christos } 3493 1.1 christos 3494 1.1 christos for (i = 0; i < num_syms; i++) 3495 1.1 christos { 3496 1.11 christos p = add_string (p, syms[i]->name, abfd, &tmp_space, &tmp_space_size, 3497 1.11 christos strings_size, 3498 1.11 christos &som_symbol_data (syms[i])->stringtab_offset); 3499 1.11 christos if (p == NULL) 3500 1.11 christos return false; 3501 1.1 christos } 3502 1.1 christos 3503 1.1 christos /* Scribble out any partial block. */ 3504 1.11 christos size_t amt = p - tmp_space; 3505 1.11 christos bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true; 3506 1.6 christos free (tmp_space); 3507 1.11 christos return ok; 3508 1.1 christos } 3509 1.1 christos 3510 1.1 christos /* Compute variable information to be placed in the SOM headers, 3511 1.1 christos space/subspace dictionaries, relocation streams, etc. Begin 3512 1.1 christos writing parts of the object file. */ 3513 1.1 christos 3514 1.10 christos static bool 3515 1.1 christos som_begin_writing (bfd *abfd) 3516 1.1 christos { 3517 1.1 christos unsigned long current_offset = 0; 3518 1.1 christos unsigned int strings_size = 0; 3519 1.1 christos unsigned long num_spaces, num_subspaces, i; 3520 1.1 christos asection *section; 3521 1.1 christos unsigned int total_subspaces = 0; 3522 1.1 christos struct som_exec_auxhdr *exec_header = NULL; 3523 1.1 christos 3524 1.1 christos /* The file header will always be first in an object file, 3525 1.1 christos everything else can be in random locations. To keep things 3526 1.1 christos "simple" BFD will lay out the object file in the manner suggested 3527 1.1 christos by the PRO ABI for PA-RISC Systems. */ 3528 1.1 christos 3529 1.1 christos /* Before any output can really begin offsets for all the major 3530 1.1 christos portions of the object file must be computed. So, starting 3531 1.1 christos with the initial file header compute (and sometimes write) 3532 1.1 christos each portion of the object file. */ 3533 1.1 christos 3534 1.1 christos /* Make room for the file header, it's contents are not complete 3535 1.1 christos yet, so it can not be written at this time. */ 3536 1.1 christos current_offset += sizeof (struct som_external_header); 3537 1.1 christos 3538 1.1 christos /* Any auxiliary headers will follow the file header. Right now 3539 1.1 christos we support only the copyright and version headers. */ 3540 1.1 christos obj_som_file_hdr (abfd)->aux_header_location = current_offset; 3541 1.1 christos obj_som_file_hdr (abfd)->aux_header_size = 0; 3542 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 3543 1.1 christos { 3544 1.1 christos /* Parts of the exec header will be filled in later, so 3545 1.1 christos delay writing the header itself. Fill in the defaults, 3546 1.1 christos and write it later. */ 3547 1.1 christos current_offset += sizeof (struct som_external_exec_auxhdr); 3548 1.1 christos obj_som_file_hdr (abfd)->aux_header_size 3549 1.1 christos += sizeof (struct som_external_exec_auxhdr); 3550 1.1 christos exec_header = obj_som_exec_hdr (abfd); 3551 1.1 christos exec_header->som_auxhdr.type = EXEC_AUX_ID; 3552 1.1 christos exec_header->som_auxhdr.length = 40; 3553 1.1 christos } 3554 1.1 christos if (obj_som_version_hdr (abfd) != NULL) 3555 1.1 christos { 3556 1.1 christos struct som_external_string_auxhdr ext_string_auxhdr; 3557 1.1 christos bfd_size_type len; 3558 1.1 christos 3559 1.11 christos if (bfd_seek (abfd, current_offset, SEEK_SET) != 0) 3560 1.10 christos return false; 3561 1.1 christos 3562 1.1 christos /* Write the aux_id structure and the string length. */ 3563 1.1 christos len = sizeof (struct som_external_string_auxhdr); 3564 1.1 christos obj_som_file_hdr (abfd)->aux_header_size += len; 3565 1.1 christos current_offset += len; 3566 1.1 christos som_swap_string_auxhdr_out 3567 1.8 christos (obj_som_version_hdr (abfd), &ext_string_auxhdr); 3568 1.11 christos if (bfd_write (&ext_string_auxhdr, len, abfd) != len) 3569 1.10 christos return false; 3570 1.1 christos 3571 1.1 christos /* Write the version string. */ 3572 1.1 christos len = obj_som_version_hdr (abfd)->header_id.length - 4; 3573 1.1 christos obj_som_file_hdr (abfd)->aux_header_size += len; 3574 1.1 christos current_offset += len; 3575 1.11 christos if (bfd_write (obj_som_version_hdr (abfd)->string, len, abfd) != len) 3576 1.10 christos return false; 3577 1.1 christos } 3578 1.1 christos 3579 1.1 christos if (obj_som_copyright_hdr (abfd) != NULL) 3580 1.1 christos { 3581 1.1 christos struct som_external_string_auxhdr ext_string_auxhdr; 3582 1.1 christos bfd_size_type len; 3583 1.1 christos 3584 1.11 christos if (bfd_seek (abfd, current_offset, SEEK_SET) != 0) 3585 1.10 christos return false; 3586 1.1 christos 3587 1.1 christos /* Write the aux_id structure and the string length. */ 3588 1.1 christos len = sizeof (struct som_external_string_auxhdr); 3589 1.1 christos obj_som_file_hdr (abfd)->aux_header_size += len; 3590 1.1 christos current_offset += len; 3591 1.1 christos som_swap_string_auxhdr_out 3592 1.8 christos (obj_som_copyright_hdr (abfd), &ext_string_auxhdr); 3593 1.11 christos if (bfd_write (&ext_string_auxhdr, len, abfd) != len) 3594 1.10 christos return false; 3595 1.1 christos 3596 1.1 christos /* Write the copyright string. */ 3597 1.1 christos len = obj_som_copyright_hdr (abfd)->header_id.length - 4; 3598 1.1 christos obj_som_file_hdr (abfd)->aux_header_size += len; 3599 1.1 christos current_offset += len; 3600 1.11 christos if (bfd_write (obj_som_copyright_hdr (abfd)->string, len, abfd) != len) 3601 1.10 christos return false; 3602 1.1 christos } 3603 1.1 christos 3604 1.1 christos /* Next comes the initialization pointers; we have no initialization 3605 1.1 christos pointers, so current offset does not change. */ 3606 1.1 christos obj_som_file_hdr (abfd)->init_array_location = current_offset; 3607 1.1 christos obj_som_file_hdr (abfd)->init_array_total = 0; 3608 1.1 christos 3609 1.1 christos /* Next are the space records. These are fixed length records. 3610 1.1 christos 3611 1.1 christos Count the number of spaces to determine how much room is needed 3612 1.1 christos in the object file for the space records. 3613 1.1 christos 3614 1.1 christos The names of the spaces are stored in a separate string table, 3615 1.1 christos and the index for each space into the string table is computed 3616 1.1 christos below. Therefore, it is not possible to write the space headers 3617 1.1 christos at this time. */ 3618 1.1 christos num_spaces = som_count_spaces (abfd); 3619 1.1 christos obj_som_file_hdr (abfd)->space_location = current_offset; 3620 1.1 christos obj_som_file_hdr (abfd)->space_total = num_spaces; 3621 1.1 christos current_offset += 3622 1.1 christos num_spaces * sizeof (struct som_external_space_dictionary_record); 3623 1.1 christos 3624 1.1 christos /* Next are the subspace records. These are fixed length records. 3625 1.1 christos 3626 1.1 christos Count the number of subspaes to determine how much room is needed 3627 1.1 christos in the object file for the subspace records. 3628 1.1 christos 3629 1.1 christos A variety if fields in the subspace record are still unknown at 3630 1.1 christos this time (index into string table, fixup stream location/size, etc). */ 3631 1.1 christos num_subspaces = som_count_subspaces (abfd); 3632 1.1 christos obj_som_file_hdr (abfd)->subspace_location = current_offset; 3633 1.1 christos obj_som_file_hdr (abfd)->subspace_total = num_subspaces; 3634 1.1 christos current_offset 3635 1.1 christos += num_subspaces * sizeof (struct som_external_subspace_dictionary_record); 3636 1.1 christos 3637 1.1 christos /* Next is the string table for the space/subspace names. We will 3638 1.1 christos build and write the string table on the fly. At the same time 3639 1.1 christos we will fill in the space/subspace name index fields. */ 3640 1.1 christos 3641 1.1 christos /* The string table needs to be aligned on a word boundary. */ 3642 1.1 christos if (current_offset % 4) 3643 1.1 christos current_offset += (4 - (current_offset % 4)); 3644 1.1 christos 3645 1.1 christos /* Mark the offset of the space/subspace string table in the 3646 1.1 christos file header. */ 3647 1.1 christos obj_som_file_hdr (abfd)->space_strings_location = current_offset; 3648 1.1 christos 3649 1.1 christos /* Scribble out the space strings. */ 3650 1.1 christos if (! som_write_space_strings (abfd, current_offset, &strings_size)) 3651 1.10 christos return false; 3652 1.1 christos 3653 1.1 christos /* Record total string table size in the header and update the 3654 1.1 christos current offset. */ 3655 1.1 christos obj_som_file_hdr (abfd)->space_strings_size = strings_size; 3656 1.1 christos current_offset += strings_size; 3657 1.1 christos 3658 1.1 christos /* Next is the compilation unit. */ 3659 1.1 christos obj_som_file_hdr (abfd)->compiler_location = current_offset; 3660 1.1 christos obj_som_file_hdr (abfd)->compiler_total = 0; 3661 1.1 christos if (obj_som_compilation_unit (abfd)) 3662 1.1 christos { 3663 1.1 christos obj_som_file_hdr (abfd)->compiler_total = 1; 3664 1.1 christos current_offset += sizeof (struct som_external_compilation_unit); 3665 1.1 christos } 3666 1.1 christos 3667 1.1 christos /* Now compute the file positions for the loadable subspaces, taking 3668 1.1 christos care to make sure everything stays properly aligned. */ 3669 1.1 christos 3670 1.1 christos section = abfd->sections; 3671 1.1 christos for (i = 0; i < num_spaces; i++) 3672 1.1 christos { 3673 1.1 christos asection *subsection; 3674 1.1 christos int first_subspace; 3675 1.1 christos unsigned int subspace_offset = 0; 3676 1.1 christos 3677 1.1 christos /* Find a space. */ 3678 1.1 christos while (!som_is_space (section)) 3679 1.1 christos section = section->next; 3680 1.1 christos 3681 1.1 christos first_subspace = 1; 3682 1.1 christos /* Now look for all its subspaces. */ 3683 1.1 christos for (subsection = abfd->sections; 3684 1.1 christos subsection != NULL; 3685 1.1 christos subsection = subsection->next) 3686 1.1 christos { 3687 1.1 christos 3688 1.1 christos if (!som_is_subspace (subsection) 3689 1.1 christos || !som_is_container (section, subsection) 3690 1.1 christos || (subsection->flags & SEC_ALLOC) == 0) 3691 1.1 christos continue; 3692 1.1 christos 3693 1.1 christos /* If this is the first subspace in the space, and we are 3694 1.1 christos building an executable, then take care to make sure all 3695 1.1 christos the alignments are correct and update the exec header. */ 3696 1.1 christos if (first_subspace 3697 1.1 christos && (abfd->flags & (EXEC_P | DYNAMIC))) 3698 1.1 christos { 3699 1.1 christos /* Demand paged executables have each space aligned to a 3700 1.1 christos page boundary. Sharable executables (write-protected 3701 1.1 christos text) have just the private (aka data & bss) space aligned 3702 1.1 christos to a page boundary. Ugh. Not true for HPUX. 3703 1.1 christos 3704 1.1 christos The HPUX kernel requires the text to always be page aligned 3705 1.1 christos within the file regardless of the executable's type. */ 3706 1.1 christos if (abfd->flags & (D_PAGED | DYNAMIC) 3707 1.1 christos || (subsection->flags & SEC_CODE) 3708 1.1 christos || ((abfd->flags & WP_TEXT) 3709 1.1 christos && (subsection->flags & SEC_DATA))) 3710 1.1 christos current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE); 3711 1.1 christos 3712 1.1 christos /* Update the exec header. */ 3713 1.1 christos if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0) 3714 1.1 christos { 3715 1.1 christos exec_header->exec_tmem = section->vma; 3716 1.1 christos exec_header->exec_tfile = current_offset; 3717 1.1 christos } 3718 1.1 christos if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0) 3719 1.1 christos { 3720 1.1 christos exec_header->exec_dmem = section->vma; 3721 1.1 christos exec_header->exec_dfile = current_offset; 3722 1.1 christos } 3723 1.1 christos 3724 1.1 christos /* Keep track of exactly where we are within a particular 3725 1.1 christos space. This is necessary as the braindamaged HPUX 3726 1.1 christos loader will create holes between subspaces *and* 3727 1.1 christos subspace alignments are *NOT* preserved. What a crock. */ 3728 1.1 christos subspace_offset = subsection->vma; 3729 1.1 christos 3730 1.1 christos /* Only do this for the first subspace within each space. */ 3731 1.1 christos first_subspace = 0; 3732 1.1 christos } 3733 1.1 christos else if (abfd->flags & (EXEC_P | DYNAMIC)) 3734 1.1 christos { 3735 1.1 christos /* The braindamaged HPUX loader may have created a hole 3736 1.1 christos between two subspaces. It is *not* sufficient to use 3737 1.1 christos the alignment specifications within the subspaces to 3738 1.1 christos account for these holes -- I've run into at least one 3739 1.1 christos case where the loader left one code subspace unaligned 3740 1.1 christos in a final executable. 3741 1.1 christos 3742 1.1 christos To combat this we keep a current offset within each space, 3743 1.1 christos and use the subspace vma fields to detect and preserve 3744 1.1 christos holes. What a crock! 3745 1.1 christos 3746 1.1 christos ps. This is not necessary for unloadable space/subspaces. */ 3747 1.1 christos current_offset += subsection->vma - subspace_offset; 3748 1.1 christos if (subsection->flags & SEC_CODE) 3749 1.1 christos exec_header->exec_tsize += subsection->vma - subspace_offset; 3750 1.1 christos else 3751 1.1 christos exec_header->exec_dsize += subsection->vma - subspace_offset; 3752 1.1 christos subspace_offset += subsection->vma - subspace_offset; 3753 1.1 christos } 3754 1.1 christos 3755 1.1 christos subsection->target_index = total_subspaces++; 3756 1.1 christos /* This is real data to be loaded from the file. */ 3757 1.1 christos if (subsection->flags & SEC_LOAD) 3758 1.1 christos { 3759 1.1 christos /* Update the size of the code & data. */ 3760 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC) 3761 1.1 christos && subsection->flags & SEC_CODE) 3762 1.1 christos exec_header->exec_tsize += subsection->size; 3763 1.1 christos else if (abfd->flags & (EXEC_P | DYNAMIC) 3764 1.1 christos && subsection->flags & SEC_DATA) 3765 1.1 christos exec_header->exec_dsize += subsection->size; 3766 1.1 christos som_section_data (subsection)->subspace_dict->file_loc_init_value 3767 1.1 christos = current_offset; 3768 1.1 christos subsection->filepos = current_offset; 3769 1.1 christos current_offset += subsection->size; 3770 1.1 christos subspace_offset += subsection->size; 3771 1.1 christos } 3772 1.1 christos /* Looks like uninitialized data. */ 3773 1.1 christos else 3774 1.1 christos { 3775 1.1 christos /* Update the size of the bss section. */ 3776 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 3777 1.1 christos exec_header->exec_bsize += subsection->size; 3778 1.1 christos 3779 1.1 christos som_section_data (subsection)->subspace_dict->file_loc_init_value 3780 1.1 christos = 0; 3781 1.1 christos som_section_data (subsection)->subspace_dict-> 3782 1.1 christos initialization_length = 0; 3783 1.1 christos } 3784 1.1 christos } 3785 1.1 christos /* Goto the next section. */ 3786 1.1 christos section = section->next; 3787 1.1 christos } 3788 1.1 christos 3789 1.1 christos /* Finally compute the file positions for unloadable subspaces. 3790 1.1 christos If building an executable, start the unloadable stuff on its 3791 1.1 christos own page. */ 3792 1.1 christos 3793 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 3794 1.1 christos current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE); 3795 1.1 christos 3796 1.1 christos obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset; 3797 1.1 christos section = abfd->sections; 3798 1.1 christos for (i = 0; i < num_spaces; i++) 3799 1.1 christos { 3800 1.1 christos asection *subsection; 3801 1.1 christos 3802 1.1 christos /* Find a space. */ 3803 1.1 christos while (!som_is_space (section)) 3804 1.1 christos section = section->next; 3805 1.1 christos 3806 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 3807 1.1 christos current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE); 3808 1.1 christos 3809 1.1 christos /* Now look for all its subspaces. */ 3810 1.1 christos for (subsection = abfd->sections; 3811 1.1 christos subsection != NULL; 3812 1.1 christos subsection = subsection->next) 3813 1.1 christos { 3814 1.1 christos 3815 1.1 christos if (!som_is_subspace (subsection) 3816 1.1 christos || !som_is_container (section, subsection) 3817 1.1 christos || (subsection->flags & SEC_ALLOC) != 0) 3818 1.1 christos continue; 3819 1.1 christos 3820 1.1 christos subsection->target_index = total_subspaces++; 3821 1.1 christos /* This is real data to be loaded from the file. */ 3822 1.1 christos if ((subsection->flags & SEC_LOAD) == 0) 3823 1.1 christos { 3824 1.1 christos som_section_data (subsection)->subspace_dict->file_loc_init_value 3825 1.1 christos = current_offset; 3826 1.1 christos subsection->filepos = current_offset; 3827 1.1 christos current_offset += subsection->size; 3828 1.1 christos } 3829 1.1 christos /* Looks like uninitialized data. */ 3830 1.1 christos else 3831 1.1 christos { 3832 1.1 christos som_section_data (subsection)->subspace_dict->file_loc_init_value 3833 1.1 christos = 0; 3834 1.1 christos som_section_data (subsection)->subspace_dict-> 3835 1.1 christos initialization_length = subsection->size; 3836 1.1 christos } 3837 1.1 christos } 3838 1.1 christos /* Goto the next section. */ 3839 1.1 christos section = section->next; 3840 1.1 christos } 3841 1.1 christos 3842 1.1 christos /* If building an executable, then make sure to seek to and write 3843 1.1 christos one byte at the end of the file to make sure any necessary 3844 1.1 christos zeros are filled in. Ugh. */ 3845 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 3846 1.1 christos current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE); 3847 1.11 christos if (bfd_seek (abfd, current_offset - 1, SEEK_SET) != 0) 3848 1.10 christos return false; 3849 1.11 christos if (bfd_write ("", 1, abfd) != 1) 3850 1.10 christos return false; 3851 1.1 christos 3852 1.1 christos obj_som_file_hdr (abfd)->unloadable_sp_size 3853 1.1 christos = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location; 3854 1.1 christos 3855 1.1 christos /* Loader fixups are not supported in any way shape or form. */ 3856 1.1 christos obj_som_file_hdr (abfd)->loader_fixup_location = 0; 3857 1.1 christos obj_som_file_hdr (abfd)->loader_fixup_total = 0; 3858 1.1 christos 3859 1.1 christos /* Done. Store the total size of the SOM so far. */ 3860 1.1 christos obj_som_file_hdr (abfd)->som_length = current_offset; 3861 1.1 christos 3862 1.10 christos return true; 3863 1.1 christos } 3864 1.1 christos 3865 1.1 christos /* Finally, scribble out the various headers to the disk. */ 3866 1.1 christos 3867 1.10 christos static bool 3868 1.1 christos som_finish_writing (bfd *abfd) 3869 1.1 christos { 3870 1.1 christos int num_spaces = som_count_spaces (abfd); 3871 1.1 christos asymbol **syms = bfd_get_outsymbols (abfd); 3872 1.1 christos int i, num_syms; 3873 1.1 christos int subspace_index = 0; 3874 1.1 christos file_ptr location; 3875 1.1 christos asection *section; 3876 1.1 christos unsigned long current_offset; 3877 1.1 christos unsigned int strings_size, total_reloc_size; 3878 1.9 christos size_t amt; 3879 1.1 christos struct som_external_header ext_header; 3880 1.1 christos 3881 1.1 christos /* We must set up the version identifier here as objcopy/strip copy 3882 1.1 christos private BFD data too late for us to handle this in som_begin_writing. */ 3883 1.1 christos if (obj_som_exec_data (abfd) 3884 1.1 christos && obj_som_exec_data (abfd)->version_id) 3885 1.1 christos obj_som_file_hdr (abfd)->version_id = obj_som_exec_data (abfd)->version_id; 3886 1.1 christos else 3887 1.1 christos obj_som_file_hdr (abfd)->version_id = NEW_VERSION_ID; 3888 1.1 christos 3889 1.1 christos /* Next is the symbol table. These are fixed length records. 3890 1.1 christos 3891 1.1 christos Count the number of symbols to determine how much room is needed 3892 1.1 christos in the object file for the symbol table. 3893 1.1 christos 3894 1.1 christos The names of the symbols are stored in a separate string table, 3895 1.1 christos and the index for each symbol name into the string table is computed 3896 1.1 christos below. Therefore, it is not possible to write the symbol table 3897 1.1 christos at this time. 3898 1.1 christos 3899 1.1 christos These used to be output before the subspace contents, but they 3900 1.1 christos were moved here to work around a stupid bug in the hpux linker 3901 1.1 christos (fixed in hpux10). */ 3902 1.1 christos current_offset = obj_som_file_hdr (abfd)->som_length; 3903 1.1 christos 3904 1.1 christos /* Make sure we're on a word boundary. */ 3905 1.1 christos if (current_offset % 4) 3906 1.1 christos current_offset += (4 - (current_offset % 4)); 3907 1.1 christos 3908 1.1 christos num_syms = bfd_get_symcount (abfd); 3909 1.1 christos obj_som_file_hdr (abfd)->symbol_location = current_offset; 3910 1.1 christos obj_som_file_hdr (abfd)->symbol_total = num_syms; 3911 1.1 christos current_offset += 3912 1.1 christos num_syms * sizeof (struct som_external_symbol_dictionary_record); 3913 1.1 christos 3914 1.1 christos /* Next are the symbol strings. 3915 1.1 christos Align them to a word boundary. */ 3916 1.1 christos if (current_offset % 4) 3917 1.1 christos current_offset += (4 - (current_offset % 4)); 3918 1.1 christos obj_som_file_hdr (abfd)->symbol_strings_location = current_offset; 3919 1.1 christos 3920 1.1 christos /* Scribble out the symbol strings. */ 3921 1.1 christos if (! som_write_symbol_strings (abfd, current_offset, syms, 3922 1.1 christos num_syms, &strings_size, 3923 1.1 christos obj_som_compilation_unit (abfd))) 3924 1.10 christos return false; 3925 1.1 christos 3926 1.1 christos /* Record total string table size in header and update the 3927 1.1 christos current offset. */ 3928 1.1 christos obj_som_file_hdr (abfd)->symbol_strings_size = strings_size; 3929 1.1 christos current_offset += strings_size; 3930 1.1 christos 3931 1.1 christos /* Do prep work before handling fixups. */ 3932 1.9 christos if (!som_prep_for_fixups (abfd, 3933 1.9 christos bfd_get_outsymbols (abfd), 3934 1.9 christos bfd_get_symcount (abfd))) 3935 1.10 christos return false; 3936 1.1 christos 3937 1.1 christos /* At the end of the file is the fixup stream which starts on a 3938 1.1 christos word boundary. */ 3939 1.1 christos if (current_offset % 4) 3940 1.1 christos current_offset += (4 - (current_offset % 4)); 3941 1.1 christos obj_som_file_hdr (abfd)->fixup_request_location = current_offset; 3942 1.1 christos 3943 1.1 christos /* Write the fixups and update fields in subspace headers which 3944 1.1 christos relate to the fixup stream. */ 3945 1.1 christos if (! som_write_fixups (abfd, current_offset, &total_reloc_size)) 3946 1.10 christos return false; 3947 1.1 christos 3948 1.1 christos /* Record the total size of the fixup stream in the file header. */ 3949 1.1 christos obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size; 3950 1.1 christos 3951 1.1 christos /* Done. Store the total size of the SOM. */ 3952 1.1 christos obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size; 3953 1.1 christos 3954 1.1 christos /* Now that the symbol table information is complete, build and 3955 1.1 christos write the symbol table. */ 3956 1.1 christos if (! som_build_and_write_symbol_table (abfd)) 3957 1.10 christos return false; 3958 1.1 christos 3959 1.1 christos /* Subspaces are written first so that we can set up information 3960 1.1 christos about them in their containing spaces as the subspace is written. */ 3961 1.1 christos 3962 1.1 christos /* Seek to the start of the subspace dictionary records. */ 3963 1.1 christos location = obj_som_file_hdr (abfd)->subspace_location; 3964 1.1 christos if (bfd_seek (abfd, location, SEEK_SET) != 0) 3965 1.10 christos return false; 3966 1.1 christos 3967 1.1 christos section = abfd->sections; 3968 1.1 christos /* Now for each loadable space write out records for its subspaces. */ 3969 1.1 christos for (i = 0; i < num_spaces; i++) 3970 1.1 christos { 3971 1.1 christos asection *subsection; 3972 1.1 christos 3973 1.1 christos /* Find a space. */ 3974 1.1 christos while (!som_is_space (section)) 3975 1.1 christos section = section->next; 3976 1.1 christos 3977 1.1 christos /* Now look for all its subspaces. */ 3978 1.1 christos for (subsection = abfd->sections; 3979 1.1 christos subsection != NULL; 3980 1.1 christos subsection = subsection->next) 3981 1.1 christos { 3982 1.8 christos struct som_external_subspace_dictionary_record ext_subspace_dict; 3983 1.1 christos 3984 1.1 christos /* Skip any section which does not correspond to a space 3985 1.1 christos or subspace. Or does not have SEC_ALLOC set (and therefore 3986 1.1 christos has no real bits on the disk). */ 3987 1.1 christos if (!som_is_subspace (subsection) 3988 1.1 christos || !som_is_container (section, subsection) 3989 1.1 christos || (subsection->flags & SEC_ALLOC) == 0) 3990 1.1 christos continue; 3991 1.1 christos 3992 1.1 christos /* If this is the first subspace for this space, then save 3993 1.1 christos the index of the subspace in its containing space. Also 3994 1.1 christos set "is_loadable" in the containing space. */ 3995 1.1 christos 3996 1.1 christos if (som_section_data (section)->space_dict->subspace_quantity == 0) 3997 1.1 christos { 3998 1.1 christos som_section_data (section)->space_dict->is_loadable = 1; 3999 1.1 christos som_section_data (section)->space_dict->subspace_index 4000 1.1 christos = subspace_index; 4001 1.1 christos } 4002 1.1 christos 4003 1.1 christos /* Increment the number of subspaces seen and the number of 4004 1.1 christos subspaces contained within the current space. */ 4005 1.1 christos subspace_index++; 4006 1.1 christos som_section_data (section)->space_dict->subspace_quantity++; 4007 1.1 christos 4008 1.1 christos /* Mark the index of the current space within the subspace's 4009 1.1 christos dictionary record. */ 4010 1.1 christos som_section_data (subsection)->subspace_dict->space_index = i; 4011 1.1 christos 4012 1.1 christos /* Dump the current subspace header. */ 4013 1.8 christos som_swap_subspace_dictionary_record_out 4014 1.8 christos (som_section_data (subsection)->subspace_dict, &ext_subspace_dict); 4015 1.1 christos amt = sizeof (struct som_subspace_dictionary_record); 4016 1.11 christos if (bfd_write (&ext_subspace_dict, amt, abfd) != amt) 4017 1.10 christos return false; 4018 1.1 christos } 4019 1.1 christos /* Goto the next section. */ 4020 1.1 christos section = section->next; 4021 1.1 christos } 4022 1.1 christos 4023 1.1 christos /* Now repeat the process for unloadable subspaces. */ 4024 1.1 christos section = abfd->sections; 4025 1.1 christos /* Now for each space write out records for its subspaces. */ 4026 1.1 christos for (i = 0; i < num_spaces; i++) 4027 1.1 christos { 4028 1.1 christos asection *subsection; 4029 1.1 christos 4030 1.1 christos /* Find a space. */ 4031 1.1 christos while (!som_is_space (section)) 4032 1.1 christos section = section->next; 4033 1.1 christos 4034 1.1 christos /* Now look for all its subspaces. */ 4035 1.1 christos for (subsection = abfd->sections; 4036 1.1 christos subsection != NULL; 4037 1.1 christos subsection = subsection->next) 4038 1.1 christos { 4039 1.8 christos struct som_external_subspace_dictionary_record ext_subspace_dict; 4040 1.1 christos 4041 1.1 christos /* Skip any section which does not correspond to a space or 4042 1.1 christos subspace, or which SEC_ALLOC set (and therefore handled 4043 1.1 christos in the loadable spaces/subspaces code above). */ 4044 1.1 christos 4045 1.1 christos if (!som_is_subspace (subsection) 4046 1.1 christos || !som_is_container (section, subsection) 4047 1.1 christos || (subsection->flags & SEC_ALLOC) != 0) 4048 1.1 christos continue; 4049 1.1 christos 4050 1.1 christos /* If this is the first subspace for this space, then save 4051 1.1 christos the index of the subspace in its containing space. Clear 4052 1.1 christos "is_loadable". */ 4053 1.1 christos 4054 1.1 christos if (som_section_data (section)->space_dict->subspace_quantity == 0) 4055 1.1 christos { 4056 1.1 christos som_section_data (section)->space_dict->is_loadable = 0; 4057 1.1 christos som_section_data (section)->space_dict->subspace_index 4058 1.1 christos = subspace_index; 4059 1.1 christos } 4060 1.1 christos 4061 1.1 christos /* Increment the number of subspaces seen and the number of 4062 1.1 christos subspaces contained within the current space. */ 4063 1.1 christos som_section_data (section)->space_dict->subspace_quantity++; 4064 1.1 christos subspace_index++; 4065 1.1 christos 4066 1.1 christos /* Mark the index of the current space within the subspace's 4067 1.1 christos dictionary record. */ 4068 1.1 christos som_section_data (subsection)->subspace_dict->space_index = i; 4069 1.1 christos 4070 1.1 christos /* Dump this subspace header. */ 4071 1.8 christos som_swap_subspace_dictionary_record_out 4072 1.8 christos (som_section_data (subsection)->subspace_dict, &ext_subspace_dict); 4073 1.1 christos amt = sizeof (struct som_subspace_dictionary_record); 4074 1.11 christos if (bfd_write (&ext_subspace_dict, amt, abfd) != amt) 4075 1.10 christos return false; 4076 1.1 christos } 4077 1.1 christos /* Goto the next section. */ 4078 1.1 christos section = section->next; 4079 1.1 christos } 4080 1.1 christos 4081 1.1 christos /* All the subspace dictionary records are written, and all the 4082 1.1 christos fields are set up in the space dictionary records. 4083 1.1 christos 4084 1.1 christos Seek to the right location and start writing the space 4085 1.1 christos dictionary records. */ 4086 1.1 christos location = obj_som_file_hdr (abfd)->space_location; 4087 1.1 christos if (bfd_seek (abfd, location, SEEK_SET) != 0) 4088 1.10 christos return false; 4089 1.1 christos 4090 1.1 christos section = abfd->sections; 4091 1.1 christos for (i = 0; i < num_spaces; i++) 4092 1.1 christos { 4093 1.1 christos struct som_external_space_dictionary_record ext_space_dict; 4094 1.1 christos 4095 1.1 christos /* Find a space. */ 4096 1.1 christos while (!som_is_space (section)) 4097 1.1 christos section = section->next; 4098 1.1 christos 4099 1.1 christos /* Dump its header. */ 4100 1.1 christos som_swap_space_dictionary_out (som_section_data (section)->space_dict, 4101 1.8 christos &ext_space_dict); 4102 1.1 christos amt = sizeof (struct som_external_space_dictionary_record); 4103 1.11 christos if (bfd_write (&ext_space_dict, amt, abfd) != amt) 4104 1.10 christos return false; 4105 1.1 christos 4106 1.1 christos /* Goto the next section. */ 4107 1.1 christos section = section->next; 4108 1.1 christos } 4109 1.1 christos 4110 1.1 christos /* Write the compilation unit record if there is one. */ 4111 1.1 christos if (obj_som_compilation_unit (abfd)) 4112 1.1 christos { 4113 1.1 christos struct som_external_compilation_unit ext_comp_unit; 4114 1.1 christos 4115 1.1 christos location = obj_som_file_hdr (abfd)->compiler_location; 4116 1.1 christos if (bfd_seek (abfd, location, SEEK_SET) != 0) 4117 1.10 christos return false; 4118 1.1 christos 4119 1.1 christos som_swap_compilation_unit_out 4120 1.8 christos (obj_som_compilation_unit (abfd), &ext_comp_unit); 4121 1.1 christos 4122 1.1 christos amt = sizeof (struct som_external_compilation_unit); 4123 1.11 christos if (bfd_write (&ext_comp_unit, amt, abfd) != amt) 4124 1.10 christos return false; 4125 1.1 christos } 4126 1.1 christos 4127 1.1 christos /* Setting of the system_id has to happen very late now that copying of 4128 1.1 christos BFD private data happens *after* section contents are set. */ 4129 1.10 christos if ((abfd->flags & (EXEC_P | DYNAMIC)) && obj_som_exec_data (abfd)) 4130 1.1 christos obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id; 4131 1.1 christos else if (bfd_get_mach (abfd) == pa20) 4132 1.1 christos obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0; 4133 1.1 christos else if (bfd_get_mach (abfd) == pa11) 4134 1.1 christos obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_1; 4135 1.1 christos else 4136 1.1 christos obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_0; 4137 1.1 christos 4138 1.1 christos /* Swap and compute the checksum for the file header just before writing 4139 1.1 christos the header to disk. */ 4140 1.1 christos som_swap_header_out (obj_som_file_hdr (abfd), &ext_header); 4141 1.1 christos bfd_putb32 (som_compute_checksum (&ext_header), ext_header.checksum); 4142 1.1 christos 4143 1.1 christos /* Only thing left to do is write out the file header. It is always 4144 1.1 christos at location zero. Seek there and write it. */ 4145 1.11 christos if (bfd_seek (abfd, 0, SEEK_SET) != 0) 4146 1.10 christos return false; 4147 1.1 christos amt = sizeof (struct som_external_header); 4148 1.11 christos if (bfd_write (&ext_header, amt, abfd) != amt) 4149 1.10 christos return false; 4150 1.1 christos 4151 1.1 christos /* Now write the exec header. */ 4152 1.1 christos if (abfd->flags & (EXEC_P | DYNAMIC)) 4153 1.1 christos { 4154 1.1 christos long tmp, som_length; 4155 1.1 christos struct som_exec_auxhdr *exec_header; 4156 1.1 christos struct som_external_exec_auxhdr ext_exec_header; 4157 1.1 christos 4158 1.1 christos exec_header = obj_som_exec_hdr (abfd); 4159 1.1 christos exec_header->exec_entry = bfd_get_start_address (abfd); 4160 1.10 christos if (obj_som_exec_data (abfd)) 4161 1.10 christos exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags; 4162 1.1 christos 4163 1.1 christos /* Oh joys. Ram some of the BSS data into the DATA section 4164 1.1 christos to be compatible with how the hp linker makes objects 4165 1.1 christos (saves memory space). */ 4166 1.1 christos tmp = exec_header->exec_dsize; 4167 1.1 christos tmp = SOM_ALIGN (tmp, PA_PAGESIZE); 4168 1.1 christos exec_header->exec_bsize -= (tmp - exec_header->exec_dsize); 4169 1.1 christos if (exec_header->exec_bsize < 0) 4170 1.1 christos exec_header->exec_bsize = 0; 4171 1.1 christos exec_header->exec_dsize = tmp; 4172 1.1 christos 4173 1.1 christos /* Now perform some sanity checks. The idea is to catch bogons now and 4174 1.1 christos inform the user, instead of silently generating a bogus file. */ 4175 1.1 christos som_length = obj_som_file_hdr (abfd)->som_length; 4176 1.1 christos if (exec_header->exec_tfile + exec_header->exec_tsize > som_length 4177 1.1 christos || exec_header->exec_dfile + exec_header->exec_dsize > som_length) 4178 1.1 christos { 4179 1.1 christos bfd_set_error (bfd_error_bad_value); 4180 1.10 christos return false; 4181 1.1 christos } 4182 1.1 christos 4183 1.1 christos som_swap_exec_auxhdr_out (exec_header, &ext_exec_header); 4184 1.1 christos 4185 1.1 christos if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location, 4186 1.1 christos SEEK_SET) != 0) 4187 1.10 christos return false; 4188 1.1 christos 4189 1.1 christos amt = sizeof (ext_exec_header); 4190 1.11 christos if (bfd_write (&ext_exec_header, amt, abfd) != amt) 4191 1.10 christos return false; 4192 1.1 christos } 4193 1.10 christos return true; 4194 1.1 christos } 4195 1.1 christos 4196 1.1 christos /* Compute and return the checksum for a SOM file header. */ 4197 1.1 christos 4198 1.9 christos static uint32_t 4199 1.1 christos som_compute_checksum (struct som_external_header *hdr) 4200 1.1 christos { 4201 1.9 christos size_t count, i; 4202 1.9 christos uint32_t checksum; 4203 1.9 christos uint32_t *buffer = (uint32_t *) hdr; 4204 1.1 christos 4205 1.1 christos checksum = 0; 4206 1.9 christos count = sizeof (*hdr) / sizeof (*buffer); 4207 1.1 christos for (i = 0; i < count; i++) 4208 1.1 christos checksum ^= *(buffer + i); 4209 1.1 christos 4210 1.1 christos return checksum; 4211 1.1 christos } 4212 1.1 christos 4213 1.1 christos static void 4214 1.1 christos som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, 4215 1.1 christos asymbol *sym, 4216 1.1 christos struct som_misc_symbol_info *info) 4217 1.1 christos { 4218 1.1 christos /* Initialize. */ 4219 1.1 christos memset (info, 0, sizeof (struct som_misc_symbol_info)); 4220 1.1 christos 4221 1.1 christos /* The HP SOM linker requires detailed type information about 4222 1.1 christos all symbols (including undefined symbols!). Unfortunately, 4223 1.1 christos the type specified in an import/export statement does not 4224 1.1 christos always match what the linker wants. Severe braindamage. */ 4225 1.1 christos 4226 1.1 christos /* Section symbols will not have a SOM symbol type assigned to 4227 1.1 christos them yet. Assign all section symbols type ST_DATA. */ 4228 1.1 christos if (sym->flags & BSF_SECTION_SYM) 4229 1.1 christos info->symbol_type = ST_DATA; 4230 1.1 christos else 4231 1.1 christos { 4232 1.1 christos /* For BFD style common, the linker will choke unless we set the 4233 1.1 christos type and scope to ST_STORAGE and SS_UNSAT, respectively. */ 4234 1.1 christos if (bfd_is_com_section (sym->section)) 4235 1.1 christos { 4236 1.1 christos info->symbol_type = ST_STORAGE; 4237 1.1 christos info->symbol_scope = SS_UNSAT; 4238 1.1 christos } 4239 1.1 christos 4240 1.1 christos /* It is possible to have a symbol without an associated 4241 1.1 christos type. This happens if the user imported the symbol 4242 1.1 christos without a type and the symbol was never defined 4243 1.1 christos locally. If BSF_FUNCTION is set for this symbol, then 4244 1.1 christos assign it type ST_CODE (the HP linker requires undefined 4245 1.1 christos external functions to have type ST_CODE rather than ST_ENTRY). */ 4246 1.1 christos else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN 4247 1.1 christos || som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE) 4248 1.1 christos && bfd_is_und_section (sym->section) 4249 1.1 christos && sym->flags & BSF_FUNCTION) 4250 1.1 christos info->symbol_type = ST_CODE; 4251 1.1 christos 4252 1.1 christos /* Handle function symbols which were defined in this file. 4253 1.1 christos They should have type ST_ENTRY. Also retrieve the argument 4254 1.1 christos relocation bits from the SOM backend information. */ 4255 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY 4256 1.1 christos || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE 4257 1.1 christos && (sym->flags & BSF_FUNCTION)) 4258 1.1 christos || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN 4259 1.1 christos && (sym->flags & BSF_FUNCTION))) 4260 1.1 christos { 4261 1.1 christos info->symbol_type = ST_ENTRY; 4262 1.1 christos info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc; 4263 1.1 christos info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level; 4264 1.1 christos } 4265 1.1 christos 4266 1.1 christos /* For unknown symbols set the symbol's type based on the symbol's 4267 1.1 christos section (ST_DATA for DATA sections, ST_CODE for CODE sections). */ 4268 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN) 4269 1.1 christos { 4270 1.1 christos if (bfd_is_abs_section (sym->section)) 4271 1.1 christos info->symbol_type = ST_ABSOLUTE; 4272 1.1 christos else if (sym->section->flags & SEC_CODE) 4273 1.1 christos info->symbol_type = ST_CODE; 4274 1.1 christos else 4275 1.1 christos info->symbol_type = ST_DATA; 4276 1.1 christos } 4277 1.1 christos 4278 1.1 christos /* From now on it's a very simple mapping. */ 4279 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE) 4280 1.1 christos info->symbol_type = ST_ABSOLUTE; 4281 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE) 4282 1.1 christos info->symbol_type = ST_CODE; 4283 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA) 4284 1.1 christos info->symbol_type = ST_DATA; 4285 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE) 4286 1.1 christos info->symbol_type = ST_MILLICODE; 4287 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL) 4288 1.1 christos info->symbol_type = ST_PLABEL; 4289 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG) 4290 1.1 christos info->symbol_type = ST_PRI_PROG; 4291 1.1 christos else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG) 4292 1.1 christos info->symbol_type = ST_SEC_PROG; 4293 1.1 christos } 4294 1.1 christos 4295 1.1 christos /* Now handle the symbol's scope. Exported data which is not 4296 1.1 christos in the common section has scope SS_UNIVERSAL. Note scope 4297 1.1 christos of common symbols was handled earlier! */ 4298 1.1 christos if (bfd_is_com_section (sym->section)) 4299 1.1 christos ; 4300 1.1 christos else if (bfd_is_und_section (sym->section)) 4301 1.1 christos info->symbol_scope = SS_UNSAT; 4302 1.1 christos else if (sym->flags & (BSF_EXPORT | BSF_WEAK)) 4303 1.1 christos info->symbol_scope = SS_UNIVERSAL; 4304 1.1 christos /* Anything else which is not in the common section has scope 4305 1.1 christos SS_LOCAL. */ 4306 1.1 christos else 4307 1.1 christos info->symbol_scope = SS_LOCAL; 4308 1.1 christos 4309 1.1 christos /* Now set the symbol_info field. It has no real meaning 4310 1.1 christos for undefined or common symbols, but the HP linker will 4311 1.1 christos choke if it's not set to some "reasonable" value. We 4312 1.1 christos use zero as a reasonable value. */ 4313 1.1 christos if (bfd_is_com_section (sym->section) 4314 1.1 christos || bfd_is_und_section (sym->section) 4315 1.1 christos || bfd_is_abs_section (sym->section)) 4316 1.1 christos info->symbol_info = 0; 4317 1.1 christos /* For all other symbols, the symbol_info field contains the 4318 1.1 christos subspace index of the space this symbol is contained in. */ 4319 1.1 christos else 4320 1.1 christos info->symbol_info = sym->section->target_index; 4321 1.1 christos 4322 1.1 christos /* Set the symbol's value. */ 4323 1.1 christos info->symbol_value = sym->value + sym->section->vma; 4324 1.1 christos 4325 1.1 christos /* The secondary_def field is for "weak" symbols. */ 4326 1.1 christos if (sym->flags & BSF_WEAK) 4327 1.10 christos info->secondary_def = true; 4328 1.1 christos else 4329 1.10 christos info->secondary_def = false; 4330 1.1 christos 4331 1.1 christos /* The is_comdat, is_common and dup_common fields provide various 4332 1.1 christos flavors of common. 4333 1.1 christos 4334 1.1 christos For data symbols, setting IS_COMMON provides Fortran style common 4335 1.1 christos (duplicate definitions and overlapped initialization). Setting both 4336 1.1 christos IS_COMMON and DUP_COMMON provides Cobol style common (duplicate 4337 1.1 christos definitions as long as they are all the same length). In a shared 4338 1.1 christos link data symbols retain their IS_COMMON and DUP_COMMON flags. 4339 1.1 christos An IS_COMDAT data symbol is similar to a IS_COMMON | DUP_COMMON 4340 1.1 christos symbol except in that it loses its IS_COMDAT flag in a shared link. 4341 1.1 christos 4342 1.1 christos For code symbols, IS_COMDAT and DUP_COMMON have effect. Universal 4343 1.1 christos DUP_COMMON code symbols are not exported from shared libraries. 4344 1.1 christos IS_COMDAT symbols are exported but they lose their IS_COMDAT flag. 4345 1.1 christos 4346 1.1 christos We take a simplified approach to setting the is_comdat, is_common 4347 1.1 christos and dup_common flags in symbols based on the flag settings of their 4348 1.1 christos subspace. This avoids having to add directives like `.comdat' but 4349 1.1 christos the linker behavior is probably undefined if there is more than one 4350 1.1 christos universal symbol (comdat key sysmbol) in a subspace. 4351 1.1 christos 4352 1.1 christos The behavior of these flags is not well documentmented, so there 4353 1.1 christos may be bugs and some surprising interactions with other flags. */ 4354 1.1 christos if (som_section_data (sym->section) 4355 1.1 christos && som_section_data (sym->section)->subspace_dict 4356 1.1 christos && info->symbol_scope == SS_UNIVERSAL 4357 1.1 christos && (info->symbol_type == ST_ENTRY 4358 1.1 christos || info->symbol_type == ST_CODE 4359 1.1 christos || info->symbol_type == ST_DATA)) 4360 1.1 christos { 4361 1.1 christos info->is_comdat 4362 1.1 christos = som_section_data (sym->section)->subspace_dict->is_comdat; 4363 1.1 christos info->is_common 4364 1.1 christos = som_section_data (sym->section)->subspace_dict->is_common; 4365 1.1 christos info->dup_common 4366 1.1 christos = som_section_data (sym->section)->subspace_dict->dup_common; 4367 1.1 christos } 4368 1.1 christos } 4369 1.1 christos 4370 1.1 christos /* Build and write, in one big chunk, the entire symbol table for 4371 1.1 christos this BFD. */ 4372 1.1 christos 4373 1.10 christos static bool 4374 1.1 christos som_build_and_write_symbol_table (bfd *abfd) 4375 1.1 christos { 4376 1.1 christos unsigned int num_syms = bfd_get_symcount (abfd); 4377 1.1 christos file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location; 4378 1.1 christos asymbol **bfd_syms = obj_som_sorted_syms (abfd); 4379 1.1 christos struct som_external_symbol_dictionary_record *som_symtab = NULL; 4380 1.1 christos unsigned int i; 4381 1.1 christos bfd_size_type symtab_size; 4382 1.9 christos size_t amt; 4383 1.1 christos 4384 1.1 christos /* Compute total symbol table size and allocate a chunk of memory 4385 1.1 christos to hold the symbol table as we build it. */ 4386 1.9 christos if (_bfd_mul_overflow (num_syms, 4387 1.9 christos sizeof (struct som_external_symbol_dictionary_record), 4388 1.9 christos &amt)) 4389 1.9 christos { 4390 1.9 christos bfd_set_error (bfd_error_no_memory); 4391 1.10 christos return false; 4392 1.9 christos } 4393 1.9 christos som_symtab = bfd_zmalloc (amt); 4394 1.9 christos if (som_symtab == NULL && num_syms != 0) 4395 1.1 christos goto error_return; 4396 1.1 christos 4397 1.1 christos /* Walk over each symbol. */ 4398 1.1 christos for (i = 0; i < num_syms; i++) 4399 1.1 christos { 4400 1.1 christos struct som_misc_symbol_info info; 4401 1.1 christos unsigned int flags; 4402 1.1 christos 4403 1.1 christos /* This is really an index into the symbol strings table. 4404 1.1 christos By the time we get here, the index has already been 4405 1.1 christos computed and stored into the name field in the BFD symbol. */ 4406 1.1 christos bfd_putb32 (som_symbol_data (bfd_syms[i])->stringtab_offset, 4407 1.8 christos som_symtab[i].name); 4408 1.1 christos 4409 1.1 christos /* Derive SOM information from the BFD symbol. */ 4410 1.1 christos som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info); 4411 1.1 christos 4412 1.1 christos /* Now use it. */ 4413 1.1 christos flags = (info.symbol_type << SOM_SYMBOL_TYPE_SH) 4414 1.8 christos | (info.symbol_scope << SOM_SYMBOL_SCOPE_SH) 4415 1.8 christos | (info.arg_reloc << SOM_SYMBOL_ARG_RELOC_SH) 4416 1.8 christos | (3 << SOM_SYMBOL_XLEAST_SH) 4417 1.8 christos | (info.secondary_def ? SOM_SYMBOL_SECONDARY_DEF : 0) 4418 1.8 christos | (info.is_common ? SOM_SYMBOL_IS_COMMON : 0) 4419 1.8 christos | (info.dup_common ? SOM_SYMBOL_DUP_COMMON : 0); 4420 1.1 christos bfd_putb32 (flags, som_symtab[i].flags); 4421 1.1 christos 4422 1.1 christos flags = (info.symbol_info << SOM_SYMBOL_SYMBOL_INFO_SH) 4423 1.8 christos | (info.is_comdat ? SOM_SYMBOL_IS_COMDAT : 0); 4424 1.1 christos bfd_putb32 (flags, som_symtab[i].info); 4425 1.1 christos bfd_putb32 (info.symbol_value | info.priv_level, 4426 1.8 christos som_symtab[i].symbol_value); 4427 1.1 christos } 4428 1.1 christos 4429 1.1 christos /* Everything is ready, seek to the right location and 4430 1.1 christos scribble out the symbol table. */ 4431 1.1 christos if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0) 4432 1.9 christos goto error_return; 4433 1.1 christos 4434 1.9 christos symtab_size = num_syms; 4435 1.9 christos symtab_size *= sizeof (struct som_external_symbol_dictionary_record); 4436 1.11 christos if (bfd_write (som_symtab, symtab_size, abfd) != symtab_size) 4437 1.1 christos goto error_return; 4438 1.1 christos 4439 1.9 christos free (som_symtab); 4440 1.10 christos return true; 4441 1.9 christos 4442 1.1 christos error_return: 4443 1.9 christos free (som_symtab); 4444 1.10 christos return false; 4445 1.1 christos } 4446 1.1 christos 4447 1.1 christos /* Write an object in SOM format. */ 4448 1.1 christos 4449 1.10 christos static bool 4450 1.1 christos som_write_object_contents (bfd *abfd) 4451 1.1 christos { 4452 1.1 christos if (! abfd->output_has_begun) 4453 1.1 christos { 4454 1.1 christos /* Set up fixed parts of the file, space, and subspace headers. 4455 1.1 christos Notify the world that output has begun. */ 4456 1.1 christos som_prep_headers (abfd); 4457 1.10 christos abfd->output_has_begun = true; 4458 1.1 christos /* Start writing the object file. This include all the string 4459 1.1 christos tables, fixup streams, and other portions of the object file. */ 4460 1.1 christos som_begin_writing (abfd); 4461 1.1 christos } 4462 1.1 christos 4463 1.1 christos return som_finish_writing (abfd); 4464 1.1 christos } 4465 1.1 christos 4466 1.1 christos /* Read and save the string table associated with the given BFD. */ 4468 1.10 christos 4469 1.1 christos static bool 4470 1.1 christos som_slurp_string_table (bfd *abfd) 4471 1.1 christos { 4472 1.1 christos char *stringtab; 4473 1.1 christos bfd_size_type amt; 4474 1.1 christos 4475 1.1 christos /* Use the saved version if its available. */ 4476 1.10 christos if (obj_som_stringtab (abfd) != NULL) 4477 1.1 christos return true; 4478 1.1 christos 4479 1.1 christos /* I don't think this can currently happen, and I'm not sure it should 4480 1.1 christos really be an error, but it's better than getting unpredictable results 4481 1.1 christos from the host's malloc when passed a size of zero. */ 4482 1.1 christos if (obj_som_stringtab_size (abfd) == 0) 4483 1.1 christos { 4484 1.10 christos bfd_set_error (bfd_error_no_symbols); 4485 1.1 christos return false; 4486 1.1 christos } 4487 1.1 christos 4488 1.9 christos /* Allocate and read in the string table. */ 4489 1.10 christos if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0) 4490 1.1 christos return false; 4491 1.10 christos amt = obj_som_stringtab_size (abfd); 4492 1.1 christos stringtab = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt); 4493 1.10 christos if (stringtab == NULL) 4494 1.10 christos return false; 4495 1.10 christos /* Make sure that the strings are zero-terminated. */ 4496 1.1 christos stringtab[amt] = 0; 4497 1.1 christos 4498 1.1 christos /* Save our results and return success. */ 4499 1.10 christos obj_som_stringtab (abfd) = stringtab; 4500 1.1 christos return true; 4501 1.1 christos } 4502 1.1 christos 4503 1.1 christos /* Return the amount of data (in bytes) required to hold the symbol 4504 1.1 christos table for this object. */ 4505 1.1 christos 4506 1.1 christos static long 4507 1.1 christos som_get_symtab_upper_bound (bfd *abfd) 4508 1.1 christos { 4509 1.1 christos if (!som_slurp_symbol_table (abfd)) 4510 1.1 christos return -1; 4511 1.1 christos 4512 1.1 christos return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *); 4513 1.1 christos } 4514 1.1 christos 4515 1.1 christos /* Convert from a SOM subspace index to a BFD section. */ 4516 1.1 christos 4517 1.1 christos asection * 4518 1.1 christos bfd_section_from_som_symbol 4519 1.1 christos (bfd *abfd, struct som_external_symbol_dictionary_record *symbol) 4520 1.1 christos { 4521 1.1 christos asection *section; 4522 1.1 christos unsigned int flags = bfd_getb32 (symbol->flags); 4523 1.1 christos unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK; 4524 1.1 christos 4525 1.1 christos /* The meaning of the symbol_info field changes for functions 4526 1.1 christos within executables. So only use the quick symbol_info mapping for 4527 1.1 christos incomplete objects and non-function symbols in executables. */ 4528 1.1 christos if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0 4529 1.1 christos || (symbol_type != ST_ENTRY 4530 1.1 christos && symbol_type != ST_PRI_PROG 4531 1.1 christos && symbol_type != ST_SEC_PROG 4532 1.1 christos && symbol_type != ST_MILLICODE)) 4533 1.1 christos { 4534 1.8 christos int idx = (bfd_getb32 (symbol->info) >> SOM_SYMBOL_SYMBOL_INFO_SH) 4535 1.1 christos & SOM_SYMBOL_SYMBOL_INFO_MASK; 4536 1.1 christos 4537 1.1 christos for (section = abfd->sections; section != NULL; section = section->next) 4538 1.1 christos if (section->target_index == idx && som_is_subspace (section)) 4539 1.1 christos return section; 4540 1.1 christos } 4541 1.1 christos else 4542 1.1 christos { 4543 1.1 christos unsigned int value = bfd_getb32 (symbol->symbol_value); 4544 1.1 christos 4545 1.1 christos /* For executables we will have to use the symbol's address and 4546 1.1 christos find out what section would contain that address. Yuk. */ 4547 1.1 christos for (section = abfd->sections; section; section = section->next) 4548 1.1 christos if (value >= section->vma 4549 1.1 christos && value <= section->vma + section->size 4550 1.1 christos && som_is_subspace (section)) 4551 1.1 christos return section; 4552 1.1 christos } 4553 1.1 christos 4554 1.1 christos /* Could be a symbol from an external library (such as an OMOS 4555 1.1 christos shared library). Don't abort. */ 4556 1.1 christos return bfd_abs_section_ptr; 4557 1.1 christos } 4558 1.1 christos 4559 1.1 christos /* Read and save the symbol table associated with the given BFD. */ 4560 1.1 christos 4561 1.1 christos static unsigned int 4562 1.1 christos som_slurp_symbol_table (bfd *abfd) 4563 1.9 christos { 4564 1.9 christos unsigned int symbol_count = bfd_get_symcount (abfd); 4565 1.1 christos size_t symsize = sizeof (struct som_external_symbol_dictionary_record); 4566 1.1 christos char *stringtab; 4567 1.9 christos struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp; 4568 1.9 christos som_symbol_type *sym, *symbase = NULL; 4569 1.1 christos size_t amt; 4570 1.1 christos 4571 1.1 christos /* Return saved value if it exists. */ 4572 1.1 christos if (obj_som_symtab (abfd) != NULL) 4573 1.1 christos goto successful_return; 4574 1.1 christos 4575 1.1 christos /* Special case. This is *not* an error. */ 4576 1.1 christos if (symbol_count == 0) 4577 1.1 christos goto successful_return; 4578 1.1 christos 4579 1.1 christos if (!som_slurp_string_table (abfd)) 4580 1.1 christos goto error_return; 4581 1.1 christos 4582 1.1 christos stringtab = obj_som_stringtab (abfd); 4583 1.1 christos 4584 1.9 christos /* Read in the external SOM representation. */ 4585 1.9 christos if (_bfd_mul_overflow (symbol_count, symsize, &amt)) 4586 1.9 christos { 4587 1.9 christos bfd_set_error (bfd_error_file_too_big); 4588 1.9 christos goto error_return; 4589 1.1 christos } 4590 1.1 christos if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0) 4591 1.9 christos goto error_return; 4592 1.9 christos buf = (struct som_external_symbol_dictionary_record *) 4593 1.9 christos _bfd_malloc_and_read (abfd, amt, amt); 4594 1.9 christos if (buf == NULL) 4595 1.9 christos goto error_return; 4596 1.9 christos 4597 1.9 christos if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt)) 4598 1.9 christos { 4599 1.9 christos bfd_set_error (bfd_error_file_too_big); 4600 1.9 christos goto error_return; 4601 1.9 christos } 4602 1.9 christos symbase = bfd_zmalloc (amt); 4603 1.1 christos if (symbase == NULL) 4604 1.1 christos goto error_return; 4605 1.1 christos 4606 1.1 christos /* Iterate over all the symbols and internalize them. */ 4607 1.1 christos endbufp = buf + symbol_count; 4608 1.1 christos for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp) 4609 1.1 christos { 4610 1.1 christos unsigned int flags = bfd_getb32 (bufp->flags); 4611 1.8 christos unsigned int symbol_type = 4612 1.1 christos (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK; 4613 1.8 christos unsigned int symbol_scope = 4614 1.10 christos (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK; 4615 1.1 christos bfd_vma offset; 4616 1.1 christos 4617 1.1 christos /* I don't think we care about these. */ 4618 1.1 christos if (symbol_type == ST_SYM_EXT || symbol_type == ST_ARG_EXT) 4619 1.1 christos continue; 4620 1.1 christos 4621 1.1 christos /* Set some private data we care about. */ 4622 1.1 christos if (symbol_type == ST_NULL) 4623 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN; 4624 1.1 christos else if (symbol_type == ST_ABSOLUTE) 4625 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE; 4626 1.1 christos else if (symbol_type == ST_DATA) 4627 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA; 4628 1.1 christos else if (symbol_type == ST_CODE) 4629 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE; 4630 1.1 christos else if (symbol_type == ST_PRI_PROG) 4631 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG; 4632 1.1 christos else if (symbol_type == ST_SEC_PROG) 4633 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG; 4634 1.1 christos else if (symbol_type == ST_ENTRY) 4635 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY; 4636 1.1 christos else if (symbol_type == ST_MILLICODE) 4637 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE; 4638 1.1 christos else if (symbol_type == ST_PLABEL) 4639 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL; 4640 1.1 christos else 4641 1.1 christos som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN; 4642 1.8 christos som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc = 4643 1.1 christos (flags >> SOM_SYMBOL_ARG_RELOC_SH) & SOM_SYMBOL_ARG_RELOC_MASK; 4644 1.1 christos 4645 1.1 christos /* Some reasonable defaults. */ 4646 1.10 christos sym->symbol.the_bfd = abfd; 4647 1.10 christos offset = bfd_getb32 (bufp->name); 4648 1.10 christos if (offset < obj_som_stringtab_size (abfd)) 4649 1.10 christos sym->symbol.name = offset + stringtab; 4650 1.10 christos else 4651 1.10 christos { 4652 1.10 christos bfd_set_error (bfd_error_bad_value); 4653 1.10 christos goto error_return; 4654 1.1 christos } 4655 1.10 christos sym->symbol.value = bfd_getb32 (bufp->symbol_value); 4656 1.1 christos sym->symbol.section = NULL; 4657 1.1 christos sym->symbol.flags = 0; 4658 1.1 christos 4659 1.1 christos switch (symbol_type) 4660 1.1 christos { 4661 1.1 christos case ST_ENTRY: 4662 1.1 christos case ST_MILLICODE: 4663 1.1 christos sym->symbol.flags |= BSF_FUNCTION; 4664 1.1 christos som_symbol_data (sym)->tc_data.ap.hppa_priv_level = 4665 1.1 christos sym->symbol.value & 0x3; 4666 1.1 christos sym->symbol.value &= ~0x3; 4667 1.1 christos break; 4668 1.1 christos 4669 1.1 christos case ST_STUB: 4670 1.1 christos case ST_CODE: 4671 1.1 christos case ST_PRI_PROG: 4672 1.1 christos case ST_SEC_PROG: 4673 1.1 christos som_symbol_data (sym)->tc_data.ap.hppa_priv_level = 4674 1.1 christos sym->symbol.value & 0x3; 4675 1.1 christos sym->symbol.value &= ~0x3; 4676 1.1 christos /* If the symbol's scope is SS_UNSAT, then these are 4677 1.1 christos undefined function symbols. */ 4678 1.1 christos if (symbol_scope == SS_UNSAT) 4679 1.1 christos sym->symbol.flags |= BSF_FUNCTION; 4680 1.1 christos 4681 1.1 christos default: 4682 1.1 christos break; 4683 1.1 christos } 4684 1.1 christos 4685 1.1 christos /* Handle scoping and section information. */ 4686 1.1 christos switch (symbol_scope) 4687 1.1 christos { 4688 1.1 christos /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols, 4689 1.1 christos so the section associated with this symbol can't be known. */ 4690 1.1 christos case SS_EXTERNAL: 4691 1.1 christos if (symbol_type != ST_STORAGE) 4692 1.1 christos sym->symbol.section = bfd_und_section_ptr; 4693 1.1 christos else 4694 1.1 christos sym->symbol.section = bfd_com_section_ptr; 4695 1.1 christos sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL); 4696 1.1 christos break; 4697 1.1 christos 4698 1.1 christos case SS_UNSAT: 4699 1.1 christos if (symbol_type != ST_STORAGE) 4700 1.1 christos sym->symbol.section = bfd_und_section_ptr; 4701 1.1 christos else 4702 1.1 christos sym->symbol.section = bfd_com_section_ptr; 4703 1.1 christos break; 4704 1.1 christos 4705 1.1 christos case SS_UNIVERSAL: 4706 1.1 christos sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL); 4707 1.1 christos sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp); 4708 1.1 christos sym->symbol.value -= sym->symbol.section->vma; 4709 1.1 christos break; 4710 1.1 christos 4711 1.1 christos case SS_LOCAL: 4712 1.1 christos sym->symbol.flags |= BSF_LOCAL; 4713 1.1 christos sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp); 4714 1.1 christos sym->symbol.value -= sym->symbol.section->vma; 4715 1.10 christos break; 4716 1.10 christos 4717 1.10 christos default: 4718 1.10 christos sym->symbol.section = bfd_und_section_ptr; 4719 1.1 christos break; 4720 1.1 christos } 4721 1.1 christos 4722 1.1 christos /* Check for a weak symbol. */ 4723 1.1 christos if (flags & SOM_SYMBOL_SECONDARY_DEF) 4724 1.1 christos sym->symbol.flags |= BSF_WEAK; 4725 1.1 christos /* Mark section symbols and symbols used by the debugger. 4726 1.1 christos Note $START$ is a magic code symbol, NOT a section symbol. */ 4727 1.1 christos if (sym->symbol.name[0] == '$' 4728 1.1 christos && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$' 4729 1.1 christos && !strcmp (sym->symbol.name, sym->symbol.section->name)) 4730 1.10 christos sym->symbol.flags |= BSF_SECTION_SYM; 4731 1.1 christos else if (startswith (sym->symbol.name, "L$0\002")) 4732 1.1 christos { 4733 1.1 christos sym->symbol.flags |= BSF_SECTION_SYM; 4734 1.1 christos sym->symbol.name = sym->symbol.section->name; 4735 1.10 christos } 4736 1.1 christos else if (startswith (sym->symbol.name, "L$0\001")) 4737 1.1 christos sym->symbol.flags |= BSF_DEBUGGING; 4738 1.1 christos /* Note increment at bottom of loop, since we skip some symbols 4739 1.1 christos we can not include it as part of the for statement. */ 4740 1.1 christos sym++; 4741 1.1 christos } 4742 1.1 christos 4743 1.1 christos /* We modify the symbol count to record the number of BFD symbols we 4744 1.9 christos created. */ 4745 1.1 christos abfd->symcount = sym - symbase; 4746 1.1 christos 4747 1.1 christos /* Save our results and return success. */ 4748 1.1 christos obj_som_symtab (abfd) = symbase; 4749 1.9 christos successful_return: 4750 1.10 christos free (buf); 4751 1.1 christos return true; 4752 1.1 christos 4753 1.9 christos error_return: 4754 1.9 christos free (symbase); 4755 1.10 christos free (buf); 4756 1.1 christos return false; 4757 1.1 christos } 4758 1.1 christos 4759 1.1 christos /* Canonicalize a SOM symbol table. Return the number of entries 4760 1.1 christos in the symbol table. */ 4761 1.1 christos 4762 1.1 christos static long 4763 1.1 christos som_canonicalize_symtab (bfd *abfd, asymbol **location) 4764 1.1 christos { 4765 1.1 christos int i; 4766 1.1 christos som_symbol_type *symbase; 4767 1.1 christos 4768 1.1 christos if (!som_slurp_symbol_table (abfd)) 4769 1.1 christos return -1; 4770 1.1 christos 4771 1.1 christos i = bfd_get_symcount (abfd); 4772 1.1 christos symbase = obj_som_symtab (abfd); 4773 1.1 christos 4774 1.1 christos for (; i > 0; i--, location++, symbase++) 4775 1.1 christos *location = &symbase->symbol; 4776 1.1 christos 4777 1.1 christos /* Final null pointer. */ 4778 1.1 christos *location = 0; 4779 1.1 christos return (bfd_get_symcount (abfd)); 4780 1.1 christos } 4781 1.1 christos 4782 1.1 christos /* Make a SOM symbol. There is nothing special to do here. */ 4783 1.1 christos 4784 1.1 christos static asymbol * 4785 1.1 christos som_make_empty_symbol (bfd *abfd) 4786 1.9 christos { 4787 1.1 christos size_t amt = sizeof (som_symbol_type); 4788 1.1 christos som_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt); 4789 1.1 christos 4790 1.1 christos if (new_symbol_type == NULL) 4791 1.1 christos return NULL; 4792 1.1 christos new_symbol_type->symbol.the_bfd = abfd; 4793 1.1 christos 4794 1.1 christos return &new_symbol_type->symbol; 4795 1.1 christos } 4796 1.1 christos 4797 1.1 christos /* Print symbol information. */ 4798 1.1 christos 4799 1.1 christos static void 4800 1.1 christos som_print_symbol (bfd *abfd, 4801 1.1 christos void *afile, 4802 1.1 christos asymbol *symbol, 4803 1.1 christos bfd_print_symbol_type how) 4804 1.1 christos { 4805 1.1 christos FILE *file = (FILE *) afile; 4806 1.1 christos 4807 1.1 christos switch (how) 4808 1.1 christos { 4809 1.1 christos case bfd_print_symbol_name: 4810 1.1 christos fprintf (file, "%s", symbol->name); 4811 1.1 christos break; 4812 1.10 christos case bfd_print_symbol_more: 4813 1.10 christos fprintf (file, "som %08" PRIx64 " %x", 4814 1.1 christos (uint64_t) symbol->value, symbol->flags); 4815 1.1 christos break; 4816 1.1 christos case bfd_print_symbol_all: 4817 1.1 christos { 4818 1.1 christos const char *section_name; 4819 1.1 christos 4820 1.1 christos section_name = symbol->section ? symbol->section->name : "(*none*)"; 4821 1.1 christos bfd_print_symbol_vandf (abfd, (void *) file, symbol); 4822 1.1 christos fprintf (file, " %s\t%s", section_name, symbol->name); 4823 1.1 christos break; 4824 1.1 christos } 4825 1.1 christos } 4826 1.1 christos } 4827 1.10 christos 4828 1.1 christos static bool 4829 1.1 christos som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, 4830 1.1 christos const char *name) 4831 1.1 christos { 4832 1.1 christos return name[0] == 'L' && name[1] == '$'; 4833 1.1 christos } 4834 1.1 christos 4835 1.1 christos /* Count or process variable-length SOM fixup records. 4836 1.1 christos 4837 1.1 christos To avoid code duplication we use this code both to compute the number 4838 1.1 christos of relocations requested by a stream, and to internalize the stream. 4839 1.1 christos 4840 1.1 christos When computing the number of relocations requested by a stream the 4841 1.1 christos variables rptr, section, and symbols have no meaning. 4842 1.1 christos 4843 1.1 christos Return the number of relocations requested by the fixup stream. When 4844 1.1 christos not just counting 4845 1.1 christos 4846 1.1 christos This needs at least two or three more passes to get it cleaned up. */ 4847 1.1 christos 4848 1.1 christos static unsigned int 4849 1.1 christos som_set_reloc_info (unsigned char *fixup, 4850 1.1 christos unsigned int end, 4851 1.1 christos arelent *internal_relocs, 4852 1.1 christos asection *section, 4853 1.10 christos asymbol **symbols, 4854 1.10 christos unsigned int symcount, 4855 1.1 christos bool just_count) 4856 1.10 christos { 4857 1.1 christos unsigned int deallocate_contents = 0; 4858 1.10 christos unsigned char *end_fixups = &fixup[end]; 4859 1.1 christos int variables[26], stack[20], count, prev_fixup, *sp, saved_unwind_bits; 4860 1.1 christos arelent *rptr = internal_relocs; 4861 1.1 christos unsigned int offset = 0; 4862 1.1 christos 4863 1.1 christos #define var(c) variables[(c) - 'A'] 4864 1.1 christos #define push(v) (*sp++ = (v)) 4865 1.1 christos #define pop() (*--sp) 4866 1.1 christos #define emptystack() (sp == stack) 4867 1.1 christos 4868 1.1 christos som_initialize_reloc_queue (reloc_queue); 4869 1.1 christos memset (variables, 0, sizeof (variables)); 4870 1.1 christos memset (stack, 0, sizeof (stack)); 4871 1.1 christos count = 0; 4872 1.1 christos prev_fixup = 0; 4873 1.1 christos saved_unwind_bits = 0; 4874 1.1 christos sp = stack; 4875 1.1 christos 4876 1.1 christos while (fixup < end_fixups) 4877 1.10 christos { 4878 1.10 christos const char *cp; 4879 1.10 christos unsigned int op; 4880 1.10 christos const struct fixup_format *fp; 4881 1.1 christos 4882 1.1 christos /* Save pointer to the start of this fixup. We'll use 4883 1.1 christos it later to determine if it is necessary to put this fixup 4884 1.10 christos on the queue. */ 4885 1.1 christos unsigned char *save_fixup = fixup; 4886 1.1 christos 4887 1.1 christos /* Get the fixup code and its associated format. */ 4888 1.1 christos op = *fixup++; 4889 1.1 christos fp = &som_fixup_formats[op]; 4890 1.1 christos 4891 1.1 christos /* Handle a request for a previous fixup. */ 4892 1.1 christos if (*fp->format == 'P') 4893 1.10 christos { 4894 1.10 christos if (!reloc_queue[fp->D].reloc) 4895 1.10 christos /* The back-reference doesn't exist. This is a broken 4896 1.10 christos object file, likely fuzzed. Just ignore the fixup. */ 4897 1.10 christos continue; 4898 1.1 christos 4899 1.1 christos /* Get pointer to the beginning of the prev fixup, move 4900 1.1 christos the repeated fixup to the head of the queue. */ 4901 1.1 christos fixup = reloc_queue[fp->D].reloc; 4902 1.1 christos som_reloc_queue_fix (reloc_queue, fp->D); 4903 1.1 christos prev_fixup = 1; 4904 1.1 christos 4905 1.1 christos /* Get the fixup code and its associated format. */ 4906 1.1 christos op = *fixup++; 4907 1.1 christos fp = &som_fixup_formats[op]; 4908 1.1 christos } 4909 1.1 christos 4910 1.1 christos /* If this fixup will be passed to BFD, set some reasonable defaults. */ 4911 1.1 christos if (! just_count 4912 1.1 christos && som_hppa_howto_table[op].type != R_NO_RELOCATION 4913 1.1 christos && som_hppa_howto_table[op].type != R_DATA_OVERRIDE) 4914 1.1 christos { 4915 1.1 christos rptr->address = offset; 4916 1.1 christos rptr->howto = &som_hppa_howto_table[op]; 4917 1.1 christos rptr->addend = 0; 4918 1.1 christos rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 4919 1.1 christos } 4920 1.1 christos 4921 1.1 christos /* Set default input length to 0. Get the opcode class index 4922 1.1 christos into D. */ 4923 1.1 christos var ('L') = 0; 4924 1.1 christos var ('D') = fp->D; 4925 1.1 christos var ('U') = saved_unwind_bits; 4926 1.1 christos 4927 1.1 christos /* Get the opcode format. */ 4928 1.1 christos cp = fp->format; 4929 1.1 christos 4930 1.1 christos /* Process the format string. Parsing happens in two phases, 4931 1.1 christos parse RHS, then assign to LHS. Repeat until no more 4932 1.1 christos characters in the format string. */ 4933 1.1 christos while (*cp) 4934 1.1 christos { 4935 1.10 christos /* The variable this pass is going to compute a value for. */ 4936 1.10 christos unsigned int varname = *cp++; 4937 1.10 christos const int *subop; 4938 1.1 christos int c; 4939 1.1 christos 4940 1.1 christos /* Start processing RHS. Continue until a NULL or '=' is found. */ 4941 1.1 christos do 4942 1.10 christos { 4943 1.10 christos unsigned v; 4944 1.1 christos 4945 1.1 christos c = *cp++; 4946 1.1 christos 4947 1.1 christos /* If this is a variable, push it on the stack. */ 4948 1.1 christos if (ISUPPER (c)) 4949 1.1 christos push (var (c)); 4950 1.1 christos 4951 1.1 christos /* If this is a lower case letter, then it represents 4952 1.1 christos additional data from the fixup stream to be pushed onto 4953 1.1 christos the stack. */ 4954 1.1 christos else if (ISLOWER (c)) 4955 1.1 christos { 4956 1.10 christos int bits = (c - 'a') * 8; 4957 1.1 christos for (v = 0; c > 'a' && fixup < end_fixups; --c) 4958 1.1 christos v = (v << 8) | *fixup++; 4959 1.1 christos if (varname == 'V') 4960 1.1 christos v = sign_extend (v, bits); 4961 1.1 christos push (v); 4962 1.1 christos } 4963 1.1 christos 4964 1.1 christos /* A decimal constant. Push it on the stack. */ 4965 1.1 christos else if (ISDIGIT (c)) 4966 1.1 christos { 4967 1.1 christos v = c - '0'; 4968 1.1 christos while (ISDIGIT (*cp)) 4969 1.1 christos v = (v * 10) + (*cp++ - '0'); 4970 1.1 christos push (v); 4971 1.1 christos } 4972 1.8 christos else 4973 1.1 christos /* An operator. Pop two values from the stack and 4974 1.1 christos use them as operands to the given operation. Push 4975 1.1 christos the result of the operation back on the stack. */ 4976 1.1 christos switch (c) 4977 1.1 christos { 4978 1.1 christos case '+': 4979 1.1 christos v = pop (); 4980 1.1 christos v += pop (); 4981 1.1 christos push (v); 4982 1.1 christos break; 4983 1.1 christos case '*': 4984 1.1 christos v = pop (); 4985 1.1 christos v *= pop (); 4986 1.1 christos push (v); 4987 1.1 christos break; 4988 1.1 christos case '<': 4989 1.1 christos v = pop (); 4990 1.1 christos v = pop () << v; 4991 1.1 christos push (v); 4992 1.1 christos break; 4993 1.1 christos default: 4994 1.1 christos abort (); 4995 1.1 christos } 4996 1.1 christos } 4997 1.1 christos while (*cp && *cp != '='); 4998 1.1 christos 4999 1.1 christos /* Move over the equal operator. */ 5000 1.1 christos cp++; 5001 1.1 christos 5002 1.1 christos /* Pop the RHS off the stack. */ 5003 1.1 christos c = pop (); 5004 1.1 christos 5005 1.1 christos /* Perform the assignment. */ 5006 1.1 christos var (varname) = c; 5007 1.1 christos 5008 1.1 christos /* Handle side effects. and special 'O' stack cases. */ 5009 1.1 christos switch (varname) 5010 1.1 christos { 5011 1.1 christos /* Consume some bytes from the input space. */ 5012 1.1 christos case 'L': 5013 1.1 christos offset += c; 5014 1.1 christos break; 5015 1.1 christos /* A symbol to use in the relocation. Make a note 5016 1.1 christos of this if we are not just counting. */ 5017 1.10 christos case 'S': 5018 1.1 christos if (!just_count && symbols != NULL && (unsigned int) c < symcount) 5019 1.1 christos rptr->sym_ptr_ptr = &symbols[c]; 5020 1.1 christos break; 5021 1.1 christos /* Argument relocation bits for a function call. */ 5022 1.1 christos case 'R': 5023 1.1 christos if (! just_count) 5024 1.1 christos { 5025 1.1 christos unsigned int tmp = var ('R'); 5026 1.1 christos rptr->addend = 0; 5027 1.1 christos 5028 1.1 christos if ((som_hppa_howto_table[op].type == R_PCREL_CALL 5029 1.1 christos && R_PCREL_CALL + 10 > op) 5030 1.1 christos || (som_hppa_howto_table[op].type == R_ABS_CALL 5031 1.1 christos && R_ABS_CALL + 10 > op)) 5032 1.1 christos { 5033 1.1 christos /* Simple encoding. */ 5034 1.1 christos if (tmp > 4) 5035 1.1 christos { 5036 1.1 christos tmp -= 5; 5037 1.1 christos rptr->addend |= 1; 5038 1.1 christos } 5039 1.1 christos if (tmp == 4) 5040 1.1 christos rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2; 5041 1.1 christos else if (tmp == 3) 5042 1.1 christos rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4; 5043 1.1 christos else if (tmp == 2) 5044 1.1 christos rptr->addend |= 1 << 8 | 1 << 6; 5045 1.1 christos else if (tmp == 1) 5046 1.1 christos rptr->addend |= 1 << 8; 5047 1.1 christos } 5048 1.1 christos else 5049 1.1 christos { 5050 1.1 christos unsigned int tmp1, tmp2; 5051 1.1 christos 5052 1.1 christos /* First part is easy -- low order two bits are 5053 1.1 christos directly copied, then shifted away. */ 5054 1.1 christos rptr->addend = tmp & 0x3; 5055 1.1 christos tmp >>= 2; 5056 1.1 christos 5057 1.1 christos /* Diving the result by 10 gives us the second 5058 1.1 christos part. If it is 9, then the first two words 5059 1.1 christos are a double precision paramater, else it is 5060 1.1 christos 3 * the first arg bits + the 2nd arg bits. */ 5061 1.1 christos tmp1 = tmp / 10; 5062 1.1 christos tmp -= tmp1 * 10; 5063 1.1 christos if (tmp1 == 9) 5064 1.1 christos rptr->addend += (0xe << 6); 5065 1.1 christos else 5066 1.1 christos { 5067 1.1 christos /* Get the two pieces. */ 5068 1.1 christos tmp2 = tmp1 / 3; 5069 1.1 christos tmp1 -= tmp2 * 3; 5070 1.1 christos /* Put them in the addend. */ 5071 1.1 christos rptr->addend += (tmp2 << 8) + (tmp1 << 6); 5072 1.1 christos } 5073 1.1 christos 5074 1.1 christos /* What's left is the third part. It's unpacked 5075 1.1 christos just like the second. */ 5076 1.1 christos if (tmp == 9) 5077 1.1 christos rptr->addend += (0xe << 2); 5078 1.1 christos else 5079 1.1 christos { 5080 1.1 christos tmp2 = tmp / 3; 5081 1.1 christos tmp -= tmp2 * 3; 5082 1.1 christos rptr->addend += (tmp2 << 4) + (tmp << 2); 5083 1.1 christos } 5084 1.1 christos } 5085 1.1 christos rptr->addend = HPPA_R_ADDEND (rptr->addend, 0); 5086 1.1 christos } 5087 1.1 christos break; 5088 1.1 christos /* Handle the linker expression stack. */ 5089 1.1 christos case 'O': 5090 1.1 christos switch (op) 5091 1.1 christos { 5092 1.1 christos case R_COMP1: 5093 1.1 christos subop = comp1_opcodes; 5094 1.1 christos break; 5095 1.1 christos case R_COMP2: 5096 1.1 christos subop = comp2_opcodes; 5097 1.1 christos break; 5098 1.1 christos case R_COMP3: 5099 1.1 christos subop = comp3_opcodes; 5100 1.1 christos break; 5101 1.1 christos default: 5102 1.1 christos abort (); 5103 1.1 christos } 5104 1.1 christos while (*subop <= (unsigned char) c) 5105 1.1 christos ++subop; 5106 1.1 christos --subop; 5107 1.1 christos break; 5108 1.1 christos /* The lower 32unwind bits must be persistent. */ 5109 1.1 christos case 'U': 5110 1.1 christos saved_unwind_bits = var ('U'); 5111 1.1 christos break; 5112 1.1 christos 5113 1.1 christos default: 5114 1.1 christos break; 5115 1.1 christos } 5116 1.1 christos } 5117 1.1 christos 5118 1.1 christos /* If we used a previous fixup, clean up after it. */ 5119 1.1 christos if (prev_fixup) 5120 1.1 christos { 5121 1.1 christos fixup = save_fixup + 1; 5122 1.1 christos prev_fixup = 0; 5123 1.1 christos } 5124 1.1 christos /* Queue it. */ 5125 1.1 christos else if (fixup > save_fixup + 1) 5126 1.1 christos som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue); 5127 1.1 christos 5128 1.1 christos /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION 5129 1.1 christos fixups to BFD. */ 5130 1.1 christos if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE 5131 1.1 christos && som_hppa_howto_table[op].type != R_NO_RELOCATION) 5132 1.1 christos { 5133 1.1 christos /* Done with a single reloction. Loop back to the top. */ 5134 1.1 christos if (! just_count) 5135 1.1 christos { 5136 1.1 christos if (som_hppa_howto_table[op].type == R_ENTRY) 5137 1.1 christos rptr->addend = var ('T'); 5138 1.1 christos else if (som_hppa_howto_table[op].type == R_EXIT) 5139 1.1 christos rptr->addend = var ('U'); 5140 1.1 christos else if (som_hppa_howto_table[op].type == R_PCREL_CALL 5141 1.1 christos || som_hppa_howto_table[op].type == R_ABS_CALL) 5142 1.1 christos ; 5143 1.1 christos else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL) 5144 1.1 christos { 5145 1.1 christos /* Try what was specified in R_DATA_OVERRIDE first 5146 1.1 christos (if anything). Then the hard way using the 5147 1.1 christos section contents. */ 5148 1.1 christos rptr->addend = var ('V'); 5149 1.11 christos 5150 1.11 christos if (rptr->addend == 0 5151 1.1 christos && (section->flags & SEC_HAS_CONTENTS) != 0) 5152 1.11 christos { 5153 1.1 christos if (!section->contents) 5154 1.11 christos { 5155 1.11 christos /* Got to read the damn contents first. We don't 5156 1.11 christos bother saving the contents (yet). Add it one 5157 1.11 christos day if the need arises. */ 5158 1.11 christos bfd_byte *contents; 5159 1.11 christos if (!bfd_malloc_and_get_section (section->owner, 5160 1.11 christos section, &contents)) 5161 1.11 christos { 5162 1.11 christos free (contents); 5163 1.11 christos return (unsigned) -1; 5164 1.11 christos } 5165 1.11 christos section->contents = contents; 5166 1.1 christos deallocate_contents = 1; 5167 1.11 christos } 5168 1.11 christos if (offset - var ('L') <= section->size 5169 1.11 christos && section->size - (offset - var ('L')) >= 4) 5170 1.11 christos rptr->addend = bfd_get_32 (section->owner, 5171 1.11 christos (section->contents 5172 1.1 christos + offset - var ('L'))); 5173 1.1 christos } 5174 1.1 christos } 5175 1.1 christos else 5176 1.1 christos rptr->addend = var ('V'); 5177 1.1 christos rptr++; 5178 1.1 christos } 5179 1.1 christos count++; 5180 1.1 christos /* Now that we've handled a "full" relocation, reset 5181 1.1 christos some state. */ 5182 1.1 christos memset (variables, 0, sizeof (variables)); 5183 1.1 christos memset (stack, 0, sizeof (stack)); 5184 1.1 christos } 5185 1.1 christos } 5186 1.10 christos if (deallocate_contents) 5187 1.10 christos { 5188 1.10 christos free (section->contents); 5189 1.10 christos section->contents = NULL; 5190 1.1 christos } 5191 1.1 christos 5192 1.1 christos return count; 5193 1.1 christos 5194 1.1 christos #undef var 5195 1.1 christos #undef push 5196 1.1 christos #undef pop 5197 1.1 christos #undef emptystack 5198 1.1 christos } 5199 1.1 christos 5200 1.1 christos /* Read in the relocs (aka fixups in SOM terms) for a section. 5201 1.1 christos 5202 1.1 christos som_get_reloc_upper_bound calls this routine with JUST_COUNT 5203 1.1 christos set to TRUE to indicate it only needs a count of the number 5204 1.1 christos of actual relocations. */ 5205 1.10 christos 5206 1.1 christos static bool 5207 1.1 christos som_slurp_reloc_table (bfd *abfd, 5208 1.1 christos asection *section, 5209 1.10 christos asymbol **symbols, 5210 1.1 christos bool just_count) 5211 1.1 christos { 5212 1.1 christos unsigned char *external_relocs; 5213 1.1 christos unsigned int fixup_stream_size; 5214 1.1 christos arelent *internal_relocs; 5215 1.9 christos unsigned int num_relocs; 5216 1.1 christos size_t amt; 5217 1.1 christos 5218 1.1 christos fixup_stream_size = som_section_data (section)->reloc_size; 5219 1.1 christos /* If there were no relocations, then there is nothing to do. */ 5220 1.10 christos if (section->reloc_count == 0) 5221 1.1 christos return true; 5222 1.1 christos 5223 1.1 christos /* If reloc_count is -1, then the relocation stream has not been 5224 1.1 christos parsed. We must do so now to know how many relocations exist. */ 5225 1.1 christos if (section->reloc_count == (unsigned) -1) 5226 1.9 christos { 5227 1.9 christos /* Read in the external forms. */ 5228 1.9 christos if (bfd_seek (abfd, obj_som_reloc_filepos (abfd) + section->rel_filepos, 5229 1.10 christos SEEK_SET) != 0) 5230 1.1 christos return false; 5231 1.9 christos amt = fixup_stream_size; 5232 1.1 christos external_relocs = _bfd_malloc_and_read (abfd, amt, amt); 5233 1.10 christos if (external_relocs == NULL) 5234 1.1 christos return false; 5235 1.1 christos 5236 1.1 christos /* Let callers know how many relocations found. 5237 1.1 christos also save the relocation stream as we will 5238 1.1 christos need it again. */ 5239 1.1 christos section->reloc_count = som_set_reloc_info (external_relocs, 5240 1.10 christos fixup_stream_size, 5241 1.1 christos NULL, NULL, NULL, 0, true); 5242 1.1 christos 5243 1.1 christos som_section_data (section)->reloc_stream = external_relocs; 5244 1.1 christos } 5245 1.1 christos 5246 1.1 christos /* If the caller only wanted a count, then return now. */ 5247 1.10 christos if (just_count) 5248 1.1 christos return true; 5249 1.1 christos 5250 1.1 christos num_relocs = section->reloc_count; 5251 1.1 christos external_relocs = som_section_data (section)->reloc_stream; 5252 1.1 christos /* Return saved information about the relocations if it is available. */ 5253 1.10 christos if (section->relocation != NULL) 5254 1.1 christos return true; 5255 1.9 christos 5256 1.9 christos if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt)) 5257 1.9 christos { 5258 1.10 christos bfd_set_error (bfd_error_file_too_big); 5259 1.9 christos return false; 5260 1.9 christos } 5261 1.1 christos internal_relocs = bfd_zalloc (abfd, amt); 5262 1.10 christos if (internal_relocs == NULL) 5263 1.1 christos return false; 5264 1.1 christos 5265 1.1 christos /* Process and internalize the relocations. */ 5266 1.10 christos som_set_reloc_info (external_relocs, fixup_stream_size, 5267 1.10 christos internal_relocs, section, symbols, 5268 1.1 christos bfd_get_symcount (abfd), false); 5269 1.1 christos 5270 1.1 christos /* We're done with the external relocations. Free them. */ 5271 1.1 christos free (external_relocs); 5272 1.1 christos som_section_data (section)->reloc_stream = NULL; 5273 1.1 christos 5274 1.1 christos /* Save our results and return success. */ 5275 1.10 christos section->relocation = internal_relocs; 5276 1.1 christos return true; 5277 1.1 christos } 5278 1.1 christos 5279 1.1 christos /* Return the number of bytes required to store the relocation 5280 1.1 christos information associated with the given section. */ 5281 1.1 christos 5282 1.1 christos static long 5283 1.1 christos som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect) 5284 1.1 christos { 5285 1.1 christos /* If section has relocations, then read in the relocation stream 5286 1.1 christos and parse it to determine how many relocations exist. */ 5287 1.1 christos if (asect->flags & SEC_RELOC) 5288 1.10 christos { 5289 1.1 christos if (! som_slurp_reloc_table (abfd, asect, NULL, true)) 5290 1.1 christos return -1; 5291 1.1 christos return (asect->reloc_count + 1) * sizeof (arelent *); 5292 1.1 christos } 5293 1.1 christos 5294 1.1 christos /* There are no relocations. Return enough space to hold the 5295 1.1 christos NULL pointer which will be installed if som_canonicalize_reloc 5296 1.1 christos is called. */ 5297 1.1 christos return sizeof (arelent *); 5298 1.1 christos } 5299 1.1 christos 5300 1.1 christos /* Convert relocations from SOM (external) form into BFD internal 5301 1.1 christos form. Return the number of relocations. */ 5302 1.1 christos 5303 1.1 christos static long 5304 1.1 christos som_canonicalize_reloc (bfd *abfd, 5305 1.1 christos sec_ptr section, 5306 1.1 christos arelent **relptr, 5307 1.1 christos asymbol **symbols) 5308 1.1 christos { 5309 1.1 christos arelent *tblptr; 5310 1.1 christos int count; 5311 1.10 christos 5312 1.1 christos if (! som_slurp_reloc_table (abfd, section, symbols, false)) 5313 1.1 christos return -1; 5314 1.1 christos 5315 1.1 christos count = section->reloc_count; 5316 1.1 christos tblptr = section->relocation; 5317 1.1 christos 5318 1.1 christos while (count--) 5319 1.1 christos *relptr++ = tblptr++; 5320 1.1 christos 5321 1.1 christos *relptr = NULL; 5322 1.1 christos return section->reloc_count; 5323 1.1 christos } 5324 1.3 christos 5325 1.1 christos extern const bfd_target hppa_som_vec; 5326 1.1 christos 5327 1.1 christos /* A hook to set up object file dependent section information. */ 5328 1.10 christos 5329 1.1 christos static bool 5330 1.1 christos som_new_section_hook (bfd *abfd, asection *newsect) 5331 1.1 christos { 5332 1.1 christos if (!newsect->used_by_bfd) 5333 1.9 christos { 5334 1.1 christos size_t amt = sizeof (struct som_section_data_struct); 5335 1.1 christos 5336 1.1 christos newsect->used_by_bfd = bfd_zalloc (abfd, amt); 5337 1.10 christos if (!newsect->used_by_bfd) 5338 1.1 christos return false; 5339 1.1 christos } 5340 1.1 christos newsect->alignment_power = 3; 5341 1.1 christos 5342 1.1 christos /* We allow more than three sections internally. */ 5343 1.1 christos return _bfd_generic_new_section_hook (abfd, newsect); 5344 1.1 christos } 5345 1.1 christos 5346 1.1 christos /* Copy any private info we understand from the input symbol 5347 1.1 christos to the output symbol. */ 5348 1.10 christos 5349 1.1 christos static bool 5350 1.1 christos som_bfd_copy_private_symbol_data (bfd *ibfd, 5351 1.1 christos asymbol *isymbol, 5352 1.1 christos bfd *obfd, 5353 1.1 christos asymbol *osymbol) 5354 1.1 christos { 5355 1.1 christos struct som_symbol *input_symbol = (struct som_symbol *) isymbol; 5356 1.1 christos struct som_symbol *output_symbol = (struct som_symbol *) osymbol; 5357 1.1 christos 5358 1.1 christos /* One day we may try to grok other private data. */ 5359 1.1 christos if (ibfd->xvec->flavour != bfd_target_som_flavour 5360 1.10 christos || obfd->xvec->flavour != bfd_target_som_flavour) 5361 1.1 christos return false; 5362 1.1 christos 5363 1.1 christos /* The only private information we need to copy is the argument relocation 5364 1.1 christos bits. */ 5365 1.1 christos output_symbol->tc_data.ap.hppa_arg_reloc = 5366 1.1 christos input_symbol->tc_data.ap.hppa_arg_reloc; 5367 1.10 christos 5368 1.1 christos return true; 5369 1.1 christos } 5370 1.1 christos 5371 1.1 christos /* Copy any private info we understand from the input section 5372 1.1 christos to the output section. */ 5373 1.10 christos 5374 1.1 christos static bool 5375 1.1 christos som_bfd_copy_private_section_data (bfd *ibfd, 5376 1.1 christos asection *isection, 5377 1.1 christos bfd *obfd, 5378 1.1 christos asection *osection) 5379 1.9 christos { 5380 1.1 christos size_t amt; 5381 1.1 christos 5382 1.1 christos /* One day we may try to grok other private data. */ 5383 1.1 christos if (ibfd->xvec->flavour != bfd_target_som_flavour 5384 1.1 christos || obfd->xvec->flavour != bfd_target_som_flavour 5385 1.10 christos || (!som_is_space (isection) && !som_is_subspace (isection))) 5386 1.1 christos return true; 5387 1.1 christos 5388 1.1 christos amt = sizeof (struct som_copyable_section_data_struct); 5389 1.1 christos som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt); 5390 1.10 christos if (som_section_data (osection)->copy_data == NULL) 5391 1.1 christos return false; 5392 1.1 christos 5393 1.1 christos memcpy (som_section_data (osection)->copy_data, 5394 1.1 christos som_section_data (isection)->copy_data, 5395 1.1 christos sizeof (struct som_copyable_section_data_struct)); 5396 1.1 christos 5397 1.1 christos /* Reparent if necessary. */ 5398 1.9 christos if (som_section_data (osection)->copy_data->container) 5399 1.9 christos { 5400 1.9 christos if (som_section_data (osection)->copy_data->container->output_section) 5401 1.9 christos som_section_data (osection)->copy_data->container = 5402 1.9 christos som_section_data (osection)->copy_data->container->output_section; 5403 1.9 christos else 5404 1.9 christos { 5405 1.9 christos /* User has specified a subspace without its containing space. */ 5406 1.9 christos _bfd_error_handler (_("%pB[%pA]: no output section for space %pA"), 5407 1.10 christos obfd, osection, som_section_data (osection)->copy_data->container); 5408 1.9 christos return false; 5409 1.9 christos } 5410 1.1 christos } 5411 1.10 christos 5412 1.1 christos return true; 5413 1.1 christos } 5414 1.1 christos 5415 1.1 christos /* Copy any private info we understand from the input bfd 5416 1.1 christos to the output bfd. */ 5417 1.10 christos 5418 1.1 christos static bool 5419 1.1 christos som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 5420 1.1 christos { 5421 1.1 christos /* One day we may try to grok other private data. */ 5422 1.1 christos if (ibfd->xvec->flavour != bfd_target_som_flavour 5423 1.10 christos || obfd->xvec->flavour != bfd_target_som_flavour) 5424 1.1 christos return true; 5425 1.1 christos 5426 1.1 christos /* Allocate some memory to hold the data we need. */ 5427 1.1 christos obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data)); 5428 1.10 christos if (obj_som_exec_data (obfd) == NULL) 5429 1.1 christos return false; 5430 1.1 christos 5431 1.1 christos /* Now copy the data. */ 5432 1.1 christos memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd), 5433 1.1 christos sizeof (struct som_exec_data)); 5434 1.10 christos 5435 1.1 christos return true; 5436 1.1 christos } 5437 1.1 christos 5438 1.1 christos /* Display the SOM header. */ 5439 1.10 christos 5440 1.1 christos static bool 5441 1.1 christos som_bfd_print_private_bfd_data (bfd *abfd, void *farg) 5442 1.1 christos { 5443 1.1 christos struct som_exec_auxhdr *exec_header; 5444 1.1 christos struct som_aux_id* auxhdr; 5445 1.1 christos FILE *f; 5446 1.1 christos 5447 1.1 christos f = (FILE *) farg; 5448 1.1 christos 5449 1.1 christos exec_header = obj_som_exec_hdr (abfd); 5450 1.1 christos if (exec_header) 5451 1.1 christos { 5452 1.1 christos fprintf (f, _("\nExec Auxiliary Header\n")); 5453 1.1 christos fprintf (f, " flags "); 5454 1.1 christos auxhdr = &exec_header->som_auxhdr; 5455 1.1 christos if (auxhdr->mandatory) 5456 1.1 christos fprintf (f, "mandatory "); 5457 1.1 christos if (auxhdr->copy) 5458 1.1 christos fprintf (f, "copy "); 5459 1.1 christos if (auxhdr->append) 5460 1.1 christos fprintf (f, "append "); 5461 1.1 christos if (auxhdr->ignore) 5462 1.1 christos fprintf (f, "ignore "); 5463 1.1 christos fprintf (f, "\n"); 5464 1.1 christos fprintf (f, " type %#x\n", auxhdr->type); 5465 1.1 christos fprintf (f, " length %#x\n", auxhdr->length); 5466 1.1 christos 5467 1.8 christos /* Note that, depending on the HP-UX version, the following fields can be 5468 1.1 christos either ints, or longs. */ 5469 1.1 christos 5470 1.1 christos fprintf (f, " text size %#lx\n", (long) exec_header->exec_tsize); 5471 1.1 christos fprintf (f, " text memory offset %#lx\n", (long) exec_header->exec_tmem); 5472 1.1 christos fprintf (f, " text file offset %#lx\n", (long) exec_header->exec_tfile); 5473 1.1 christos fprintf (f, " data size %#lx\n", (long) exec_header->exec_dsize); 5474 1.1 christos fprintf (f, " data memory offset %#lx\n", (long) exec_header->exec_dmem); 5475 1.1 christos fprintf (f, " data file offset %#lx\n", (long) exec_header->exec_dfile); 5476 1.1 christos fprintf (f, " bss size %#lx\n", (long) exec_header->exec_bsize); 5477 1.1 christos fprintf (f, " entry point %#lx\n", (long) exec_header->exec_entry); 5478 1.1 christos fprintf (f, " loader flags %#lx\n", (long) exec_header->exec_flags); 5479 1.1 christos fprintf (f, " bss initializer %#lx\n", (long) exec_header->exec_bfill); 5480 1.1 christos } 5481 1.10 christos 5482 1.1 christos return true; 5483 1.1 christos } 5484 1.1 christos 5485 1.1 christos /* Set backend info for sections which can not be described 5486 1.1 christos in the BFD data structures. */ 5487 1.10 christos 5488 1.1 christos bool 5489 1.1 christos bfd_som_set_section_attributes (asection *section, 5490 1.1 christos int defined, 5491 1.1 christos int private, 5492 1.1 christos unsigned int sort_key, 5493 1.1 christos int spnum) 5494 1.1 christos { 5495 1.1 christos /* Allocate memory to hold the magic information. */ 5496 1.1 christos if (som_section_data (section)->copy_data == NULL) 5497 1.9 christos { 5498 1.1 christos size_t amt = sizeof (struct som_copyable_section_data_struct); 5499 1.1 christos 5500 1.1 christos som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt); 5501 1.10 christos if (som_section_data (section)->copy_data == NULL) 5502 1.1 christos return false; 5503 1.1 christos } 5504 1.1 christos som_section_data (section)->copy_data->sort_key = sort_key; 5505 1.1 christos som_section_data (section)->copy_data->is_defined = defined; 5506 1.1 christos som_section_data (section)->copy_data->is_private = private; 5507 1.1 christos som_section_data (section)->copy_data->container = section; 5508 1.10 christos som_section_data (section)->copy_data->space_number = spnum; 5509 1.1 christos return true; 5510 1.1 christos } 5511 1.1 christos 5512 1.1 christos /* Set backend info for subsections which can not be described 5513 1.1 christos in the BFD data structures. */ 5514 1.10 christos 5515 1.1 christos bool 5516 1.1 christos bfd_som_set_subsection_attributes (asection *section, 5517 1.1 christos asection *container, 5518 1.1 christos int access_ctr, 5519 1.1 christos unsigned int sort_key, 5520 1.1 christos int quadrant, 5521 1.1 christos int comdat, 5522 1.1 christos int common, 5523 1.1 christos int dup_common) 5524 1.1 christos { 5525 1.1 christos /* Allocate memory to hold the magic information. */ 5526 1.1 christos if (som_section_data (section)->copy_data == NULL) 5527 1.9 christos { 5528 1.1 christos size_t amt = sizeof (struct som_copyable_section_data_struct); 5529 1.1 christos 5530 1.1 christos som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt); 5531 1.10 christos if (som_section_data (section)->copy_data == NULL) 5532 1.1 christos return false; 5533 1.1 christos } 5534 1.1 christos som_section_data (section)->copy_data->sort_key = sort_key; 5535 1.1 christos som_section_data (section)->copy_data->access_control_bits = access_ctr; 5536 1.1 christos som_section_data (section)->copy_data->quadrant = quadrant; 5537 1.1 christos som_section_data (section)->copy_data->container = container; 5538 1.1 christos som_section_data (section)->copy_data->is_comdat = comdat; 5539 1.1 christos som_section_data (section)->copy_data->is_common = common; 5540 1.10 christos som_section_data (section)->copy_data->dup_common = dup_common; 5541 1.1 christos return true; 5542 1.1 christos } 5543 1.1 christos 5544 1.1 christos /* Set the full SOM symbol type. SOM needs far more symbol information 5545 1.1 christos than any other object file format I'm aware of. It is mandatory 5546 1.1 christos to be able to know if a symbol is an entry point, millicode, data, 5547 1.1 christos code, absolute, storage request, or procedure label. If you get 5548 1.1 christos the symbol type wrong your program will not link. */ 5549 1.1 christos 5550 1.1 christos void 5551 1.1 christos bfd_som_set_symbol_type (asymbol *symbol, unsigned int type) 5552 1.1 christos { 5553 1.1 christos som_symbol_data (symbol)->som_type = type; 5554 1.1 christos } 5555 1.1 christos 5556 1.1 christos /* Attach an auxiliary header to the BFD backend so that it may be 5557 1.1 christos written into the object file. */ 5558 1.10 christos 5559 1.1 christos bool 5560 1.1 christos bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string) 5561 1.9 christos { 5562 1.1 christos size_t amt; 5563 1.1 christos 5564 1.1 christos if (type == VERSION_AUX_ID) 5565 1.1 christos { 5566 1.1 christos size_t len = strlen (string); 5567 1.1 christos int pad = 0; 5568 1.1 christos 5569 1.1 christos if (len % 4) 5570 1.1 christos pad = (4 - (len % 4)); 5571 1.1 christos amt = sizeof (struct som_string_auxhdr) + len + pad; 5572 1.1 christos obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt); 5573 1.10 christos if (!obj_som_version_hdr (abfd)) 5574 1.1 christos return false; 5575 1.1 christos obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID; 5576 1.1 christos obj_som_version_hdr (abfd)->header_id.length = 4 + len + pad; 5577 1.1 christos obj_som_version_hdr (abfd)->string_length = len; 5578 1.1 christos memcpy (obj_som_version_hdr (abfd)->string, string, len); 5579 1.1 christos memset (obj_som_version_hdr (abfd)->string + len, 0, pad); 5580 1.1 christos } 5581 1.1 christos else if (type == COPYRIGHT_AUX_ID) 5582 1.9 christos { 5583 1.1 christos size_t len = strlen (string); 5584 1.1 christos int pad = 0; 5585 1.1 christos 5586 1.1 christos if (len % 4) 5587 1.1 christos pad = (4 - (len % 4)); 5588 1.1 christos amt = sizeof (struct som_string_auxhdr) + len + pad; 5589 1.1 christos obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt); 5590 1.10 christos if (!obj_som_copyright_hdr (abfd)) 5591 1.1 christos return false; 5592 1.1 christos obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID; 5593 1.1 christos obj_som_copyright_hdr (abfd)->header_id.length = len + pad + 4; 5594 1.1 christos obj_som_copyright_hdr (abfd)->string_length = len; 5595 1.1 christos memcpy (obj_som_copyright_hdr (abfd)->string, string, len); 5596 1.1 christos memset (obj_som_copyright_hdr (abfd)->string + len, 0, pad); 5597 1.10 christos } 5598 1.1 christos return true; 5599 1.1 christos } 5600 1.1 christos 5601 1.1 christos /* Attach a compilation unit header to the BFD backend so that it may be 5602 1.1 christos written into the object file. */ 5603 1.10 christos 5604 1.1 christos bool 5605 1.1 christos bfd_som_attach_compilation_unit (bfd *abfd, 5606 1.1 christos const char *name, 5607 1.1 christos const char *language_name, 5608 1.1 christos const char *product_id, 5609 1.1 christos const char *version_id) 5610 1.1 christos { 5611 1.1 christos struct som_compilation_unit *n; 5612 1.1 christos 5613 1.1 christos n = (struct som_compilation_unit *) bfd_zalloc 5614 1.1 christos (abfd, (bfd_size_type) sizeof (*n)); 5615 1.10 christos if (n == NULL) 5616 1.1 christos return false; 5617 1.1 christos 5618 1.1 christos #define STRDUP(f) \ 5619 1.1 christos if (f != NULL) \ 5620 1.1 christos { \ 5621 1.1 christos n->f.name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \ 5622 1.10 christos if (n->f.name == NULL) \ 5623 1.1 christos return false; \ 5624 1.1 christos strcpy (n->f.name, f); \ 5625 1.1 christos } 5626 1.1 christos 5627 1.1 christos STRDUP (name); 5628 1.1 christos STRDUP (language_name); 5629 1.1 christos STRDUP (product_id); 5630 1.1 christos STRDUP (version_id); 5631 1.1 christos 5632 1.1 christos #undef STRDUP 5633 1.1 christos 5634 1.1 christos obj_som_compilation_unit (abfd) = n; 5635 1.10 christos 5636 1.1 christos return true; 5637 1.1 christos } 5638 1.10 christos 5639 1.1 christos static bool 5640 1.1 christos som_get_section_contents (bfd *abfd, 5641 1.1 christos sec_ptr section, 5642 1.1 christos void *location, 5643 1.1 christos file_ptr offset, 5644 1.1 christos bfd_size_type count) 5645 1.1 christos { 5646 1.10 christos if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0)) 5647 1.11 christos return true; 5648 1.11 christos if ((bfd_size_type) (offset + count) > section->size 5649 1.11 christos || bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0 5650 1.10 christos || bfd_read (location, count, abfd) != count) 5651 1.10 christos return false; /* On error. */ 5652 1.1 christos return true; 5653 1.1 christos } 5654 1.10 christos 5655 1.1 christos static bool 5656 1.1 christos som_set_section_contents (bfd *abfd, 5657 1.1 christos sec_ptr section, 5658 1.1 christos const void *location, 5659 1.1 christos file_ptr offset, 5660 1.1 christos bfd_size_type count) 5661 1.1 christos { 5662 1.1 christos if (! abfd->output_has_begun) 5663 1.1 christos { 5664 1.1 christos /* Set up fixed parts of the file, space, and subspace headers. 5665 1.1 christos Notify the world that output has begun. */ 5666 1.10 christos som_prep_headers (abfd); 5667 1.1 christos abfd->output_has_begun = true; 5668 1.1 christos /* Start writing the object file. This include all the string 5669 1.1 christos tables, fixup streams, and other portions of the object file. */ 5670 1.1 christos som_begin_writing (abfd); 5671 1.1 christos } 5672 1.1 christos 5673 1.1 christos /* Only write subspaces which have "real" contents (eg. the contents 5674 1.1 christos are not generated at run time by the OS). */ 5675 1.1 christos if (!som_is_subspace (section) 5676 1.10 christos || ((section->flags & SEC_HAS_CONTENTS) == 0)) 5677 1.1 christos return true; 5678 1.1 christos 5679 1.1 christos /* Seek to the proper offset within the object file and write the 5680 1.1 christos data. */ 5681 1.1 christos offset += som_section_data (section)->subspace_dict->file_loc_init_value; 5682 1.10 christos if (bfd_seek (abfd, offset, SEEK_SET) != 0) 5683 1.1 christos return false; 5684 1.11 christos 5685 1.10 christos if (bfd_write (location, count, abfd) != count) 5686 1.10 christos return false; 5687 1.1 christos return true; 5688 1.1 christos } 5689 1.10 christos 5690 1.1 christos static bool 5691 1.1 christos som_set_arch_mach (bfd *abfd, 5692 1.1 christos enum bfd_architecture arch, 5693 1.1 christos unsigned long machine) 5694 1.1 christos { 5695 1.1 christos /* Allow any architecture to be supported by the SOM backend. */ 5696 1.1 christos return bfd_default_set_arch_mach (abfd, arch, machine); 5697 1.1 christos } 5698 1.10 christos 5699 1.1 christos static bool 5700 1.3 christos som_find_nearest_line (bfd *abfd, 5701 1.1 christos asymbol **symbols, 5702 1.1 christos asection *section, 5703 1.1 christos bfd_vma offset, 5704 1.1 christos const char **filename_ptr, 5705 1.3 christos const char **functionname_ptr, 5706 1.3 christos unsigned int *line_ptr, 5707 1.1 christos unsigned int *discriminator_ptr) 5708 1.10 christos { 5709 1.1 christos bool found; 5710 1.1 christos asymbol *func; 5711 1.1 christos bfd_vma low_func; 5712 1.1 christos asymbol **p; 5713 1.3 christos 5714 1.3 christos if (discriminator_ptr) 5715 1.3 christos *discriminator_ptr = 0; 5716 1.1 christos 5717 1.8 christos if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, 5718 1.8 christos & found, filename_ptr, 5719 1.8 christos functionname_ptr, line_ptr, 5720 1.10 christos & somdata (abfd).line_info)) 5721 1.1 christos return false; 5722 1.1 christos 5723 1.10 christos if (found) 5724 1.1 christos return true; 5725 1.1 christos 5726 1.10 christos if (symbols == NULL) 5727 1.1 christos return false; 5728 1.1 christos 5729 1.1 christos /* Fallback: find function name from symbols table. */ 5730 1.1 christos func = NULL; 5731 1.1 christos low_func = 0; 5732 1.1 christos 5733 1.1 christos for (p = symbols; *p != NULL; p++) 5734 1.1 christos { 5735 1.1 christos som_symbol_type *q = (som_symbol_type *) *p; 5736 1.1 christos 5737 1.1 christos if (q->som_type == SYMBOL_TYPE_ENTRY 5738 1.1 christos && q->symbol.section == section 5739 1.1 christos && q->symbol.value >= low_func 5740 1.1 christos && q->symbol.value <= offset) 5741 1.1 christos { 5742 1.1 christos func = (asymbol *) q; 5743 1.1 christos low_func = q->symbol.value; 5744 1.1 christos } 5745 1.1 christos } 5746 1.1 christos 5747 1.10 christos if (func == NULL) 5748 1.1 christos return false; 5749 1.1 christos 5750 1.1 christos *filename_ptr = NULL; 5751 1.1 christos *functionname_ptr = bfd_asymbol_name (func); 5752 1.1 christos *line_ptr = 0; 5753 1.10 christos 5754 1.1 christos return true; 5755 1.1 christos } 5756 1.1 christos 5757 1.1 christos static int 5758 1.1 christos som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, 5759 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED) 5760 1.7 christos { 5761 1.1 christos _bfd_error_handler (_("som_sizeof_headers unimplemented")); 5762 1.1 christos abort (); 5763 1.1 christos return 0; 5764 1.1 christos } 5765 1.1 christos 5766 1.1 christos /* Return the single-character symbol type corresponding to 5767 1.1 christos SOM section S, or '?' for an unknown SOM section. */ 5768 1.1 christos 5769 1.1 christos static char 5770 1.1 christos som_section_type (const char *s) 5771 1.1 christos { 5772 1.1 christos const struct section_to_type *t; 5773 1.1 christos 5774 1.1 christos for (t = &stt[0]; t->section; t++) 5775 1.1 christos if (!strcmp (s, t->section)) 5776 1.1 christos return t->type; 5777 1.1 christos return '?'; 5778 1.1 christos } 5779 1.1 christos 5780 1.1 christos static int 5781 1.1 christos som_decode_symclass (asymbol *symbol) 5782 1.1 christos { 5783 1.1 christos char c; 5784 1.10 christos 5785 1.10 christos /* If the symbol did not have a scope specified, 5786 1.10 christos then it will not have associated section. */ 5787 1.10 christos if (symbol == NULL || symbol->section == NULL) 5788 1.10 christos return '?'; 5789 1.1 christos 5790 1.1 christos if (bfd_is_com_section (symbol->section)) 5791 1.1 christos return 'C'; 5792 1.1 christos if (bfd_is_und_section (symbol->section)) 5793 1.1 christos { 5794 1.1 christos if (symbol->flags & BSF_WEAK) 5795 1.1 christos { 5796 1.1 christos /* If weak, determine if it's specifically an object 5797 1.1 christos or non-object weak. */ 5798 1.1 christos if (symbol->flags & BSF_OBJECT) 5799 1.1 christos return 'v'; 5800 1.1 christos else 5801 1.1 christos return 'w'; 5802 1.1 christos } 5803 1.1 christos else 5804 1.1 christos return 'U'; 5805 1.1 christos } 5806 1.1 christos if (bfd_is_ind_section (symbol->section)) 5807 1.1 christos return 'I'; 5808 1.1 christos if (symbol->flags & BSF_WEAK) 5809 1.1 christos { 5810 1.1 christos /* If weak, determine if it's specifically an object 5811 1.1 christos or non-object weak. */ 5812 1.1 christos if (symbol->flags & BSF_OBJECT) 5813 1.1 christos return 'V'; 5814 1.1 christos else 5815 1.1 christos return 'W'; 5816 1.1 christos } 5817 1.1 christos if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) 5818 1.1 christos return '?'; 5819 1.1 christos 5820 1.1 christos if (bfd_is_abs_section (symbol->section) 5821 1.1 christos || (som_symbol_data (symbol) != NULL 5822 1.1 christos && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE)) 5823 1.1 christos c = 'a'; 5824 1.1 christos else if (symbol->section) 5825 1.1 christos c = som_section_type (symbol->section->name); 5826 1.1 christos else 5827 1.1 christos return '?'; 5828 1.1 christos if (symbol->flags & BSF_GLOBAL) 5829 1.1 christos c = TOUPPER (c); 5830 1.1 christos return c; 5831 1.1 christos } 5832 1.1 christos 5833 1.1 christos /* Return information about SOM symbol SYMBOL in RET. */ 5834 1.1 christos 5835 1.1 christos static void 5836 1.1 christos som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED, 5837 1.1 christos asymbol *symbol, 5838 1.1 christos symbol_info *ret) 5839 1.1 christos { 5840 1.1 christos ret->type = som_decode_symclass (symbol); 5841 1.1 christos if (ret->type != 'U') 5842 1.1 christos ret->value = symbol->value + symbol->section->vma; 5843 1.1 christos else 5844 1.1 christos ret->value = 0; 5845 1.1 christos ret->name = symbol->name; 5846 1.1 christos } 5847 1.1 christos 5848 1.1 christos /* Count the number of symbols in the archive symbol table. Necessary 5849 1.1 christos so that we can allocate space for all the carsyms at once. */ 5850 1.10 christos 5851 1.1 christos static bool 5852 1.1 christos som_bfd_count_ar_symbols (bfd *abfd, 5853 1.1 christos struct som_lst_header *lst_header, 5854 1.1 christos symindex *count) 5855 1.1 christos { 5856 1.1 christos unsigned int i; 5857 1.9 christos unsigned char *hash_table; 5858 1.1 christos size_t amt; 5859 1.1 christos file_ptr lst_filepos; 5860 1.1 christos 5861 1.1 christos lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header); 5862 1.9 christos 5863 1.9 christos /* Read in the hash table. The hash table is an array of 32-bit 5864 1.9 christos file offsets which point to the hash chains. */ 5865 1.9 christos if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt)) 5866 1.9 christos { 5867 1.10 christos bfd_set_error (bfd_error_file_too_big); 5868 1.9 christos return false; 5869 1.9 christos } 5870 1.9 christos hash_table = _bfd_malloc_and_read (abfd, amt, amt); 5871 1.1 christos if (hash_table == NULL && lst_header->hash_size != 0) 5872 1.1 christos goto error_return; 5873 1.1 christos 5874 1.1 christos /* Don't forget to initialize the counter! */ 5875 1.1 christos *count = 0; 5876 1.1 christos 5877 1.1 christos /* Walk each chain counting the number of symbols found on that particular 5878 1.1 christos chain. */ 5879 1.1 christos for (i = 0; i < lst_header->hash_size; i++) 5880 1.1 christos { 5881 1.1 christos struct som_external_lst_symbol_record ext_lst_symbol; 5882 1.1 christos unsigned int hash_val = bfd_getb32 (hash_table + 4 * i); 5883 1.1 christos 5884 1.1 christos /* An empty chain has zero as it's file offset. */ 5885 1.1 christos if (hash_val == 0) 5886 1.1 christos continue; 5887 1.1 christos 5888 1.1 christos /* Seek to the first symbol in this hash chain. */ 5889 1.1 christos if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0) 5890 1.1 christos goto error_return; 5891 1.1 christos 5892 1.1 christos /* Read in this symbol and update the counter. */ 5893 1.11 christos amt = sizeof (ext_lst_symbol); 5894 1.1 christos if (bfd_read (&ext_lst_symbol, amt, abfd) != amt) 5895 1.1 christos goto error_return; 5896 1.1 christos 5897 1.1 christos (*count)++; 5898 1.1 christos 5899 1.1 christos /* Now iterate through the rest of the symbols on this chain. */ 5900 1.1 christos while (1) 5901 1.8 christos { 5902 1.1 christos unsigned int next_entry = bfd_getb32 (ext_lst_symbol.next_entry); 5903 1.8 christos 5904 1.8 christos if (next_entry == 0) 5905 1.1 christos break; 5906 1.9 christos 5907 1.9 christos /* Assume symbols on a chain are in increasing file offset 5908 1.9 christos order. Otherwise we can loop here with fuzzed input. */ 5909 1.9 christos if (next_entry < hash_val + sizeof (ext_lst_symbol)) 5910 1.9 christos { 5911 1.9 christos bfd_set_error (bfd_error_bad_value); 5912 1.9 christos goto error_return; 5913 1.9 christos } 5914 1.9 christos hash_val = next_entry; 5915 1.1 christos 5916 1.1 christos /* Seek to the next symbol. */ 5917 1.1 christos if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0) 5918 1.1 christos goto error_return; 5919 1.1 christos 5920 1.1 christos /* Read the symbol in and update the counter. */ 5921 1.11 christos amt = sizeof (ext_lst_symbol); 5922 1.1 christos if (bfd_read (&ext_lst_symbol, amt, abfd) != amt) 5923 1.1 christos goto error_return; 5924 1.1 christos 5925 1.1 christos (*count)++; 5926 1.1 christos } 5927 1.9 christos } 5928 1.10 christos free (hash_table); 5929 1.1 christos return true; 5930 1.1 christos 5931 1.9 christos error_return: 5932 1.10 christos free (hash_table); 5933 1.1 christos return false; 5934 1.1 christos } 5935 1.1 christos 5936 1.1 christos /* Fill in the canonical archive symbols (SYMS) from the archive described 5937 1.1 christos by ABFD and LST_HEADER. */ 5938 1.10 christos 5939 1.1 christos static bool 5940 1.1 christos som_bfd_fill_in_ar_symbols (bfd *abfd, 5941 1.1 christos struct som_lst_header *lst_header, 5942 1.1 christos carsym **syms) 5943 1.1 christos { 5944 1.1 christos unsigned int i; 5945 1.1 christos carsym *set = syms[0]; 5946 1.1 christos unsigned char *hash_table; 5947 1.9 christos struct som_external_som_entry *som_dict = NULL; 5948 1.1 christos size_t amt; 5949 1.1 christos file_ptr lst_filepos; 5950 1.1 christos unsigned int string_loc; 5951 1.1 christos 5952 1.1 christos lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header); 5953 1.1 christos 5954 1.1 christos /* Read in the hash table. The has table is an array of 32bit file offsets 5955 1.9 christos which point to the hash chains. */ 5956 1.9 christos if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt)) 5957 1.9 christos { 5958 1.10 christos bfd_set_error (bfd_error_file_too_big); 5959 1.9 christos return false; 5960 1.9 christos } 5961 1.9 christos hash_table = _bfd_malloc_and_read (abfd, amt, amt); 5962 1.1 christos if (hash_table == NULL && lst_header->hash_size != 0) 5963 1.1 christos goto error_return; 5964 1.1 christos 5965 1.1 christos /* Seek to and read in the SOM dictionary. We will need this to fill 5966 1.1 christos in the carsym's filepos field. */ 5967 1.1 christos if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0) 5968 1.1 christos goto error_return; 5969 1.9 christos 5970 1.9 christos if (_bfd_mul_overflow (lst_header->module_count, 5971 1.9 christos sizeof (struct som_external_som_entry), &amt)) 5972 1.9 christos { 5973 1.9 christos bfd_set_error (bfd_error_file_too_big); 5974 1.9 christos goto error_return; 5975 1.9 christos } 5976 1.9 christos som_dict = (struct som_external_som_entry *) 5977 1.9 christos _bfd_malloc_and_read (abfd, amt, amt); 5978 1.1 christos if (som_dict == NULL && lst_header->module_count != 0) 5979 1.1 christos goto error_return; 5980 1.1 christos 5981 1.1 christos string_loc = lst_header->string_loc; 5982 1.1 christos 5983 1.1 christos /* Walk each chain filling in the carsyms as we go along. */ 5984 1.1 christos for (i = 0; i < lst_header->hash_size; i++) 5985 1.1 christos { 5986 1.1 christos struct som_external_lst_symbol_record lst_symbol; 5987 1.9 christos unsigned int hash_val; 5988 1.1 christos size_t len; 5989 1.9 christos unsigned char ext_len[4]; 5990 1.9 christos char *name; 5991 1.1 christos unsigned int ndx; 5992 1.1 christos 5993 1.1 christos /* An empty chain has zero as it's file offset. */ 5994 1.1 christos hash_val = bfd_getb32 (hash_table + 4 * i); 5995 1.1 christos if (hash_val == 0) 5996 1.1 christos continue; 5997 1.1 christos 5998 1.1 christos /* Seek to and read the first symbol on the chain. */ 5999 1.1 christos if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0) 6000 1.1 christos goto error_return; 6001 1.1 christos 6002 1.11 christos amt = sizeof (lst_symbol); 6003 1.1 christos if (bfd_read (&lst_symbol, amt, abfd) != amt) 6004 1.1 christos goto error_return; 6005 1.1 christos 6006 1.1 christos /* Get the name of the symbol, first get the length which is stored 6007 1.1 christos as a 32bit integer just before the symbol. 6008 1.1 christos 6009 1.1 christos One might ask why we don't just read in the entire string table 6010 1.1 christos and index into it. Well, according to the SOM ABI the string 6011 1.1 christos index can point *anywhere* in the archive to save space, so just 6012 1.1 christos using the string table would not be safe. */ 6013 1.8 christos if (bfd_seek (abfd, (lst_filepos + string_loc 6014 1.1 christos + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0) 6015 1.1 christos goto error_return; 6016 1.11 christos 6017 1.1 christos if (bfd_read (&ext_len, 4, abfd) != 4) 6018 1.1 christos goto error_return; 6019 1.1 christos len = bfd_getb32 (ext_len); 6020 1.1 christos 6021 1.9 christos /* Allocate space for the name and null terminate it too. */ 6022 1.9 christos if (len == (size_t) -1) 6023 1.9 christos { 6024 1.9 christos bfd_set_error (bfd_error_no_memory); 6025 1.9 christos goto error_return; 6026 1.9 christos } 6027 1.9 christos name = (char *) _bfd_alloc_and_read (abfd, len + 1, len); 6028 1.1 christos if (!name) 6029 1.9 christos goto error_return; 6030 1.9 christos name[len] = 0; 6031 1.1 christos set->name = name; 6032 1.1 christos 6033 1.1 christos /* Fill in the file offset. Note that the "location" field points 6034 1.9 christos to the SOM itself, not the ar_hdr in front of it. */ 6035 1.9 christos ndx = bfd_getb32 (lst_symbol.som_index); 6036 1.9 christos if (ndx >= lst_header->module_count) 6037 1.9 christos { 6038 1.9 christos bfd_set_error (bfd_error_bad_value); 6039 1.9 christos goto error_return; 6040 1.9 christos } 6041 1.9 christos set->file_offset 6042 1.1 christos = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr); 6043 1.1 christos 6044 1.1 christos /* Go to the next symbol. */ 6045 1.1 christos set++; 6046 1.1 christos 6047 1.1 christos /* Iterate through the rest of the chain. */ 6048 1.1 christos while (1) 6049 1.8 christos { 6050 1.1 christos unsigned int next_entry = bfd_getb32 (lst_symbol.next_entry); 6051 1.8 christos 6052 1.8 christos if (next_entry == 0) 6053 1.1 christos break; 6054 1.1 christos 6055 1.1 christos /* Seek to the next symbol and read it in. */ 6056 1.1 christos if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0) 6057 1.1 christos goto error_return; 6058 1.1 christos 6059 1.11 christos amt = sizeof (lst_symbol); 6060 1.1 christos if (bfd_read (&lst_symbol, amt, abfd) != amt) 6061 1.1 christos goto error_return; 6062 1.1 christos 6063 1.1 christos /* Seek to the name length & string and read them in. */ 6064 1.8 christos if (bfd_seek (abfd, lst_filepos + string_loc 6065 1.1 christos + bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0) 6066 1.1 christos goto error_return; 6067 1.11 christos 6068 1.1 christos if (bfd_read (&ext_len, 4, abfd) != 4) 6069 1.8 christos goto error_return; 6070 1.1 christos len = bfd_getb32 (ext_len); 6071 1.1 christos 6072 1.9 christos /* Allocate space for the name and null terminate it too. */ 6073 1.9 christos if (len == (size_t) -1) 6074 1.9 christos { 6075 1.9 christos bfd_set_error (bfd_error_no_memory); 6076 1.9 christos goto error_return; 6077 1.9 christos } 6078 1.9 christos name = (char *) _bfd_alloc_and_read (abfd, len + 1, len); 6079 1.1 christos if (!name) 6080 1.9 christos goto error_return; 6081 1.9 christos name[len] = 0; 6082 1.1 christos set->name = name; 6083 1.1 christos 6084 1.1 christos /* Fill in the file offset. Note that the "location" field points 6085 1.9 christos to the SOM itself, not the ar_hdr in front of it. */ 6086 1.9 christos ndx = bfd_getb32 (lst_symbol.som_index); 6087 1.9 christos if (ndx >= lst_header->module_count) 6088 1.9 christos { 6089 1.9 christos bfd_set_error (bfd_error_bad_value); 6090 1.9 christos goto error_return; 6091 1.9 christos } 6092 1.9 christos set->file_offset 6093 1.1 christos = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr); 6094 1.1 christos 6095 1.1 christos /* Go on to the next symbol. */ 6096 1.1 christos set++; 6097 1.1 christos } 6098 1.1 christos } 6099 1.1 christos /* If we haven't died by now, then we successfully read the entire 6100 1.9 christos archive symbol table. */ 6101 1.9 christos free (hash_table); 6102 1.10 christos free (som_dict); 6103 1.1 christos return true; 6104 1.1 christos 6105 1.9 christos error_return: 6106 1.9 christos free (hash_table); 6107 1.10 christos free (som_dict); 6108 1.1 christos return false; 6109 1.1 christos } 6110 1.1 christos 6111 1.1 christos /* Read in the LST from the archive. */ 6112 1.10 christos 6113 1.1 christos static bool 6114 1.1 christos som_slurp_armap (bfd *abfd) 6115 1.1 christos { 6116 1.1 christos struct som_external_lst_header ext_lst_header; 6117 1.1 christos struct som_lst_header lst_header; 6118 1.1 christos struct ar_hdr ar_header; 6119 1.1 christos unsigned int parsed_size; 6120 1.1 christos struct artdata *ardata = bfd_ardata (abfd); 6121 1.9 christos char nextname[17]; 6122 1.11 christos size_t amt = 16; 6123 1.1 christos int i = bfd_read (nextname, amt, abfd); 6124 1.1 christos 6125 1.1 christos /* Special cases. */ 6126 1.10 christos if (i == 0) 6127 1.1 christos return true; 6128 1.10 christos if (i != 16) 6129 1.1 christos return false; 6130 1.11 christos 6131 1.10 christos if (bfd_seek (abfd, -16, SEEK_CUR) != 0) 6132 1.1 christos return false; 6133 1.1 christos 6134 1.10 christos /* For archives without .o files there is no symbol table. */ 6135 1.1 christos if (! startswith (nextname, "/ ")) 6136 1.10 christos { 6137 1.10 christos abfd->has_armap = false; 6138 1.1 christos return true; 6139 1.1 christos } 6140 1.1 christos 6141 1.1 christos /* Read in and sanity check the archive header. */ 6142 1.11 christos amt = sizeof (struct ar_hdr); 6143 1.10 christos if (bfd_read (&ar_header, amt, abfd) != amt) 6144 1.1 christos return false; 6145 1.1 christos 6146 1.1 christos if (strncmp (ar_header.ar_fmag, ARFMAG, 2)) 6147 1.1 christos { 6148 1.10 christos bfd_set_error (bfd_error_malformed_archive); 6149 1.1 christos return false; 6150 1.1 christos } 6151 1.1 christos 6152 1.1 christos /* How big is the archive symbol table entry? */ 6153 1.1 christos errno = 0; 6154 1.1 christos parsed_size = strtol (ar_header.ar_size, NULL, 10); 6155 1.1 christos if (errno != 0) 6156 1.1 christos { 6157 1.10 christos bfd_set_error (bfd_error_malformed_archive); 6158 1.1 christos return false; 6159 1.1 christos } 6160 1.1 christos 6161 1.1 christos /* Save off the file offset of the first real user data. */ 6162 1.1 christos ardata->first_file_filepos = bfd_tell (abfd) + parsed_size; 6163 1.1 christos 6164 1.1 christos /* Read in the library symbol table. We'll make heavy use of this 6165 1.1 christos in just a minute. */ 6166 1.11 christos amt = sizeof (struct som_external_lst_header); 6167 1.10 christos if (bfd_read (&ext_lst_header, amt, abfd) != amt) 6168 1.1 christos return false; 6169 1.1 christos 6170 1.1 christos som_swap_lst_header_in (&ext_lst_header, &lst_header); 6171 1.1 christos 6172 1.1 christos /* Sanity check. */ 6173 1.1 christos if (lst_header.a_magic != LIBMAGIC) 6174 1.1 christos { 6175 1.10 christos bfd_set_error (bfd_error_malformed_archive); 6176 1.1 christos return false; 6177 1.1 christos } 6178 1.1 christos 6179 1.1 christos /* Count the number of symbols in the library symbol table. */ 6180 1.10 christos if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)) 6181 1.1 christos return false; 6182 1.1 christos 6183 1.1 christos /* Get back to the start of the library symbol table. */ 6184 1.1 christos if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size 6185 1.8 christos + sizeof (struct som_external_lst_header)), 6186 1.10 christos SEEK_SET) != 0) 6187 1.1 christos return false; 6188 1.1 christos 6189 1.1 christos /* Initialize the cache and allocate space for the library symbols. */ 6190 1.9 christos ardata->cache = 0; 6191 1.9 christos if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt)) 6192 1.9 christos { 6193 1.10 christos bfd_set_error (bfd_error_file_too_big); 6194 1.9 christos return false; 6195 1.1 christos } 6196 1.1 christos ardata->symdefs = bfd_alloc (abfd, amt); 6197 1.10 christos if (!ardata->symdefs) 6198 1.1 christos return false; 6199 1.1 christos 6200 1.1 christos /* Now fill in the canonical archive symbols. */ 6201 1.10 christos if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)) 6202 1.1 christos return false; 6203 1.1 christos 6204 1.1 christos /* Seek back to the "first" file in the archive. Note the "first" 6205 1.1 christos file may be the extended name table. */ 6206 1.10 christos if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0) 6207 1.1 christos return false; 6208 1.1 christos 6209 1.10 christos /* Notify the generic archive code that we have a symbol map. */ 6210 1.10 christos abfd->has_armap = true; 6211 1.1 christos return true; 6212 1.1 christos } 6213 1.1 christos 6214 1.1 christos /* Begin preparing to write a SOM library symbol table. 6215 1.1 christos 6216 1.1 christos As part of the prep work we need to determine the number of symbols 6217 1.1 christos and the size of the associated string section. */ 6218 1.10 christos 6219 1.1 christos static bool 6220 1.1 christos som_bfd_prep_for_ar_write (bfd *abfd, 6221 1.1 christos unsigned int *num_syms, 6222 1.1 christos unsigned int *stringsize) 6223 1.1 christos { 6224 1.1 christos bfd *curr_bfd = abfd->archive_head; 6225 1.1 christos 6226 1.1 christos /* Some initialization. */ 6227 1.1 christos *num_syms = 0; 6228 1.1 christos *stringsize = 0; 6229 1.1 christos 6230 1.1 christos /* Iterate over each BFD within this archive. */ 6231 1.1 christos while (curr_bfd != NULL) 6232 1.1 christos { 6233 1.1 christos unsigned int curr_count, i; 6234 1.1 christos som_symbol_type *sym; 6235 1.1 christos 6236 1.1 christos /* Don't bother for non-SOM objects. */ 6237 1.1 christos if (curr_bfd->format != bfd_object 6238 1.1 christos || curr_bfd->xvec->flavour != bfd_target_som_flavour) 6239 1.1 christos { 6240 1.1 christos curr_bfd = curr_bfd->archive_next; 6241 1.1 christos continue; 6242 1.1 christos } 6243 1.1 christos 6244 1.1 christos /* Make sure the symbol table has been read, then snag a pointer 6245 1.1 christos to it. It's a little slimey to grab the symbols via obj_som_symtab, 6246 1.1 christos but doing so avoids allocating lots of extra memory. */ 6247 1.10 christos if (! som_slurp_symbol_table (curr_bfd)) 6248 1.1 christos return false; 6249 1.1 christos 6250 1.1 christos sym = obj_som_symtab (curr_bfd); 6251 1.1 christos curr_count = bfd_get_symcount (curr_bfd); 6252 1.1 christos 6253 1.1 christos /* Examine each symbol to determine if it belongs in the 6254 1.1 christos library symbol table. */ 6255 1.1 christos for (i = 0; i < curr_count; i++, sym++) 6256 1.1 christos { 6257 1.1 christos struct som_misc_symbol_info info; 6258 1.1 christos 6259 1.1 christos /* Derive SOM information from the BFD symbol. */ 6260 1.1 christos som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info); 6261 1.1 christos 6262 1.1 christos /* Should we include this symbol? */ 6263 1.1 christos if (info.symbol_type == ST_NULL 6264 1.1 christos || info.symbol_type == ST_SYM_EXT 6265 1.1 christos || info.symbol_type == ST_ARG_EXT) 6266 1.1 christos continue; 6267 1.1 christos 6268 1.1 christos /* Only global symbols and unsatisfied commons. */ 6269 1.1 christos if (info.symbol_scope != SS_UNIVERSAL 6270 1.1 christos && info.symbol_type != ST_STORAGE) 6271 1.1 christos continue; 6272 1.1 christos 6273 1.1 christos /* Do no include undefined symbols. */ 6274 1.1 christos if (bfd_is_und_section (sym->symbol.section)) 6275 1.1 christos continue; 6276 1.1 christos 6277 1.1 christos /* Bump the various counters, being careful to honor 6278 1.1 christos alignment considerations in the string table. */ 6279 1.1 christos (*num_syms)++; 6280 1.1 christos *stringsize += strlen (sym->symbol.name) + 5; 6281 1.1 christos while (*stringsize % 4) 6282 1.1 christos (*stringsize)++; 6283 1.1 christos } 6284 1.1 christos 6285 1.1 christos curr_bfd = curr_bfd->archive_next; 6286 1.10 christos } 6287 1.1 christos return true; 6288 1.1 christos } 6289 1.1 christos 6290 1.1 christos /* Hash a symbol name based on the hashing algorithm presented in the 6291 1.1 christos SOM ABI. */ 6292 1.1 christos 6293 1.1 christos static unsigned int 6294 1.1 christos som_bfd_ar_symbol_hash (asymbol *symbol) 6295 1.1 christos { 6296 1.1 christos unsigned int len = strlen (symbol->name); 6297 1.1 christos 6298 1.1 christos /* Names with length 1 are special. */ 6299 1.1 christos if (len == 1) 6300 1.1 christos return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0]; 6301 1.1 christos 6302 1.1 christos return ((len & 0x7f) << 24) | (symbol->name[1] << 16) 6303 1.1 christos | (symbol->name[len - 2] << 8) | symbol->name[len - 1]; 6304 1.1 christos } 6305 1.1 christos 6306 1.1 christos /* Do the bulk of the work required to write the SOM library 6307 1.1 christos symbol table. */ 6308 1.10 christos 6309 1.1 christos static bool 6310 1.1 christos som_bfd_ar_write_symbol_stuff (bfd *abfd, 6311 1.1 christos unsigned int nsyms, 6312 1.1 christos unsigned int string_size, 6313 1.1 christos struct som_external_lst_header lst, 6314 1.1 christos unsigned elength) 6315 1.1 christos { 6316 1.1 christos char *strings = NULL, *p; 6317 1.1 christos struct som_external_lst_symbol_record *lst_syms = NULL, *curr_lst_sym; 6318 1.1 christos bfd *curr_bfd; 6319 1.1 christos unsigned char *hash_table = NULL; 6320 1.1 christos struct som_external_som_entry *som_dict = NULL; 6321 1.1 christos struct som_external_lst_symbol_record **last_hash_entry = NULL; 6322 1.9 christos unsigned int curr_som_offset, som_index = 0; 6323 1.1 christos size_t amt; 6324 1.1 christos unsigned int module_count; 6325 1.1 christos unsigned int hash_size; 6326 1.1 christos 6327 1.9 christos hash_size = bfd_getb32 (lst.hash_size); 6328 1.9 christos if (_bfd_mul_overflow (hash_size, 4, &amt)) 6329 1.9 christos { 6330 1.10 christos bfd_set_error (bfd_error_no_memory); 6331 1.9 christos return false; 6332 1.1 christos } 6333 1.1 christos hash_table = bfd_zmalloc (amt); 6334 1.1 christos if (hash_table == NULL && hash_size != 0) 6335 1.1 christos goto error_return; 6336 1.1 christos 6337 1.9 christos module_count = bfd_getb32 (lst.module_count); 6338 1.9 christos if (_bfd_mul_overflow (module_count, 6339 1.9 christos sizeof (struct som_external_som_entry), &amt)) 6340 1.9 christos { 6341 1.9 christos bfd_set_error (bfd_error_no_memory); 6342 1.9 christos goto error_return; 6343 1.1 christos } 6344 1.1 christos som_dict = bfd_zmalloc (amt); 6345 1.1 christos if (som_dict == NULL && module_count != 0) 6346 1.1 christos goto error_return; 6347 1.9 christos 6348 1.9 christos if (_bfd_mul_overflow (hash_size, 6349 1.9 christos sizeof (struct som_external_lst_symbol_record *), 6350 1.9 christos &amt)) 6351 1.9 christos { 6352 1.9 christos bfd_set_error (bfd_error_no_memory); 6353 1.9 christos goto error_return; 6354 1.1 christos } 6355 1.1 christos last_hash_entry = bfd_zmalloc (amt); 6356 1.1 christos if (last_hash_entry == NULL && hash_size != 0) 6357 1.1 christos goto error_return; 6358 1.1 christos 6359 1.1 christos /* Symbols have som_index fields, so we have to keep track of the 6360 1.1 christos index of each SOM in the archive. 6361 1.1 christos 6362 1.1 christos The SOM dictionary has (among other things) the absolute file 6363 1.1 christos position for the SOM which a particular dictionary entry 6364 1.1 christos describes. We have to compute that information as we iterate 6365 1.1 christos through the SOMs/symbols. */ 6366 1.1 christos som_index = 0; 6367 1.1 christos 6368 1.1 christos /* We add in the size of the archive header twice as the location 6369 1.1 christos in the SOM dictionary is the actual offset of the SOM, not the 6370 1.1 christos archive header before the SOM. */ 6371 1.1 christos curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + bfd_getb32 (lst.file_end); 6372 1.1 christos 6373 1.1 christos /* Make room for the archive header and the contents of the 6374 1.1 christos extended string table. Note that elength includes the size 6375 1.1 christos of the archive header for the extended name table! */ 6376 1.1 christos if (elength) 6377 1.1 christos curr_som_offset += elength; 6378 1.1 christos 6379 1.1 christos /* Make sure we're properly aligned. */ 6380 1.1 christos curr_som_offset = (curr_som_offset + 0x1) & ~0x1; 6381 1.1 christos 6382 1.9 christos /* FIXME should be done with buffers just like everything else... */ 6383 1.9 christos if (_bfd_mul_overflow (nsyms, 6384 1.9 christos sizeof (struct som_external_lst_symbol_record), &amt)) 6385 1.9 christos { 6386 1.9 christos bfd_set_error (bfd_error_no_memory); 6387 1.9 christos goto error_return; 6388 1.1 christos } 6389 1.1 christos lst_syms = bfd_malloc (amt); 6390 1.1 christos if (lst_syms == NULL && nsyms != 0) 6391 1.9 christos goto error_return; 6392 1.1 christos strings = bfd_malloc (string_size); 6393 1.1 christos if (strings == NULL && string_size != 0) 6394 1.1 christos goto error_return; 6395 1.1 christos 6396 1.1 christos p = strings; 6397 1.1 christos curr_lst_sym = lst_syms; 6398 1.1 christos 6399 1.1 christos curr_bfd = abfd->archive_head; 6400 1.1 christos while (curr_bfd != NULL) 6401 1.1 christos { 6402 1.1 christos unsigned int curr_count, i; 6403 1.1 christos som_symbol_type *sym; 6404 1.1 christos 6405 1.1 christos /* Don't bother for non-SOM objects. */ 6406 1.1 christos if (curr_bfd->format != bfd_object 6407 1.1 christos || curr_bfd->xvec->flavour != bfd_target_som_flavour) 6408 1.1 christos { 6409 1.1 christos curr_bfd = curr_bfd->archive_next; 6410 1.1 christos continue; 6411 1.1 christos } 6412 1.1 christos 6413 1.1 christos /* Make sure the symbol table has been read, then snag a pointer 6414 1.1 christos to it. It's a little slimey to grab the symbols via obj_som_symtab, 6415 1.1 christos but doing so avoids allocating lots of extra memory. */ 6416 1.1 christos if (! som_slurp_symbol_table (curr_bfd)) 6417 1.1 christos goto error_return; 6418 1.1 christos 6419 1.1 christos sym = obj_som_symtab (curr_bfd); 6420 1.1 christos curr_count = bfd_get_symcount (curr_bfd); 6421 1.1 christos 6422 1.1 christos for (i = 0; i < curr_count; i++, sym++) 6423 1.1 christos { 6424 1.8 christos struct som_misc_symbol_info info; 6425 1.8 christos struct som_external_lst_symbol_record *last; 6426 1.8 christos unsigned int symbol_pos; 6427 1.8 christos unsigned int slen; 6428 1.8 christos unsigned int symbol_key; 6429 1.1 christos unsigned int flags; 6430 1.1 christos 6431 1.1 christos /* Derive SOM information from the BFD symbol. */ 6432 1.1 christos som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info); 6433 1.1 christos 6434 1.1 christos /* Should we include this symbol? */ 6435 1.1 christos if (info.symbol_type == ST_NULL 6436 1.1 christos || info.symbol_type == ST_SYM_EXT 6437 1.1 christos || info.symbol_type == ST_ARG_EXT) 6438 1.1 christos continue; 6439 1.1 christos 6440 1.1 christos /* Only global symbols and unsatisfied commons. */ 6441 1.1 christos if (info.symbol_scope != SS_UNIVERSAL 6442 1.1 christos && info.symbol_type != ST_STORAGE) 6443 1.1 christos continue; 6444 1.1 christos 6445 1.1 christos /* Do no include undefined symbols. */ 6446 1.1 christos if (bfd_is_und_section (sym->symbol.section)) 6447 1.1 christos continue; 6448 1.1 christos 6449 1.1 christos /* If this is the first symbol from this SOM, then update 6450 1.1 christos the SOM dictionary too. */ 6451 1.1 christos if (bfd_getb32 (som_dict[som_index].location) == 0) 6452 1.1 christos { 6453 1.1 christos bfd_putb32 (curr_som_offset, som_dict[som_index].location); 6454 1.1 christos bfd_putb32 (arelt_size (curr_bfd), som_dict[som_index].length); 6455 1.1 christos } 6456 1.8 christos 6457 1.1 christos symbol_key = som_bfd_ar_symbol_hash (&sym->symbol); 6458 1.1 christos 6459 1.8 christos /* Fill in the lst symbol record. */ 6460 1.8 christos flags = 0; 6461 1.8 christos if (info.secondary_def) 6462 1.8 christos flags |= LST_SYMBOL_SECONDARY_DEF; 6463 1.8 christos flags |= info.symbol_type << LST_SYMBOL_SYMBOL_TYPE_SH; 6464 1.8 christos flags |= info.symbol_scope << LST_SYMBOL_SYMBOL_SCOPE_SH; 6465 1.8 christos if (bfd_is_com_section (sym->symbol.section)) 6466 1.8 christos flags |= LST_SYMBOL_IS_COMMON; 6467 1.8 christos if (info.dup_common) 6468 1.8 christos flags |= LST_SYMBOL_DUP_COMMON; 6469 1.8 christos flags |= 3 << LST_SYMBOL_XLEAST_SH; 6470 1.8 christos flags |= info.arg_reloc << LST_SYMBOL_ARG_RELOC_SH; 6471 1.8 christos bfd_putb32 (flags, curr_lst_sym->flags); 6472 1.8 christos bfd_putb32 (p - strings + 4, curr_lst_sym->name); 6473 1.8 christos bfd_putb32 (0, curr_lst_sym->qualifier_name); 6474 1.8 christos bfd_putb32 (info.symbol_info, curr_lst_sym->symbol_info); 6475 1.8 christos bfd_putb32 (info.symbol_value | info.priv_level, 6476 1.8 christos curr_lst_sym->symbol_value); 6477 1.8 christos bfd_putb32 (0, curr_lst_sym->symbol_descriptor); 6478 1.8 christos curr_lst_sym->reserved = 0; 6479 1.8 christos bfd_putb32 (som_index, curr_lst_sym->som_index); 6480 1.8 christos bfd_putb32 (symbol_key, curr_lst_sym->symbol_key); 6481 1.1 christos bfd_putb32 (0, curr_lst_sym->next_entry); 6482 1.1 christos 6483 1.8 christos /* Insert into the hash table. */ 6484 1.8 christos symbol_pos = 6485 1.8 christos (curr_lst_sym - lst_syms) 6486 1.8 christos * sizeof (struct som_external_lst_symbol_record) 6487 1.8 christos + hash_size * 4 6488 1.8 christos + module_count * sizeof (struct som_external_som_entry) 6489 1.8 christos + sizeof (struct som_external_lst_header); 6490 1.1 christos last = last_hash_entry[symbol_key % hash_size]; 6491 1.1 christos if (last != NULL) 6492 1.1 christos { 6493 1.1 christos /* There is already something at the head of this hash chain, 6494 1.1 christos so tack this symbol onto the end of the chain. */ 6495 1.1 christos bfd_putb32 (symbol_pos, last->next_entry); 6496 1.1 christos } 6497 1.1 christos else 6498 1.8 christos /* First entry in this hash chain. */ 6499 1.1 christos bfd_putb32 (symbol_pos, hash_table + 4 * (symbol_key % hash_size)); 6500 1.1 christos 6501 1.1 christos /* Keep track of the last symbol we added to this chain so we can 6502 1.8 christos easily update its next_entry pointer. */ 6503 1.1 christos last_hash_entry[symbol_key % hash_size] = curr_lst_sym; 6504 1.1 christos 6505 1.8 christos /* Update the string table. */ 6506 1.1 christos slen = strlen (sym->symbol.name); 6507 1.1 christos bfd_put_32 (abfd, slen, p); 6508 1.8 christos p += 4; 6509 1.1 christos slen++; /* Nul terminator. */ 6510 1.1 christos memcpy (p, sym->symbol.name, slen); 6511 1.1 christos p += slen; 6512 1.1 christos while (slen % 4) 6513 1.1 christos { 6514 1.1 christos bfd_put_8 (abfd, 0, p); 6515 1.8 christos p++; 6516 1.1 christos slen++; 6517 1.8 christos } 6518 1.1 christos BFD_ASSERT (p <= strings + string_size); 6519 1.1 christos 6520 1.1 christos /* Head to the next symbol. */ 6521 1.1 christos curr_lst_sym++; 6522 1.1 christos } 6523 1.1 christos 6524 1.1 christos /* Keep track of where each SOM will finally reside; then look 6525 1.1 christos at the next BFD. */ 6526 1.1 christos curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr); 6527 1.1 christos 6528 1.1 christos /* A particular object in the archive may have an odd length; the 6529 1.1 christos linker requires objects begin on an even boundary. So round 6530 1.1 christos up the current offset as necessary. */ 6531 1.1 christos curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1; 6532 1.1 christos curr_bfd = curr_bfd->archive_next; 6533 1.1 christos som_index++; 6534 1.1 christos } 6535 1.1 christos 6536 1.9 christos /* Now scribble out the hash table. */ 6537 1.11 christos amt = (size_t) hash_size * 4; 6538 1.1 christos if (bfd_write (hash_table, amt, abfd) != amt) 6539 1.1 christos goto error_return; 6540 1.1 christos 6541 1.9 christos /* Then the SOM dictionary. */ 6542 1.11 christos amt = (size_t) module_count * sizeof (struct som_external_som_entry); 6543 1.1 christos if (bfd_write (som_dict, amt, abfd) != amt) 6544 1.1 christos goto error_return; 6545 1.1 christos 6546 1.9 christos /* The library symbols. */ 6547 1.11 christos amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record); 6548 1.1 christos if (bfd_write (lst_syms, amt, abfd) != amt) 6549 1.1 christos goto error_return; 6550 1.1 christos 6551 1.1 christos /* And finally the strings. */ 6552 1.11 christos amt = string_size; 6553 1.1 christos if (bfd_write (strings, amt, abfd) != amt) 6554 1.1 christos goto error_return; 6555 1.9 christos 6556 1.9 christos free (hash_table); 6557 1.9 christos free (som_dict); 6558 1.9 christos free (last_hash_entry); 6559 1.9 christos free (lst_syms); 6560 1.10 christos free (strings); 6561 1.1 christos return true; 6562 1.1 christos 6563 1.9 christos error_return: 6564 1.9 christos free (hash_table); 6565 1.9 christos free (som_dict); 6566 1.9 christos free (last_hash_entry); 6567 1.9 christos free (lst_syms); 6568 1.1 christos free (strings); 6569 1.10 christos 6570 1.1 christos return false; 6571 1.1 christos } 6572 1.1 christos 6573 1.1 christos /* Write out the LST for the archive. 6574 1.1 christos 6575 1.1 christos You'll never believe this is really how armaps are handled in SOM... */ 6576 1.10 christos 6577 1.1 christos static bool 6578 1.1 christos som_write_armap (bfd *abfd, 6579 1.1 christos unsigned int elength, 6580 1.1 christos struct orl *map ATTRIBUTE_UNUSED, 6581 1.1 christos unsigned int orl_count ATTRIBUTE_UNUSED, 6582 1.1 christos int stridx ATTRIBUTE_UNUSED) 6583 1.1 christos { 6584 1.1 christos bfd *curr_bfd; 6585 1.1 christos struct stat statbuf; 6586 1.1 christos unsigned int i, lst_size, nsyms, stringsize; 6587 1.1 christos struct ar_hdr hdr; 6588 1.1 christos struct som_external_lst_header lst; 6589 1.9 christos unsigned char *p; 6590 1.1 christos size_t amt; 6591 1.1 christos unsigned int csum; 6592 1.1 christos unsigned int module_count; 6593 1.1 christos 6594 1.9 christos /* We'll use this for the archive's date and mode later. */ 6595 1.1 christos if (stat (bfd_get_filename (abfd), &statbuf) != 0) 6596 1.1 christos { 6597 1.10 christos bfd_set_error (bfd_error_system_call); 6598 1.1 christos return false; 6599 1.1 christos } 6600 1.1 christos /* Fudge factor. */ 6601 1.1 christos bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60; 6602 1.1 christos 6603 1.1 christos /* Account for the lst header first. */ 6604 1.1 christos lst_size = sizeof (struct som_external_lst_header); 6605 1.1 christos 6606 1.1 christos /* Start building the LST header. */ 6607 1.1 christos /* FIXME: Do we need to examine each element to determine the 6608 1.1 christos largest id number? */ 6609 1.1 christos bfd_putb16 (CPU_PA_RISC1_0, &lst.system_id); 6610 1.1 christos bfd_putb16 (LIBMAGIC, &lst.a_magic); 6611 1.1 christos bfd_putb32 (VERSION_ID, &lst.version_id); 6612 1.1 christos bfd_putb32 (0, &lst.file_time.secs); 6613 1.1 christos bfd_putb32 (0, &lst.file_time.nanosecs); 6614 1.1 christos 6615 1.1 christos bfd_putb32 (lst_size, &lst.hash_loc); 6616 1.1 christos bfd_putb32 (SOM_LST_HASH_SIZE, &lst.hash_size); 6617 1.1 christos 6618 1.1 christos /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets. */ 6619 1.1 christos lst_size += 4 * SOM_LST_HASH_SIZE; 6620 1.1 christos 6621 1.1 christos /* We need to count the number of SOMs in this archive. */ 6622 1.1 christos curr_bfd = abfd->archive_head; 6623 1.1 christos module_count = 0; 6624 1.1 christos while (curr_bfd != NULL) 6625 1.1 christos { 6626 1.1 christos /* Only true SOM objects count. */ 6627 1.1 christos if (curr_bfd->format == bfd_object 6628 1.1 christos && curr_bfd->xvec->flavour == bfd_target_som_flavour) 6629 1.1 christos module_count++; 6630 1.1 christos curr_bfd = curr_bfd->archive_next; 6631 1.1 christos } 6632 1.1 christos bfd_putb32 (module_count, &lst.module_count); 6633 1.1 christos bfd_putb32 (module_count, &lst.module_limit); 6634 1.1 christos bfd_putb32 (lst_size, &lst.dir_loc); 6635 1.1 christos lst_size += sizeof (struct som_external_som_entry) * module_count; 6636 1.1 christos 6637 1.1 christos /* We don't support import/export tables, auxiliary headers, 6638 1.1 christos or free lists yet. Make the linker work a little harder 6639 1.1 christos to make our life easier. */ 6640 1.1 christos 6641 1.1 christos bfd_putb32 (0, &lst.export_loc); 6642 1.1 christos bfd_putb32 (0, &lst.export_count); 6643 1.1 christos bfd_putb32 (0, &lst.import_loc); 6644 1.1 christos bfd_putb32 (0, &lst.aux_loc); 6645 1.1 christos bfd_putb32 (0, &lst.aux_size); 6646 1.1 christos 6647 1.1 christos /* Count how many symbols we will have on the hash chains and the 6648 1.1 christos size of the associated string table. */ 6649 1.10 christos if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize)) 6650 1.1 christos return false; 6651 1.1 christos 6652 1.1 christos lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms; 6653 1.1 christos 6654 1.1 christos /* For the string table. One day we might actually use this info 6655 1.1 christos to avoid small seeks/reads when reading archives. */ 6656 1.1 christos bfd_putb32 (lst_size, &lst.string_loc); 6657 1.1 christos bfd_putb32 (stringsize, &lst.string_size); 6658 1.1 christos lst_size += stringsize; 6659 1.1 christos 6660 1.1 christos /* SOM ABI says this must be zero. */ 6661 1.1 christos bfd_putb32 (0, &lst.free_list); 6662 1.1 christos bfd_putb32 (lst_size, &lst.file_end); 6663 1.1 christos 6664 1.1 christos /* Compute the checksum. Must happen after the entire lst header 6665 1.1 christos has filled in. */ 6666 1.1 christos p = (unsigned char *) &lst; 6667 1.1 christos csum = 0; 6668 1.1 christos for (i = 0; i < sizeof (struct som_external_lst_header) - sizeof (int); 6669 1.1 christos i += 4) 6670 1.1 christos csum ^= bfd_getb32 (&p[i]); 6671 1.1 christos bfd_putb32 (csum, &lst.checksum); 6672 1.1 christos 6673 1.1 christos sprintf (hdr.ar_name, "/ "); 6674 1.8 christos _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%-12ld", 6675 1.1 christos bfd_ardata (abfd)->armap_timestamp); 6676 1.8 christos _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 6677 1.1 christos statbuf.st_uid); 6678 1.8 christos _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 6679 1.1 christos statbuf.st_gid); 6680 1.8 christos _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-8o", 6681 1.1 christos (unsigned int)statbuf.st_mode); 6682 1.8 christos _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10d", 6683 1.1 christos (int) lst_size); 6684 1.1 christos hdr.ar_fmag[0] = '`'; 6685 1.1 christos hdr.ar_fmag[1] = '\012'; 6686 1.1 christos 6687 1.1 christos /* Turn any nulls into spaces. */ 6688 1.1 christos for (i = 0; i < sizeof (struct ar_hdr); i++) 6689 1.1 christos if (((char *) (&hdr))[i] == '\0') 6690 1.1 christos (((char *) (&hdr))[i]) = ' '; 6691 1.1 christos 6692 1.1 christos /* Scribble out the ar header. */ 6693 1.11 christos amt = sizeof (struct ar_hdr); 6694 1.10 christos if (bfd_write (&hdr, amt, abfd) != amt) 6695 1.1 christos return false; 6696 1.1 christos 6697 1.1 christos /* Now scribble out the lst header. */ 6698 1.11 christos amt = sizeof (struct som_external_lst_header); 6699 1.10 christos if (bfd_write (&lst, amt, abfd) != amt) 6700 1.1 christos return false; 6701 1.1 christos 6702 1.1 christos /* Build and write the armap. */ 6703 1.10 christos if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength)) 6704 1.1 christos return false; 6705 1.1 christos 6706 1.10 christos /* Done. */ 6707 1.1 christos return true; 6708 1.1 christos } 6709 1.11 christos 6710 1.1 christos /* Throw away some malloc'd information for this BFD. */ 6711 1.10 christos 6712 1.1 christos static bool 6713 1.1 christos som_bfd_free_cached_info (bfd *abfd) 6714 1.11 christos { 6715 1.11 christos if (bfd_get_format (abfd) == bfd_object 6716 1.9 christos || bfd_get_format (abfd) == bfd_core) 6717 1.9 christos { 6718 1.1 christos asection *o; 6719 1.9 christos 6720 1.9 christos #define FREE(x) do { free (x); x = NULL; } while (0) 6721 1.9 christos /* Free the native string and symbol tables. */ 6722 1.9 christos FREE (obj_som_symtab (abfd)); 6723 1.9 christos FREE (obj_som_stringtab (abfd)); 6724 1.9 christos for (o = abfd->sections; o != NULL; o = o->next) 6725 1.9 christos { 6726 1.9 christos /* Free the native relocations. */ 6727 1.9 christos o->reloc_count = (unsigned) -1; 6728 1.9 christos FREE (som_section_data (o)->reloc_stream); 6729 1.9 christos /* Do not free the generic relocations as they are objalloc'ed. */ 6730 1.9 christos } 6731 1.1 christos #undef FREE 6732 1.1 christos } 6733 1.11 christos 6734 1.11 christos /* Do not call _bfd_generic_bfd_free_cached_info here. 6735 1.11 christos som_write_armap needs to access the bfd objalloc memory. */ 6736 1.1 christos return true; 6737 1.1 christos } 6738 1.1 christos 6739 1.1 christos /* End of miscellaneous support functions. */ 6740 1.1 christos 6741 1.1 christos /* Linker support functions. */ 6742 1.10 christos 6743 1.1 christos static bool 6744 1.1 christos som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) 6745 1.1 christos { 6746 1.1 christos return som_is_subspace (sec) && sec->size > 240000; 6747 1.1 christos } 6748 1.8 christos 6749 1.3 christos #define som_find_line _bfd_nosymbols_find_line 6750 1.11 christos #define som_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string 6751 1.8 christos #define som_close_and_cleanup _bfd_generic_close_and_cleanup 6752 1.8 christos #define som_read_ar_hdr _bfd_generic_read_ar_hdr 6753 1.8 christos #define som_write_ar_hdr _bfd_generic_write_ar_hdr 6754 1.8 christos #define som_openr_next_archived_file bfd_generic_openr_next_archived_file 6755 1.8 christos #define som_get_elt_at_index _bfd_generic_get_elt_at_index 6756 1.8 christos #define som_generic_stat_arch_elt bfd_generic_stat_arch_elt 6757 1.8 christos #define som_truncate_arname bfd_bsd_truncate_arname 6758 1.8 christos #define som_slurp_extended_name_table _bfd_slurp_extended_name_table 6759 1.8 christos #define som_construct_extended_name_table _bfd_archive_coff_construct_extended_name_table 6760 1.8 christos #define som_update_armap_timestamp _bfd_bool_bfd_true 6761 1.8 christos #define som_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false 6762 1.8 christos #define som_get_lineno _bfd_nosymbols_get_lineno 6763 1.8 christos #define som_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 6764 1.8 christos #define som_read_minisymbols _bfd_generic_read_minisymbols 6765 1.8 christos #define som_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 6766 1.8 christos #define som_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 6767 1.8 christos #define som_bfd_relax_section bfd_generic_relax_section 6768 1.8 christos #define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 6769 1.8 christos #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols 6770 1.1 christos #define som_bfd_link_just_syms _bfd_generic_link_just_syms 6771 1.1 christos #define som_bfd_copy_link_hash_symbol_type \ 6772 1.8 christos _bfd_generic_copy_link_hash_symbol_type 6773 1.8 christos #define som_bfd_final_link _bfd_generic_final_link 6774 1.8 christos #define som_bfd_gc_sections bfd_generic_gc_sections 6775 1.8 christos #define som_bfd_lookup_section_flags bfd_generic_lookup_section_flags 6776 1.8 christos #define som_bfd_merge_sections bfd_generic_merge_sections 6777 1.9 christos #define som_bfd_is_group_section bfd_generic_is_group_section 6778 1.8 christos #define som_bfd_group_name bfd_generic_group_name 6779 1.8 christos #define som_bfd_discard_group bfd_generic_discard_group 6780 1.8 christos #define som_section_already_linked _bfd_generic_section_already_linked 6781 1.8 christos #define som_bfd_define_common_symbol bfd_generic_define_common_symbol 6782 1.8 christos #define som_bfd_link_hide_symbol _bfd_generic_link_hide_symbol 6783 1.1 christos #define som_bfd_define_start_stop bfd_generic_define_start_stop 6784 1.11 christos #define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data 6785 1.1 christos #define som_init_private_section_data _bfd_generic_init_private_section_data 6786 1.1 christos #define som_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data 6787 1.1 christos #define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flags 6788 1.8 christos #define som_find_inliner_info _bfd_nosymbols_find_inliner_info 6789 1.8 christos #define som_bfd_link_check_relocs _bfd_generic_link_check_relocs 6790 1.1 christos #define som_set_reloc _bfd_generic_set_reloc 6791 1.3 christos 6792 1.1 christos const bfd_target hppa_som_vec = 6793 1.1 christos { 6794 1.1 christos "som", /* Name. */ 6795 1.1 christos bfd_target_som_flavour, 6796 1.1 christos BFD_ENDIAN_BIG, /* Target byte order. */ 6797 1.1 christos BFD_ENDIAN_BIG, /* Target headers byte order. */ 6798 1.1 christos (HAS_RELOC | EXEC_P | /* Object flags. */ 6799 1.1 christos HAS_LINENO | HAS_DEBUG | 6800 1.1 christos HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC), 6801 1.1 christos (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE 6802 1.1 christos | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */ 6803 1.1 christos 6804 1.1 christos /* Leading_symbol_char: is the first char of a user symbol 6805 1.1 christos predictable, and if so what is it. */ 6806 1.1 christos 0, 6807 1.1 christos '/', /* AR_pad_char. */ 6808 1.1 christos 14, /* AR_max_namelen. */ 6809 1.10 christos 0, /* match priority. */ 6810 1.1 christos TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 6811 1.1 christos bfd_getb64, bfd_getb_signed_64, bfd_putb64, 6812 1.1 christos bfd_getb32, bfd_getb_signed_32, bfd_putb32, 6813 1.1 christos bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 6814 1.1 christos bfd_getb64, bfd_getb_signed_64, bfd_putb64, 6815 1.1 christos bfd_getb32, bfd_getb_signed_32, bfd_putb32, 6816 1.1 christos bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 6817 1.1 christos {_bfd_dummy_target, 6818 1.1 christos som_object_p, /* bfd_check_format. */ 6819 1.1 christos bfd_generic_archive_p, 6820 1.1 christos _bfd_dummy_target 6821 1.1 christos }, 6822 1.8 christos { 6823 1.1 christos _bfd_bool_bfd_false_error, 6824 1.1 christos som_mkobject, 6825 1.8 christos _bfd_generic_mkarchive, 6826 1.1 christos _bfd_bool_bfd_false_error 6827 1.1 christos }, 6828 1.8 christos { 6829 1.1 christos _bfd_bool_bfd_false_error, 6830 1.1 christos som_write_object_contents, 6831 1.8 christos _bfd_write_archive_contents, 6832 1.1 christos _bfd_bool_bfd_false_error, 6833 1.1 christos }, 6834 1.1 christos #undef som 6835 1.1 christos 6836 1.1 christos BFD_JUMP_TABLE_GENERIC (som), 6837 1.1 christos BFD_JUMP_TABLE_COPY (som), 6838 1.1 christos BFD_JUMP_TABLE_CORE (_bfd_nocore), 6839 1.1 christos BFD_JUMP_TABLE_ARCHIVE (som), 6840 1.1 christos BFD_JUMP_TABLE_SYMBOLS (som), 6841 1.1 christos BFD_JUMP_TABLE_RELOCS (som), 6842 1.1 christos BFD_JUMP_TABLE_WRITE (som), 6843 1.1 christos BFD_JUMP_TABLE_LINK (som), 6844 1.1 christos BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 6845 1.1 christos 6846 1.1 christos NULL, 6847 1.1 christos 6848 1.1 christos NULL 6849 1.1 christos }; 6850 6851