* opncls.c (bfd_alloc_by_size_t): Set bfd_error_no_memory if
[deliverable/binutils-gdb.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 *) malloc (count * sizeof (arelent));
422 if (!reloc_cache && count != 0)
423 {
424 bfd_set_error (bfd_error_no_memory);
425 return false;
426 }
427 memset (reloc_cache, 0, count * sizeof (arelent));
428
429 relocs = (PTR) bfd_alloc (abfd, reloc_size);
430 if (!relocs && reloc_size != 0)
431 {
432 free (reloc_cache);
433 return false;
434 }
435
436 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
437 {
438 bfd_release (abfd, relocs);
439 free (reloc_cache);
440 return false;
441 }
442
443 if (each_size == RELOC_EXT_SIZE)
444 {
445 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
446 unsigned int counter = 0;
447 arelent *cache_ptr = reloc_cache;
448
449 for (; counter < count; counter++, rptr++, cache_ptr++)
450 {
451 NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
452 bfd_get_symcount (abfd));
453 }
454 }
455 else
456 {
457 register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
458 unsigned int counter = 0;
459 arelent *cache_ptr = reloc_cache;
460
461 for (; counter < count; counter++, rptr++, cache_ptr++)
462 {
463 NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
464 bfd_get_symcount (abfd));
465 }
466
467 }
468
469 bfd_release (abfd, relocs);
470 asect->relocation = reloc_cache;
471 asect->reloc_count = count;
472 return true;
473 }
474
475
476
477 /* Write out a relocation section into an object file. */
478
479 boolean
480 NAME(lynx,squirt_out_relocs) (abfd, section)
481 bfd *abfd;
482 asection *section;
483 {
484 arelent **generic;
485 unsigned char *native, *natptr;
486 size_t each_size;
487
488 unsigned int count = section->reloc_count;
489 size_t natsize;
490
491 if (count == 0)
492 return true;
493
494 each_size = obj_reloc_entry_size (abfd);
495 natsize = each_size * count;
496 native = (unsigned char *) bfd_zalloc (abfd, natsize);
497 if (!native)
498 return false;
499
500 generic = section->orelocation;
501
502 if (each_size == RELOC_EXT_SIZE)
503 {
504 for (natptr = native;
505 count != 0;
506 --count, natptr += each_size, ++generic)
507 NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
508 }
509 else
510 {
511 for (natptr = native;
512 count != 0;
513 --count, natptr += each_size, ++generic)
514 NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
515 }
516
517 if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
518 {
519 bfd_release (abfd, native);
520 return false;
521 }
522 bfd_release (abfd, native);
523
524 return true;
525 }
526
527 /* This is stupid. This function should be a boolean predicate */
528 long
529 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
530 bfd *abfd;
531 sec_ptr section;
532 arelent **relptr;
533 asymbol **symbols;
534 {
535 arelent *tblptr = section->relocation;
536 unsigned int count;
537
538 if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
539 return -1;
540
541 if (section->flags & SEC_CONSTRUCTOR)
542 {
543 arelent_chain *chain = section->constructor_chain;
544 for (count = 0; count < section->reloc_count; count++)
545 {
546 *relptr++ = &chain->relent;
547 chain = chain->next;
548 }
549 }
550 else
551 {
552 tblptr = section->relocation;
553
554 for (count = 0; count++ < section->reloc_count;)
555 {
556 *relptr++ = tblptr++;
557 }
558 }
559 *relptr = 0;
560
561 return section->reloc_count;
562 }
563
564 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
565
566 #include "aout-target.h"
This page took 0.041186 seconds and 4 git commands to generate.