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