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