PR ld/11843
[binutils.git] / bfd / nlm32-sparc.c
blobba60e44016d7828893d9bdf38a352e1245de6f55
1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2 Copyright 1993, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007, 2009, 2010 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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 3 of the License, or
10 (at your option) any later version.
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.
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,
20 MA 02110-1301, USA. */
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
26 #define ARCH_SIZE 32
28 #include "nlm/sparc32-ext.h"
29 #define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header
31 #include "libnlm.h"
33 enum reloc_type
35 R_SPARC_NONE = 0,
36 R_SPARC_8, R_SPARC_16, R_SPARC_32,
37 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
38 R_SPARC_WDISP30, R_SPARC_WDISP22,
39 R_SPARC_HI22, R_SPARC_22,
40 R_SPARC_13, R_SPARC_LO10,
41 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
42 R_SPARC_PC10, R_SPARC_PC22,
43 R_SPARC_WPLT30,
44 R_SPARC_COPY,
45 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
46 R_SPARC_RELATIVE,
47 R_SPARC_UA32,
48 R_SPARC_max
51 static reloc_howto_type nlm32_sparc_howto_table[] =
53 HOWTO (R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, 0,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE),
54 HOWTO (R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_8", FALSE,0,0x000000ff,TRUE),
55 HOWTO (R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE),
56 HOWTO (R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_32", FALSE,0,0xffffffff,TRUE),
57 HOWTO (R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE),
58 HOWTO (R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE),
59 HOWTO (R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE),
60 HOWTO (R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
61 HOWTO (R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
62 HOWTO (R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, 0,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE),
63 HOWTO (R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_22", FALSE,0,0x003fffff,TRUE),
64 HOWTO (R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_13", FALSE,0,0x00001fff,TRUE),
65 HOWTO (R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, 0,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE),
66 HOWTO (R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE),
67 HOWTO (R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE),
68 HOWTO (R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE),
69 HOWTO (R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE),
70 HOWTO (R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,0,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE),
71 HOWTO (R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE),
72 HOWTO (R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE),
73 HOWTO (R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE),
74 HOWTO (R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE),
75 HOWTO (R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
76 HOWTO (R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, 0,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE),
79 /* Read a NetWare sparc reloc. */
81 struct nlm32_sparc_reloc_ext
83 unsigned char offset[4];
84 unsigned char addend[4];
85 unsigned char type[1];
86 unsigned char pad1[3];
89 static bfd_boolean
90 nlm_sparc_read_reloc (bfd *abfd,
91 nlmNAME (symbol_type) *sym ATTRIBUTE_UNUSED,
92 asection **secp,
93 arelent *rel)
95 bfd_vma val, addend;
96 unsigned int howto_index;
97 unsigned int type;
98 struct nlm32_sparc_reloc_ext tmp_reloc;
99 asection *code_sec;
101 if (bfd_bread (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
102 return FALSE;
104 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
105 *secp = code_sec;
107 val = bfd_get_32 (abfd, tmp_reloc.offset);
108 addend = bfd_get_32 (abfd, tmp_reloc.addend);
109 type = bfd_get_8 (abfd, tmp_reloc.type);
111 rel->address = val;
112 rel->addend = addend;
113 rel->howto = NULL;
115 for (howto_index = 0;
116 howto_index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
117 howto_index++)
118 if (nlm32_sparc_howto_table[howto_index].type == type)
120 rel->howto = &nlm32_sparc_howto_table[howto_index];
121 break;
124 #ifdef DEBUG
125 fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %u, howto = %p\n",
126 __FUNCTION__, (unsigned long) rel->address,
127 (unsigned long) rel->addend, type, rel->howto);
128 #endif
129 return TRUE;
133 /* Write a NetWare sparc reloc. */
135 static bfd_boolean
136 nlm_sparc_write_reloc (bfd * abfd, asection * sec, arelent * rel)
138 bfd_vma val;
139 struct nlm32_sparc_reloc_ext tmp_reloc;
140 unsigned int howto_index;
141 int type = -1;
142 reloc_howto_type *tmp;
144 for (howto_index = 0;
145 howto_index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
146 howto_index++)
148 tmp = &nlm32_sparc_howto_table[howto_index];
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)
158 type = tmp->type;
159 break;
162 if (type == -1)
163 abort ();
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. */
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. */
176 val = bfd_get_section_vma (abfd, sec) + rel->address;
178 #ifdef DEBUG
179 fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %u\n",
180 __FUNCTION__, (unsigned long) val, (unsigned long) rel->addend,
181 rel->howto->type);
182 #endif
183 bfd_put_32 (abfd, val, tmp_reloc.offset);
184 bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
185 bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
187 if (bfd_bwrite (&tmp_reloc, (bfd_size_type) 12, abfd) != 12)
188 return FALSE;
190 return TRUE;
193 /* Mangle relocs for SPARC NetWare. We can just use the standard
194 SPARC relocs. */
196 static bfd_boolean
197 nlm_sparc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
198 asection *sec ATTRIBUTE_UNUSED,
199 const void * data ATTRIBUTE_UNUSED,
200 bfd_vma offset ATTRIBUTE_UNUSED,
201 bfd_size_type count ATTRIBUTE_UNUSED)
203 return TRUE;
206 /* Read a NetWare sparc import record. */
208 static bfd_boolean
209 nlm_sparc_read_import (bfd *abfd, nlmNAME (symbol_type) *sym)
211 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */
212 bfd_size_type rcount; /* Number of relocs. */
213 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */
214 unsigned char symlength; /* Length of symbol name. */
215 char *name;
217 /* First, read in the number of relocation
218 entries for this symbol. */
219 if (bfd_bread (temp, (bfd_size_type) 4, abfd) != 4)
220 return FALSE;
222 rcount = bfd_get_32 (abfd, temp);
224 /* Next, read in the length of the symbol. */
225 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
226 != sizeof (symlength))
227 return FALSE;
228 sym -> symbol.the_bfd = abfd;
229 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
230 if (name == NULL)
231 return FALSE;
233 /* Then read in the symbol. */
234 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
235 return FALSE;
236 name[symlength] = '\0';
237 sym -> symbol.name = name;
238 sym -> symbol.flags = 0;
239 sym -> symbol.value = 0;
240 sym -> symbol.section = bfd_und_section_ptr;
242 /* Next, start reading in the relocs. */
243 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
244 if (!nlm_relocs)
245 return FALSE;
246 sym -> relocs = nlm_relocs;
247 sym -> rcnt = 0;
248 while (sym -> rcnt < rcount)
250 asection *section;
252 if (! nlm_sparc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
253 return FALSE;
254 nlm_relocs -> section = section;
255 nlm_relocs++;
256 sym -> rcnt++;
259 return TRUE;
262 static bfd_boolean
263 nlm_sparc_write_import (bfd * abfd, asection * sec, arelent * rel)
265 char temp[4];
266 asection *code, *data, *bss, *symsec;
267 bfd_vma base;
269 code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
270 data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
271 bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
272 symsec = (*rel->sym_ptr_ptr)->section;
274 if (symsec == code)
275 base = 0;
276 else if (symsec == data)
277 base = code->size;
278 else if (symsec == bss)
279 base = code->size + data->size;
280 else
281 base = 0;
283 #ifdef DEBUG
284 fprintf (stderr, "%s: <%lx, 1>\n\t",
285 __FUNCTION__, (unsigned long) (base + (*rel->sym_ptr_ptr)->value));
286 #endif
287 bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
288 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
289 return FALSE;
290 bfd_put_32 (abfd, (bfd_vma) 1, temp);
291 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4)
292 return FALSE;
293 if (! nlm_sparc_write_reloc (abfd, sec, rel))
294 return FALSE;
295 return TRUE;
298 /* Write out an external reference. */
300 static bfd_boolean
301 nlm_sparc_write_external (bfd *abfd,
302 bfd_size_type count,
303 asymbol *sym,
304 struct reloc_and_sec *relocs)
306 unsigned int i;
307 bfd_byte len;
308 unsigned char temp[NLM_TARGET_LONG_SIZE];
310 bfd_put_32 (abfd, count, temp);
311 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
312 return FALSE;
314 len = strlen (sym->name);
315 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
316 != sizeof (bfd_byte))
317 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
318 return FALSE;
320 for (i = 0; i < count; i++)
321 if (! nlm_sparc_write_reloc (abfd, relocs[i].sec, relocs[i].rel))
322 return FALSE;
324 return TRUE;
327 static bfd_boolean
328 nlm_sparc_write_export (bfd * abfd, asymbol * sym, bfd_vma value)
330 bfd_byte len;
331 bfd_byte temp[4];
333 #ifdef DEBUG
334 fprintf (stderr, "%s: <%lx, %u, %s>\n",
335 __FUNCTION__, (unsigned long) value, strlen (sym->name), sym->name);
336 #endif
337 bfd_put_32 (abfd, value, temp);
338 len = strlen (sym->name);
340 if (bfd_bwrite (temp, (bfd_size_type) 4, abfd) != 4
341 || bfd_bwrite (&len, (bfd_size_type) 1, abfd) != 1
342 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
343 return FALSE;
345 return TRUE;
348 #undef nlm_swap_fixed_header_in
349 #undef nlm_swap_fixed_header_out
351 #include "nlmswap.h"
353 static const struct nlm_backend_data nlm32_sparc_backend =
355 "NetWare SPARC Module \032",
356 sizeof (Nlm32_sparc_External_Fixed_Header),
357 0, /* Optional_prefix_size. */
358 bfd_arch_sparc,
360 FALSE,
361 0, /* Backend_object_p. */
362 0, /* Write_prefix_func. */
363 nlm_sparc_read_reloc,
364 nlm_sparc_mangle_relocs,
365 nlm_sparc_read_import,
366 nlm_sparc_write_import,
367 0, /* Set_public_section. */
368 0, /* Get_public_offset. */
369 nlm_swap_fixed_header_in,
370 nlm_swap_fixed_header_out,
371 nlm_sparc_write_external,
372 nlm_sparc_write_export
375 #define TARGET_BIG_NAME "nlm32-sparc"
376 #define TARGET_BIG_SYM nlmNAME (sparc_vec)
377 #define TARGET_BACKEND_DATA & nlm32_sparc_backend
379 #include "nlm-target.h"