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