update copyright dates
[deliverable/binutils-gdb.git] / bfd / nlm32-sparc.c
CommitLineData
252b5132 1/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
9553c638 2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005
0f867abe 3 Free Software Foundation, Inc.
252b5132 4
42ef282f 5 This file is part of BFD, the Binary File Descriptor library.
252b5132 6
42ef282f
NC
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
252b5132 11
42ef282f
NC
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
252b5132 16
42ef282f
NC
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
252b5132
RH
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24
25#define ARCH_SIZE 32
26
27#include "nlm/sparc32-ext.h"
28#define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header
29
30#include "libnlm.h"
31
b34976b6 32static bfd_boolean nlm_sparc_read_reloc
252b5132 33 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
b34976b6 34static bfd_boolean nlm_sparc_write_reloc
252b5132 35 PARAMS ((bfd *, asection *, arelent *));
b34976b6 36static bfd_boolean nlm_sparc_mangle_relocs
0f867abe 37 PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type));
b34976b6 38static bfd_boolean nlm_sparc_read_import
252b5132 39 PARAMS ((bfd *, nlmNAME(symbol_type) *));
b34976b6 40static bfd_boolean nlm_sparc_write_import
252b5132 41 PARAMS ((bfd *, asection *, arelent *));
b34976b6 42static bfd_boolean nlm_sparc_write_external
252b5132 43 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
b34976b6 44static bfd_boolean nlm_sparc_write_export
42ef282f 45 PARAMS ((bfd *, asymbol *, bfd_vma));
252b5132
RH
46
47enum reloc_type
48 {
49 R_SPARC_NONE = 0,
1518639e
KH
50 R_SPARC_8, R_SPARC_16, R_SPARC_32,
51 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
252b5132
RH
52 R_SPARC_WDISP30, R_SPARC_WDISP22,
53 R_SPARC_HI22, R_SPARC_22,
54 R_SPARC_13, R_SPARC_LO10,
55 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
56 R_SPARC_PC10, R_SPARC_PC22,
57 R_SPARC_WPLT30,
58 R_SPARC_COPY,
59 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
60 R_SPARC_RELATIVE,
61 R_SPARC_UA32,
62 R_SPARC_max
63 };
64
1518639e 65static reloc_howto_type nlm32_sparc_howto_table[] =
42ef282f 66 {
b34976b6
AM
67 HOWTO (R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, 0,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE),
68 HOWTO (R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8", FALSE,0,0x000000ff,TRUE),
69 HOWTO (R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE),
70 HOWTO (R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32", FALSE,0,0xffffffff,TRUE),
71 HOWTO (R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE),
72 HOWTO (R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE),
73 HOWTO (R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE),
74 HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
75 HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
76 HOWTO (R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, 0,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE),
77 HOWTO (R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22", FALSE,0,0x003fffff,TRUE),
78 HOWTO (R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13", FALSE,0,0x00001fff,TRUE),
79 HOWTO (R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, 0,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE),
80 HOWTO (R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE),
81 HOWTO (R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE),
82 HOWTO (R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE),
83 HOWTO (R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE),
84 HOWTO (R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE),
85 HOWTO (R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE),
86 HOWTO (R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE),
87 HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE),
88 HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE),
89 HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
90 HOWTO (R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE),
252b5132
RH
91};
92
93/* Read a NetWare sparc reloc. */
94
42ef282f
NC
95struct nlm32_sparc_reloc_ext
96 {
97 unsigned char offset[4];
98 unsigned char addend[4];
99 unsigned char type[1];
100 unsigned char pad1[3];
101 };
252b5132 102
b34976b6 103static bfd_boolean
252b5132
RH
104nlm_sparc_read_reloc (abfd, sym, secp, rel)
105 bfd *abfd;
5f771d47 106 nlmNAME(symbol_type) *sym ATTRIBUTE_UNUSED;
252b5132
RH
107 asection **secp;
108 arelent *rel;
109{
110 bfd_vma val, addend;
111 unsigned int index;
112 unsigned int type;
113 struct nlm32_sparc_reloc_ext tmp_reloc;
114 asection *code_sec, *data_sec;
115
dc810e39 116 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
b34976b6 117 return FALSE;
252b5132
RH
118
119 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
120 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
121
122 *secp = code_sec;
123
124 val = bfd_get_32 (abfd, tmp_reloc.offset);
125 addend = bfd_get_32 (abfd, tmp_reloc.addend);
126 type = bfd_get_8 (abfd, tmp_reloc.type);
127
128 rel->address = val;
129 rel->addend = addend;
130 rel->howto = NULL;
131
132 for (index = 0;
1518639e 133 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
252b5132 134 index++)
42ef282f
NC
135 if (nlm32_sparc_howto_table[index].type == type)
136 {
137 rel->howto = &nlm32_sparc_howto_table[index];
138 break;
139 }
252b5132
RH
140
141#ifdef DEBUG
142 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
143 __FUNCTION__, rel->address, rel->addend, type, rel->howto);
144#endif
b34976b6 145 return TRUE;
252b5132
RH
146
147}
148
149/* Write a NetWare sparc reloc. */
150
b34976b6 151static bfd_boolean
252b5132
RH
152nlm_sparc_write_reloc (abfd, sec, rel)
153 bfd *abfd;
154 asection *sec;
155 arelent *rel;
156{
157 bfd_vma val;
158 struct nlm32_sparc_reloc_ext tmp_reloc;
159 unsigned int index;
160 int type = -1;
161 reloc_howto_type *tmp;
162
252b5132 163 for (index = 0;
1518639e 164 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
42ef282f
NC
165 index++)
166 {
167 tmp = &nlm32_sparc_howto_table[index];
168
169 if (tmp->rightshift == rel->howto->rightshift
170 && tmp->size == rel->howto->size
171 && tmp->bitsize == rel->howto->bitsize
172 && tmp->pc_relative == rel->howto->pc_relative
173 && tmp->bitpos == rel->howto->bitpos
174 && tmp->src_mask == rel->howto->src_mask
175 && tmp->dst_mask == rel->howto->dst_mask)
176 {
177 type = tmp->type;
178 break;
179 }
252b5132 180 }
252b5132 181 if (type == -1)
1518639e 182 abort ();
252b5132 183
42ef282f
NC
184 /* Netware wants a list of relocs for each address.
185 Format is:
186 long offset
187 long addend
188 char type
189 That should be it. */
252b5132
RH
190
191 /* The value we write out is the offset into the appropriate
192 segment. This offset is the section vma, adjusted by the vma of
193 the lowest section in that segment, plus the address of the
194 relocation. */
252b5132 195 val = bfd_get_section_vma (abfd, sec) + rel->address;
252b5132
RH
196
197#ifdef DEBUG
198 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
199 __FUNCTION__, val, rel->addend, rel->howto->type);
200#endif
201 bfd_put_32 (abfd, val, tmp_reloc.offset);
202 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
1518639e 203 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
252b5132 204
dc810e39 205 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
b34976b6 206 return FALSE;
252b5132 207
b34976b6 208 return TRUE;
252b5132
RH
209}
210
211/* Mangle relocs for SPARC NetWare. We can just use the standard
212 SPARC relocs. */
213
b34976b6 214static bfd_boolean
252b5132 215nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
5f771d47
ILT
216 bfd *abfd ATTRIBUTE_UNUSED;
217 asection *sec ATTRIBUTE_UNUSED;
0f867abe 218 const PTR data ATTRIBUTE_UNUSED;
5f771d47
ILT
219 bfd_vma offset ATTRIBUTE_UNUSED;
220 bfd_size_type count ATTRIBUTE_UNUSED;
252b5132 221{
b34976b6 222 return TRUE;
252b5132
RH
223}
224
42ef282f
NC
225/* Read a NetWare sparc import record. */
226
b34976b6 227static bfd_boolean
252b5132
RH
228nlm_sparc_read_import (abfd, sym)
229 bfd *abfd;
230 nlmNAME(symbol_type) *sym;
231{
42ef282f
NC
232 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */
233 bfd_size_type rcount; /* Number of relocs. */
234 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */
235 unsigned char symlength; /* Length of symbol name. */
252b5132 236 char *name;
1518639e 237
42ef282f
NC
238 /* First, read in the number of relocation
239 entries for this symbol. */
dc810e39 240 if (bfd_bread ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 241 return FALSE;
1518639e 242
252b5132 243 rcount = bfd_get_32 (abfd, temp);
1518639e 244
42ef282f 245 /* Next, read in the length of the symbol. */
1518639e 246
dc810e39 247 if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
252b5132 248 != sizeof (symlength))
b34976b6 249 return FALSE;
252b5132 250 sym -> symbol.the_bfd = abfd;
dc810e39 251 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
252b5132 252 if (name == NULL)
b34976b6 253 return FALSE;
1518639e 254
42ef282f 255 /* Then read in the symbol. */
1518639e 256
dc810e39 257 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
b34976b6 258 return FALSE;
252b5132
RH
259 name[symlength] = '\0';
260 sym -> symbol.name = name;
261 sym -> symbol.flags = 0;
262 sym -> symbol.value = 0;
263 sym -> symbol.section = bfd_und_section_ptr;
1518639e 264
42ef282f 265 /* Next, start reading in the relocs. */
1518639e 266
252b5132
RH
267 nlm_relocs = ((struct nlm_relent *)
268 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
269 if (!nlm_relocs)
b34976b6 270 return FALSE;
252b5132
RH
271 sym -> relocs = nlm_relocs;
272 sym -> rcnt = 0;
273 while (sym -> rcnt < rcount)
274 {
275 asection *section;
1518639e 276
82e51918 277 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
b34976b6 278 return FALSE;
252b5132
RH
279 nlm_relocs -> section = section;
280 nlm_relocs++;
281 sym -> rcnt++;
282 }
42ef282f 283
b34976b6 284 return TRUE;
252b5132
RH
285}
286
b34976b6 287static bfd_boolean
252b5132
RH
288nlm_sparc_write_import (abfd, sec, rel)
289 bfd *abfd;
290 asection *sec;
291 arelent *rel;
292{
293 char temp[4];
294 asection *code, *data, *bss, *symsec;
295 bfd_vma base;
296
297 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
298 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
299 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
300 symsec = (*rel->sym_ptr_ptr)->section;
301
42ef282f 302 if (symsec == code)
252b5132 303 base = 0;
42ef282f 304 else if (symsec == data)
eea6121a 305 base = code->size;
42ef282f 306 else if (symsec == bss)
eea6121a 307 base = code->size + data->size;
42ef282f 308 else
252b5132
RH
309 base = 0;
310
311#ifdef DEBUG
312 fprintf (stderr, "%s: <%x, 1>\n\t",
313 __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
314#endif
315 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
dc810e39 316 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 317 return FALSE;
dc810e39
AM
318 bfd_put_32 (abfd, (bfd_vma) 1, temp);
319 if (bfd_bwrite ((PTR) temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 320 return FALSE;
82e51918 321 if (! nlm_sparc_write_reloc (abfd, sec, rel))
b34976b6
AM
322 return FALSE;
323 return TRUE;
252b5132
RH
324}
325
326/* Write out an external reference. */
327
b34976b6 328static bfd_boolean
252b5132
RH
329nlm_sparc_write_external (abfd, count, sym, relocs)
330 bfd *abfd;
331 bfd_size_type count;
332 asymbol *sym;
333 struct reloc_and_sec *relocs;
334{
335 unsigned int i;
336 bfd_byte len;
337 unsigned char temp[NLM_TARGET_LONG_SIZE];
338
339 bfd_put_32 (abfd, count, temp);
dc810e39 340 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
b34976b6 341 return FALSE;
252b5132
RH
342
343 len = strlen (sym->name);
dc810e39
AM
344 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
345 != sizeof (bfd_byte))
346 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
b34976b6 347 return FALSE;
252b5132
RH
348
349 for (i = 0; i < count; i++)
350 {
82e51918 351 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
b34976b6 352 return FALSE;
252b5132
RH
353 }
354
b34976b6 355 return TRUE;
252b5132
RH
356}
357
b34976b6 358static bfd_boolean
252b5132
RH
359nlm_sparc_write_export (abfd, sym, value)
360 bfd *abfd;
361 asymbol *sym;
362 bfd_vma value;
363{
364 bfd_byte len;
365 bfd_byte temp[4];
366
367#ifdef DEBUG
368 fprintf (stderr, "%s: <%x, %d, %s>\n",
369 __FUNCTION__, value, strlen (sym->name), sym->name);
370#endif
371 bfd_put_32 (abfd, value, temp);
372 len = strlen (sym->name);
373
dc810e39
AM
374 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
375 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
376 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
b34976b6 377 return FALSE;
252b5132 378
b34976b6 379 return TRUE;
252b5132
RH
380}
381
382#undef nlm_swap_fixed_header_in
383#undef nlm_swap_fixed_header_out
384
385#include "nlmswap.h"
386
387static const struct nlm_backend_data nlm32_sparc_backend =
42ef282f
NC
388 {
389 "NetWare SPARC Module \032",
390 sizeof (Nlm32_sparc_External_Fixed_Header),
391 0, /* optional_prefix_size */
392 bfd_arch_sparc,
393 0,
b34976b6 394 FALSE,
42ef282f
NC
395 0, /* backend_object_p */
396 0, /* write_prefix_func */
397 nlm_sparc_read_reloc,
398 nlm_sparc_mangle_relocs,
399 nlm_sparc_read_import,
400 nlm_sparc_write_import,
401 0, /* set_public_section */
402 0, /* get_public_offset */
403 nlm_swap_fixed_header_in,
404 nlm_swap_fixed_header_out,
405 nlm_sparc_write_external,
406 nlm_sparc_write_export
407 };
252b5132
RH
408
409#define TARGET_BIG_NAME "nlm32-sparc"
410#define TARGET_BIG_SYM nlmNAME(sparc_vec)
42ef282f 411#define TARGET_BACKEND_DATA & nlm32_sparc_backend
252b5132
RH
412
413#include "nlm-target.h"
This page took 0.308534 seconds and 4 git commands to generate.