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, §ion, &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