Coverage Report

Created: 2023-08-28 06:26

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