Made sure that every call to bfd_read, bfd_write, and bfd_seek
[external/binutils.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"