b818cfd0481dc66c6c0e98c258b2bc36b45a8ba5
[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 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 index;
97 unsigned int type;
98 struct nlm32_sparc_reloc_ext tmp_reloc;
99 asection *code_sec, *data_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 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
106
107 *secp = code_sec;
108
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);
112
113 rel->address = val;
114 rel->addend = addend;
115 rel->howto = NULL;
116
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)
121 {
122 rel->howto = &nlm32_sparc_howto_table[index];
123 break;
124 }
125
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;
132
133 }
134
135 /* Write a NetWare sparc reloc. */
136
137 static bfd_boolean
138 nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
139 {
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;
145
146 for (index = 0;
147 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
148 index++)
149 {
150 tmp = &nlm32_sparc_howto_table[index];
151
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)
159 {
160 type = tmp->type;
161 break;
162 }
163 }
164 if (type == -1)
165 abort ();
166
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. */
173
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;
179
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);
188
189 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
190 return FALSE;
191
192 return TRUE;
193 }
194
195 /* Mangle relocs for SPARC NetWare. We can just use the standard
196 SPARC relocs. */
197
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)
204 {
205 return TRUE;
206 }
207
208 /* Read a NetWare sparc import record. */
209
210 static bfd_boolean
211 nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
212 {
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;
218
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;
223
224 rcount = bfd_get_32 (abfd, temp);
225
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;
234
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;
243
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)
251 {
252 asection *section;
253
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++;
259 }
260
261 return TRUE;
262 }
263
264 static bfd_boolean
265 nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
266 {
267 char temp[4];
268 asection *code, *data, *bss, *symsec;
269 bfd_vma base;
270
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;
275
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;
284
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;
298 }
299
300 /* Write out an external reference. */
301
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)
307 {
308 unsigned int i;
309 bfd_byte len;
310 unsigned char temp[NLM_TARGET_LONG_SIZE];
311
312 bfd_put_32 (abfd, count, temp);
313 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
314 return FALSE;
315
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;
321
322 for (i = 0; i < count; i++)
323 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
324 return FALSE;
325
326 return TRUE;
327 }
328
329 static bfd_boolean
330 nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
331 {
332 bfd_byte len;
333 bfd_byte temp[4];
334
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);
341
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;
346
347 return TRUE;
348 }
349
350 #undef nlm_swap_fixed_header_in
351 #undef nlm_swap_fixed_header_out
352
353 #include "nlmswap.h"
354
355 static const struct nlm_backend_data nlm32_sparc_backend =
356 {
357 "NetWare SPARC Module \032",
358 sizeof (Nlm32_sparc_External_Fixed_Header),
359 0, /* Optional_prefix_size. */
360 bfd_arch_sparc,
361 0,
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
375 };
376
377 #define TARGET_BIG_NAME "nlm32-sparc"
378 #define TARGET_BIG_SYM nlmNAME (sparc_vec)
379 #define TARGET_BACKEND_DATA & nlm32_sparc_backend
380
381 #include "nlm-target.h"
This page took 0.040223 seconds and 3 git commands to generate.