]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/nlm32-sparc.c
bfd/
[thirdparty/binutils-gdb.git] / bfd / nlm32-sparc.c
CommitLineData
252b5132 1/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
3db64b00
AM
2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007 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 20
252b5132 21#include "sysdep.h"
3db64b00 22#include "bfd.h"
252b5132
RH
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
e460dd0d
AM
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);
252b5132 129#endif
b34976b6 130 return TRUE;
252b5132
RH
131
132}
133
134/* Write a NetWare sparc reloc. */
135
b34976b6 136static bfd_boolean
7920ce38 137nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
252b5132
RH
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
252b5132 145 for (index = 0;
1518639e 146 index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
42ef282f
NC
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 }
252b5132 162 }
252b5132 163 if (type == -1)
1518639e 164 abort ();
252b5132 165
42ef282f
NC
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. */
252b5132
RH
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. */
252b5132 177 val = bfd_get_section_vma (abfd, sec) + rel->address;
252b5132
RH
178
179#ifdef DEBUG
e460dd0d
AM
180 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %u\n",
181 __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend,
182 rel->howto->type);
252b5132
RH
183#endif
184 bfd_put_32 (abfd, val, tmp_reloc.offset);
185 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
1518639e 186 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
252b5132 187
dc810e39 188 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
b34976b6 189 return FALSE;
252b5132 190
b34976b6 191 return TRUE;
252b5132
RH
192}
193
194/* Mangle relocs for SPARC NetWare. We can just use the standard
195 SPARC relocs. */
196
b34976b6 197static bfd_boolean
7920ce38
NC
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)
252b5132 203{
b34976b6 204 return TRUE;
252b5132
RH
205}
206
42ef282f
NC
207/* Read a NetWare sparc import record. */
208
b34976b6 209static bfd_boolean
7920ce38 210nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
252b5132 211{
42ef282f
NC
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. */
252b5132 216 char *name;
1518639e 217
42ef282f
NC
218 /* First, read in the number of relocation
219 entries for this symbol. */
7920ce38 220 if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 221 return FALSE;
1518639e 222
252b5132 223 rcount = bfd_get_32 (abfd, temp);
1518639e 224
42ef282f 225 /* Next, read in the length of the symbol. */
7920ce38 226 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
252b5132 227 != sizeof (symlength))
b34976b6 228 return FALSE;
252b5132 229 sym -> symbol.the_bfd = abfd;
dc810e39 230 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
252b5132 231 if (name == NULL)
b34976b6 232 return FALSE;
1518639e 233
42ef282f 234 /* Then read in the symbol. */
dc810e39 235 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
b34976b6 236 return FALSE;
252b5132
RH
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;
1518639e 242
42ef282f 243 /* Next, start reading in the relocs. */
7920ce38 244 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
252b5132 245 if (!nlm_relocs)
b34976b6 246 return FALSE;
252b5132
RH
247 sym -> relocs = nlm_relocs;
248 sym -> rcnt = 0;
249 while (sym -> rcnt < rcount)
250 {
251 asection *section;
1518639e 252
82e51918 253 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
b34976b6 254 return FALSE;
252b5132
RH
255 nlm_relocs -> section = section;
256 nlm_relocs++;
257 sym -> rcnt++;
258 }
42ef282f 259
b34976b6 260 return TRUE;
252b5132
RH
261}
262
b34976b6 263static bfd_boolean
7920ce38 264nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
252b5132
RH
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
42ef282f 275 if (symsec == code)
252b5132 276 base = 0;
42ef282f 277 else if (symsec == data)
eea6121a 278 base = code->size;
42ef282f 279 else if (symsec == bss)
eea6121a 280 base = code->size + data->size;
42ef282f 281 else
252b5132
RH
282 base = 0;
283
284#ifdef DEBUG
e460dd0d
AM
285 fprintf (stderr, "%s: <%lx, 1>\n\t",
286 __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value));
252b5132
RH
287#endif
288 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
7920ce38 289 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 290 return FALSE;
dc810e39 291 bfd_put_32 (abfd, (bfd_vma) 1, temp);
7920ce38 292 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
b34976b6 293 return FALSE;
82e51918 294 if (! nlm_sparc_write_reloc (abfd, sec, rel))
b34976b6
AM
295 return FALSE;
296 return TRUE;
252b5132
RH
297}
298
299/* Write out an external reference. */
300
b34976b6 301static bfd_boolean
7920ce38
NC
302nlm_sparc_write_external (bfd *abfd,
303 bfd_size_type count,
304 asymbol *sym,
305 struct reloc_and_sec *relocs)
252b5132
RH
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);
dc810e39 312 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
b34976b6 313 return FALSE;
252b5132
RH
314
315 len = strlen (sym->name);
dc810e39
AM
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)
b34976b6 319 return FALSE;
252b5132
RH
320
321 for (i = 0; i < count; i++)
7920ce38
NC
322 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
323 return FALSE;
252b5132 324
b34976b6 325 return TRUE;
252b5132
RH
326}
327
b34976b6 328static bfd_boolean
7920ce38 329nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
252b5132
RH
330{
331 bfd_byte len;
332 bfd_byte temp[4];
333
334#ifdef DEBUG
e460dd0d
AM
335 fprintf (stderr, "%s: <%lx, %u, %s>\n",
336 __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name);
252b5132
RH
337#endif
338 bfd_put_32 (abfd, value, temp);
339 len = strlen (sym->name);
340
dc810e39
AM
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)
b34976b6 344 return FALSE;
252b5132 345
b34976b6 346 return TRUE;
252b5132
RH
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 =
7920ce38
NC
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};
252b5132
RH
375
376#define TARGET_BIG_NAME "nlm32-sparc"
7920ce38 377#define TARGET_BIG_SYM nlmNAME (sparc_vec)
42ef282f 378#define TARGET_BACKEND_DATA & nlm32_sparc_backend
252b5132
RH
379
380#include "nlm-target.h"