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