1/* Support for 32-bit SPARC NLM (NetWare Loadable Module) 2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 3 2007 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 3 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., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22#include "sysdep.h" 23#include "bfd.h" 24#include "libbfd.h" 25 26#define ARCH_SIZE 32 27 28#include "nlm/sparc32-ext.h" 29#define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header 30 31#include "libnlm.h" 32 33enum reloc_type 34{ 35 R_SPARC_NONE = 0, 36 R_SPARC_8, R_SPARC_16, R_SPARC_32, 37 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, 38 R_SPARC_WDISP30, R_SPARC_WDISP22, 39 R_SPARC_HI22, R_SPARC_22, 40 R_SPARC_13, R_SPARC_LO10, 41 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, 42 R_SPARC_PC10, R_SPARC_PC22, 43 R_SPARC_WPLT30, 44 R_SPARC_COPY, 45 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, 46 R_SPARC_RELATIVE, 47 R_SPARC_UA32, 48 R_SPARC_max 49}; 50 51static reloc_howto_type nlm32_sparc_howto_table[] = 52{ 53 HOWTO (R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, 0,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE), 54 HOWTO (R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8", FALSE,0,0x000000ff,TRUE), 55 HOWTO (R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE), 56 HOWTO (R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32", FALSE,0,0xffffffff,TRUE), 57 HOWTO (R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE), 58 HOWTO (R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE), 59 HOWTO (R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE), 60 HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE), 61 HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE), 62 HOWTO (R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, 0,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE), 63 HOWTO (R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22", FALSE,0,0x003fffff,TRUE), 64 HOWTO (R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13", FALSE,0,0x00001fff,TRUE), 65 HOWTO (R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, 0,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE), 66 HOWTO (R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE), 67 HOWTO (R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE), 68 HOWTO (R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE), 69 HOWTO (R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE), 70 HOWTO (R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE), 71 HOWTO (R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE), 72 HOWTO (R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE), 73 HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE), 74 HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE), 75 HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE), 76 HOWTO (R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE), 77}; 78 79/* Read a NetWare sparc reloc. */ 80 81struct nlm32_sparc_reloc_ext 82{ 83 unsigned char offset[4]; 84 unsigned char addend[4]; 85 unsigned char type[1]; 86 unsigned char pad1[3]; 87}; 88 89static bfd_boolean 90nlm_sparc_read_reloc (bfd *abfd, 91 nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED, 92 asection **secp, 93 arelent *rel) 94{ 95 bfd_vma val, addend; 96 unsigned int index; 97 unsigned int type; 98 struct nlm32_sparc_reloc_ext tmp_reloc; 99 asection *code_sec, *data_sec; 100 101 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12) 102 return FALSE; 103 104 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME); 105 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); 106 107 *secp = code_sec; 108 109 val = bfd_get_32 (abfd, tmp_reloc.offset); 110 addend = bfd_get_32 (abfd, tmp_reloc.addend); 111 type = bfd_get_8 (abfd, tmp_reloc.type); 112 113 rel->address = val; 114 rel->addend = addend; 115 rel->howto = NULL; 116 117 for (index = 0; 118 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type); 119 index++) 120 if (nlm32_sparc_howto_table[index].type == type) 121 { 122 rel->howto = &nlm32_sparc_howto_table[index]; 123 break; 124 } 125 126#ifdef DEBUG 127 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %u, howto = %p\n", 128 __FUNCTION__, (unsigned long) rel->address, 129 (unsigned long) rel->addend, type, rel->howto); 130#endif 131 return TRUE; 132 133} 134 135/* Write a NetWare sparc reloc. */ 136 137static bfd_boolean 138nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel) 139{ 140 bfd_vma val; 141 struct nlm32_sparc_reloc_ext tmp_reloc; 142 unsigned int index; 143 int type = -1; 144 reloc_howto_type *tmp; 145 146 for (index = 0; 147 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type); 148 index++) 149 { 150 tmp = &nlm32_sparc_howto_table[index]; 151 152 if (tmp->rightshift == rel->howto->rightshift 153 && tmp->size == rel->howto->size 154 && tmp->bitsize == rel->howto->bitsize 155 && tmp->pc_relative == rel->howto->pc_relative 156 && tmp->bitpos == rel->howto->bitpos 157 && tmp->src_mask == rel->howto->src_mask 158 && tmp->dst_mask == rel->howto->dst_mask) 159 { 160 type = tmp->type; 161 break; 162 } 163 } 164 if (type == -1) 165 abort (); 166 167 /* Netware wants a list of relocs for each address. 168 Format is: 169 long offset 170 long addend 171 char type 172 That should be it. */ 173 174 /* The value we write out is the offset into the appropriate 175 segment. This offset is the section vma, adjusted by the vma of 176 the lowest section in that segment, plus the address of the 177 relocation. */ 178 val = bfd_get_section_vma (abfd, sec) + rel->address; 179 180#ifdef DEBUG 181 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %u\n", 182 __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend, 183 rel->howto->type); 184#endif 185 bfd_put_32 (abfd, val, tmp_reloc.offset); 186 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend); 187 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type); 188 189 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12) 190 return FALSE; 191 192 return TRUE; 193} 194 195/* Mangle relocs for SPARC NetWare. We can just use the standard 196 SPARC relocs. */ 197 198static bfd_boolean 199nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED, 200 asection *sec ATTRIBUTE_UNUSED, 201 const void * data ATTRIBUTE_UNUSED, 202 bfd_vma offset ATTRIBUTE_UNUSED, 203 bfd_size_type count ATTRIBUTE_UNUSED) 204{ 205 return TRUE; 206} 207 208/* Read a NetWare sparc import record. */ 209 210static bfd_boolean 211nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym) 212{ 213 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */ 214 bfd_size_type rcount; /* Number of relocs. */ 215 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */ 216 unsigned char symlength; /* Length of symbol name. */ 217 char *name; 218 219 /* First, read in the number of relocation 220 entries for this symbol. */ 221 if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4) 222 return FALSE; 223 224 rcount = bfd_get_32 (abfd, temp); 225 226 /* Next, read in the length of the symbol. */ 227 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd) 228 != sizeof (symlength)) 229 return FALSE; 230 sym -> symbol.the_bfd = abfd; 231 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); 232 if (name == NULL) 233 return FALSE; 234 235 /* Then read in the symbol. */ 236 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) 237 return FALSE; 238 name[symlength] = '\0'; 239 sym -> symbol.name = name; 240 sym -> symbol.flags = 0; 241 sym -> symbol.value = 0; 242 sym -> symbol.section = bfd_und_section_ptr; 243 244 /* Next, start reading in the relocs. */ 245 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)); 246 if (!nlm_relocs) 247 return FALSE; 248 sym -> relocs = nlm_relocs; 249 sym -> rcnt = 0; 250 while (sym -> rcnt < rcount) 251 { 252 asection *section; 253 254 if (! nlm_sparc_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) 255 return FALSE; 256 nlm_relocs -> section = section; 257 nlm_relocs++; 258 sym -> rcnt++; 259 } 260 261 return TRUE; 262} 263 264static bfd_boolean 265nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel) 266{ 267 char temp[4]; 268 asection *code, *data, *bss, *symsec; 269 bfd_vma base; 270 271 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME); 272 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); 273 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME); 274 symsec = (*rel->sym_ptr_ptr)->section; 275 276 if (symsec == code) 277 base = 0; 278 else if (symsec == data) 279 base = code->size; 280 else if (symsec == bss) 281 base = code->size + data->size; 282 else 283 base = 0; 284 285#ifdef DEBUG 286 fprintf (stderr, "%s: <%lx, 1>\n\t", 287 __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value)); 288#endif 289 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp); 290 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4) 291 return FALSE; 292 bfd_put_32 (abfd, (bfd_vma) 1, temp); 293 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4) 294 return FALSE; 295 if (! nlm_sparc_write_reloc (abfd, sec, rel)) 296 return FALSE; 297 return TRUE; 298} 299 300/* Write out an external reference. */ 301 302static bfd_boolean 303nlm_sparc_write_external (bfd *abfd, 304 bfd_size_type count, 305 asymbol *sym, 306 struct reloc_and_sec *relocs) 307{ 308 unsigned int i; 309 bfd_byte len; 310 unsigned char temp[NLM_TARGET_LONG_SIZE]; 311 312 bfd_put_32 (abfd, count, temp); 313 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) 314 return FALSE; 315 316 len = strlen (sym->name); 317 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) 318 != sizeof (bfd_byte)) 319 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) 320 return FALSE; 321 322 for (i = 0; i < count; i++) 323 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel)) 324 return FALSE; 325 326 return TRUE; 327} 328 329static bfd_boolean 330nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value) 331{ 332 bfd_byte len; 333 bfd_byte temp[4]; 334 335#ifdef DEBUG 336 fprintf (stderr, "%s: <%lx, %u, %s>\n", 337 __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name); 338#endif 339 bfd_put_32 (abfd, value, temp); 340 len = strlen (sym->name); 341 342 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4 343 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1 344 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) 345 return FALSE; 346 347 return TRUE; 348} 349 350#undef nlm_swap_fixed_header_in 351#undef nlm_swap_fixed_header_out 352 353#include "nlmswap.h" 354 355static const struct nlm_backend_data nlm32_sparc_backend = 356{ 357 "NetWare SPARC Module \032", 358 sizeof (Nlm32_sparc_External_Fixed_Header), 359 0, /* Optional_prefix_size. */ 360 bfd_arch_sparc, 361 0, 362 FALSE, 363 0, /* Backend_object_p. */ 364 0, /* Write_prefix_func. */ 365 nlm_sparc_read_reloc, 366 nlm_sparc_mangle_relocs, 367 nlm_sparc_read_import, 368 nlm_sparc_write_import, 369 0, /* Set_public_section. */ 370 0, /* Get_public_offset. */ 371 nlm_swap_fixed_header_in, 372 nlm_swap_fixed_header_out, 373 nlm_sparc_write_external, 374 nlm_sparc_write_export 375}; 376 377#define TARGET_BIG_NAME "nlm32-sparc" 378#define TARGET_BIG_SYM nlmNAME (sparc_vec) 379#define TARGET_BACKEND_DATA & nlm32_sparc_backend 380 381#include "nlm-target.h" 382