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