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