bfd/
[deliverable/binutils-gdb.git] / bfd / i386lynx.c
1 /* BFD back-end for i386 a.out binaries under LynxOS.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2001, 2002,
3 2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
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.
11
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.
16
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. */
21
22 #define TEXT_START_ADDR 0
23 #define TARGET_PAGE_SIZE 4096
24 #define SEGMENT_SIZE TARGET_PAGE_SIZE
25 #define DEFAULT_ARCH bfd_arch_i386
26
27 /* Do not "beautify" the CONCAT* macro args. Traditional C will not
28 remove whitespace added here, and thus will fail to concatenate
29 the tokens. */
30 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
31 #define TARGETNAME "a.out-i386-lynx"
32
33 #include "sysdep.h"
34 #include "bfd.h"
35 #include "libbfd.h"
36
37 #ifndef WRITE_HEADERS
38 #define WRITE_HEADERS(abfd, execp) \
39 { \
40 bfd_size_type text_size; /* dummy vars */ \
41 file_ptr text_end; \
42 if (adata(abfd).magic == undecided_magic) \
43 NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
44 \
45 execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
46 execp->a_entry = bfd_get_start_address (abfd); \
47 \
48 execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
49 obj_reloc_entry_size (abfd)); \
50 execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
51 obj_reloc_entry_size (abfd)); \
52 NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
53 \
54 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 \
55 || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
56 abfd) != EXEC_BYTES_SIZE) \
57 return FALSE; \
58 /* Now write out reloc info, followed by syms and strings */ \
59 \
60 if (bfd_get_symcount (abfd) != 0) \
61 { \
62 if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) \
63 != 0) \
64 return FALSE; \
65 \
66 if (! NAME(aout,write_syms) (abfd)) return FALSE; \
67 \
68 if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) \
69 != 0) \
70 return FALSE; \
71 \
72 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
73 return FALSE; \
74 if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) \
75 != 0) \
76 return 0; \
77 \
78 if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd))) \
79 return FALSE; \
80 } \
81 }
82 #endif
83
84 #include "libaout.h"
85 #include "aout/aout64.h"
86
87 void NAME (lynx,swap_std_reloc_out)
88 PARAMS ((bfd *, arelent *, struct reloc_std_external *));
89 void NAME (lynx,swap_ext_reloc_out)
90 PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
91 void NAME (lynx,swap_ext_reloc_in)
92 PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
93 bfd_size_type));
94 void NAME (lynx,swap_std_reloc_in)
95 PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
96 bfd_size_type));
97 bfd_boolean NAME (lynx,slurp_reloc_table)
98 PARAMS ((bfd *, sec_ptr, asymbol **));
99 bfd_boolean NAME (lynx,squirt_out_relocs)
100 PARAMS ((bfd *, asection *));
101 long NAME (lynx,canonicalize_reloc)
102 PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
103
104 #ifdef LYNX_CORE
105
106 char *lynx_core_file_failing_command ();
107 int lynx_core_file_failing_signal ();
108 bfd_boolean lynx_core_file_matches_executable_p ();
109 const bfd_target *lynx_core_file_p ();
110
111 #define MY_core_file_failing_command lynx_core_file_failing_command
112 #define MY_core_file_failing_signal lynx_core_file_failing_signal
113 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
114 #define MY_core_file_p lynx_core_file_p
115
116 #endif /* LYNX_CORE */
117 \f
118
119 #define KEEPIT udata.i
120
121 extern reloc_howto_type aout_32_ext_howto_table[];
122 extern reloc_howto_type aout_32_std_howto_table[];
123
124 /* Standard reloc stuff */
125 /* Output standard relocation information to a file in target byte order. */
126
127 void
128 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
129 bfd *abfd;
130 arelent *g;
131 struct reloc_std_external *natptr;
132 {
133 int r_index;
134 asymbol *sym = *(g->sym_ptr_ptr);
135 int r_extern;
136 unsigned int r_length;
137 int r_pcrel;
138 int r_baserel, r_jmptable, r_relative;
139 asection *output_section = sym->section->output_section;
140
141 PUT_WORD (abfd, g->address, natptr->r_address);
142
143 r_length = g->howto->size; /* Size as a power of two */
144 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
145 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
146 r_baserel = 0;
147 r_jmptable = 0;
148 r_relative = 0;
149
150 /* name was clobbered by aout_write_syms to be symbol index */
151
152 /* If this relocation is relative to a symbol then set the
153 r_index to the symbols index, and the r_extern bit.
154
155 Absolute symbols can come in in two ways, either as an offset
156 from the abs section, or as a symbol which has an abs value.
157 check for that here
158 */
159
160
161 if (bfd_is_com_section (output_section)
162 || bfd_is_abs_section (output_section)
163 || bfd_is_und_section (output_section))
164 {
165 if (bfd_abs_section_ptr->symbol == sym)
166 {
167 /* Whoops, looked like an abs symbol, but is really an offset
168 from the abs section */
169 r_index = 0;
170 r_extern = 0;
171 }
172 else
173 {
174 /* Fill in symbol */
175 r_extern = 1;
176 r_index = (*g->sym_ptr_ptr)->KEEPIT;
177 }
178 }
179 else
180 {
181 /* Just an ordinary section */
182 r_extern = 0;
183 r_index = output_section->target_index;
184 }
185
186 /* now the fun stuff */
187 if (bfd_header_big_endian (abfd))
188 {
189 natptr->r_index[0] = r_index >> 16;
190 natptr->r_index[1] = r_index >> 8;
191 natptr->r_index[2] = r_index;
192 natptr->r_type[0] =
193 (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
194 | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
195 | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
196 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
197 | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
198 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
199 }
200 else
201 {
202 natptr->r_index[2] = r_index >> 16;
203 natptr->r_index[1] = r_index >> 8;
204 natptr->r_index[0] = r_index;
205 natptr->r_type[0] =
206 (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
207 | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
208 | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
209 | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
210 | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
211 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
212 }
213 }
214
215
216 /* Extended stuff */
217 /* Output extended relocation information to a file in target byte order. */
218
219 void
220 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
221 bfd *abfd;
222 arelent *g;
223 register struct reloc_ext_external *natptr;
224 {
225 int r_index;
226 int r_extern;
227 unsigned int r_type;
228 unsigned int r_addend;
229 asymbol *sym = *(g->sym_ptr_ptr);
230 asection *output_section = sym->section->output_section;
231
232 PUT_WORD (abfd, g->address, natptr->r_address);
233
234 r_type = (unsigned int) g->howto->type;
235
236 r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
237
238
239 /* If this relocation is relative to a symbol then set the
240 r_index to the symbols index, and the r_extern bit.
241
242 Absolute symbols can come in in two ways, either as an offset
243 from the abs section, or as a symbol which has an abs value.
244 check for that here
245 */
246
247 if (bfd_is_com_section (output_section)
248 || bfd_is_abs_section (output_section)
249 || bfd_is_und_section (output_section))
250 {
251 if (bfd_abs_section_ptr->symbol == sym)
252 {
253 /* Whoops, looked like an abs symbol, but is really an offset
254 from the abs section */
255 r_index = 0;
256 r_extern = 0;
257 }
258 else
259 {
260 r_extern = 1;
261 r_index = (*g->sym_ptr_ptr)->KEEPIT;
262 }
263 }
264 else
265 {
266 /* Just an ordinary section */
267 r_extern = 0;
268 r_index = output_section->target_index;
269 }
270
271
272 /* now the fun stuff */
273 if (bfd_header_big_endian (abfd))
274 {
275 natptr->r_index[0] = r_index >> 16;
276 natptr->r_index[1] = r_index >> 8;
277 natptr->r_index[2] = r_index;
278 natptr->r_type[0] =
279 (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
280 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
281 }
282 else
283 {
284 natptr->r_index[2] = r_index >> 16;
285 natptr->r_index[1] = r_index >> 8;
286 natptr->r_index[0] = r_index;
287 natptr->r_type[0] =
288 (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
289 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
290 }
291
292 PUT_WORD (abfd, r_addend, natptr->r_addend);
293 }
294
295 /* BFD deals internally with all things based from the section they're
296 in. so, something in 10 bytes into a text section with a base of
297 50 would have a symbol (.text+10) and know .text vma was 50.
298
299 Aout keeps all it's symbols based from zero, so the symbol would
300 contain 60. This macro subs the base of each section from the value
301 to give the true offset from the section */
302
303
304 #define MOVE_ADDRESS(ad) \
305 if (r_extern) { \
306 /* undefined symbol */ \
307 cache_ptr->sym_ptr_ptr = symbols + r_index; \
308 cache_ptr->addend = ad; \
309 } else { \
310 /* defined, section relative. replace symbol with pointer to \
311 symbol which points to section */ \
312 switch (r_index) { \
313 case N_TEXT: \
314 case N_TEXT | N_EXT: \
315 cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
316 cache_ptr->addend = ad - su->textsec->vma; \
317 break; \
318 case N_DATA: \
319 case N_DATA | N_EXT: \
320 cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
321 cache_ptr->addend = ad - su->datasec->vma; \
322 break; \
323 case N_BSS: \
324 case N_BSS | N_EXT: \
325 cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
326 cache_ptr->addend = ad - su->bsssec->vma; \
327 break; \
328 default: \
329 case N_ABS: \
330 case N_ABS | N_EXT: \
331 cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
332 cache_ptr->addend = ad; \
333 break; \
334 } \
335 } \
336
337 void
338 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
339 bfd *abfd;
340 struct reloc_ext_external *bytes;
341 arelent *cache_ptr;
342 asymbol **symbols;
343 bfd_size_type symcount ATTRIBUTE_UNUSED;
344 {
345 int r_index;
346 int r_extern;
347 unsigned int r_type;
348 struct aoutdata *su = &(abfd->tdata.aout_data->a);
349
350 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
351
352 r_index = bytes->r_index[1];
353 r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
354 r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
355 >> RELOC_EXT_BITS_TYPE_SH_BIG;
356
357 cache_ptr->howto = aout_32_ext_howto_table + r_type;
358 MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
359 }
360
361 void
362 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
363 bfd *abfd;
364 struct reloc_std_external *bytes;
365 arelent *cache_ptr;
366 asymbol **symbols;
367 bfd_size_type symcount ATTRIBUTE_UNUSED;
368 {
369 int r_index;
370 int r_extern;
371 unsigned int r_length;
372 int r_pcrel;
373 struct aoutdata *su = &(abfd->tdata.aout_data->a);
374
375 cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
376
377 r_index = bytes->r_index[1];
378 r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
379 r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
380 r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
381 >> RELOC_STD_BITS_LENGTH_SH_BIG;
382
383 cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
384 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
385
386 MOVE_ADDRESS (0);
387 }
388
389 /* Reloc hackery */
390
391 bfd_boolean
392 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
393 bfd *abfd;
394 sec_ptr asect;
395 asymbol **symbols;
396 {
397 bfd_size_type count;
398 bfd_size_type reloc_size;
399 PTR relocs;
400 arelent *reloc_cache;
401 size_t each_size;
402
403 if (asect->relocation)
404 return TRUE;
405
406 if (asect->flags & SEC_CONSTRUCTOR)
407 return TRUE;
408
409 if (asect == obj_datasec (abfd))
410 {
411 reloc_size = exec_hdr (abfd)->a_drsize;
412 goto doit;
413 }
414
415 if (asect == obj_textsec (abfd))
416 {
417 reloc_size = exec_hdr (abfd)->a_trsize;
418 goto doit;
419 }
420
421 bfd_set_error (bfd_error_invalid_operation);
422 return FALSE;
423
424 doit:
425 if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
426 return FALSE;
427 each_size = obj_reloc_entry_size (abfd);
428
429 count = reloc_size / each_size;
430
431
432 reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
433 if (!reloc_cache && count != 0)
434 return FALSE;
435
436 relocs = (PTR) bfd_alloc (abfd, reloc_size);
437 if (!relocs && reloc_size != 0)
438 {
439 free (reloc_cache);
440 return FALSE;
441 }
442
443 if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
444 {
445 bfd_release (abfd, relocs);
446 free (reloc_cache);
447 return FALSE;
448 }
449
450 if (each_size == RELOC_EXT_SIZE)
451 {
452 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
453 unsigned int counter = 0;
454 arelent *cache_ptr = reloc_cache;
455
456 for (; counter < count; counter++, rptr++, cache_ptr++)
457 {
458 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
459 (bfd_size_type) bfd_get_symcount (abfd));
460 }
461 }
462 else
463 {
464 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
465 unsigned int counter = 0;
466 arelent *cache_ptr = reloc_cache;
467
468 for (; counter < count; counter++, rptr++, cache_ptr++)
469 {
470 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
471 (bfd_size_type) bfd_get_symcount (abfd));
472 }
473
474 }
475
476 bfd_release (abfd, relocs);
477 asect->relocation = reloc_cache;
478 asect->reloc_count = count;
479 return TRUE;
480 }
481
482
483
484 /* Write out a relocation section into an object file. */
485
486 bfd_boolean
487 NAME(lynx,squirt_out_relocs) (abfd, section)
488 bfd *abfd;
489 asection *section;
490 {
491 arelent **generic;
492 unsigned char *native, *natptr;
493 size_t each_size;
494
495 unsigned int count = section->reloc_count;
496 bfd_size_type natsize;
497
498 if (count == 0)
499 return TRUE;
500
501 each_size = obj_reloc_entry_size (abfd);
502 natsize = count;
503 natsize *= each_size;
504 native = (unsigned char *) bfd_zalloc (abfd, natsize);
505 if (!native)
506 return FALSE;
507
508 generic = section->orelocation;
509
510 if (each_size == RELOC_EXT_SIZE)
511 {
512 for (natptr = native;
513 count != 0;
514 --count, natptr += each_size, ++generic)
515 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
516 }
517 else
518 {
519 for (natptr = native;
520 count != 0;
521 --count, natptr += each_size, ++generic)
522 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
523 }
524
525 if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
526 {
527 bfd_release (abfd, native);
528 return FALSE;
529 }
530 bfd_release (abfd, native);
531
532 return TRUE;
533 }
534
535 /* This is stupid. This function should be a boolean predicate */
536 long
537 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
538 bfd *abfd;
539 sec_ptr section;
540 arelent **relptr;
541 asymbol **symbols;
542 {
543 arelent *tblptr = section->relocation;
544 unsigned int count;
545
546 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
547 return -1;
548
549 if (section->flags & SEC_CONSTRUCTOR)
550 {
551 arelent_chain *chain = section->constructor_chain;
552 for (count = 0; count < section->reloc_count; count++)
553 {
554 *relptr++ = &chain->relent;
555 chain = chain->next;
556 }
557 }
558 else
559 {
560 tblptr = section->relocation;
561
562 for (count = 0; count++ < section->reloc_count;)
563 {
564 *relptr++ = tblptr++;
565 }
566 }
567 *relptr = 0;
568
569 return section->reloc_count;
570 }
571
572 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
573
574 #include "aout-target.h"
This page took 0.043291 seconds and 4 git commands to generate.