* libbfd.c (bfd_read): Set bfd_error as appropriate for a short
[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 return false;
135
136 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
137 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
138
139 *secp = code_sec;
140
141 val = bfd_get_32 (abfd, tmp_reloc.offset);
142 addend = bfd_get_32 (abfd, tmp_reloc.addend);
143 type = bfd_get_8 (abfd, tmp_reloc.type);
144
145 rel->address = val;
146 rel->addend = addend;
147 rel->howto = NULL;
148
149 for (index = 0;
150 index < sizeof(nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
151 index++)
152 if (nlm32_sparc_howto_table[index].type == type) {
153 rel->howto = &nlm32_sparc_howto_table[index];
154 break;
155 }
156
157 #ifdef DEBUG
158 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
159 __FUNCTION__, rel->address, rel->addend, type, rel->howto);
160 #endif
161 return true;
162
163 }
164
165 /* Write a NetWare sparc reloc. */
166
167 static boolean
168 nlm_sparc_write_reloc (abfd, sec, rel)
169 bfd *abfd;
170 asection *sec;
171 arelent *rel;
172 {
173 bfd_vma val;
174 struct nlm32_sparc_reloc_ext tmp_reloc;
175 int index;
176 int type = -1;
177 reloc_howto_type *tmp;
178
179
180 for (index = 0;
181 index < sizeof (nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
182 index++) {
183 tmp = &nlm32_sparc_howto_table[index];
184
185 if (tmp->rightshift == rel->howto->rightshift
186 && tmp->size == rel->howto->size
187 && tmp->bitsize == rel->howto->bitsize
188 && tmp->pc_relative == rel->howto->pc_relative
189 && tmp->bitpos == rel->howto->bitpos
190 && tmp->src_mask == rel->howto->src_mask
191 && tmp->dst_mask == rel->howto->dst_mask) {
192 type = tmp->type;
193 break;
194 }
195 }
196 if (type == -1)
197 abort();
198
199 /*
200 * Netware wants a list of relocs for each address.
201 * Format is:
202 * long offset
203 * long addend
204 * char type
205 * That should be it.
206 */
207
208 /* The value we write out is the offset into the appropriate
209 segment. This offset is the section vma, adjusted by the vma of
210 the lowest section in that segment, plus the address of the
211 relocation. */
212 #if 0
213 val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
214 #else
215 val = bfd_get_section_vma (abfd, sec) + rel->address;
216 #endif
217
218 #ifdef DEBUG
219 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
220 __FUNCTION__, val, rel->addend, rel->howto->type);
221 #endif
222 bfd_put_32 (abfd, val, tmp_reloc.offset);
223 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
224 bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type);
225
226 if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
227 {
228 abort();
229 }
230
231 return true;
232 }
233
234 /* Mangle relocs for SPARC NetWare. We can just use the standard
235 SPARC relocs. */
236
237 static boolean
238 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
239 bfd *abfd;
240 asection *sec;
241 PTR data;
242 bfd_vma offset;
243 bfd_size_type count;
244 {
245 return true;
246 }
247
248 /* Read a NetWare sparc import record */
249 static boolean
250 nlm_sparc_read_import (abfd, sym)
251 bfd *abfd;
252 nlmNAME(symbol_type) *sym;
253 {
254 struct nlm_relent *nlm_relocs; /* relocation records for symbol */
255 bfd_size_type rcount; /* number of relocs */
256 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
257 unsigned char symlength; /* length of symbol name */
258
259 /*
260 * First, read in the number of relocation
261 * entries for this symbol
262 */
263 if (bfd_read ((PTR) temp, 4, 1, abfd) != 4)
264 return false;
265
266 rcount = bfd_get_32 (abfd, temp);
267
268 /*
269 * Next, read in the length of the symbol
270 */
271
272 if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
273 != sizeof (symlength))
274 return false;
275 sym -> symbol.the_bfd = abfd;
276 sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
277 if (!sym -> symbol.name)
278 {
279 bfd_set_error (bfd_error_no_memory);
280 return false;
281 }
282
283 /*
284 * Then read in the symbol
285 */
286
287 if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
288 != symlength)
289 return false;
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.040561 seconds and 4 git commands to generate.