OSDN Git Service

* Many files: Changes to avoid gcc warnings: Add ATTRIBUTE_UNUSED
[pf3gnuchains/pf3gnuchains3x.git] / bfd / i386lynx.c
1 /* BFD back-end for i386 a.out binaries under LynxOS.
2    Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1999
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) 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 LYNX_CORE
87
88 char *lynx_core_file_failing_command ();
89 int lynx_core_file_failing_signal ();
90 boolean lynx_core_file_matches_executable_p ();
91 const 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 /* LYNX_CORE */
99 \f
100
101 #define KEEPIT udata.i
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       || bfd_is_abs_section (output_section)
148       || bfd_is_und_section (output_section))
149     {
150       if (bfd_abs_section_ptr->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 = (*g->sym_ptr_ptr)->KEEPIT;
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 (bfd_header_big_endian (abfd))
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 = (*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 (bfd_header_big_endian (abfd))
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 ATTRIBUTE_UNUSED;
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 ATTRIBUTE_UNUSED;
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 *) bfd_malloc (count * sizeof (arelent));
422   if (!reloc_cache && count != 0)
423     return false;
424   memset (reloc_cache, 0, count * sizeof (arelent));
425
426   relocs = (PTR) bfd_alloc (abfd, reloc_size);
427   if (!relocs && reloc_size != 0)
428     {
429       free (reloc_cache);
430       return false;
431     }
432
433   if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
434     {
435       bfd_release (abfd, relocs);
436       free (reloc_cache);
437       return false;
438     }
439
440   if (each_size == RELOC_EXT_SIZE)
441     {
442       register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
443       unsigned int counter = 0;
444       arelent *cache_ptr = reloc_cache;
445
446       for (; counter < count; counter++, rptr++, cache_ptr++)
447         {
448           NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
449                                         bfd_get_symcount (abfd));
450         }
451     }
452   else
453     {
454       register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
455       unsigned int counter = 0;
456       arelent *cache_ptr = reloc_cache;
457
458       for (; counter < count; counter++, rptr++, cache_ptr++)
459         {
460           NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
461                                         bfd_get_symcount (abfd));
462         }
463
464     }
465
466   bfd_release (abfd, relocs);
467   asect->relocation = reloc_cache;
468   asect->reloc_count = count;
469   return true;
470 }
471
472
473
474 /* Write out a relocation section into an object file.  */
475
476 boolean
477 NAME(lynx,squirt_out_relocs) (abfd, section)
478      bfd *abfd;
479      asection *section;
480 {
481   arelent **generic;
482   unsigned char *native, *natptr;
483   size_t each_size;
484
485   unsigned int count = section->reloc_count;
486   size_t natsize;
487
488   if (count == 0)
489     return true;
490
491   each_size = obj_reloc_entry_size (abfd);
492   natsize = each_size * count;
493   native = (unsigned char *) bfd_zalloc (abfd, natsize);
494   if (!native)
495     return false;
496
497   generic = section->orelocation;
498
499   if (each_size == RELOC_EXT_SIZE)
500     {
501       for (natptr = native;
502            count != 0;
503            --count, natptr += each_size, ++generic)
504         NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
505     }
506   else
507     {
508       for (natptr = native;
509            count != 0;
510            --count, natptr += each_size, ++generic)
511         NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
512     }
513
514   if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
515     {
516       bfd_release (abfd, native);
517       return false;
518     }
519   bfd_release (abfd, native);
520
521   return true;
522 }
523
524 /* This is stupid.  This function should be a boolean predicate */
525 long
526 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
527      bfd *abfd;
528      sec_ptr section;
529      arelent **relptr;
530      asymbol **symbols;
531 {
532   arelent *tblptr = section->relocation;
533   unsigned int count;
534
535   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
536     return -1;
537
538   if (section->flags & SEC_CONSTRUCTOR)
539     {
540       arelent_chain *chain = section->constructor_chain;
541       for (count = 0; count < section->reloc_count; count++)
542         {
543           *relptr++ = &chain->relent;
544           chain = chain->next;
545         }
546     }
547   else
548     {
549       tblptr = section->relocation;
550
551       for (count = 0; count++ < section->reloc_count;)
552         {
553           *relptr++ = tblptr++;
554         }
555     }
556   *relptr = 0;
557
558   return section->reloc_count;
559 }
560
561 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
562
563 #include "aout-target.h"