top level:
[binutils.git] / bfd / nlm32-sparc.c
blob701a6d81c1cd2b8846143d3dbf698e8ced2812f2
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.
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 enum reloc_type
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
50 static reloc_howto_type nlm32_sparc_howto_table[] =
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),
78 /* Read a NetWare sparc reloc. */
80 struct nlm32_sparc_reloc_ext
82 unsigned char offset[4];
83 unsigned char addend[4];
84 unsigned char type[1];
85 unsigned char pad1[3];
88 static bfd_boolean
89 nlm_sparc_read_reloc (bfd *abfd,
90 nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED,
91 asection **secp,
92 arelent *rel)
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;
100 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
101 return FALSE;
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);
106 *secp = code_sec;
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);
112 rel->address = val;
113 rel->addend = addend;
114 rel->howto = NULL;
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)
121 rel->howto = &nlm32_sparc_howto_table[index];
122 break;
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;
134 /* Write a NetWare sparc reloc. */
136 static bfd_boolean
137 nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
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;
145 for (index = 0;
146 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
147 index++)
149 tmp = &nlm32_sparc_howto_table[index];
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)
159 type = tmp->type;
160 break;
163 if (type == -1)
164 abort ();
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. */
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;
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);
188 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
189 return FALSE;
191 return TRUE;
194 /* Mangle relocs for SPARC NetWare. We can just use the standard
195 SPARC relocs. */
197 static bfd_boolean
198 nlm_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)
204 return TRUE;
207 /* Read a NetWare sparc import record. */
209 static bfd_boolean
210 nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
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;
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;
223 rcount = bfd_get_32 (abfd, temp);
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;
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;
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)
251 asection *section;
253 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
254 return FALSE;
255 nlm_relocs -> section = section;
256 nlm_relocs++;
257 sym -> rcnt++;
260 return TRUE;
263 static bfd_boolean
264 nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
266 char temp[4];
267 asection *code, *data, *bss, *symsec;
268 bfd_vma base;
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;
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;
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;
299 /* Write out an external reference. */
301 static bfd_boolean
302 nlm_sparc_write_external (bfd *abfd,
303 bfd_size_type count,
304 asymbol *sym,
305 struct reloc_and_sec *relocs)
307 unsigned int i;
308 bfd_byte len;
309 unsigned char temp[NLM_TARGET_LONG_SIZE];
311 bfd_put_32 (abfd, count, temp);
312 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
313 return FALSE;
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;
321 for (i = 0; i < count; i++)
322 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
323 return FALSE;
325 return TRUE;
328 static bfd_boolean
329 nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
331 bfd_byte len;
332 bfd_byte temp[4];
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);
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;
346 return TRUE;
349 #undef nlm_swap_fixed_header_in
350 #undef nlm_swap_fixed_header_out
352 #include "nlmswap.h"
354 static const struct nlm_backend_data nlm32_sparc_backend =
356 "NetWare SPARC Module \032",
357 sizeof (Nlm32_sparc_External_Fixed_Header),
358 0, /* Optional_prefix_size. */
359 bfd_arch_sparc,
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
376 #define TARGET_BIG_NAME "nlm32-sparc"
377 #define TARGET_BIG_SYM nlmNAME (sparc_vec)
378 #define TARGET_BACKEND_DATA & nlm32_sparc_backend
380 #include "nlm-target.h"