Coverage Report

Created: 2025-06-24 06:45

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