2009-07-25 H.J. Lu <hongjiu.lu@intel.com>
[binutils.git] / bfd / nlm32-sparc.c
blobb818cfd0481dc66c6c0e98c258b2bc36b45a8ba5
1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007 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 3 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,
20 MA 02110-1301, USA. */
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
26 #define ARCH_SIZE 32
28 #include "nlm/sparc32-ext.h"
29 #define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header
31 #include "libnlm.h"
33 enum reloc_type
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
51 static reloc_howto_type nlm32_sparc_howto_table[] =
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),
79 /* Read a NetWare sparc reloc. */
81 struct nlm32_sparc_reloc_ext
83 unsigned char offset[4];
84 unsigned char addend[4];
85 unsigned char type[1];
86 unsigned char pad1[3];
89 static bfd_boolean
90 nlm_sparc_read_reloc (bfd *abfd,
91 nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED,
92 asection **secp,
93 arelent *rel)
95 bfd_vma val, addend;
96 unsigned int index;
97 unsigned int type;
98 struct nlm32_sparc_reloc_ext tmp_reloc;
99 asection *code_sec, *data_sec;
101 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
102 return FALSE;
104 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
105 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
107 *secp = code_sec;
109 val = bfd_get_32 (abfd, tmp_reloc.offset);
110 addend = bfd_get_32 (abfd, tmp_reloc.addend);
111 type = bfd_get_8 (abfd, tmp_reloc.type);
113 rel->address = val;
114 rel->addend = addend;
115 rel->howto = NULL;
117 for (index = 0;
118 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
119 index++)
120 if (nlm32_sparc_howto_table[index].type == type)
122 rel->howto = &nlm32_sparc_howto_table[index];
123 break;
126 #ifdef DEBUG
127 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %u, howto = %p\n",
128 __FUNCTION__, (unsigned long) rel->address,
129 (unsigned long) rel->addend, type, rel->howto);
130 #endif
131 return TRUE;
135 /* Write a NetWare sparc reloc. */
137 static bfd_boolean
138 nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
140 bfd_vma val;
141 struct nlm32_sparc_reloc_ext tmp_reloc;
142 unsigned int index;
143 int type = -1;
144 reloc_howto_type *tmp;
146 for (index = 0;
147 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
148 index++)
150 tmp = &nlm32_sparc_howto_table[index];
152 if (tmp->rightshift == rel->howto->rightshift
153 && tmp->size == rel->howto->size
154 && tmp->bitsize == rel->howto->bitsize
155 && tmp->pc_relative == rel->howto->pc_relative
156 && tmp->bitpos == rel->howto->bitpos
157 && tmp->src_mask == rel->howto->src_mask
158 && tmp->dst_mask == rel->howto->dst_mask)
160 type = tmp->type;
161 break;
164 if (type == -1)
165 abort ();
167 /* Netware wants a list of relocs for each address.
168 Format is:
169 long offset
170 long addend
171 char type
172 That should be it. */
174 /* The value we write out is the offset into the appropriate
175 segment. This offset is the section vma, adjusted by the vma of
176 the lowest section in that segment, plus the address of the
177 relocation. */
178 val = bfd_get_section_vma (abfd, sec) + rel->address;
180 #ifdef DEBUG
181 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %u\n",
182 __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend,
183 rel->howto->type);
184 #endif
185 bfd_put_32 (abfd, val, tmp_reloc.offset);
186 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
187 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
189 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
190 return FALSE;
192 return TRUE;
195 /* Mangle relocs for SPARC NetWare. We can just use the standard
196 SPARC relocs. */
198 static bfd_boolean
199 nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
200 asection *sec ATTRIBUTE_UNUSED,
201 const void * data ATTRIBUTE_UNUSED,
202 bfd_vma offset ATTRIBUTE_UNUSED,
203 bfd_size_type count ATTRIBUTE_UNUSED)
205 return TRUE;
208 /* Read a NetWare sparc import record. */
210 static bfd_boolean
211 nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
213 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */
214 bfd_size_type rcount; /* Number of relocs. */
215 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */
216 unsigned char symlength; /* Length of symbol name. */
217 char *name;
219 /* First, read in the number of relocation
220 entries for this symbol. */
221 if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4)
222 return FALSE;
224 rcount = bfd_get_32 (abfd, temp);
226 /* Next, read in the length of the symbol. */
227 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
228 != sizeof (symlength))
229 return FALSE;
230 sym -> symbol.the_bfd = abfd;
231 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
232 if (name == NULL)
233 return FALSE;
235 /* Then read in the symbol. */
236 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
237 return FALSE;
238 name[symlength] = '\0';
239 sym -> symbol.name = name;
240 sym -> symbol.flags = 0;
241 sym -> symbol.value = 0;
242 sym -> symbol.section = bfd_und_section_ptr;
244 /* Next, start reading in the relocs. */
245 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
246 if (!nlm_relocs)
247 return FALSE;
248 sym -> relocs = nlm_relocs;
249 sym -> rcnt = 0;
250 while (sym -> rcnt < rcount)
252 asection *section;
254 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
255 return FALSE;
256 nlm_relocs -> section = section;
257 nlm_relocs++;
258 sym -> rcnt++;
261 return TRUE;
264 static bfd_boolean
265 nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
267 char temp[4];
268 asection *code, *data, *bss, *symsec;
269 bfd_vma base;
271 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
272 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
273 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
274 symsec = (*rel->sym_ptr_ptr)->section;
276 if (symsec == code)
277 base = 0;
278 else if (symsec == data)
279 base = code->size;
280 else if (symsec == bss)
281 base = code->size + data->size;
282 else
283 base = 0;
285 #ifdef DEBUG
286 fprintf (stderr, "%s: <%lx, 1>\n\t",
287 __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value));
288 #endif
289 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
290 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
291 return FALSE;
292 bfd_put_32 (abfd, (bfd_vma) 1, temp);
293 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
294 return FALSE;
295 if (! nlm_sparc_write_reloc (abfd, sec, rel))
296 return FALSE;
297 return TRUE;
300 /* Write out an external reference. */
302 static bfd_boolean
303 nlm_sparc_write_external (bfd *abfd,
304 bfd_size_type count,
305 asymbol *sym,
306 struct reloc_and_sec *relocs)
308 unsigned int i;
309 bfd_byte len;
310 unsigned char temp[NLM_TARGET_LONG_SIZE];
312 bfd_put_32 (abfd, count, temp);
313 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
314 return FALSE;
316 len = strlen (sym->name);
317 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
318 != sizeof (bfd_byte))
319 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
320 return FALSE;
322 for (i = 0; i < count; i++)
323 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
324 return FALSE;
326 return TRUE;
329 static bfd_boolean
330 nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
332 bfd_byte len;
333 bfd_byte temp[4];
335 #ifdef DEBUG
336 fprintf (stderr, "%s: <%lx, %u, %s>\n",
337 __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name);
338 #endif
339 bfd_put_32 (abfd, value, temp);
340 len = strlen (sym->name);
342 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
343 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
344 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
345 return FALSE;
347 return TRUE;
350 #undef nlm_swap_fixed_header_in
351 #undef nlm_swap_fixed_header_out
353 #include "nlmswap.h"
355 static const struct nlm_backend_data nlm32_sparc_backend =
357 "NetWare SPARC Module \032",
358 sizeof (Nlm32_sparc_External_Fixed_Header),
359 0, /* Optional_prefix_size. */
360 bfd_arch_sparc,
362 FALSE,
363 0, /* Backend_object_p. */
364 0, /* Write_prefix_func. */
365 nlm_sparc_read_reloc,
366 nlm_sparc_mangle_relocs,
367 nlm_sparc_read_import,
368 nlm_sparc_write_import,
369 0, /* Set_public_section. */
370 0, /* Get_public_offset. */
371 nlm_swap_fixed_header_in,
372 nlm_swap_fixed_header_out,
373 nlm_sparc_write_external,
374 nlm_sparc_write_export
377 #define TARGET_BIG_NAME "nlm32-sparc"
378 #define TARGET_BIG_SYM nlmNAME (sparc_vec)
379 #define TARGET_BACKEND_DATA & nlm32_sparc_backend
381 #include "nlm-target.h"