6b27bd19ed317124b7c063543114a62fd142e1a1
[platform/upstream/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., 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
87 char *lynx_core_file_failing_command ();
88 int lynx_core_file_failing_signal ();
89 boolean lynx_core_file_matches_executable_p ();
90 const 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 flags
101
102 extern reloc_howto_type aout_32_ext_howto_table[];
103 extern 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
108 void
109 NAME(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 = stoi ((*(g->sym_ptr_ptr))->KEEPIT);
161
162         }
163     }
164   else
165     {
166       /* Just an ordinary section */
167       r_extern = 0;
168       r_index = output_section->target_index;
169     }
170
171   /* now the fun stuff */
172   if (abfd->xvec->header_byteorder_big_p != false)
173     {
174       natptr->r_index[0] = r_index >> 16;
175       natptr->r_index[1] = r_index >> 8;
176       natptr->r_index[2] = r_index;
177       natptr->r_type[0] =
178         (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
179         | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
180         | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
181         | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
182         | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
183         | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
184     }
185   else
186     {
187       natptr->r_index[2] = r_index >> 16;
188       natptr->r_index[1] = r_index >> 8;
189       natptr->r_index[0] = r_index;
190       natptr->r_type[0] =
191         (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
192         | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
193         | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
194         | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
195         | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
196         | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
197     }
198 }
199
200
201 /* Extended stuff */
202 /* Output extended relocation information to a file in target byte order. */
203
204 void
205 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
206      bfd *abfd;
207      arelent *g;
208      register struct reloc_ext_external *natptr;
209 {
210   int r_index;
211   int r_extern;
212   unsigned int r_type;
213   unsigned int r_addend;
214   asymbol *sym = *(g->sym_ptr_ptr);
215   asection *output_section = sym->section->output_section;
216
217   PUT_WORD (abfd, g->address, natptr->r_address);
218
219   r_type = (unsigned int) g->howto->type;
220
221   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
222
223
224   /* If this relocation is relative to a symbol then set the
225      r_index to the symbols index, and the r_extern bit.
226
227      Absolute symbols can come in in two ways, either as an offset
228      from the abs section, or as a symbol which has an abs value.
229      check for that here
230      */
231
232   if (bfd_is_com_section (output_section)
233       || bfd_is_abs_section (output_section)
234       || bfd_is_und_section (output_section))
235     {
236       if (bfd_abs_section_ptr->symbol == sym)
237         {
238           /* Whoops, looked like an abs symbol, but is really an offset
239          from the abs section */
240           r_index = 0;
241           r_extern = 0;
242         }
243       else
244         {
245           r_extern = 1;
246           r_index = stoi ((*(g->sym_ptr_ptr))->KEEPIT);
247         }
248     }
249   else
250     {
251       /* Just an ordinary section */
252       r_extern = 0;
253       r_index = output_section->target_index;
254     }
255
256
257   /* now the fun stuff */
258   if (abfd->xvec->header_byteorder_big_p != false)
259     {
260       natptr->r_index[0] = r_index >> 16;
261       natptr->r_index[1] = r_index >> 8;
262       natptr->r_index[2] = r_index;
263       natptr->r_type[0] =
264         (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
265         | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
266     }
267   else
268     {
269       natptr->r_index[2] = r_index >> 16;
270       natptr->r_index[1] = r_index >> 8;
271       natptr->r_index[0] = r_index;
272       natptr->r_type[0] =
273         (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
274         | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
275     }
276
277   PUT_WORD (abfd, r_addend, natptr->r_addend);
278 }
279
280 /* BFD deals internally with all things based from the section they're
281    in. so, something in 10 bytes into a text section  with a base of
282    50 would have a symbol (.text+10) and know .text vma was 50.
283
284    Aout keeps all it's symbols based from zero, so the symbol would
285    contain 60. This macro subs the base of each section from the value
286    to give the true offset from the section */
287
288
289 #define MOVE_ADDRESS(ad)                                                \
290   if (r_extern) {                                                       \
291    /* undefined symbol */                                               \
292      cache_ptr->sym_ptr_ptr = symbols + r_index;                        \
293      cache_ptr->addend = ad;                                            \
294      } else {                                                           \
295     /* defined, section relative. replace symbol with pointer to        \
296        symbol which points to section  */                               \
297     switch (r_index) {                                                  \
298     case N_TEXT:                                                        \
299     case N_TEXT | N_EXT:                                                \
300       cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;      \
301       cache_ptr->addend = ad  - su->textsec->vma;                       \
302       break;                                                            \
303     case N_DATA:                                                        \
304     case N_DATA | N_EXT:                                                \
305       cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;      \
306       cache_ptr->addend = ad - su->datasec->vma;                        \
307       break;                                                            \
308     case N_BSS:                                                         \
309     case N_BSS | N_EXT:                                                 \
310       cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;       \
311       cache_ptr->addend = ad - su->bsssec->vma;                         \
312       break;                                                            \
313     default:                                                            \
314     case N_ABS:                                                         \
315     case N_ABS | N_EXT:                                                 \
316      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;      \
317       cache_ptr->addend = ad;                                           \
318       break;                                                            \
319     }                                                                   \
320   }                                                                     \
321
322 void
323 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
324      bfd *abfd;
325      struct reloc_ext_external *bytes;
326      arelent *cache_ptr;
327      asymbol **symbols;
328      bfd_size_type symcount;
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, symcount)
348      bfd *abfd;
349      struct reloc_std_external *bytes;
350      arelent *cache_ptr;
351      asymbol **symbols;
352      bfd_size_type symcount;
353 {
354   int r_index;
355   int r_extern;
356   unsigned int r_length;
357   int r_pcrel;
358   int r_baserel, r_jmptable, r_relative;
359   struct aoutdata *su = &(abfd->tdata.aout_data->a);
360
361   cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
362
363   r_index = bytes->r_index[1];
364   r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
365   r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
366   r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
367   r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
368   r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
369   r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
370     >> RELOC_STD_BITS_LENGTH_SH_BIG;
371
372   cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
373   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
374
375   MOVE_ADDRESS (0);
376 }
377
378 /* Reloc hackery */
379
380 boolean
381 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
382      bfd *abfd;
383      sec_ptr asect;
384      asymbol **symbols;
385 {
386   unsigned int count;
387   bfd_size_type reloc_size;
388   PTR relocs;
389   arelent *reloc_cache;
390   size_t each_size;
391
392   if (asect->relocation)
393     return true;
394
395   if (asect->flags & SEC_CONSTRUCTOR)
396     return true;
397
398   if (asect == obj_datasec (abfd))
399     {
400       reloc_size = exec_hdr (abfd)->a_drsize;
401       goto doit;
402     }
403
404   if (asect == obj_textsec (abfd))
405     {
406       reloc_size = exec_hdr (abfd)->a_trsize;
407       goto doit;
408     }
409
410   bfd_set_error (bfd_error_invalid_operation);
411   return false;
412
413 doit:
414   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
415     return false;
416   each_size = obj_reloc_entry_size (abfd);
417
418   count = reloc_size / each_size;
419
420
421   reloc_cache = (arelent *) malloc (count * sizeof (arelent));
422   if (!reloc_cache && count != 0)
423     {
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 && reloc_size != 0)
431     {
432       free (reloc_cache);
433       return false;
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                                         bfd_get_symcount (abfd));
453         }
454     }
455   else
456     {
457       register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
458       unsigned int counter = 0;
459       arelent *cache_ptr = reloc_cache;
460
461       for (; counter < count; counter++, rptr++, cache_ptr++)
462         {
463           NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
464                                         bfd_get_symcount (abfd));
465         }
466
467     }
468
469   bfd_release (abfd, relocs);
470   asect->relocation = reloc_cache;
471   asect->reloc_count = count;
472   return true;
473 }
474
475
476
477 /* Write out a relocation section into an object file.  */
478
479 boolean
480 NAME(lynx,squirt_out_relocs) (abfd, section)
481      bfd *abfd;
482      asection *section;
483 {
484   arelent **generic;
485   unsigned char *native, *natptr;
486   size_t each_size;
487
488   unsigned int count = section->reloc_count;
489   size_t natsize;
490
491   if (count == 0)
492     return true;
493
494   each_size = obj_reloc_entry_size (abfd);
495   natsize = each_size * count;
496   native = (unsigned char *) bfd_zalloc (abfd, natsize);
497   if (!native)
498     return false;
499
500   generic = section->orelocation;
501
502   if (each_size == RELOC_EXT_SIZE)
503     {
504       for (natptr = native;
505            count != 0;
506            --count, natptr += each_size, ++generic)
507         NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
508     }
509   else
510     {
511       for (natptr = native;
512            count != 0;
513            --count, natptr += each_size, ++generic)
514         NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
515     }
516
517   if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
518     {
519       bfd_release (abfd, native);
520       return false;
521     }
522   bfd_release (abfd, native);
523
524   return true;
525 }
526
527 /* This is stupid.  This function should be a boolean predicate */
528 long
529 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
530      bfd *abfd;
531      sec_ptr section;
532      arelent **relptr;
533      asymbol **symbols;
534 {
535   arelent *tblptr = section->relocation;
536   unsigned int count;
537
538   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
539     return -1;
540
541   if (section->flags & SEC_CONSTRUCTOR)
542     {
543       arelent_chain *chain = section->constructor_chain;
544       for (count = 0; count < section->reloc_count; count++)
545         {
546           *relptr++ = &chain->relent;
547           chain = chain->next;
548         }
549     }
550   else
551     {
552       tblptr = section->relocation;
553
554       for (count = 0; count++ < section->reloc_count;)
555         {
556           *relptr++ = tblptr++;
557         }
558     }
559   *relptr = 0;
560
561   return section->reloc_count;
562 }
563
564 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
565
566 #include "aout-target.h"