OSDN Git Service

Touches most files in bfd/, so likely will be blamed for everything..
[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 #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                      \
54             || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
55                           abfd) != 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 void NAME (lynx,swap_std_reloc_out) PARAMS ((bfd *, arelent *, struct reloc_std_external *));
87 void NAME (lynx,swap_ext_reloc_out) PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
88 void NAME (lynx,swap_ext_reloc_in)  PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **, bfd_size_type));
89 void NAME (lynx,swap_std_reloc_in)  PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **, bfd_size_type));
90 boolean NAME (lynx,slurp_reloc_table) PARAMS ((bfd *, sec_ptr, asymbol **));
91 boolean NAME (lynx,squirt_out_relocs) PARAMS ((bfd *, asection *));
92 long NAME (lynx,canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
93
94 #ifdef LYNX_CORE
95
96 char *lynx_core_file_failing_command ();
97 int lynx_core_file_failing_signal ();
98 boolean lynx_core_file_matches_executable_p ();
99 const bfd_target *lynx_core_file_p ();
100
101 #define MY_core_file_failing_command lynx_core_file_failing_command
102 #define MY_core_file_failing_signal lynx_core_file_failing_signal
103 #define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
104 #define MY_core_file_p lynx_core_file_p
105
106 #endif /* LYNX_CORE */
107 \f
108
109 #define KEEPIT udata.i
110
111 extern reloc_howto_type aout_32_ext_howto_table[];
112 extern reloc_howto_type aout_32_std_howto_table[];
113
114 /* Standard reloc stuff */
115 /* Output standard relocation information to a file in target byte order. */
116
117 void
118 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
119      bfd *abfd;
120      arelent *g;
121      struct reloc_std_external *natptr;
122 {
123   int r_index;
124   asymbol *sym = *(g->sym_ptr_ptr);
125   int r_extern;
126   unsigned int r_length;
127   int r_pcrel;
128   int r_baserel, r_jmptable, r_relative;
129   unsigned int r_addend;
130   asection *output_section = sym->section->output_section;
131
132   PUT_WORD (abfd, g->address, natptr->r_address);
133
134   r_length = g->howto->size;    /* Size as a power of two */
135   r_pcrel = (int) g->howto->pc_relative;        /* Relative to PC? */
136   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
137   r_baserel = 0;
138   r_jmptable = 0;
139   r_relative = 0;
140
141   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
142
143   /* name was clobbered by aout_write_syms to be symbol index */
144
145   /* If this relocation is relative to a symbol then set the
146      r_index to the symbols index, and the r_extern bit.
147
148      Absolute symbols can come in in two ways, either as an offset
149      from the abs section, or as a symbol which has an abs value.
150      check for that here
151      */
152
153
154   if (bfd_is_com_section (output_section)
155       || bfd_is_abs_section (output_section)
156       || bfd_is_und_section (output_section))
157     {
158       if (bfd_abs_section_ptr->symbol == sym)
159         {
160           /* Whoops, looked like an abs symbol, but is really an offset
161            from the abs section */
162           r_index = 0;
163           r_extern = 0;
164         }
165       else
166         {
167           /* Fill in symbol */
168           r_extern = 1;
169           r_index = (*g->sym_ptr_ptr)->KEEPIT;
170         }
171     }
172   else
173     {
174       /* Just an ordinary section */
175       r_extern = 0;
176       r_index = output_section->target_index;
177     }
178
179   /* now the fun stuff */
180   if (bfd_header_big_endian (abfd))
181     {
182       natptr->r_index[0] = r_index >> 16;
183       natptr->r_index[1] = r_index >> 8;
184       natptr->r_index[2] = r_index;
185       natptr->r_type[0] =
186         (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
187         | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
188         | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
189         | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
190         | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
191         | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
192     }
193   else
194     {
195       natptr->r_index[2] = r_index >> 16;
196       natptr->r_index[1] = r_index >> 8;
197       natptr->r_index[0] = r_index;
198       natptr->r_type[0] =
199         (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
200         | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
201         | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
202         | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
203         | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
204         | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
205     }
206 }
207
208
209 /* Extended stuff */
210 /* Output extended relocation information to a file in target byte order. */
211
212 void
213 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
214      bfd *abfd;
215      arelent *g;
216      register struct reloc_ext_external *natptr;
217 {
218   int r_index;
219   int r_extern;
220   unsigned int r_type;
221   unsigned int r_addend;
222   asymbol *sym = *(g->sym_ptr_ptr);
223   asection *output_section = sym->section->output_section;
224
225   PUT_WORD (abfd, g->address, natptr->r_address);
226
227   r_type = (unsigned int) g->howto->type;
228
229   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
230
231
232   /* If this relocation is relative to a symbol then set the
233      r_index to the symbols index, and the r_extern bit.
234
235      Absolute symbols can come in in two ways, either as an offset
236      from the abs section, or as a symbol which has an abs value.
237      check for that here
238      */
239
240   if (bfd_is_com_section (output_section)
241       || bfd_is_abs_section (output_section)
242       || bfd_is_und_section (output_section))
243     {
244       if (bfd_abs_section_ptr->symbol == sym)
245         {
246           /* Whoops, looked like an abs symbol, but is really an offset
247          from the abs section */
248           r_index = 0;
249           r_extern = 0;
250         }
251       else
252         {
253           r_extern = 1;
254           r_index = (*g->sym_ptr_ptr)->KEEPIT;
255         }
256     }
257   else
258     {
259       /* Just an ordinary section */
260       r_extern = 0;
261       r_index = output_section->target_index;
262     }
263
264
265   /* now the fun stuff */
266   if (bfd_header_big_endian (abfd))
267     {
268       natptr->r_index[0] = r_index >> 16;
269       natptr->r_index[1] = r_index >> 8;
270       natptr->r_index[2] = r_index;
271       natptr->r_type[0] =
272         (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
273         | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
274     }
275   else
276     {
277       natptr->r_index[2] = r_index >> 16;
278       natptr->r_index[1] = r_index >> 8;
279       natptr->r_index[0] = r_index;
280       natptr->r_type[0] =
281         (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
282         | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
283     }
284
285   PUT_WORD (abfd, r_addend, natptr->r_addend);
286 }
287
288 /* BFD deals internally with all things based from the section they're
289    in. so, something in 10 bytes into a text section  with a base of
290    50 would have a symbol (.text+10) and know .text vma was 50.
291
292    Aout keeps all it's symbols based from zero, so the symbol would
293    contain 60. This macro subs the base of each section from the value
294    to give the true offset from the section */
295
296
297 #define MOVE_ADDRESS(ad)                                                \
298   if (r_extern) {                                                       \
299    /* undefined symbol */                                               \
300      cache_ptr->sym_ptr_ptr = symbols + r_index;                        \
301      cache_ptr->addend = ad;                                            \
302      } else {                                                           \
303     /* defined, section relative. replace symbol with pointer to        \
304        symbol which points to section  */                               \
305     switch (r_index) {                                                  \
306     case N_TEXT:                                                        \
307     case N_TEXT | N_EXT:                                                \
308       cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;      \
309       cache_ptr->addend = ad  - su->textsec->vma;                       \
310       break;                                                            \
311     case N_DATA:                                                        \
312     case N_DATA | N_EXT:                                                \
313       cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;      \
314       cache_ptr->addend = ad - su->datasec->vma;                        \
315       break;                                                            \
316     case N_BSS:                                                         \
317     case N_BSS | N_EXT:                                                 \
318       cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;       \
319       cache_ptr->addend = ad - su->bsssec->vma;                         \
320       break;                                                            \
321     default:                                                            \
322     case N_ABS:                                                         \
323     case N_ABS | N_EXT:                                                 \
324      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;      \
325       cache_ptr->addend = ad;                                           \
326       break;                                                            \
327     }                                                                   \
328   }                                                                     \
329
330 void
331 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
332      bfd *abfd;
333      struct reloc_ext_external *bytes;
334      arelent *cache_ptr;
335      asymbol **symbols;
336      bfd_size_type symcount ATTRIBUTE_UNUSED;
337 {
338   int r_index;
339   int r_extern;
340   unsigned int r_type;
341   struct aoutdata *su = &(abfd->tdata.aout_data->a);
342
343   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
344
345   r_index = bytes->r_index[1];
346   r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
347   r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
348     >> RELOC_EXT_BITS_TYPE_SH_BIG;
349
350   cache_ptr->howto = aout_32_ext_howto_table + r_type;
351   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
352 }
353
354 void
355 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
356      bfd *abfd;
357      struct reloc_std_external *bytes;
358      arelent *cache_ptr;
359      asymbol **symbols;
360      bfd_size_type symcount ATTRIBUTE_UNUSED;
361 {
362   int r_index;
363   int r_extern;
364   unsigned int r_length;
365   int r_pcrel;
366   int r_baserel, r_jmptable, r_relative;
367   struct aoutdata *su = &(abfd->tdata.aout_data->a);
368
369   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
370
371   r_index = bytes->r_index[1];
372   r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
373   r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
374   r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
375   r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
376   r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
377   r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
378     >> RELOC_STD_BITS_LENGTH_SH_BIG;
379
380   cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
381   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
382
383   MOVE_ADDRESS (0);
384 }
385
386 /* Reloc hackery */
387
388 boolean
389 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
390      bfd *abfd;
391      sec_ptr asect;
392      asymbol **symbols;
393 {
394   bfd_size_type count;
395   bfd_size_type reloc_size;
396   PTR relocs;
397   arelent *reloc_cache;
398   size_t each_size;
399
400   if (asect->relocation)
401     return true;
402
403   if (asect->flags & SEC_CONSTRUCTOR)
404     return true;
405
406   if (asect == obj_datasec (abfd))
407     {
408       reloc_size = exec_hdr (abfd)->a_drsize;
409       goto doit;
410     }
411
412   if (asect == obj_textsec (abfd))
413     {
414       reloc_size = exec_hdr (abfd)->a_trsize;
415       goto doit;
416     }
417
418   bfd_set_error (bfd_error_invalid_operation);
419   return false;
420
421 doit:
422   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
423     return false;
424   each_size = obj_reloc_entry_size (abfd);
425
426   count = reloc_size / each_size;
427
428
429   reloc_cache = (arelent *) bfd_malloc (count * sizeof (arelent));
430   if (!reloc_cache && count != 0)
431     return false;
432   memset (reloc_cache, 0, (size_t) count * sizeof (arelent));
433
434   relocs = (PTR) bfd_alloc (abfd, reloc_size);
435   if (!relocs && reloc_size != 0)
436     {
437       free (reloc_cache);
438       return false;
439     }
440
441   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
442     {
443       bfd_release (abfd, relocs);
444       free (reloc_cache);
445       return false;
446     }
447
448   if (each_size == RELOC_EXT_SIZE)
449     {
450       register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
451       unsigned int counter = 0;
452       arelent *cache_ptr = reloc_cache;
453
454       for (; counter < count; counter++, rptr++, cache_ptr++)
455         {
456           NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
457                                         (bfd_size_type) bfd_get_symcount (abfd));
458         }
459     }
460   else
461     {
462       register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
463       unsigned int counter = 0;
464       arelent *cache_ptr = reloc_cache;
465
466       for (; counter < count; counter++, rptr++, cache_ptr++)
467         {
468           NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
469                                         (bfd_size_type) bfd_get_symcount (abfd));
470         }
471
472     }
473
474   bfd_release (abfd, relocs);
475   asect->relocation = reloc_cache;
476   asect->reloc_count = count;
477   return true;
478 }
479
480
481
482 /* Write out a relocation section into an object file.  */
483
484 boolean
485 NAME(lynx,squirt_out_relocs) (abfd, section)
486      bfd *abfd;
487      asection *section;
488 {
489   arelent **generic;
490   unsigned char *native, *natptr;
491   size_t each_size;
492
493   unsigned int count = section->reloc_count;
494   bfd_size_type natsize;
495
496   if (count == 0)
497     return true;
498
499   each_size = obj_reloc_entry_size (abfd);
500   natsize = count;
501   natsize *= each_size;
502   native = (unsigned char *) bfd_zalloc (abfd, natsize);
503   if (!native)
504     return false;
505
506   generic = section->orelocation;
507
508   if (each_size == RELOC_EXT_SIZE)
509     {
510       for (natptr = native;
511            count != 0;
512            --count, natptr += each_size, ++generic)
513         NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
514     }
515   else
516     {
517       for (natptr = native;
518            count != 0;
519            --count, natptr += each_size, ++generic)
520         NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
521     }
522
523   if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
524     {
525       bfd_release (abfd, native);
526       return false;
527     }
528   bfd_release (abfd, native);
529
530   return true;
531 }
532
533 /* This is stupid.  This function should be a boolean predicate */
534 long
535 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
536      bfd *abfd;
537      sec_ptr section;
538      arelent **relptr;
539      asymbol **symbols;
540 {
541   arelent *tblptr = section->relocation;
542   unsigned int count;
543
544   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
545     return -1;
546
547   if (section->flags & SEC_CONSTRUCTOR)
548     {
549       arelent_chain *chain = section->constructor_chain;
550       for (count = 0; count < section->reloc_count; count++)
551         {
552           *relptr++ = &chain->relent;
553           chain = chain->next;
554         }
555     }
556   else
557     {
558       tblptr = section->relocation;
559
560       for (count = 0; count++ < section->reloc_count;)
561         {
562           *relptr++ = tblptr++;
563         }
564     }
565   *relptr = 0;
566
567   return section->reloc_count;
568 }
569
570 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
571
572 #include "aout-target.h"