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