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, 1994, 1995, 1999 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ATTRIBUTE_UNUSED;
122 asection **secp;
123 arelent *rel;
124 {
125 bfd_vma val, addend;
126 unsigned 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 unsigned 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 return false;
226
227 return true;
228 }
229
230 /* Mangle relocs for SPARC NetWare. We can just use the standard
231 SPARC relocs. */
232
233 static boolean
234 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
235 bfd *abfd ATTRIBUTE_UNUSED;
236 asection *sec ATTRIBUTE_UNUSED;
237 PTR data ATTRIBUTE_UNUSED;
238 bfd_vma offset ATTRIBUTE_UNUSED;
239 bfd_size_type count ATTRIBUTE_UNUSED;
240 {
241 return true;
242 }
243
244 /* Read a NetWare sparc import record */
245 static boolean
246 nlm_sparc_read_import (abfd, sym)
247 bfd *abfd;
248 nlmNAME(symbol_type) *sym;
249 {
250 struct nlm_relent *nlm_relocs; /* relocation records for symbol */
251 bfd_size_type rcount; /* number of relocs */
252 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
253 unsigned char symlength; /* length of symbol name */
254 char *name;
255
256 /*
257 * First, read in the number of relocation
258 * entries for this symbol
259 */
260 if (bfd_read ((PTR) temp, 4, 1, abfd) != 4)
261 return false;
262
263 rcount = bfd_get_32 (abfd, temp);
264
265 /*
266 * Next, read in the length of the symbol
267 */
268
269 if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
270 != sizeof (symlength))
271 return false;
272 sym -> symbol.the_bfd = abfd;
273 name = bfd_alloc (abfd, symlength + 1);
274 if (name == NULL)
275 return false;
276
277 /*
278 * Then read in the symbol
279 */
280
281 if (bfd_read (name, symlength, 1, abfd) != symlength)
282 return false;
283 name[symlength] = '\0';
284 sym -> symbol.name = name;
285 sym -> symbol.flags = 0;
286 sym -> symbol.value = 0;
287 sym -> symbol.section = bfd_und_section_ptr;
288
289 /*
290 * Next, start reading in the relocs.
291 */
292
293 nlm_relocs = ((struct nlm_relent *)
294 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
295 if (!nlm_relocs)
296 return false;
297 sym -> relocs = nlm_relocs;
298 sym -> rcnt = 0;
299 while (sym -> rcnt < rcount)
300 {
301 asection *section;
302
303 if (nlm_sparc_read_reloc (abfd, sym, &section,
304 &nlm_relocs -> reloc)
305 == false)
306 return false;
307 nlm_relocs -> section = section;
308 nlm_relocs++;
309 sym -> rcnt++;
310 }
311 return true;
312 }
313
314 static boolean
315 nlm_sparc_write_import (abfd, sec, rel)
316 bfd *abfd;
317 asection *sec;
318 arelent *rel;
319 {
320 char temp[4];
321 asection *code, *data, *bss, *symsec;
322 bfd_vma base;
323
324 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
325 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
326 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
327 symsec = (*rel->sym_ptr_ptr)->section;
328
329 if (symsec == code) {
330 base = 0;
331 } else if (symsec == data) {
332 base = bfd_section_size (abfd, code);
333 } else if (symsec == bss) {
334 base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
335 } else
336 base = 0;
337
338 #ifdef DEBUG
339 fprintf (stderr, "%s: <%x, 1>\n\t",
340 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
341 #endif
342 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
343 if (bfd_write ((PTR)temp, 4, 1, abfd) != 4)
344 return false;
345 bfd_put_32 (abfd, 1, temp);
346 if (bfd_write ((PTR)temp, 4, 1, abfd) != 4)
347 return false;
348 if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
349 return false;
350 return true;
351 }
352
353 /* Write out an external reference. */
354
355 static boolean
356 nlm_sparc_write_external (abfd, count, sym, relocs)
357 bfd *abfd;
358 bfd_size_type count;
359 asymbol *sym;
360 struct reloc_and_sec *relocs;
361 {
362 unsigned int i;
363 bfd_byte len;
364 unsigned char temp[NLM_TARGET_LONG_SIZE];
365
366 bfd_put_32 (abfd, count, temp);
367 if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
368 return false;
369
370 len = strlen (sym->name);
371 if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
372 || bfd_write (sym->name, len, 1, abfd) != len)
373 return false;
374
375 for (i = 0; i < count; i++)
376 {
377 if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
378 relocs[i].rel) == false)
379 return false;
380 }
381
382 return true;
383 }
384
385 static boolean
386 nlm_sparc_write_export (abfd, sym, value)
387 bfd *abfd;
388 asymbol *sym;
389 bfd_vma value;
390 {
391 bfd_byte len;
392 bfd_byte temp[4];
393
394 #ifdef DEBUG
395 fprintf (stderr, "%s: <%x, %d, %s>\n",
396 __FUNCTION__, value, strlen (sym->name), sym->name);
397 #endif
398 bfd_put_32 (abfd, value, temp);
399 len = strlen (sym->name);
400
401 if (bfd_write (temp, 4, 1, abfd) != 4
402 || bfd_write (&len, 1, 1, abfd) != 1
403 || bfd_write (sym->name, len, 1, abfd) != len)
404 return false;
405
406 return true;
407 }
408
409 #undef nlm_swap_fixed_header_in
410 #undef nlm_swap_fixed_header_out
411
412 #include "nlmswap.h"
413
414 static const struct nlm_backend_data nlm32_sparc_backend =
415 {
416 "NetWare SPARC Module \032",
417 sizeof (Nlm32_sparc_External_Fixed_Header),
418 0, /* optional_prefix_size */
419 bfd_arch_sparc,
420 0,
421 false,
422 0, /* backend_object_p */
423 0, /* write_prefix_func */
424 nlm_sparc_read_reloc,
425 nlm_sparc_mangle_relocs,
426 nlm_sparc_read_import,
427 nlm_sparc_write_import,
428 0, /* set_public_section */
429 0, /* get_public_offset */
430 nlm_swap_fixed_header_in,
431 nlm_swap_fixed_header_out,
432 nlm_sparc_write_external,
433 nlm_sparc_write_export
434 };
435
436 #define TARGET_BIG_NAME "nlm32-sparc"
437 #define TARGET_BIG_SYM nlmNAME(sparc_vec)
438 #define TARGET_BACKEND_DATA &nlm32_sparc_backend
439
440 #include "nlm-target.h"
This page took 0.058765 seconds and 5 git commands to generate.