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