]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame_incremental - bfd/nlm32-sparc.c
bfd/
[thirdparty/binutils-gdb.git] / bfd / nlm32-sparc.c
... / ...
CommitLineData
1/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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.
11
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.
16
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21#include "sysdep.h"
22#include "bfd.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
32enum reloc_type
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};
49
50static reloc_howto_type nlm32_sparc_howto_table[] =
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),
76};
77
78/* Read a NetWare sparc reloc. */
79
80struct nlm32_sparc_reloc_ext
81{
82 unsigned char offset[4];
83 unsigned char addend[4];
84 unsigned char type[1];
85 unsigned char pad1[3];
86};
87
88static bfd_boolean
89nlm_sparc_read_reloc (bfd *abfd,
90 nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED,
91 asection **secp,
92 arelent *rel)
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
100 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
101 return FALSE;
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;
117 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
118 index++)
119 if (nlm32_sparc_howto_table[index].type == type)
120 {
121 rel->howto = &nlm32_sparc_howto_table[index];
122 break;
123 }
124
125#ifdef DEBUG
126 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %u, howto = %p\n",
127 __FUNCTION__, (unsigned long) rel->address,
128 (unsigned long) rel->addend, type, rel->howto);
129#endif
130 return TRUE;
131
132}
133
134/* Write a NetWare sparc reloc. */
135
136static bfd_boolean
137nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
138{
139 bfd_vma val;
140 struct nlm32_sparc_reloc_ext tmp_reloc;
141 unsigned int index;
142 int type = -1;
143 reloc_howto_type *tmp;
144
145 for (index = 0;
146 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
147 index++)
148 {
149 tmp = &nlm32_sparc_howto_table[index];
150
151 if (tmp->rightshift == rel->howto->rightshift
152 && tmp->size == rel->howto->size
153 && tmp->bitsize == rel->howto->bitsize
154 && tmp->pc_relative == rel->howto->pc_relative
155 && tmp->bitpos == rel->howto->bitpos
156 && tmp->src_mask == rel->howto->src_mask
157 && tmp->dst_mask == rel->howto->dst_mask)
158 {
159 type = tmp->type;
160 break;
161 }
162 }
163 if (type == -1)
164 abort ();
165
166 /* Netware wants a list of relocs for each address.
167 Format is:
168 long offset
169 long addend
170 char type
171 That should be it. */
172
173 /* The value we write out is the offset into the appropriate
174 segment. This offset is the section vma, adjusted by the vma of
175 the lowest section in that segment, plus the address of the
176 relocation. */
177 val = bfd_get_section_vma (abfd, sec) + rel->address;
178
179#ifdef DEBUG
180 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %u\n",
181 __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend,
182 rel->howto->type);
183#endif
184 bfd_put_32 (abfd, val, tmp_reloc.offset);
185 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
186 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
187
188 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
189 return FALSE;
190
191 return TRUE;
192}
193
194/* Mangle relocs for SPARC NetWare. We can just use the standard
195 SPARC relocs. */
196
197static bfd_boolean
198nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
199 asection *sec ATTRIBUTE_UNUSED,
200 const void * data ATTRIBUTE_UNUSED,
201 bfd_vma offset ATTRIBUTE_UNUSED,
202 bfd_size_type count ATTRIBUTE_UNUSED)
203{
204 return TRUE;
205}
206
207/* Read a NetWare sparc import record. */
208
209static bfd_boolean
210nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
211{
212 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */
213 bfd_size_type rcount; /* Number of relocs. */
214 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */
215 unsigned char symlength; /* Length of symbol name. */
216 char *name;
217
218 /* First, read in the number of relocation
219 entries for this symbol. */
220 if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4)
221 return FALSE;
222
223 rcount = bfd_get_32 (abfd, temp);
224
225 /* Next, read in the length of the symbol. */
226 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
227 != sizeof (symlength))
228 return FALSE;
229 sym -> symbol.the_bfd = abfd;
230 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
231 if (name == NULL)
232 return FALSE;
233
234 /* Then read in the symbol. */
235 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
236 return FALSE;
237 name[symlength] = '\0';
238 sym -> symbol.name = name;
239 sym -> symbol.flags = 0;
240 sym -> symbol.value = 0;
241 sym -> symbol.section = bfd_und_section_ptr;
242
243 /* Next, start reading in the relocs. */
244 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
245 if (!nlm_relocs)
246 return FALSE;
247 sym -> relocs = nlm_relocs;
248 sym -> rcnt = 0;
249 while (sym -> rcnt < rcount)
250 {
251 asection *section;
252
253 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
254 return FALSE;
255 nlm_relocs -> section = section;
256 nlm_relocs++;
257 sym -> rcnt++;
258 }
259
260 return TRUE;
261}
262
263static bfd_boolean
264nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
265{
266 char temp[4];
267 asection *code, *data, *bss, *symsec;
268 bfd_vma base;
269
270 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
271 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
272 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
273 symsec = (*rel->sym_ptr_ptr)->section;
274
275 if (symsec == code)
276 base = 0;
277 else if (symsec == data)
278 base = code->size;
279 else if (symsec == bss)
280 base = code->size + data->size;
281 else
282 base = 0;
283
284#ifdef DEBUG
285 fprintf (stderr, "%s: <%lx, 1>\n\t",
286 __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value));
287#endif
288 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
289 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
290 return FALSE;
291 bfd_put_32 (abfd, (bfd_vma) 1, temp);
292 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
293 return FALSE;
294 if (! nlm_sparc_write_reloc (abfd, sec, rel))
295 return FALSE;
296 return TRUE;
297}
298
299/* Write out an external reference. */
300
301static bfd_boolean
302nlm_sparc_write_external (bfd *abfd,
303 bfd_size_type count,
304 asymbol *sym,
305 struct reloc_and_sec *relocs)
306{
307 unsigned int i;
308 bfd_byte len;
309 unsigned char temp[NLM_TARGET_LONG_SIZE];
310
311 bfd_put_32 (abfd, count, temp);
312 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
313 return FALSE;
314
315 len = strlen (sym->name);
316 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
317 != sizeof (bfd_byte))
318 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
319 return FALSE;
320
321 for (i = 0; i < count; i++)
322 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
323 return FALSE;
324
325 return TRUE;
326}
327
328static bfd_boolean
329nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
330{
331 bfd_byte len;
332 bfd_byte temp[4];
333
334#ifdef DEBUG
335 fprintf (stderr, "%s: <%lx, %u, %s>\n",
336 __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name);
337#endif
338 bfd_put_32 (abfd, value, temp);
339 len = strlen (sym->name);
340
341 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
342 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
343 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
344 return FALSE;
345
346 return TRUE;
347}
348
349#undef nlm_swap_fixed_header_in
350#undef nlm_swap_fixed_header_out
351
352#include "nlmswap.h"
353
354static const struct nlm_backend_data nlm32_sparc_backend =
355{
356 "NetWare SPARC Module \032",
357 sizeof (Nlm32_sparc_External_Fixed_Header),
358 0, /* Optional_prefix_size. */
359 bfd_arch_sparc,
360 0,
361 FALSE,
362 0, /* Backend_object_p. */
363 0, /* Write_prefix_func. */
364 nlm_sparc_read_reloc,
365 nlm_sparc_mangle_relocs,
366 nlm_sparc_read_import,
367 nlm_sparc_write_import,
368 0, /* Set_public_section. */
369 0, /* Get_public_offset. */
370 nlm_swap_fixed_header_in,
371 nlm_swap_fixed_header_out,
372 nlm_sparc_write_external,
373 nlm_sparc_write_export
374};
375
376#define TARGET_BIG_NAME "nlm32-sparc"
377#define TARGET_BIG_SYM nlmNAME (sparc_vec)
378#define TARGET_BACKEND_DATA & nlm32_sparc_backend
379
380#include "nlm-target.h"