* reloc.c: Add BFD_RELOC_XSTORMY16_12.
[deliverable/binutils-gdb.git] / bfd / nlm32-sparc.c
CommitLineData
252b5132 1/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
82e51918 2 Copyright 1993, 1994, 2000, 2001, 2002 Free Software Foundation, Inc.
252b5132 3
42ef282f 4 This file is part of BFD, the Binary File Descriptor library.
252b5132 5
42ef282f
NC
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.
252b5132 10
42ef282f
NC
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.
252b5132 15
42ef282f
NC
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. */
252b5132
RH
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
b34976b6 31static bfd_boolean nlm_sparc_read_reloc
252b5132 32 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
b34976b6 33static bfd_boolean nlm_sparc_write_reloc
252b5132 34 PARAMS ((bfd *, asection *, arelent *));
b34976b6 35static bfd_boolean nlm_sparc_mangle_relocs
252b5132 36 PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
b34976b6 37static bfd_boolean nlm_sparc_read_import
252b5132 38 PARAMS ((bfd *, nlmNAME(symbol_type) *));
b34976b6 39static bfd_boolean nlm_sparc_write_import
252b5132 40 PARAMS ((bfd *, asection *, arelent *));
b34976b6 41static bfd_boolean nlm_sparc_write_external
252b5132 42 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
b34976b6 43static bfd_boolean nlm_sparc_write_export
42ef282f 44 PARAMS ((bfd *, asymbol *, bfd_vma));
252b5132
RH
45
46enum reloc_type
47 {
48 R_SPARC_NONE = 0,
1518639e
KH
49 R_SPARC_8, R_SPARC_16, R_SPARC_32,
50 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
252b5132
RH
51 R_SPARC_WDISP30, R_SPARC_WDISP22,
52 R_SPARC_HI22, R_SPARC_22,
53 R_SPARC_13, R_SPARC_LO10,
54 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
55 R_SPARC_PC10, R_SPARC_PC22,
56 R_SPARC_WPLT30,
57 R_SPARC_COPY,
58 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
59 R_SPARC_RELATIVE,
60 R_SPARC_UA32,
61 R_SPARC_max
62 };
63
64#if 0
dc810e39 65static const char *const reloc_type_names[] =
42ef282f
NC
66 {
67 "R_SPARC_NONE",
68 "R_SPARC_8", "R_SPARC_16", "R_SPARC_32",
69 "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32",
70 "R_SPARC_WDISP30", "R_SPARC_WDISP22",
71 "R_SPARC_HI22", "R_SPARC_22",
72 "R_SPARC_13", "R_SPARC_LO10",
73 "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22",
74 "R_SPARC_PC10", "R_SPARC_PC22",
75 "R_SPARC_WPLT30",
76 "R_SPARC_COPY",
77 "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
78 "R_SPARC_RELATIVE",
79 "R_SPARC_UA32",
80 };
252b5132
RH
81#endif
82
1518639e 83static reloc_howto_type nlm32_sparc_howto_table[] =
42ef282f 84 {
b34976b6
AM
85 HOWTO (R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, 0,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE),
86 HOWTO (R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8", FALSE,0,0x000000ff,TRUE),
87 HOWTO (R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE),
88 HOWTO (R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32", FALSE,0,0xffffffff,TRUE),
89 HOWTO (R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE),
90 HOWTO (R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE),
91 HOWTO (R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE),
92 HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
93 HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
94 HOWTO (R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, 0,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE),
95 HOWTO (R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22", FALSE,0,0x003fffff,TRUE),
96 HOWTO (R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13", FALSE,0,0x00001fff,TRUE),
97 HOWTO (R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, 0,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE),
98 HOWTO (R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE),
99 HOWTO (R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE),
100 HOWTO (R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE),
101 HOWTO (R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE),
102 HOWTO (R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE),
103 HOWTO (R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE),
104 HOWTO (R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE),
105 HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE),
106 HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE),
107 HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
108 HOWTO (R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE),
252b5132
RH
109};
110
111/* Read a NetWare sparc reloc. */
112
42ef282f
NC
113struct nlm32_sparc_reloc_ext
114 {
115 unsigned char offset[4];
116 unsigned char addend[4];
117 unsigned char type[1];
118 unsigned char pad1[3];
119 };
252b5132 120
b34976b6 121static bfd_boolean
252b5132
RH
122nlm_sparc_read_reloc (abfd, sym, secp, rel)
123 bfd *abfd;
5f771d47 124 nlmNAME(symbol_type) *sym ATTRIBUTE_UNUSED;
252b5132
RH
125 asection **secp;
126 arelent *rel;
127{
128 bfd_vma val, addend;
129 unsigned int index;
130 unsigned int type;
131 struct nlm32_sparc_reloc_ext tmp_reloc;
132 asection *code_sec, *data_sec;
133
dc810e39 134 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
b34976b6 135 return FALSE;
252b5132
RH
136
137 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
138 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
139
140 *secp = code_sec;
141
142 val = bfd_get_32 (abfd, tmp_reloc.offset);
143 addend = bfd_get_32 (abfd, tmp_reloc.addend);
144 type = bfd_get_8 (abfd, tmp_reloc.type);
145
146 rel->address = val;
147 rel->addend = addend;
148 rel->howto = NULL;
149
150 for (index = 0;
1518639e 151 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
252b5132 152 index++)
42ef282f
NC
153 if (nlm32_sparc_howto_table[index].type == type)
154 {
155 rel->howto = &nlm32_sparc_howto_table[index];
156 break;
157 }
252b5132
RH
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
b34976b6 163 return TRUE;
252b5132
RH
164
165}
166
167/* Write a NetWare sparc reloc. */
168
b34976b6 169static bfd_boolean
252b5132
RH
170nlm_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;
177 unsigned int index;
178 int type = -1;
179 reloc_howto_type *tmp;
180
252b5132 181 for (index = 0;
1518639e 182 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
42ef282f
NC
183 index++)
184 {
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 {
195 type = tmp->type;
196 break;
197 }
252b5132 198 }
252b5132 199 if (type == -1)
1518639e 200 abort ();
252b5132 201
42ef282f
NC
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. */
252b5132
RH
208
209 /* The value we write out is the offset into the appropriate
210 segment. This offset is the section vma, adjusted by the vma of
211 the lowest section in that segment, plus the address of the
212 relocation. */
213#if 0
214 val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
215#else
216 val = bfd_get_section_vma (abfd, sec) + rel->address;
217#endif
218
219#ifdef DEBUG
220 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
221 __FUNCTION__, val, rel->addend, rel->howto->type);
222#endif
223 bfd_put_32 (abfd, val, tmp_reloc.offset);
224 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
1518639e 225 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
252b5132 226
dc810e39 227 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
b34976b6 228 return FALSE;
252b5132 229
b34976b6 230 return TRUE;
252b5132
RH
231}
232
233/* Mangle relocs for SPARC NetWare. We can just use the standard
234 SPARC relocs. */
235
b34976b6 236static bfd_boolean
252b5132 237nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
5f771d47
ILT
238 bfd *abfd ATTRIBUTE_UNUSED;
239 asection *sec ATTRIBUTE_UNUSED;
240 PTR data ATTRIBUTE_UNUSED;
241 bfd_vma offset ATTRIBUTE_UNUSED;
242 bfd_size_type count ATTRIBUTE_UNUSED;
252b5132 243{
b34976b6 244 return TRUE;
252b5132
RH
245}
246
42ef282f
NC
247/* Read a NetWare sparc import record. */
248
b34976b6 249static bfd_boolean
252b5132
RH
250nlm_sparc_read_import (abfd, sym)
251 bfd *abfd;
252 nlmNAME(symbol_type) *sym;
253{
42ef282f
NC
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. */
252b5132 258 char *name;
1518639e 259
42ef282f
NC
260 /* First, read in the number of relocation
261 entries for this symbol. */
dc810e39 262 if (bfd_bread ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 263 return FALSE;
1518639e 264
252b5132 265 rcount = bfd_get_32 (abfd, temp);
1518639e 266
42ef282f 267 /* Next, read in the length of the symbol. */
1518639e 268
dc810e39 269 if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
252b5132 270 != sizeof (symlength))
b34976b6 271 return FALSE;
252b5132 272 sym -> symbol.the_bfd = abfd;
dc810e39 273 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
252b5132 274 if (name == NULL)
b34976b6 275 return FALSE;
1518639e 276
42ef282f 277 /* Then read in the symbol. */
1518639e 278
dc810e39 279 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
b34976b6 280 return FALSE;
252b5132
RH
281 name[symlength] = '\0';
282 sym -> symbol.name = name;
283 sym -> symbol.flags = 0;
284 sym -> symbol.value = 0;
285 sym -> symbol.section = bfd_und_section_ptr;
1518639e 286
42ef282f 287 /* Next, start reading in the relocs. */
1518639e 288
252b5132
RH
289 nlm_relocs = ((struct nlm_relent *)
290 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
291 if (!nlm_relocs)
b34976b6 292 return FALSE;
252b5132
RH
293 sym -> relocs = nlm_relocs;
294 sym -> rcnt = 0;
295 while (sym -> rcnt < rcount)
296 {
297 asection *section;
1518639e 298
82e51918 299 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
b34976b6 300 return FALSE;
252b5132
RH
301 nlm_relocs -> section = section;
302 nlm_relocs++;
303 sym -> rcnt++;
304 }
42ef282f 305
b34976b6 306 return TRUE;
252b5132
RH
307}
308
b34976b6 309static bfd_boolean
252b5132
RH
310nlm_sparc_write_import (abfd, sec, rel)
311 bfd *abfd;
312 asection *sec;
313 arelent *rel;
314{
315 char temp[4];
316 asection *code, *data, *bss, *symsec;
317 bfd_vma base;
318
319 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
320 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
321 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
322 symsec = (*rel->sym_ptr_ptr)->section;
323
42ef282f 324 if (symsec == code)
252b5132 325 base = 0;
42ef282f 326 else if (symsec == data)
252b5132 327 base = bfd_section_size (abfd, code);
42ef282f 328 else if (symsec == bss)
252b5132 329 base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
42ef282f 330 else
252b5132
RH
331 base = 0;
332
333#ifdef DEBUG
334 fprintf (stderr, "%s: <%x, 1>\n\t",
335 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
336#endif
337 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
dc810e39 338 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 339 return FALSE;
dc810e39
AM
340 bfd_put_32 (abfd, (bfd_vma) 1, temp);
341 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 342 return FALSE;
82e51918 343 if (! nlm_sparc_write_reloc (abfd, sec, rel))
b34976b6
AM
344 return FALSE;
345 return TRUE;
252b5132
RH
346}
347
348/* Write out an external reference. */
349
b34976b6 350static bfd_boolean
252b5132
RH
351nlm_sparc_write_external (abfd, count, sym, relocs)
352 bfd *abfd;
353 bfd_size_type count;
354 asymbol *sym;
355 struct reloc_and_sec *relocs;
356{
357 unsigned int i;
358 bfd_byte len;
359 unsigned char temp[NLM_TARGET_LONG_SIZE];
360
361 bfd_put_32 (abfd, count, temp);
dc810e39 362 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
b34976b6 363 return FALSE;
252b5132
RH
364
365 len = strlen (sym->name);
dc810e39
AM
366 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
367 != sizeof (bfd_byte))
368 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
b34976b6 369 return FALSE;
252b5132
RH
370
371 for (i = 0; i < count; i++)
372 {
82e51918 373 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
b34976b6 374 return FALSE;
252b5132
RH
375 }
376
b34976b6 377 return TRUE;
252b5132
RH
378}
379
b34976b6 380static bfd_boolean
252b5132
RH
381nlm_sparc_write_export (abfd, sym, value)
382 bfd *abfd;
383 asymbol *sym;
384 bfd_vma value;
385{
386 bfd_byte len;
387 bfd_byte temp[4];
388
389#ifdef DEBUG
390 fprintf (stderr, "%s: <%x, %d, %s>\n",
391 __FUNCTION__, value, strlen (sym->name), sym->name);
392#endif
393 bfd_put_32 (abfd, value, temp);
394 len = strlen (sym->name);
395
dc810e39
AM
396 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
397 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
398 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
b34976b6 399 return FALSE;
252b5132 400
b34976b6 401 return TRUE;
252b5132
RH
402}
403
404#undef nlm_swap_fixed_header_in
405#undef nlm_swap_fixed_header_out
406
407#include "nlmswap.h"
408
409static const struct nlm_backend_data nlm32_sparc_backend =
42ef282f
NC
410 {
411 "NetWare SPARC Module \032",
412 sizeof (Nlm32_sparc_External_Fixed_Header),
413 0, /* optional_prefix_size */
414 bfd_arch_sparc,
415 0,
b34976b6 416 FALSE,
42ef282f
NC
417 0, /* backend_object_p */
418 0, /* write_prefix_func */
419 nlm_sparc_read_reloc,
420 nlm_sparc_mangle_relocs,
421 nlm_sparc_read_import,
422 nlm_sparc_write_import,
423 0, /* set_public_section */
424 0, /* get_public_offset */
425 nlm_swap_fixed_header_in,
426 nlm_swap_fixed_header_out,
427 nlm_sparc_write_external,
428 nlm_sparc_write_export
429 };
252b5132
RH
430
431#define TARGET_BIG_NAME "nlm32-sparc"
432#define TARGET_BIG_SYM nlmNAME(sparc_vec)
42ef282f 433#define TARGET_BACKEND_DATA & nlm32_sparc_backend
252b5132
RH
434
435#include "nlm-target.h"
This page took 0.327909 seconds and 4 git commands to generate.