OSDN Git Service

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