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