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