1/* Support for 32-bit SPARC NLM (NetWare Loadable Module) 2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 3 2007, 2009, 2010 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 howto_index; 97 unsigned int type; 98 struct nlm32_sparc_reloc_ext tmp_reloc; 99 asection *code_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 *secp = code_sec; 106 107 val = bfd_get_32 (abfd, tmp_reloc.offset); 108 addend = bfd_get_32 (abfd, tmp_reloc.addend); 109 type = bfd_get_8 (abfd, tmp_reloc.type); 110 111 rel->address = val; 112 rel->addend = addend; 113 rel->howto = NULL; 114 115 for (howto_index = 0; 116 howto_index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type); 117 howto_index++) 118 if (nlm32_sparc_howto_table[howto_index].type == type) 119 { 120 rel->howto = &nlm32_sparc_howto_table[howto_index]; 121 break; 122 } 123 124#ifdef DEBUG 125 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %u, howto = %p\n", 126 __FUNCTION__, (unsigned long) rel->address, 127 (unsigned long) rel->addend, type, rel->howto); 128#endif 129 return TRUE; 130 131} 132 133/* Write a NetWare sparc reloc. */ 134 135static bfd_boolean 136nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel) 137{ 138 bfd_vma val; 139 struct nlm32_sparc_reloc_ext tmp_reloc; 140 unsigned int howto_index; 141 int type = -1; 142 reloc_howto_type *tmp; 143 144 for (howto_index = 0; 145 howto_index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type); 146 howto_index++) 147 { 148 tmp = &nlm32_sparc_howto_table[howto_index]; 149 150 if (tmp->rightshift == rel->howto->rightshift 151 && tmp->size == rel->howto->size 152 && tmp->bitsize == rel->howto->bitsize 153 && tmp->pc_relative == rel->howto->pc_relative 154 && tmp->bitpos == rel->howto->bitpos 155 && tmp->src_mask == rel->howto->src_mask 156 && tmp->dst_mask == rel->howto->dst_mask) 157 { 158 type = tmp->type; 159 break; 160 } 161 } 162 if (type == -1) 163 abort (); 164 165 /* Netware wants a list of relocs for each address. 166 Format is: 167 long offset 168 long addend 169 char type 170 That should be it. */ 171 172 /* The value we write out is the offset into the appropriate 173 segment. This offset is the section vma, adjusted by the vma of 174 the lowest section in that segment, plus the address of the 175 relocation. */ 176 val = bfd_get_section_vma (abfd, sec) + rel->address; 177 178#ifdef DEBUG 179 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %u\n", 180 __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend, 181 rel->howto->type); 182#endif 183 bfd_put_32 (abfd, val, tmp_reloc.offset); 184 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend); 185 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type); 186 187 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12) 188 return FALSE; 189 190 return TRUE; 191} 192 193/* Mangle relocs for SPARC NetWare. We can just use the standard 194 SPARC relocs. */ 195 196static bfd_boolean 197nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED, 198 asection *sec ATTRIBUTE_UNUSED, 199 const void * data ATTRIBUTE_UNUSED, 200 bfd_vma offset ATTRIBUTE_UNUSED, 201 bfd_size_type count ATTRIBUTE_UNUSED) 202{ 203 return TRUE; 204} 205 206/* Read a NetWare sparc import record. */ 207 208static bfd_boolean 209nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym) 210{ 211 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */ 212 bfd_size_type rcount; /* Number of relocs. */ 213 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */ 214 unsigned char symlength; /* Length of symbol name. */ 215 char *name; 216 217 /* First, read in the number of relocation 218 entries for this symbol. */ 219 if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4) 220 return FALSE; 221 222 rcount = bfd_get_32 (abfd, temp); 223 224 /* Next, read in the length of the symbol. */ 225 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd) 226 != sizeof (symlength)) 227 return FALSE; 228 sym -> symbol.the_bfd = abfd; 229 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); 230 if (name == NULL) 231 return FALSE; 232 233 /* Then read in the symbol. */ 234 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) 235 return FALSE; 236 name[symlength] = '\0'; 237 sym -> symbol.name = name; 238 sym -> symbol.flags = 0; 239 sym -> symbol.value = 0; 240 sym -> symbol.section = bfd_und_section_ptr; 241 242 /* Next, start reading in the relocs. */ 243 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)); 244 if (!nlm_relocs) 245 return FALSE; 246 sym -> relocs = nlm_relocs; 247 sym -> rcnt = 0; 248 while (sym -> rcnt < rcount) 249 { 250 asection *section; 251 252 if (! nlm_sparc_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) 253 return FALSE; 254 nlm_relocs -> section = section; 255 nlm_relocs++; 256 sym -> rcnt++; 257 } 258 259 return TRUE; 260} 261 262static bfd_boolean 263nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel) 264{ 265 char temp[4]; 266 asection *code, *data, *bss, *symsec; 267 bfd_vma base; 268 269 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME); 270 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); 271 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME); 272 symsec = (*rel->sym_ptr_ptr)->section; 273 274 if (symsec == code) 275 base = 0; 276 else if (symsec == data) 277 base = code->size; 278 else if (symsec == bss) 279 base = code->size + data->size; 280 else 281 base = 0; 282 283#ifdef DEBUG 284 fprintf (stderr, "%s: <%lx, 1>\n\t", 285 __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value)); 286#endif 287 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp); 288 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4) 289 return FALSE; 290 bfd_put_32 (abfd, (bfd_vma) 1, temp); 291 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4) 292 return FALSE; 293 if (! nlm_sparc_write_reloc (abfd, sec, rel)) 294 return FALSE; 295 return TRUE; 296} 297 298/* Write out an external reference. */ 299 300static bfd_boolean 301nlm_sparc_write_external (bfd *abfd, 302 bfd_size_type count, 303 asymbol *sym, 304 struct reloc_and_sec *relocs) 305{ 306 unsigned int i; 307 bfd_byte len; 308 unsigned char temp[NLM_TARGET_LONG_SIZE]; 309 310 bfd_put_32 (abfd, count, temp); 311 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) 312 return FALSE; 313 314 len = strlen (sym->name); 315 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) 316 != sizeof (bfd_byte)) 317 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) 318 return FALSE; 319 320 for (i = 0; i < count; i++) 321 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel)) 322 return FALSE; 323 324 return TRUE; 325} 326 327static bfd_boolean 328nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value) 329{ 330 bfd_byte len; 331 bfd_byte temp[4]; 332 333#ifdef DEBUG 334 fprintf (stderr, "%s: <%lx, %u, %s>\n", 335 __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name); 336#endif 337 bfd_put_32 (abfd, value, temp); 338 len = strlen (sym->name); 339 340 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4 341 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1 342 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) 343 return FALSE; 344 345 return TRUE; 346} 347 348#undef nlm_swap_fixed_header_in 349#undef nlm_swap_fixed_header_out 350 351#include "nlmswap.h" 352 353static const struct nlm_backend_data nlm32_sparc_backend = 354{ 355 "NetWare SPARC Module \032", 356 sizeof (Nlm32_sparc_External_Fixed_Header), 357 0, /* Optional_prefix_size. */ 358 bfd_arch_sparc, 359 0, 360 FALSE, 361 0, /* Backend_object_p. */ 362 0, /* Write_prefix_func. */ 363 nlm_sparc_read_reloc, 364 nlm_sparc_mangle_relocs, 365 nlm_sparc_read_import, 366 nlm_sparc_write_import, 367 0, /* Set_public_section. */ 368 0, /* Get_public_offset. */ 369 nlm_swap_fixed_header_in, 370 nlm_swap_fixed_header_out, 371 nlm_sparc_write_external, 372 nlm_sparc_write_export 373}; 374 375#define TARGET_BIG_NAME "nlm32-sparc" 376#define TARGET_BIG_SYM nlmNAME (sparc_vec) 377#define TARGET_BACKEND_DATA & nlm32_sparc_backend 378 379#include "nlm-target.h" 380