* libbfd.c (bfd_read): Set bfd_error as appropriate for a short
[deliverable/binutils-gdb.git] / bfd / nlm32-sparc.c
CommitLineData
cdbfad1c
ILT
1/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2 Copyright (C) 1993 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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
31static boolean nlm_sparc_read_reloc
32 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
33static boolean nlm_sparc_write_reloc
34 PARAMS ((bfd *, asection *, arelent *));
35static boolean nlm_sparc_mangle_relocs
36 PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
37static boolean nlm_sparc_read_import
38 PARAMS ((bfd *, nlmNAME(symbol_type) *));
39static boolean nlm_sparc_write_import
40 PARAMS ((bfd *, asection *, arelent *));
41static boolean nlm_sparc_write_external
42 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
43
44enum 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
63static 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
81static 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
111struct 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
118static boolean
119nlm_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;
df561b14 131 asection *code_sec, *data_sec;
cdbfad1c 132
25057836 133 if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12)
cdbfad1c 134 return false;
cdbfad1c 135
df561b14
SEF
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;
cdbfad1c
ILT
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",
df561b14 159 __FUNCTION__, rel->address, rel->addend, type, rel->howto);
cdbfad1c
ILT
160#endif
161 return true;
162
163}
164
165/* Write a NetWare sparc reloc. */
166
167static boolean
168nlm_sparc_write_reloc (abfd, sec, rel)
169 bfd *abfd;
170 asection *sec;
171 arelent *rel;
172{
173 bfd_vma val;
9783e04a 174 struct nlm32_sparc_reloc_ext tmp_reloc;
cdbfad1c
ILT
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. */
df561b14
SEF
212#if 0
213 val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
214#else
cdbfad1c 215 val = bfd_get_section_vma (abfd, sec) + rel->address;
df561b14 216#endif
cdbfad1c
ILT
217
218#ifdef DEBUG
219 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
df561b14 220 __FUNCTION__, val, rel->addend, rel->howto->type);
cdbfad1c
ILT
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
237static boolean
238nlm_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 */
249static boolean
250nlm_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 */
25057836
JL
263 if (bfd_read ((PTR) temp, 4, 1, abfd) != 4)
264 return false;
cdbfad1c
ILT
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))
25057836 274 return false;
cdbfad1c
ILT
275 sym -> symbol.the_bfd = abfd;
276 sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
9783e04a
DM
277 if (!sym -> symbol.name)
278 {
25057836 279 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
280 return false;
281 }
cdbfad1c
ILT
282
283 /*
284 * Then read in the symbol
285 */
286
287 if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
288 != symlength)
25057836 289 return false;
cdbfad1c
ILT
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)));
9783e04a
DM
300 if (!nlm_relocs)
301 {
25057836 302 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
303 return false;
304 }
cdbfad1c
ILT
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
322static boolean
323nlm_sparc_write_import (abfd, sec, rel)
324 bfd *abfd;
325 asection *sec;
326 arelent *rel;
327{
328 char temp[4];
df561b14
SEF
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;
cdbfad1c 345
df561b14
SEF
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);
cdbfad1c
ILT
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
361static boolean
362nlm_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))
25057836 374 return false;
cdbfad1c
ILT
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)
25057836 379 return false;
cdbfad1c
ILT
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
df561b14
SEF
391static boolean
392nlm_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)
25057836 410 return false;
df561b14
SEF
411
412 return true;
413}
414
cdbfad1c
ILT
415#undef nlm_swap_fixed_header_in
416#undef nlm_swap_fixed_header_out
417
418#include "nlmswap.h"
419
420static 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,
df561b14 427 false,
cdbfad1c
ILT
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,
df561b14 439 nlm_sparc_write_export
cdbfad1c
ILT
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.054521 seconds and 4 git commands to generate.