Add missing prototypes
[external/binutils.git] / bfd / nlm32-sparc.c
1 /* Support for 32-bit SPARC NLM (NetWare Loadable Module)
2    Copyright 1993, 1994, 2000, 2001 Free Software Foundation, Inc.
3
4    This file is part of BFD, the Binary File Descriptor library.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23
24 #define ARCH_SIZE 32
25
26 #include "nlm/sparc32-ext.h"
27 #define Nlm_External_Fixed_Header       Nlm32_sparc_External_Fixed_Header
28
29 #include "libnlm.h"
30
31 static boolean nlm_sparc_read_reloc
32   PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
33 static boolean nlm_sparc_write_reloc
34   PARAMS ((bfd *, asection *, arelent *));
35 static boolean nlm_sparc_mangle_relocs
36   PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
37 static boolean nlm_sparc_read_import
38   PARAMS ((bfd *, nlmNAME(symbol_type) *));
39 static boolean nlm_sparc_write_import
40   PARAMS ((bfd *, asection *, arelent *));
41 static boolean nlm_sparc_write_external
42   PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
43 static boolean nlm_sparc_write_export
44   PARAMS ((bfd *, asymbol *, bfd_vma));
45
46 enum reloc_type
47   {
48     R_SPARC_NONE = 0,
49     R_SPARC_8,          R_SPARC_16,             R_SPARC_32,
50     R_SPARC_DISP8,      R_SPARC_DISP16,         R_SPARC_DISP32,
51     R_SPARC_WDISP30,    R_SPARC_WDISP22,
52     R_SPARC_HI22,       R_SPARC_22,
53     R_SPARC_13,         R_SPARC_LO10,
54     R_SPARC_GOT10,      R_SPARC_GOT13,          R_SPARC_GOT22,
55     R_SPARC_PC10,       R_SPARC_PC22,
56     R_SPARC_WPLT30,
57     R_SPARC_COPY,
58     R_SPARC_GLOB_DAT,   R_SPARC_JMP_SLOT,
59     R_SPARC_RELATIVE,
60     R_SPARC_UA32,
61     R_SPARC_max
62   };
63
64 #if 0
65 static CONST char *CONST reloc_type_names[] =
66   {
67     "R_SPARC_NONE",
68     "R_SPARC_8",                "R_SPARC_16",           "R_SPARC_32",
69     "R_SPARC_DISP8",    "R_SPARC_DISP16",       "R_SPARC_DISP32",
70     "R_SPARC_WDISP30",  "R_SPARC_WDISP22",
71     "R_SPARC_HI22",     "R_SPARC_22",
72     "R_SPARC_13",               "R_SPARC_LO10",
73     "R_SPARC_GOT10",    "R_SPARC_GOT13",        "R_SPARC_GOT22",
74     "R_SPARC_PC10",     "R_SPARC_PC22",
75     "R_SPARC_WPLT30",
76     "R_SPARC_COPY",
77     "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
78     "R_SPARC_RELATIVE",
79     "R_SPARC_UA32",
80   };
81 #endif
82
83 static reloc_howto_type nlm32_sparc_howto_table[] =
84   {
85     HOWTO (R_SPARC_NONE,    0,0, 0,false,0,complain_overflow_dont,    0,"R_SPARC_NONE",    false,0,0x00000000,true),
86     HOWTO (R_SPARC_8,       0,0, 8,false,0,complain_overflow_bitfield,0,"R_SPARC_8",       false,0,0x000000ff,true),
87     HOWTO (R_SPARC_16,      0,1,16,false,0,complain_overflow_bitfield,0,"R_SPARC_16",      false,0,0x0000ffff,true),
88     HOWTO (R_SPARC_32,      0,2,32,false,0,complain_overflow_bitfield,0,"R_SPARC_32",      false,0,0xffffffff,true),
89     HOWTO (R_SPARC_DISP8,   0,0, 8,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP8",   false,0,0x000000ff,true),
90     HOWTO (R_SPARC_DISP16,  0,1,16,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP16",  false,0,0x0000ffff,true),
91     HOWTO (R_SPARC_DISP32,  0,2,32,true, 0,complain_overflow_signed,  0,"R_SPARC_DISP32",  false,0,0x00ffffff,true),
92     HOWTO (R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed,  0,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
93     HOWTO (R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed,  0,"R_SPARC_WDISP22", false,0,0x003fffff,true),
94     HOWTO (R_SPARC_HI22,   10,2,22,false,0,complain_overflow_dont,    0,"R_SPARC_HI22",    false,0,0x003fffff,true),
95     HOWTO (R_SPARC_22,      0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_22",      false,0,0x003fffff,true),
96     HOWTO (R_SPARC_13,      0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_13",      false,0,0x00001fff,true),
97     HOWTO (R_SPARC_LO10,    0,2,10,false,0,complain_overflow_dont,    0,"R_SPARC_LO10",    false,0,0x000003ff,true),
98     HOWTO (R_SPARC_GOT10,   0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT10",   false,0,0x000003ff,true),
99     HOWTO (R_SPARC_GOT13,   0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT13",   false,0,0x00001fff,true),
100     HOWTO (R_SPARC_GOT22,  10,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT22",   false,0,0x003fffff,true),
101     HOWTO (R_SPARC_PC10,    0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_PC10",    false,0,0x000003ff,true),
102     HOWTO (R_SPARC_PC22,    0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_PC22",    false,0,0x003fffff,true),
103     HOWTO (R_SPARC_WPLT30,  0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_WPLT30",  false,0,0x00000000,true),
104     HOWTO (R_SPARC_COPY,    0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_COPY",    false,0,0x00000000,true),
105     HOWTO (R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
106     HOWTO (R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
107     HOWTO (R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_RELATIVE",false,0,0x00000000,true),
108     HOWTO (R_SPARC_UA32,    0,0,00,false,0,complain_overflow_dont,    0,"R_SPARC_UA32",    false,0,0x00000000,true),
109 };
110
111 /* Read a NetWare sparc reloc.  */
112
113 struct nlm32_sparc_reloc_ext
114   {
115     unsigned char offset[4];
116     unsigned char addend[4];
117     unsigned char type[1];
118     unsigned char pad1[3];
119   };
120
121 static boolean
122 nlm_sparc_read_reloc (abfd, sym, secp, rel)
123      bfd *abfd;
124      nlmNAME(symbol_type) *sym ATTRIBUTE_UNUSED;
125      asection **secp;
126      arelent *rel;
127 {
128   bfd_vma val, addend;
129   unsigned int index;
130   unsigned int type;
131   struct nlm32_sparc_reloc_ext tmp_reloc;
132   asection *code_sec, *data_sec;
133
134   if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12)
135     return false;
136
137   code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
138   data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
139
140   *secp = code_sec;
141
142   val = bfd_get_32 (abfd, tmp_reloc.offset);
143   addend = bfd_get_32 (abfd, tmp_reloc.addend);
144   type = bfd_get_8 (abfd, tmp_reloc.type);
145
146   rel->address = val;
147   rel->addend = addend;
148   rel->howto = NULL;
149
150   for (index = 0;
151        index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
152        index++)
153     if (nlm32_sparc_howto_table[index].type == type)
154       {
155         rel->howto = &nlm32_sparc_howto_table[index];
156         break;
157       }
158
159 #ifdef DEBUG
160   fprintf (stderr, "%s:  address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
161            __FUNCTION__, rel->address, rel->addend, type, rel->howto);
162 #endif
163   return true;
164
165 }
166
167 /* Write a NetWare sparc reloc.  */
168
169 static boolean
170 nlm_sparc_write_reloc (abfd, sec, rel)
171      bfd *abfd;
172      asection *sec;
173      arelent *rel;
174 {
175   bfd_vma val;
176   struct nlm32_sparc_reloc_ext tmp_reloc;
177   unsigned int index;
178   int type = -1;
179   reloc_howto_type *tmp;
180
181   for (index = 0;
182        index < sizeof (nlm32_sparc_howto_table) / sizeof (reloc_howto_type);
183        index++)
184     {
185       tmp = &nlm32_sparc_howto_table[index];
186
187       if (tmp->rightshift == rel->howto->rightshift
188           && tmp->size == rel->howto->size
189           && tmp->bitsize == rel->howto->bitsize
190           && tmp->pc_relative == rel->howto->pc_relative
191           && tmp->bitpos == rel->howto->bitpos
192           && tmp->src_mask == rel->howto->src_mask
193           && tmp->dst_mask == rel->howto->dst_mask)
194         {
195           type = tmp->type;
196           break;
197         }
198     }
199   if (type == -1)
200     abort ();
201
202   /* Netware wants a list of relocs for each address.
203      Format is:
204         long    offset
205         long    addend
206         char    type
207      That should be it.  */
208
209   /* The value we write out is the offset into the appropriate
210      segment.  This offset is the section vma, adjusted by the vma of
211      the lowest section in that segment, plus the address of the
212      relocation.  */
213 #if 0
214   val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
215 #else
216   val = bfd_get_section_vma (abfd, sec) + rel->address;
217 #endif
218
219 #ifdef DEBUG
220   fprintf (stderr, "%s:  val = %08lx, addend = %08lx, type = %d\n",
221            __FUNCTION__, val, rel->addend, rel->howto->type);
222 #endif
223   bfd_put_32 (abfd, val, tmp_reloc.offset);
224   bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
225   bfd_put_8 (abfd, (short) (rel->howto->type), tmp_reloc.type);
226
227   if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
228     return false;
229
230   return true;
231 }
232
233 /* Mangle relocs for SPARC NetWare.  We can just use the standard
234    SPARC relocs.  */
235
236 static boolean
237 nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
238      bfd *abfd ATTRIBUTE_UNUSED;
239      asection *sec ATTRIBUTE_UNUSED;
240      PTR data ATTRIBUTE_UNUSED;
241      bfd_vma offset ATTRIBUTE_UNUSED;
242      bfd_size_type count ATTRIBUTE_UNUSED;
243 {
244   return true;
245 }
246
247 /* Read a NetWare sparc import record.  */
248
249 static boolean
250 nlm_sparc_read_import (abfd, sym)
251      bfd *abfd;
252      nlmNAME(symbol_type) *sym;
253 {
254   struct nlm_relent *nlm_relocs;        /* Relocation records for symbol.  */
255   bfd_size_type rcount;                 /* Number of relocs.  */
256   bfd_byte temp[NLM_TARGET_LONG_SIZE];  /* Temporary 32-bit value.  */
257   unsigned char symlength;              /* Length of symbol name.  */
258   char *name;
259
260   /* First, read in the number of relocation
261      entries for this symbol.  */
262   if (bfd_read ((PTR) temp, 4, 1, abfd) != 4)
263     return false;
264
265   rcount = bfd_get_32 (abfd, temp);
266
267   /* Next, read in the length of the symbol.  */
268
269   if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
270       != sizeof (symlength))
271     return false;
272   sym -> symbol.the_bfd = abfd;
273   name = bfd_alloc (abfd, symlength + 1);
274   if (name == NULL)
275     return false;
276
277   /* Then read in the symbol.  */
278
279   if (bfd_read (name, symlength, 1, abfd) != symlength)
280     return false;
281   name[symlength] = '\0';
282   sym -> symbol.name = name;
283   sym -> symbol.flags = 0;
284   sym -> symbol.value = 0;
285   sym -> symbol.section = bfd_und_section_ptr;
286
287   /* Next, start reading in the relocs.  */
288
289   nlm_relocs = ((struct nlm_relent *)
290                 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
291   if (!nlm_relocs)
292     return false;
293   sym -> relocs = nlm_relocs;
294   sym -> rcnt = 0;
295   while (sym -> rcnt < rcount)
296     {
297       asection *section;
298
299       if (nlm_sparc_read_reloc (abfd, sym, &section,
300                               &nlm_relocs -> reloc)
301           == false)
302         return false;
303       nlm_relocs -> section = section;
304       nlm_relocs++;
305       sym -> rcnt++;
306     }
307
308   return true;
309 }
310
311 static boolean
312 nlm_sparc_write_import (abfd, sec, rel)
313      bfd *abfd;
314      asection *sec;
315      arelent *rel;
316 {
317   char temp[4];
318   asection *code, *data, *bss, *symsec;
319   bfd_vma base;
320
321   code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
322   data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
323   bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
324   symsec = (*rel->sym_ptr_ptr)->section;
325
326   if (symsec == code)
327     base = 0;
328   else if (symsec == data)
329     base = bfd_section_size (abfd, code);
330   else if (symsec == bss)
331     base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
332   else
333     base = 0;
334
335 #ifdef DEBUG
336   fprintf (stderr, "%s:  <%x, 1>\n\t",
337            __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
338 #endif
339   bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
340   if (bfd_write ((PTR)temp, 4, 1, abfd) != 4)
341     return false;
342   bfd_put_32 (abfd, 1, temp);
343   if (bfd_write ((PTR)temp, 4, 1, abfd) != 4)
344     return false;
345   if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
346     return false;
347   return true;
348 }
349
350 /* Write out an external reference.  */
351
352 static boolean
353 nlm_sparc_write_external (abfd, count, sym, relocs)
354      bfd *abfd;
355      bfd_size_type count;
356      asymbol *sym;
357      struct reloc_and_sec *relocs;
358 {
359   unsigned int i;
360   bfd_byte len;
361   unsigned char temp[NLM_TARGET_LONG_SIZE];
362
363   bfd_put_32 (abfd, count, temp);
364   if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
365     return false;
366
367   len = strlen (sym->name);
368   if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof (bfd_byte))
369       || bfd_write (sym->name, len, 1, abfd) != len)
370     return false;
371
372   for (i = 0; i < count; i++)
373     {
374       if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
375                                  relocs[i].rel) == false)
376         return false;
377     }
378
379   return true;
380 }
381
382 static boolean
383 nlm_sparc_write_export (abfd, sym, value)
384      bfd *abfd;
385      asymbol *sym;
386      bfd_vma value;
387 {
388   bfd_byte len;
389   bfd_byte temp[4];
390
391 #ifdef DEBUG
392   fprintf (stderr, "%s: <%x, %d, %s>\n",
393            __FUNCTION__, value, strlen (sym->name), sym->name);
394 #endif
395   bfd_put_32 (abfd, value, temp);
396   len = strlen (sym->name);
397
398   if (bfd_write (temp, 4, 1, abfd) != 4
399       || bfd_write (&len, 1, 1, abfd) != 1
400       || bfd_write (sym->name, len, 1, abfd) != len)
401     return false;
402
403   return true;
404 }
405
406 #undef nlm_swap_fixed_header_in
407 #undef nlm_swap_fixed_header_out
408
409 #include "nlmswap.h"
410
411 static const struct nlm_backend_data nlm32_sparc_backend =
412   {
413     "NetWare SPARC Module   \032",
414     sizeof (Nlm32_sparc_External_Fixed_Header),
415     0,  /* optional_prefix_size */
416     bfd_arch_sparc,
417     0,
418     false,
419     0,  /* backend_object_p */
420     0,  /* write_prefix_func */
421     nlm_sparc_read_reloc,
422     nlm_sparc_mangle_relocs,
423     nlm_sparc_read_import,
424     nlm_sparc_write_import,
425     0,  /* set_public_section */
426     0,  /* get_public_offset */
427     nlm_swap_fixed_header_in,
428     nlm_swap_fixed_header_out,
429     nlm_sparc_write_external,
430     nlm_sparc_write_export
431   };
432
433 #define TARGET_BIG_NAME         "nlm32-sparc"
434 #define TARGET_BIG_SYM          nlmNAME(sparc_vec)
435 #define TARGET_BACKEND_DATA     & nlm32_sparc_backend
436
437 #include "nlm-target.h"