The sparc (and possibly other?) NLM format requires a different way to
[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_byte temp[4];
126 bfd_vma val, addend;
127 const char *name;
128 int index;
129 unsigned int type;
130 struct nlm32_sparc_reloc_ext tmp_reloc;
131 asection *code_sec, *data_sec;
132
133 if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12) {
134 bfd_error = system_call_error;
135 return false;
136 }
137
138 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
139 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
140
141 *secp = code_sec;
142
143 val = bfd_get_32 (abfd, tmp_reloc.offset);
144 addend = bfd_get_32 (abfd, tmp_reloc.addend);
145 type = bfd_get_8 (abfd, tmp_reloc.type);
146
147 rel->address = val;
148 rel->addend = addend;
149 rel->howto = NULL;
150
151 for (index = 0;
152 index < sizeof(nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
153 index++)
154 if (nlm32_sparc_howto_table[index].type == type) {
155 rel->howto = &nlm32_sparc_howto_table[index];
156 break;
157 }
158
159 #ifdef DEBUG
160 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
161 __FUNCTION__, rel->address, rel->addend, type, rel->howto);
162 #endif
163 return true;
164
165 }
166
167 /* Write a NetWare sparc reloc. */
168
169 static boolean
170 nlm_sparc_write_reloc (abfd, sec, rel)
171 bfd *abfd;
172 asection *sec;
173 arelent *rel;
174 {
175 bfd_vma val;
176 struct nlm32_sparc_reloc_ext tmp_reloc = {0};
177 int index;
178 int type = -1;
179 reloc_howto_type *tmp;
180
181
182 for (index = 0;
183 index < sizeof (nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
184 index++) {
185 tmp = &nlm32_sparc_howto_table[index];
186
187 if (tmp->rightshift == rel->howto->rightshift
188 && tmp->size == rel->howto->size
189 && tmp->bitsize == rel->howto->bitsize
190 && tmp->pc_relative == rel->howto->pc_relative
191 && tmp->bitpos == rel->howto->bitpos
192 && tmp->src_mask == rel->howto->src_mask
193 && tmp->dst_mask == rel->howto->dst_mask) {
194 type = tmp->type;
195 break;
196 }
197 }
198 if (type == -1)
199 abort();
200
201 /*
202 * Netware wants a list of relocs for each address.
203 * Format is:
204 * long offset
205 * long addend
206 * char type
207 * That should be it.
208 */
209
210 /* The value we write out is the offset into the appropriate
211 segment. This offset is the section vma, adjusted by the vma of
212 the lowest section in that segment, plus the address of the
213 relocation. */
214 #if 0
215 val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
216 #else
217 val = bfd_get_section_vma (abfd, sec) + rel->address;
218 #endif
219
220 #ifdef DEBUG
221 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
222 __FUNCTION__, val, rel->addend, rel->howto->type);
223 #endif
224 bfd_put_32 (abfd, val, tmp_reloc.offset);
225 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
226 bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type);
227
228 if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
229 {
230 abort();
231 }
232
233 return true;
234 }
235
236 /* Mangle relocs for SPARC NetWare. We can just use the standard
237 SPARC relocs. */
238
239 static boolean
240 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
241 bfd *abfd;
242 asection *sec;
243 PTR data;
244 bfd_vma offset;
245 bfd_size_type count;
246 {
247 return true;
248 }
249
250 /* Read a NetWare sparc import record */
251 static boolean
252 nlm_sparc_read_import (abfd, sym)
253 bfd *abfd;
254 nlmNAME(symbol_type) *sym;
255 {
256 struct nlm_relent *nlm_relocs; /* relocation records for symbol */
257 bfd_size_type rcount; /* number of relocs */
258 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
259 unsigned char symlength; /* length of symbol name */
260
261 /*
262 * First, read in the number of relocation
263 * entries for this symbol
264 */
265 if (bfd_read ((PTR) temp, 4, 1, abfd)
266 != 4)
267 {
268 bfd_error = system_call_error;
269 return (false);
270 }
271
272 rcount = bfd_get_32 (abfd, temp);
273
274 /*
275 * Next, read in the length of the symbol
276 */
277
278 if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
279 != sizeof (symlength))
280 {
281 bfd_error = system_call_error;
282 return (false);
283 }
284 sym -> symbol.the_bfd = abfd;
285 sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
286
287 /*
288 * Then read in the symbol
289 */
290
291 if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
292 != symlength)
293 {
294 bfd_error = system_call_error;
295 return (false);
296 }
297 sym -> symbol.flags = 0;
298 sym -> symbol.value = 0;
299 sym -> symbol.section = &bfd_und_section;
300
301 /*
302 * Next, start reading in the relocs.
303 */
304
305 nlm_relocs = ((struct nlm_relent *)
306 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
307 sym -> relocs = nlm_relocs;
308 sym -> rcnt = 0;
309 while (sym -> rcnt < rcount)
310 {
311 asection *section;
312
313 if (nlm_sparc_read_reloc (abfd, sym, &section,
314 &nlm_relocs -> reloc)
315 == false)
316 return false;
317 nlm_relocs -> section = section;
318 nlm_relocs++;
319 sym -> rcnt++;
320 }
321 return true;
322 }
323
324 static boolean
325 nlm_sparc_write_import (abfd, sec, rel)
326 bfd *abfd;
327 asection *sec;
328 arelent *rel;
329 {
330 char temp[4];
331 asection *code, *data, *bss, *symsec;
332 bfd_vma base;
333
334 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
335 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
336 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
337 symsec = (*rel->sym_ptr_ptr)->section;
338
339 if (symsec == code) {
340 base = 0;
341 } else if (symsec == data) {
342 base = bfd_section_size (abfd, code);
343 } else if (symsec == bss) {
344 base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
345 } else
346 base = 0;
347
348 #ifdef DEBUG
349 fprintf (stderr, "%s: <%x, 1>\n\t",
350 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
351 #endif
352 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
353 bfd_write ((PTR)temp, 4, 1, abfd);
354 bfd_put_32 (abfd, 1, temp);
355 bfd_write ((PTR)temp, 4, 1, abfd);
356 if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
357 return false;
358 return true;
359 }
360
361 /* Write out an external reference. */
362
363 static boolean
364 nlm_sparc_write_external (abfd, count, sym, relocs)
365 bfd *abfd;
366 bfd_size_type count;
367 asymbol *sym;
368 struct reloc_and_sec *relocs;
369 {
370 int i;
371 bfd_byte len;
372 unsigned char temp[NLM_TARGET_LONG_SIZE];
373
374 bfd_put_32 (abfd, count, temp);
375 if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
376 {
377 bfd_error = system_call_error;
378 return false;
379 }
380
381 len = strlen (sym->name);
382 if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
383 || bfd_write (sym->name, len, 1, abfd) != len)
384 {
385 bfd_error = system_call_error;
386 return false;
387 }
388
389 for (i = 0; i < count; i++)
390 {
391 if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
392 relocs[i].rel) == false)
393 return false;
394 }
395
396 return true;
397 }
398
399 static boolean
400 nlm_sparc_write_export (abfd, sym, value)
401 bfd *abfd;
402 asymbol *sym;
403 bfd_vma value;
404 {
405 bfd_byte len;
406 bfd_byte temp[4];
407
408 #ifdef DEBUG
409 fprintf (stderr, "%s: <%x, %d, %s>\n",
410 __FUNCTION__, value, strlen (sym->name), sym->name);
411 #endif
412 bfd_put_32 (abfd, value, temp);
413 len = strlen (sym->name);
414
415 if (bfd_write (temp, 4, 1, abfd) != 4
416 || bfd_write (&len, 1, 1, abfd) != 1
417 || bfd_write (sym->name, len, 1, abfd) != len)
418 {
419 bfd_error = system_call_error;
420 return false;
421 }
422
423 return true;
424 }
425
426 #undef nlm_swap_fixed_header_in
427 #undef nlm_swap_fixed_header_out
428
429 #include "nlmswap.h"
430
431 static const struct nlm_backend_data nlm32_sparc_backend =
432 {
433 "NetWare SPARC Module \032",
434 sizeof (Nlm32_sparc_External_Fixed_Header),
435 0, /* optional_prefix_size */
436 bfd_arch_sparc,
437 0,
438 false,
439 0, /* backend_object_p */
440 0, /* write_prefix_func */
441 nlm_sparc_read_reloc,
442 nlm_sparc_mangle_relocs,
443 nlm_sparc_read_import,
444 nlm_sparc_write_import,
445 0, /* set_public_section */
446 0, /* get_public_offset */
447 nlm_swap_fixed_header_in,
448 nlm_swap_fixed_header_out,
449 nlm_sparc_write_external,
450 nlm_sparc_write_export
451 };
452
453 #define TARGET_BIG_NAME "nlm32-sparc"
454 #define TARGET_BIG_SYM nlmNAME(sparc_vec)
455 #define TARGET_BACKEND_DATA &nlm32_sparc_backend
456
457 #include "nlm-target.h"
This page took 0.041864 seconds and 5 git commands to generate.