update copyright dates
[binutils.git] / bfd / nlm32-sparc.c
blob487617653bb770547d4ed2d1a39ec6c2fa214dcb
1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
25 #define ARCH_SIZE 32
27 #include "nlm/sparc32-ext.h"
28 #define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header
30 #include "libnlm.h"
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));
47 enum reloc_type
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
65 static reloc_howto_type nlm32_sparc_howto_table[] =
67 HOWTO (R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, 0,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE),
68 HOWTO (R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8", FALSE,0,0x000000ff,TRUE),
69 HOWTO (R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE),
70 HOWTO (R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32", FALSE,0,0xffffffff,TRUE),
71 HOWTO (R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE),
72 HOWTO (R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE),
73 HOWTO (R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE),
74 HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
75 HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
76 HOWTO (R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, 0,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE),
77 HOWTO (R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22", FALSE,0,0x003fffff,TRUE),
78 HOWTO (R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13", FALSE,0,0x00001fff,TRUE),
79 HOWTO (R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, 0,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE),
80 HOWTO (R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE),
81 HOWTO (R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE),
82 HOWTO (R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE),
83 HOWTO (R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE),
84 HOWTO (R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE),
85 HOWTO (R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE),
86 HOWTO (R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE),
87 HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE),
88 HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE),
89 HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
90 HOWTO (R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE),
93 /* Read a NetWare sparc reloc. */
95 struct nlm32_sparc_reloc_ext
97 unsigned char offset[4];
98 unsigned char addend[4];
99 unsigned char type[1];
100 unsigned char pad1[3];
103 static bfd_boolean
104 nlm_sparc_read_reloc (abfd, sym, secp, rel)
105 bfd *abfd;
106 nlmNAME(symbol_type) *sym ATTRIBUTE_UNUSED;
107 asection **secp;
108 arelent *rel;
110 bfd_vma val, addend;
111 unsigned int index;
112 unsigned int type;
113 struct nlm32_sparc_reloc_ext tmp_reloc;
114 asection *code_sec, *data_sec;
116 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
117 return FALSE;
119 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
120 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
122 *secp = code_sec;
124 val = bfd_get_32 (abfd, tmp_reloc.offset);
125 addend = bfd_get_32 (abfd, tmp_reloc.addend);
126 type = bfd_get_8 (abfd, tmp_reloc.type);
128 rel->address = val;
129 rel->addend = addend;
130 rel->howto = NULL;
132 for (index = 0;
133 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
134 index++)
135 if (nlm32_sparc_howto_table[index].type == type)
137 rel->howto = &nlm32_sparc_howto_table[index];
138 break;
141 #ifdef DEBUG
142 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
143 __FUNCTION__, rel->address, rel->addend, type, rel->howto);
144 #endif
145 return TRUE;
149 /* Write a NetWare sparc reloc. */
151 static bfd_boolean
152 nlm_sparc_write_reloc (abfd, sec, rel)
153 bfd *abfd;
154 asection *sec;
155 arelent *rel;
157 bfd_vma val;
158 struct nlm32_sparc_reloc_ext tmp_reloc;
159 unsigned int index;
160 int type = -1;
161 reloc_howto_type *tmp;
163 for (index = 0;
164 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
165 index++)
167 tmp = &nlm32_sparc_howto_table[index];
169 if (tmp->rightshift == rel->howto->rightshift
170 && tmp->size == rel->howto->size
171 && tmp->bitsize == rel->howto->bitsize
172 && tmp->pc_relative == rel->howto->pc_relative
173 && tmp->bitpos == rel->howto->bitpos
174 && tmp->src_mask == rel->howto->src_mask
175 && tmp->dst_mask == rel->howto->dst_mask)
177 type = tmp->type;
178 break;
181 if (type == -1)
182 abort ();
184 /* Netware wants a list of relocs for each address.
185 Format is:
186 long offset
187 long addend
188 char type
189 That should be it. */
191 /* The value we write out is the offset into the appropriate
192 segment. This offset is the section vma, adjusted by the vma of
193 the lowest section in that segment, plus the address of the
194 relocation. */
195 val = bfd_get_section_vma (abfd, sec) + rel->address;
197 #ifdef DEBUG
198 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
199 __FUNCTION__, val, rel->addend, rel->howto->type);
200 #endif
201 bfd_put_32 (abfd, val, tmp_reloc.offset);
202 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
203 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
205 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
206 return FALSE;
208 return TRUE;
211 /* Mangle relocs for SPARC NetWare. We can just use the standard
212 SPARC relocs. */
214 static bfd_boolean
215 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
216 bfd *abfd ATTRIBUTE_UNUSED;
217 asection *sec ATTRIBUTE_UNUSED;
218 const PTR data ATTRIBUTE_UNUSED;
219 bfd_vma offset ATTRIBUTE_UNUSED;
220 bfd_size_type count ATTRIBUTE_UNUSED;
222 return TRUE;
225 /* Read a NetWare sparc import record. */
227 static bfd_boolean
228 nlm_sparc_read_import (abfd, sym)
229 bfd *abfd;
230 nlmNAME(symbol_type) *sym;
232 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */
233 bfd_size_type rcount; /* Number of relocs. */
234 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */
235 unsigned char symlength; /* Length of symbol name. */
236 char *name;
238 /* First, read in the number of relocation
239 entries for this symbol. */
240 if (bfd_bread ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
241 return FALSE;
243 rcount = bfd_get_32 (abfd, temp);
245 /* Next, read in the length of the symbol. */
247 if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
248 != sizeof (symlength))
249 return FALSE;
250 sym -> symbol.the_bfd = abfd;
251 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
252 if (name == NULL)
253 return FALSE;
255 /* Then read in the symbol. */
257 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
258 return FALSE;
259 name[symlength] = '\0';
260 sym -> symbol.name = name;
261 sym -> symbol.flags = 0;
262 sym -> symbol.value = 0;
263 sym -> symbol.section = bfd_und_section_ptr;
265 /* Next, start reading in the relocs. */
267 nlm_relocs = ((struct nlm_relent *)
268 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
269 if (!nlm_relocs)
270 return FALSE;
271 sym -> relocs = nlm_relocs;
272 sym -> rcnt = 0;
273 while (sym -> rcnt < rcount)
275 asection *section;
277 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
278 return FALSE;
279 nlm_relocs -> section = section;
280 nlm_relocs++;
281 sym -> rcnt++;
284 return TRUE;
287 static bfd_boolean
288 nlm_sparc_write_import (abfd, sec, rel)
289 bfd *abfd;
290 asection *sec;
291 arelent *rel;
293 char temp[4];
294 asection *code, *data, *bss, *symsec;
295 bfd_vma base;
297 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
298 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
299 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
300 symsec = (*rel->sym_ptr_ptr)->section;
302 if (symsec == code)
303 base = 0;
304 else if (symsec == data)
305 base = code->size;
306 else if (symsec == bss)
307 base = code->size + data->size;
308 else
309 base = 0;
311 #ifdef DEBUG
312 fprintf (stderr, "%s: <%x, 1>\n\t",
313 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
314 #endif
315 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
316 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
317 return FALSE;
318 bfd_put_32 (abfd, (bfd_vma) 1, temp);
319 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
320 return FALSE;
321 if (! nlm_sparc_write_reloc (abfd, sec, rel))
322 return FALSE;
323 return TRUE;
326 /* Write out an external reference. */
328 static bfd_boolean
329 nlm_sparc_write_external (abfd, count, sym, relocs)
330 bfd *abfd;
331 bfd_size_type count;
332 asymbol *sym;
333 struct reloc_and_sec *relocs;
335 unsigned int i;
336 bfd_byte len;
337 unsigned char temp[NLM_TARGET_LONG_SIZE];
339 bfd_put_32 (abfd, count, temp);
340 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
341 return FALSE;
343 len = strlen (sym->name);
344 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
345 != sizeof (bfd_byte))
346 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
347 return FALSE;
349 for (i = 0; i < count; i++)
351 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
352 return FALSE;
355 return TRUE;
358 static bfd_boolean
359 nlm_sparc_write_export (abfd, sym, value)
360 bfd *abfd;
361 asymbol *sym;
362 bfd_vma value;
364 bfd_byte len;
365 bfd_byte temp[4];
367 #ifdef DEBUG
368 fprintf (stderr, "%s: <%x, %d, %s>\n",
369 __FUNCTION__, value, strlen (sym->name), sym->name);
370 #endif
371 bfd_put_32 (abfd, value, temp);
372 len = strlen (sym->name);
374 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
375 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
376 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
377 return FALSE;
379 return TRUE;
382 #undef nlm_swap_fixed_header_in
383 #undef nlm_swap_fixed_header_out
385 #include "nlmswap.h"
387 static const struct nlm_backend_data nlm32_sparc_backend =
389 "NetWare SPARC Module \032",
390 sizeof (Nlm32_sparc_External_Fixed_Header),
391 0, /* optional_prefix_size */
392 bfd_arch_sparc,
394 FALSE,
395 0, /* backend_object_p */
396 0, /* write_prefix_func */
397 nlm_sparc_read_reloc,
398 nlm_sparc_mangle_relocs,
399 nlm_sparc_read_import,
400 nlm_sparc_write_import,
401 0, /* set_public_section */
402 0, /* get_public_offset */
403 nlm_swap_fixed_header_in,
404 nlm_swap_fixed_header_out,
405 nlm_sparc_write_external,
406 nlm_sparc_write_export
409 #define TARGET_BIG_NAME "nlm32-sparc"
410 #define TARGET_BIG_SYM nlmNAME(sparc_vec)
411 #define TARGET_BACKEND_DATA & nlm32_sparc_backend
413 #include "nlm-target.h"