* libbfd.c (bfd_malloc, bfd_realloc): New functions.
[external/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 *) 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"