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