1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module) 2 Copyright 1993, 1994, 2000, 2001, 2002, 2003 3 Free Software Foundation, Inc. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 20 21 #include "bfd.h" 22 #include "sysdep.h" 23 #include "libbfd.h" 24 25 #define ARCH_SIZE 32 26 27 #include "nlm/sparc32-ext.h" 28 #define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header 29 30 #include "libnlm.h" 31 32 static bfd_boolean nlm_sparc_read_reloc 33 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); 34 static bfd_boolean nlm_sparc_write_reloc 35 PARAMS ((bfd *, asection *, arelent *)); 36 static bfd_boolean nlm_sparc_mangle_relocs 37 PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type)); 38 static bfd_boolean nlm_sparc_read_import 39 PARAMS ((bfd *, nlmNAME(symbol_type) *)); 40 static bfd_boolean nlm_sparc_write_import 41 PARAMS ((bfd *, asection *, arelent *)); 42 static bfd_boolean nlm_sparc_write_external 43 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); 44 static bfd_boolean nlm_sparc_write_export 45 PARAMS ((bfd *, asymbol *, bfd_vma)); 46 47 enum reloc_type 48 { 49 R_SPARC_NONE = 0, 50 R_SPARC_8, R_SPARC_16, R_SPARC_32, 51 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, 52 R_SPARC_WDISP30, R_SPARC_WDISP22, 53 R_SPARC_HI22, R_SPARC_22, 54 R_SPARC_13, R_SPARC_LO10, 55 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, 56 R_SPARC_PC10, R_SPARC_PC22, 57 R_SPARC_WPLT30, 58 R_SPARC_COPY, 59 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, 60 R_SPARC_RELATIVE, 61 R_SPARC_UA32, 62 R_SPARC_max 63 }; 64 65 #if 0 66 static const char *const reloc_type_names[] = 67 { 68 "R_SPARC_NONE", 69 "R_SPARC_8", "R_SPARC_16", "R_SPARC_32", 70 "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32", 71 "R_SPARC_WDISP30", "R_SPARC_WDISP22", 72 "R_SPARC_HI22", "R_SPARC_22", 73 "R_SPARC_13", "R_SPARC_LO10", 74 "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", 75 "R_SPARC_PC10", "R_SPARC_PC22", 76 "R_SPARC_WPLT30", 77 "R_SPARC_COPY", 78 "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", 79 "R_SPARC_RELATIVE", 80 "R_SPARC_UA32", 81 }; 82 #endif 83 84 static reloc_howto_type nlm32_sparc_howto_table[] = 85 { 86 HOWTO (R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, 0,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE), 87 HOWTO (R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8", FALSE,0,0x000000ff,TRUE), 88 HOWTO (R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE), 89 HOWTO (R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32", FALSE,0,0xffffffff,TRUE), 90 HOWTO (R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE), 91 HOWTO (R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE), 92 HOWTO (R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE), 93 HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE), 94 HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE), 95 HOWTO (R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, 0,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE), 96 HOWTO (R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22", FALSE,0,0x003fffff,TRUE), 97 HOWTO (R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13", FALSE,0,0x00001fff,TRUE), 98 HOWTO (R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, 0,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE), 99 HOWTO (R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE), 100 HOWTO (R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE), 101 HOWTO (R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE), 102 HOWTO (R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE), 103 HOWTO (R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE), 104 HOWTO (R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE), 105 HOWTO (R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE), 106 HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE), 107 HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE), 108 HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE), 109 HOWTO (R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE), 110 }; 111 112 /* Read a NetWare sparc reloc. */ 113 114 struct nlm32_sparc_reloc_ext 115 { 116 unsigned char offset[4]; 117 unsigned char addend[4]; 118 unsigned char type[1]; 119 unsigned char pad1[3]; 120 }; 121 122 static bfd_boolean 123 nlm_sparc_read_reloc (abfd, sym, secp, rel) 124 bfd *abfd; 125 nlmNAME(symbol_type) *sym ATTRIBUTE_UNUSED; 126 asection **secp; 127 arelent *rel; 128 { 129 bfd_vma val, addend; 130 unsigned int index; 131 unsigned int type; 132 struct nlm32_sparc_reloc_ext tmp_reloc; 133 asection *code_sec, *data_sec; 134 135 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12) 136 return FALSE; 137 138 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME); 139 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); 140 141 *secp = code_sec; 142 143 val = bfd_get_32 (abfd, tmp_reloc.offset); 144 addend = bfd_get_32 (abfd, tmp_reloc.addend); 145 type = bfd_get_8 (abfd, tmp_reloc.type); 146 147 rel->address = val; 148 rel->addend = addend; 149 rel->howto = NULL; 150 151 for (index = 0; 152 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type); 153 index++) 154 if (nlm32_sparc_howto_table[index].type == type) 155 { 156 rel->howto = &nlm32_sparc_howto_table[index]; 157 break; 158 } 159 160 #ifdef DEBUG 161 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n", 162 __FUNCTION__, rel->address, rel->addend, type, rel->howto); 163 #endif 164 return TRUE; 165 166 } 167 168 /* Write a NetWare sparc reloc. */ 169 170 static bfd_boolean 171 nlm_sparc_write_reloc (abfd, sec, rel) 172 bfd *abfd; 173 asection *sec; 174 arelent *rel; 175 { 176 bfd_vma val; 177 struct nlm32_sparc_reloc_ext tmp_reloc; 178 unsigned int index; 179 int type = -1; 180 reloc_howto_type *tmp; 181 182 for (index = 0; 183 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type); 184 index++) 185 { 186 tmp = &nlm32_sparc_howto_table[index]; 187 188 if (tmp->rightshift == rel->howto->rightshift 189 && tmp->size == rel->howto->size 190 && tmp->bitsize == rel->howto->bitsize 191 && tmp->pc_relative == rel->howto->pc_relative 192 && tmp->bitpos == rel->howto->bitpos 193 && tmp->src_mask == rel->howto->src_mask 194 && tmp->dst_mask == rel->howto->dst_mask) 195 { 196 type = tmp->type; 197 break; 198 } 199 } 200 if (type == -1) 201 abort (); 202 203 /* Netware wants a list of relocs for each address. 204 Format is: 205 long offset 206 long addend 207 char type 208 That should be it. */ 209 210 /* The value we write out is the offset into the appropriate 211 segment. This offset is the section vma, adjusted by the vma of 212 the lowest section in that segment, plus the address of the 213 relocation. */ 214 #if 0 215 val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address; 216 #else 217 val = bfd_get_section_vma (abfd, sec) + rel->address; 218 #endif 219 220 #ifdef DEBUG 221 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n", 222 __FUNCTION__, val, rel->addend, rel->howto->type); 223 #endif 224 bfd_put_32 (abfd, val, tmp_reloc.offset); 225 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend); 226 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type); 227 228 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12) 229 return FALSE; 230 231 return TRUE; 232 } 233 234 /* Mangle relocs for SPARC NetWare. We can just use the standard 235 SPARC relocs. */ 236 237 static bfd_boolean 238 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count) 239 bfd *abfd ATTRIBUTE_UNUSED; 240 asection *sec ATTRIBUTE_UNUSED; 241 const PTR data ATTRIBUTE_UNUSED; 242 bfd_vma offset ATTRIBUTE_UNUSED; 243 bfd_size_type count ATTRIBUTE_UNUSED; 244 { 245 return TRUE; 246 } 247 248 /* Read a NetWare sparc import record. */ 249 250 static bfd_boolean 251 nlm_sparc_read_import (abfd, sym) 252 bfd *abfd; 253 nlmNAME(symbol_type) *sym; 254 { 255 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */ 256 bfd_size_type rcount; /* Number of relocs. */ 257 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */ 258 unsigned char symlength; /* Length of symbol name. */ 259 char *name; 260 261 /* First, read in the number of relocation 262 entries for this symbol. */ 263 if (bfd_bread ((PTR) temp, (bfd_size_type) 4, abfd) != 4) 264 return FALSE; 265 266 rcount = bfd_get_32 (abfd, temp); 267 268 /* Next, read in the length of the symbol. */ 269 270 if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd) 271 != sizeof (symlength)) 272 return FALSE; 273 sym -> symbol.the_bfd = abfd; 274 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); 275 if (name == NULL) 276 return FALSE; 277 278 /* Then read in the symbol. */ 279 280 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) 281 return FALSE; 282 name[symlength] = '\0'; 283 sym -> symbol.name = name; 284 sym -> symbol.flags = 0; 285 sym -> symbol.value = 0; 286 sym -> symbol.section = bfd_und_section_ptr; 287 288 /* Next, start reading in the relocs. */ 289 290 nlm_relocs = ((struct nlm_relent *) 291 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); 292 if (!nlm_relocs) 293 return FALSE; 294 sym -> relocs = nlm_relocs; 295 sym -> rcnt = 0; 296 while (sym -> rcnt < rcount) 297 { 298 asection *section; 299 300 if (! nlm_sparc_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) 301 return FALSE; 302 nlm_relocs -> section = section; 303 nlm_relocs++; 304 sym -> rcnt++; 305 } 306 307 return TRUE; 308 } 309 310 static bfd_boolean 311 nlm_sparc_write_import (abfd, sec, rel) 312 bfd *abfd; 313 asection *sec; 314 arelent *rel; 315 { 316 char temp[4]; 317 asection *code, *data, *bss, *symsec; 318 bfd_vma base; 319 320 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME); 321 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); 322 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME); 323 symsec = (*rel->sym_ptr_ptr)->section; 324 325 if (symsec == code) 326 base = 0; 327 else if (symsec == data) 328 base = bfd_section_size (abfd, code); 329 else if (symsec == bss) 330 base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data); 331 else 332 base = 0; 333 334 #ifdef DEBUG 335 fprintf (stderr, "%s: <%x, 1>\n\t", 336 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value); 337 #endif 338 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp); 339 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4) 340 return FALSE; 341 bfd_put_32 (abfd, (bfd_vma) 1, temp); 342 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4) 343 return FALSE; 344 if (! nlm_sparc_write_reloc (abfd, sec, rel)) 345 return FALSE; 346 return TRUE; 347 } 348 349 /* Write out an external reference. */ 350 351 static bfd_boolean 352 nlm_sparc_write_external (abfd, count, sym, relocs) 353 bfd *abfd; 354 bfd_size_type count; 355 asymbol *sym; 356 struct reloc_and_sec *relocs; 357 { 358 unsigned int i; 359 bfd_byte len; 360 unsigned char temp[NLM_TARGET_LONG_SIZE]; 361 362 bfd_put_32 (abfd, count, temp); 363 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) 364 return FALSE; 365 366 len = strlen (sym->name); 367 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) 368 != sizeof (bfd_byte)) 369 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) 370 return FALSE; 371 372 for (i = 0; i < count; i++) 373 { 374 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel)) 375 return FALSE; 376 } 377 378 return TRUE; 379 } 380 381 static bfd_boolean 382 nlm_sparc_write_export (abfd, sym, value) 383 bfd *abfd; 384 asymbol *sym; 385 bfd_vma value; 386 { 387 bfd_byte len; 388 bfd_byte temp[4]; 389 390 #ifdef DEBUG 391 fprintf (stderr, "%s: <%x, %d, %s>\n", 392 __FUNCTION__, value, strlen (sym->name), sym->name); 393 #endif 394 bfd_put_32 (abfd, value, temp); 395 len = strlen (sym->name); 396 397 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4 398 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1 399 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) 400 return FALSE; 401 402 return TRUE; 403 } 404 405 #undef nlm_swap_fixed_header_in 406 #undef nlm_swap_fixed_header_out 407 408 #include "nlmswap.h" 409 410 static const struct nlm_backend_data nlm32_sparc_backend = 411 { 412 "NetWare SPARC Module \032", 413 sizeof (Nlm32_sparc_External_Fixed_Header), 414 0, /* optional_prefix_size */ 415 bfd_arch_sparc, 416 0, 417 FALSE, 418 0, /* backend_object_p */ 419 0, /* write_prefix_func */ 420 nlm_sparc_read_reloc, 421 nlm_sparc_mangle_relocs, 422 nlm_sparc_read_import, 423 nlm_sparc_write_import, 424 0, /* set_public_section */ 425 0, /* get_public_offset */ 426 nlm_swap_fixed_header_in, 427 nlm_swap_fixed_header_out, 428 nlm_sparc_write_external, 429 nlm_sparc_write_export 430 }; 431 432 #define TARGET_BIG_NAME "nlm32-sparc" 433 #define TARGET_BIG_SYM nlmNAME(sparc_vec) 434 #define TARGET_BACKEND_DATA & nlm32_sparc_backend 435 436 #include "nlm-target.h" 437