This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / bfd / nlm32-sparc.c
1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2 Copyright (C) 1993 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
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.
10
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.
15
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23
24 #define ARCH_SIZE 32
25
26 #include "nlm/sparc32-ext.h"
27 #define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header
28
29 #include "libnlm.h"
30
31 static boolean nlm_sparc_read_reloc
32 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
33 static boolean nlm_sparc_write_reloc
34 PARAMS ((bfd *, asection *, arelent *));
35 static boolean nlm_sparc_mangle_relocs
36 PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
37 static boolean nlm_sparc_read_import
38 PARAMS ((bfd *, nlmNAME(symbol_type) *));
39 static boolean nlm_sparc_write_import
40 PARAMS ((bfd *, asection *, arelent *));
41 static boolean nlm_sparc_write_external
42 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
43
44 enum reloc_type
45 {
46 R_SPARC_NONE = 0,
47 R_SPARC_8, R_SPARC_16, R_SPARC_32,
48 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
49 R_SPARC_WDISP30, R_SPARC_WDISP22,
50 R_SPARC_HI22, R_SPARC_22,
51 R_SPARC_13, R_SPARC_LO10,
52 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
53 R_SPARC_PC10, R_SPARC_PC22,
54 R_SPARC_WPLT30,
55 R_SPARC_COPY,
56 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
57 R_SPARC_RELATIVE,
58 R_SPARC_UA32,
59 R_SPARC_max
60 };
61
62 #if 0
63 static CONST char *CONST reloc_type_names[] =
64 {
65 "R_SPARC_NONE",
66 "R_SPARC_8", "R_SPARC_16", "R_SPARC_32",
67 "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32",
68 "R_SPARC_WDISP30", "R_SPARC_WDISP22",
69 "R_SPARC_HI22", "R_SPARC_22",
70 "R_SPARC_13", "R_SPARC_LO10",
71 "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22",
72 "R_SPARC_PC10", "R_SPARC_PC22",
73 "R_SPARC_WPLT30",
74 "R_SPARC_COPY",
75 "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
76 "R_SPARC_RELATIVE",
77 "R_SPARC_UA32",
78 };
79 #endif
80
81 static reloc_howto_type nlm32_sparc_howto_table[] =
82 {
83 HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, 0,"R_SPARC_NONE", false,0,0x00000000,true),
84 HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,0,"R_SPARC_8", false,0,0x000000ff,true),
85 HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,0,"R_SPARC_16", false,0,0x0000ffff,true),
86 HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,0,"R_SPARC_32", false,0,0xffffffff,true),
87 HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", false,0,0x000000ff,true),
88 HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", false,0,0x0000ffff,true),
89 HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", false,0,0x00ffffff,true),
90 HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
91 HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", false,0,0x003fffff,true),
92 HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, 0,"R_SPARC_HI22", false,0,0x003fffff,true),
93 HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_22", false,0,0x003fffff,true),
94 HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_13", false,0,0x00001fff,true),
95 HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, 0,"R_SPARC_LO10", false,0,0x000003ff,true),
96 HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", false,0,0x000003ff,true),
97 HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", false,0,0x00001fff,true),
98 HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", false,0,0x003fffff,true),
99 HOWTO(R_SPARC_PC10, 0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_PC10", false,0,0x000003ff,true),
100 HOWTO(R_SPARC_PC22, 0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_PC22", false,0,0x003fffff,true),
101 HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", false,0,0x00000000,true),
102 HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_COPY", false,0,0x00000000,true),
103 HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
104 HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
105 HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",false,0,0x00000000,true),
106 HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_UA32", false,0,0x00000000,true),
107 };
108
109 /* Read a NetWare sparc reloc. */
110
111 struct nlm32_sparc_reloc_ext {
112 unsigned char offset[4];
113 unsigned char addend[4];
114 unsigned char type[1];
115 unsigned char pad1[3];
116 };
117
118 static boolean
119 nlm_sparc_read_reloc (abfd, sym, secp, rel)
120 bfd *abfd;
121 nlmNAME(symbol_type) *sym;
122 asection **secp;
123 arelent *rel;
124 {
125 bfd_vma val, addend;
126 int index;
127 unsigned int type;
128 struct nlm32_sparc_reloc_ext tmp_reloc;
129 asection *code_sec, *data_sec;
130
131 if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12)
132 return false;
133
134 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
135 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
136
137 *secp = code_sec;
138
139 val = bfd_get_32 (abfd, tmp_reloc.offset);
140 addend = bfd_get_32 (abfd, tmp_reloc.addend);
141 type = bfd_get_8 (abfd, tmp_reloc.type);
142
143 rel->address = val;
144 rel->addend = addend;
145 rel->howto = NULL;
146
147 for (index = 0;
148 index < sizeof(nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
149 index++)
150 if (nlm32_sparc_howto_table[index].type == type) {
151 rel->howto = &nlm32_sparc_howto_table[index];
152 break;
153 }
154
155 #ifdef DEBUG
156 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
157 __FUNCTION__, rel->address, rel->addend, type, rel->howto);
158 #endif
159 return true;
160
161 }
162
163 /* Write a NetWare sparc reloc. */
164
165 static boolean
166 nlm_sparc_write_reloc (abfd, sec, rel)
167 bfd *abfd;
168 asection *sec;
169 arelent *rel;
170 {
171 bfd_vma val;
172 struct nlm32_sparc_reloc_ext tmp_reloc;
173 int index;
174 int type = -1;
175 reloc_howto_type *tmp;
176
177
178 for (index = 0;
179 index < sizeof (nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
180 index++) {
181 tmp = &nlm32_sparc_howto_table[index];
182
183 if (tmp->rightshift == rel->howto->rightshift
184 && tmp->size == rel->howto->size
185 && tmp->bitsize == rel->howto->bitsize
186 && tmp->pc_relative == rel->howto->pc_relative
187 && tmp->bitpos == rel->howto->bitpos
188 && tmp->src_mask == rel->howto->src_mask
189 && tmp->dst_mask == rel->howto->dst_mask) {
190 type = tmp->type;
191 break;
192 }
193 }
194 if (type == -1)
195 abort();
196
197 /*
198 * Netware wants a list of relocs for each address.
199 * Format is:
200 * long offset
201 * long addend
202 * char type
203 * That should be it.
204 */
205
206 /* The value we write out is the offset into the appropriate
207 segment. This offset is the section vma, adjusted by the vma of
208 the lowest section in that segment, plus the address of the
209 relocation. */
210 #if 0
211 val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
212 #else
213 val = bfd_get_section_vma (abfd, sec) + rel->address;
214 #endif
215
216 #ifdef DEBUG
217 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
218 __FUNCTION__, val, rel->addend, rel->howto->type);
219 #endif
220 bfd_put_32 (abfd, val, tmp_reloc.offset);
221 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
222 bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type);
223
224 if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
225 {
226 abort();
227 }
228
229 return true;
230 }
231
232 /* Mangle relocs for SPARC NetWare. We can just use the standard
233 SPARC relocs. */
234
235 static boolean
236 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
237 bfd *abfd;
238 asection *sec;
239 PTR data;
240 bfd_vma offset;
241 bfd_size_type count;
242 {
243 return true;
244 }
245
246 /* Read a NetWare sparc import record */
247 static boolean
248 nlm_sparc_read_import (abfd, sym)
249 bfd *abfd;
250 nlmNAME(symbol_type) *sym;
251 {
252 struct nlm_relent *nlm_relocs; /* relocation records for symbol */
253 bfd_size_type rcount; /* number of relocs */
254 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
255 unsigned char symlength; /* length of symbol name */
256 char *name;
257
258 /*
259 * First, read in the number of relocation
260 * entries for this symbol
261 */
262 if (bfd_read ((PTR) temp, 4, 1, abfd) != 4)
263 return false;
264
265 rcount = bfd_get_32 (abfd, temp);
266
267 /*
268 * Next, read in the length of the symbol
269 */
270
271 if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
272 != sizeof (symlength))
273 return false;
274 sym -> symbol.the_bfd = abfd;
275 name = bfd_alloc (abfd, symlength + 1);
276 if (name == NULL)
277 {
278 bfd_set_error (bfd_error_no_memory);
279 return false;
280 }
281
282 /*
283 * Then read in the symbol
284 */
285
286 if (bfd_read (name, symlength, 1, abfd) != symlength)
287 return false;
288 name[symlength] = '\0';
289 sym -> symbol.name = name;
290 sym -> symbol.flags = 0;
291 sym -> symbol.value = 0;
292 sym -> symbol.section = &bfd_und_section;
293
294 /*
295 * Next, start reading in the relocs.
296 */
297
298 nlm_relocs = ((struct nlm_relent *)
299 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
300 if (!nlm_relocs)
301 {
302 bfd_set_error (bfd_error_no_memory);
303 return false;
304 }
305 sym -> relocs = nlm_relocs;
306 sym -> rcnt = 0;
307 while (sym -> rcnt < rcount)
308 {
309 asection *section;
310
311 if (nlm_sparc_read_reloc (abfd, sym, &section,
312 &nlm_relocs -> reloc)
313 == false)
314 return false;
315 nlm_relocs -> section = section;
316 nlm_relocs++;
317 sym -> rcnt++;
318 }
319 return true;
320 }
321
322 static boolean
323 nlm_sparc_write_import (abfd, sec, rel)
324 bfd *abfd;
325 asection *sec;
326 arelent *rel;
327 {
328 char temp[4];
329 asection *code, *data, *bss, *symsec;
330 bfd_vma base;
331
332 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
333 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
334 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
335 symsec = (*rel->sym_ptr_ptr)->section;
336
337 if (symsec == code) {
338 base = 0;
339 } else if (symsec == data) {
340 base = bfd_section_size (abfd, code);
341 } else if (symsec == bss) {
342 base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
343 } else
344 base = 0;
345
346 #ifdef DEBUG
347 fprintf (stderr, "%s: <%x, 1>\n\t",
348 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
349 #endif
350 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
351 bfd_write ((PTR)temp, 4, 1, abfd);
352 bfd_put_32 (abfd, 1, temp);
353 bfd_write ((PTR)temp, 4, 1, abfd);
354 if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
355 return false;
356 return true;
357 }
358
359 /* Write out an external reference. */
360
361 static boolean
362 nlm_sparc_write_external (abfd, count, sym, relocs)
363 bfd *abfd;
364 bfd_size_type count;
365 asymbol *sym;
366 struct reloc_and_sec *relocs;
367 {
368 int i;
369 bfd_byte len;
370 unsigned char temp[NLM_TARGET_LONG_SIZE];
371
372 bfd_put_32 (abfd, count, temp);
373 if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
374 return false;
375
376 len = strlen (sym->name);
377 if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
378 || bfd_write (sym->name, len, 1, abfd) != len)
379 return false;
380
381 for (i = 0; i < count; i++)
382 {
383 if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
384 relocs[i].rel) == false)
385 return false;
386 }
387
388 return true;
389 }
390
391 static boolean
392 nlm_sparc_write_export (abfd, sym, value)
393 bfd *abfd;
394 asymbol *sym;
395 bfd_vma value;
396 {
397 bfd_byte len;
398 bfd_byte temp[4];
399
400 #ifdef DEBUG
401 fprintf (stderr, "%s: <%x, %d, %s>\n",
402 __FUNCTION__, value, strlen (sym->name), sym->name);
403 #endif
404 bfd_put_32 (abfd, value, temp);
405 len = strlen (sym->name);
406
407 if (bfd_write (temp, 4, 1, abfd) != 4
408 || bfd_write (&len, 1, 1, abfd) != 1
409 || bfd_write (sym->name, len, 1, abfd) != len)
410 return false;
411
412 return true;
413 }
414
415 #undef nlm_swap_fixed_header_in
416 #undef nlm_swap_fixed_header_out
417
418 #include "nlmswap.h"
419
420 static const struct nlm_backend_data nlm32_sparc_backend =
421 {
422 "NetWare SPARC Module \032",
423 sizeof (Nlm32_sparc_External_Fixed_Header),
424 0, /* optional_prefix_size */
425 bfd_arch_sparc,
426 0,
427 false,
428 0, /* backend_object_p */
429 0, /* write_prefix_func */
430 nlm_sparc_read_reloc,
431 nlm_sparc_mangle_relocs,
432 nlm_sparc_read_import,
433 nlm_sparc_write_import,
434 0, /* set_public_section */
435 0, /* get_public_offset */
436 nlm_swap_fixed_header_in,
437 nlm_swap_fixed_header_out,
438 nlm_sparc_write_external,
439 nlm_sparc_write_export
440 };
441
442 #define TARGET_BIG_NAME "nlm32-sparc"
443 #define TARGET_BIG_SYM nlmNAME(sparc_vec)
444 #define TARGET_BACKEND_DATA &nlm32_sparc_backend
445
446 #include "nlm-target.h"
This page took 0.069304 seconds and 5 git commands to generate.