ff0571be203b441435863990d21d0ce52310f152
[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
132 if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12) {
133 bfd_error = system_call_error;
134 return false;
135 }
136
137 *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
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 __FILE__, 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 = {0};
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 val = bfd_get_section_vma (abfd, sec) + rel->address;
211
212 #ifdef DEBUG
213 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
214 __FILE__, val, rel->addend, rel->howto->type);
215 #endif
216 bfd_put_32 (abfd, val, tmp_reloc.offset);
217 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
218 bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type);
219
220 if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
221 {
222 abort();
223 }
224
225 return true;
226 }
227
228 /* Mangle relocs for SPARC NetWare. We can just use the standard
229 SPARC relocs. */
230
231 static boolean
232 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
233 bfd *abfd;
234 asection *sec;
235 PTR data;
236 bfd_vma offset;
237 bfd_size_type count;
238 {
239 return true;
240 }
241
242 /* Read a NetWare sparc import record */
243 static boolean
244 nlm_sparc_read_import (abfd, sym)
245 bfd *abfd;
246 nlmNAME(symbol_type) *sym;
247 {
248 struct nlm_relent *nlm_relocs; /* relocation records for symbol */
249 bfd_size_type rcount; /* number of relocs */
250 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
251 unsigned char symlength; /* length of symbol name */
252
253 /*
254 * First, read in the number of relocation
255 * entries for this symbol
256 */
257 if (bfd_read ((PTR) temp, 4, 1, abfd)
258 != 4)
259 {
260 bfd_error = system_call_error;
261 return (false);
262 }
263
264 rcount = bfd_get_32 (abfd, temp);
265
266 /*
267 * Next, read in the length of the symbol
268 */
269
270 if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
271 != sizeof (symlength))
272 {
273 bfd_error = system_call_error;
274 return (false);
275 }
276 sym -> symbol.the_bfd = abfd;
277 sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
278
279 /*
280 * Then read in the symbol
281 */
282
283 if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
284 != symlength)
285 {
286 bfd_error = system_call_error;
287 return (false);
288 }
289 sym -> symbol.flags = 0;
290 sym -> symbol.value = 0;
291 sym -> symbol.section = &bfd_und_section;
292
293 /*
294 * Next, start reading in the relocs.
295 */
296
297 nlm_relocs = ((struct nlm_relent *)
298 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
299 sym -> relocs = nlm_relocs;
300 sym -> rcnt = 0;
301 while (sym -> rcnt < rcount)
302 {
303 asection *section;
304
305 if (nlm_sparc_read_reloc (abfd, sym, &section,
306 &nlm_relocs -> reloc)
307 == false)
308 return false;
309 nlm_relocs -> section = section;
310 nlm_relocs++;
311 sym -> rcnt++;
312 }
313 return true;
314 }
315
316 static boolean
317 nlm_sparc_write_import (abfd, sec, rel)
318 bfd *abfd;
319 asection *sec;
320 arelent *rel;
321 {
322 char temp[4];
323
324 bfd_put_32 (abfd, (*rel->sym_ptr_ptr)->value, temp);
325 bfd_write ((PTR)temp, 4, 1, abfd);
326 bfd_put_32 (abfd, 1, temp);
327 bfd_write ((PTR)temp, 4, 1, abfd);
328 if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
329 return false;
330 return true;
331 }
332
333 /* Write out an external reference. */
334
335 static boolean
336 nlm_sparc_write_external (abfd, count, sym, relocs)
337 bfd *abfd;
338 bfd_size_type count;
339 asymbol *sym;
340 struct reloc_and_sec *relocs;
341 {
342 int i;
343 bfd_byte len;
344 unsigned char temp[NLM_TARGET_LONG_SIZE];
345
346 bfd_put_32 (abfd, count, temp);
347 if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
348 {
349 bfd_error = system_call_error;
350 return false;
351 }
352
353 len = strlen (sym->name);
354 if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
355 || bfd_write (sym->name, len, 1, abfd) != len)
356 {
357 bfd_error = system_call_error;
358 return false;
359 }
360
361 for (i = 0; i < count; i++)
362 {
363 if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
364 relocs[i].rel) == false)
365 return false;
366 }
367
368 return true;
369 }
370
371 #undef nlm_swap_fixed_header_in
372 #undef nlm_swap_fixed_header_out
373
374 #include "nlmswap.h"
375
376 static const struct nlm_backend_data nlm32_sparc_backend =
377 {
378 "NetWare SPARC Module \032",
379 sizeof (Nlm32_sparc_External_Fixed_Header),
380 0, /* optional_prefix_size */
381 bfd_arch_sparc,
382 0,
383 0, /* backend_object_p */
384 0, /* write_prefix_func */
385 nlm_sparc_read_reloc,
386 nlm_sparc_mangle_relocs,
387 nlm_sparc_read_import,
388 nlm_sparc_write_import,
389 0, /* set_public_section */
390 0, /* get_public_offset */
391 nlm_swap_fixed_header_in,
392 nlm_swap_fixed_header_out,
393 nlm_sparc_write_external,
394 };
395
396 #define TARGET_BIG_NAME "nlm32-sparc"
397 #define TARGET_BIG_SYM nlmNAME(sparc_vec)
398 #define TARGET_BACKEND_DATA &nlm32_sparc_backend
399
400 #include "nlm-target.h"
This page took 0.038528 seconds and 4 git commands to generate.