OSDN Git Service

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