Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/elf32-iq2000.c
Line
Count
Source
1
/* IQ2000-specific support for 32-bit ELF.
2
   Copyright (C) 2003-2026 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, MA 02110-1301, USA.  */
19
20
#include "sysdep.h"
21
#include "bfd.h"
22
#include "libbfd.h"
23
#include "elf-bfd.h"
24
#include "elf/iq2000.h"
25
#include "libiberty.h"
26
27
/* Forward declarations.  */
28
29
static bfd_reloc_status_type iq2000_elf_howto_hi16_reloc (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
30
31

32
static reloc_howto_type iq2000_elf_howto_table [] =
33
{
34
  /* This reloc does nothing.  */
35
36
  HOWTO (R_IQ2000_NONE,        /* type */
37
   0,          /* rightshift */
38
   0,          /* size */
39
   0,          /* bitsize */
40
   false,          /* pc_relative */
41
   0,          /* bitpos */
42
   complain_overflow_dont,     /* complain_on_overflow */
43
   bfd_elf_generic_reloc,      /* special_function */
44
   "R_IQ2000_NONE",      /* name */
45
   false,          /* partial_inplace */
46
   0,          /* src_mask */
47
   0,          /* dst_mask */
48
   false),         /* pcrel_offset */
49
50
  /* A 16 bit absolute relocation.  */
51
  HOWTO (R_IQ2000_16,        /* type */
52
   0,          /* rightshift */
53
   2,          /* size */
54
   16,           /* bitsize */
55
   false,          /* pc_relative */
56
   0,          /* bitpos */
57
   complain_overflow_bitfield, /* complain_on_overflow */
58
   bfd_elf_generic_reloc,      /* special_function */
59
   "R_IQ2000_16",        /* name */
60
   false,          /* partial_inplace */
61
   0x0000,         /* src_mask */
62
   0xffff,         /* dst_mask */
63
   false),         /* pcrel_offset */
64
65
  /* A 32 bit absolute relocation.  */
66
  HOWTO (R_IQ2000_32,        /* type */
67
   0,          /* rightshift */
68
   4,          /* size */
69
   31,           /* bitsize */
70
   false,          /* pc_relative */
71
   0,          /* bitpos */
72
   complain_overflow_bitfield, /* complain_on_overflow */
73
   bfd_elf_generic_reloc,      /* special_function */
74
   "R_IQ2000_32",        /* name */
75
   false,          /* partial_inplace */
76
   0x00000000,         /* src_mask */
77
   0x7fffffff,         /* dst_mask */
78
   false),         /* pcrel_offset */
79
80
  /* 26 bit branch address.  */
81
  HOWTO (R_IQ2000_26,   /* type */
82
   2,     /* rightshift */
83
   4,     /* size */
84
   26,      /* bitsize */
85
   false,     /* pc_relative */
86
   0,     /* bitpos */
87
   complain_overflow_dont, /* complain_on_overflow */
88
        /* This needs complex overflow
89
           detection, because the upper four
90
           bits must match the PC.  */
91
   bfd_elf_generic_reloc, /* special_function */
92
   "R_IQ2000_26",   /* name */
93
   false,     /* partial_inplace */
94
   0x00000000,    /* src_mask */
95
   0x03ffffff,    /* dst_mask */
96
   false),    /* pcrel_offset */
97
98
  /* 16 bit PC relative reference.  */
99
  HOWTO (R_IQ2000_PC16,   /* type */
100
   2,     /* rightshift */
101
   4,     /* size */
102
   16,      /* bitsize */
103
   true,      /* pc_relative */
104
   0,     /* bitpos */
105
   complain_overflow_signed, /* complain_on_overflow */
106
   bfd_elf_generic_reloc, /* special_function */
107
   "R_IQ2000_PC16", /* name */
108
   false,     /* partial_inplace */
109
   0x0000,    /* src_mask */
110
   0xffff,    /* dst_mask */
111
   true),     /* pcrel_offset */
112
113
  /* high 16 bits of symbol value.  */
114
  HOWTO (R_IQ2000_HI16,   /* type */
115
   16,      /* rightshift */
116
   4,     /* size */
117
   15,      /* bitsize */
118
   false,     /* pc_relative */
119
   0,     /* bitpos */
120
   complain_overflow_dont, /* complain_on_overflow */
121
   iq2000_elf_howto_hi16_reloc, /* special_function */
122
   "R_IQ2000_HI16", /* name */
123
   false,     /* partial_inplace */
124
   0x0000,    /* src_mask */
125
   0x7fff,    /* dst_mask */
126
   false),    /* pcrel_offset */
127
128
  /* Low 16 bits of symbol value.  */
129
  HOWTO (R_IQ2000_LO16,   /* type */
130
   0,     /* rightshift */
131
   4,     /* size */
132
   16,      /* bitsize */
133
   false,     /* pc_relative */
134
   0,     /* bitpos */
135
   complain_overflow_dont, /* complain_on_overflow */
136
   bfd_elf_generic_reloc, /* special_function */
137
   "R_IQ2000_LO16", /* name */
138
   false,     /* partial_inplace */
139
   0x0000,    /* src_mask */
140
   0xffff,    /* dst_mask */
141
   false),    /* pcrel_offset */
142
143
  /* 16-bit jump offset.  */
144
  HOWTO (R_IQ2000_OFFSET_16,  /* type */
145
   2,     /* rightshift */
146
   4,     /* size */
147
   16,      /* bitsize */
148
   false,     /* pc_relative */
149
   0,     /* bitpos */
150
   complain_overflow_dont, /* complain_on_overflow */
151
   bfd_elf_generic_reloc, /* special_function */
152
   "R_IQ2000_OFFSET_16",  /* name */
153
   false,     /* partial_inplace */
154
   0x0000,    /* src_mask */
155
   0xffff,    /* dst_mask */
156
   false),    /* pcrel_offset */
157
158
  /* 21-bit jump offset.  */
159
  HOWTO (R_IQ2000_OFFSET_21,  /* type */
160
   2,     /* rightshift */
161
   4,     /* size */
162
   21,      /* bitsize */
163
   false,     /* pc_relative */
164
   0,     /* bitpos */
165
   complain_overflow_dont, /* complain_on_overflow */
166
   bfd_elf_generic_reloc, /* special_function */
167
   "R_IQ2000_OFFSET_21",  /* name */
168
   false,     /* partial_inplace */
169
   0x000000,    /* src_mask */
170
   0x1fffff,    /* dst_mask */
171
   false),    /* pcrel_offset */
172
173
  /* unsigned high 16 bits of value.  */
174
  HOWTO (R_IQ2000_OFFSET_21,  /* type */
175
   16,      /* rightshift */
176
   4,     /* size */
177
   16,      /* bitsize */
178
   false,     /* pc_relative */
179
   0,     /* bitpos */
180
   complain_overflow_dont, /* complain_on_overflow */
181
   bfd_elf_generic_reloc, /* special_function */
182
   "R_IQ2000_UHI16",  /* name */
183
   false,     /* partial_inplace */
184
   0x0000,    /* src_mask */
185
   0x7fff,    /* dst_mask */
186
   false),    /* pcrel_offset */
187
188
  /* A 32 bit absolute debug relocation.  */
189
  HOWTO (R_IQ2000_32_DEBUG,      /* type */
190
   0,          /* rightshift */
191
   4,          /* size */
192
   32,           /* bitsize */
193
   false,          /* pc_relative */
194
   0,          /* bitpos */
195
   complain_overflow_bitfield, /* complain_on_overflow */
196
   bfd_elf_generic_reloc,      /* special_function */
197
   "R_IQ2000_32",        /* name */
198
   false,          /* partial_inplace */
199
   0x00000000,         /* src_mask */
200
   0xffffffff,         /* dst_mask */
201
   false),         /* pcrel_offset */
202
203
};
204
205
/* GNU extension to record C++ vtable hierarchy.  */
206
static reloc_howto_type iq2000_elf_vtinherit_howto =
207
  HOWTO (R_IQ2000_GNU_VTINHERIT,    /* type */
208
   0,        /* rightshift */
209
   4,        /* size */
210
   0,        /* bitsize */
211
   false,        /* pc_relative */
212
   0,        /* bitpos */
213
   complain_overflow_dont,   /* complain_on_overflow */
214
   NULL,         /* special_function */
215
   "R_IQ2000_GNU_VTINHERIT",  /* name */
216
   false,        /* partial_inplace */
217
   0,        /* src_mask */
218
   0,        /* dst_mask */
219
   false);       /* pcrel_offset */
220
221
/* GNU extension to record C++ vtable member usage.  */
222
static reloc_howto_type iq2000_elf_vtentry_howto =
223
  HOWTO (R_IQ2000_GNU_VTENTRY,     /* type */
224
   0,        /* rightshift */
225
   4,        /* size */
226
   0,        /* bitsize */
227
   false,        /* pc_relative */
228
   0,        /* bitpos */
229
   complain_overflow_dont,   /* complain_on_overflow */
230
   NULL,         /* special_function */
231
   "R_IQ2000_GNU_VTENTRY",    /* name */
232
   false,        /* partial_inplace */
233
   0,        /* src_mask */
234
   0,        /* dst_mask */
235
   false);       /* pcrel_offset */
236
237

238
static bfd_reloc_status_type
239
iq2000_elf_howto_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
240
           arelent *reloc_entry,
241
           asymbol *symbol,
242
           void * data,
243
           asection *input_section,
244
           bfd *output_bfd,
245
           char **error_message ATTRIBUTE_UNUSED)
246
0
{
247
0
  bfd_reloc_status_type ret;
248
0
  bfd_vma relocation;
249
250
  /* If we're relocating and this an external symbol,
251
     we don't want to change anything.  */
252
0
  if (output_bfd != (bfd *) NULL
253
0
      && (symbol->flags & BSF_SECTION_SYM) == 0
254
0
      && reloc_entry->addend == 0)
255
0
    {
256
0
      reloc_entry->address += input_section->output_offset;
257
0
      return bfd_reloc_ok;
258
0
    }
259
260
0
  if (bfd_is_com_section (symbol->section))
261
0
    relocation = 0;
262
0
  else
263
0
    relocation = symbol->value;
264
265
0
  relocation += symbol->section->output_section->vma;
266
0
  relocation += symbol->section->output_offset;
267
0
  relocation += reloc_entry->addend;
268
269
  /* If %lo will have sign-extension, compensate by add 0x10000 to hi portion.  */
270
0
  if (relocation & 0x8000)
271
0
    reloc_entry->addend += 0x10000;
272
273
  /* Now do the reloc in the usual way.  */
274
0
  ret = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
275
0
        input_section, output_bfd, error_message);
276
277
  /* Put it back the way it was.  */
278
0
  if (relocation & 0x8000)
279
0
    reloc_entry->addend -= 0x10000;
280
281
0
  return ret;
282
0
}
283
284
static bfd_reloc_status_type
285
iq2000_elf_relocate_hi16 (bfd *input_bfd,
286
        Elf_Internal_Rela *relhi,
287
        bfd_byte *contents,
288
        bfd_vma value)
289
0
{
290
0
  bfd_vma insn;
291
292
0
  insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
293
294
0
  value += relhi->r_addend;
295
0
  value &= 0x7fffffff; /* Mask off top-bit which is Harvard mask bit.  */
296
297
  /* If top-bit of %lo value is on, this means that %lo will
298
     sign-propagate and so we compensate by adding 1 to %hi value.  */
299
0
  if (value & 0x8000)
300
0
    value += 0x10000;
301
302
0
  value >>= 16;
303
0
  insn = ((insn & ~0xFFFF) | value);
304
305
0
  bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
306
0
  return bfd_reloc_ok;
307
0
}
308
309
static bfd_reloc_status_type
310
iq2000_elf_relocate_offset16 (bfd *input_bfd,
311
            Elf_Internal_Rela *rel,
312
            bfd_byte *contents,
313
            bfd_vma value,
314
            bfd_vma location)
315
0
{
316
0
  bfd_vma insn;
317
0
  bfd_vma jtarget;
318
319
0
  insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
320
321
0
  value += rel->r_addend;
322
323
0
  if (value & 3)
324
0
    return bfd_reloc_dangerous;
325
326
0
  jtarget = (value & 0x3fffc) | (location & 0xf0000000L);
327
328
0
  if (jtarget != value)
329
0
    return bfd_reloc_overflow;
330
331
0
  insn = (insn & ~0xFFFF) | ((value >> 2) & 0xFFFF);
332
333
0
  bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
334
0
  return bfd_reloc_ok;
335
0
}
336
337
/* Map BFD reloc types to IQ2000 ELF reloc types.  */
338
339
static reloc_howto_type *
340
iq2000_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
341
        bfd_reloc_code_real_type code)
342
0
{
343
  /* Note that the iq2000_elf_howto_table is indxed by the R_
344
     constants.  Thus, the order that the howto records appear in the
345
     table *must* match the order of the relocation types defined in
346
     include/elf/iq2000.h.  */
347
348
0
  switch (code)
349
0
    {
350
0
    case BFD_RELOC_NONE:
351
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_NONE];
352
0
    case BFD_RELOC_16:
353
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_16];
354
0
    case BFD_RELOC_32:
355
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_32];
356
0
    case BFD_RELOC_MIPS_JMP:
357
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_26];
358
0
    case BFD_RELOC_IQ2000_OFFSET_16:
359
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_OFFSET_16];
360
0
    case BFD_RELOC_IQ2000_OFFSET_21:
361
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_OFFSET_21];
362
0
    case BFD_RELOC_16_PCREL_S2:
363
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_PC16];
364
0
    case BFD_RELOC_HI16:
365
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_HI16];
366
0
    case BFD_RELOC_IQ2000_UHI16:
367
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_UHI16];
368
0
    case BFD_RELOC_LO16:
369
0
      return &iq2000_elf_howto_table[ (int) R_IQ2000_LO16];
370
0
    case BFD_RELOC_VTABLE_INHERIT:
371
0
      return &iq2000_elf_vtinherit_howto;
372
0
    case BFD_RELOC_VTABLE_ENTRY:
373
0
      return &iq2000_elf_vtentry_howto;
374
0
    default:
375
      /* Pacify gcc -Wall.  */
376
0
      return NULL;
377
0
    }
378
0
  return NULL;
379
0
}
380
381
static reloc_howto_type *
382
iq2000_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
383
0
{
384
0
  unsigned int i;
385
386
0
  for (i = 0;
387
0
       i < (sizeof (iq2000_elf_howto_table)
388
0
      / sizeof (iq2000_elf_howto_table[0]));
389
0
       i++)
390
0
    if (iq2000_elf_howto_table[i].name != NULL
391
0
  && strcasecmp (iq2000_elf_howto_table[i].name, r_name) == 0)
392
0
      return &iq2000_elf_howto_table[i];
393
394
0
  if (strcasecmp (iq2000_elf_vtinherit_howto.name, r_name) == 0)
395
0
    return &iq2000_elf_vtinherit_howto;
396
0
  if (strcasecmp (iq2000_elf_vtentry_howto.name, r_name) == 0)
397
0
    return &iq2000_elf_vtentry_howto;
398
399
0
  return NULL;
400
0
}
401

402
/* Perform a single relocation.  By default we use the standard BFD
403
   routines.  */
404
405
static bfd_reloc_status_type
406
iq2000_final_link_relocate (reloc_howto_type *  howto,
407
          bfd *   input_bfd,
408
          asection *    input_section,
409
          bfd_byte *    contents,
410
          Elf_Internal_Rela * rel,
411
          bfd_vma   relocation)
412
0
{
413
0
  return _bfd_final_link_relocate (howto, input_bfd, input_section,
414
0
           contents, rel->r_offset,
415
0
           relocation, rel->r_addend);
416
0
}
417

418
/* Set the howto pointer for a IQ2000 ELF reloc.  */
419
420
static bool
421
iq2000_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
422
         arelent * cache_ptr,
423
         Elf_Internal_Rela * dst)
424
0
{
425
0
  unsigned int r_type;
426
427
0
  r_type = ELF32_R_TYPE (dst->r_info);
428
0
  switch (r_type)
429
0
    {
430
0
    case R_IQ2000_GNU_VTINHERIT:
431
0
      cache_ptr->howto = & iq2000_elf_vtinherit_howto;
432
0
      break;
433
434
0
    case R_IQ2000_GNU_VTENTRY:
435
0
      cache_ptr->howto = & iq2000_elf_vtentry_howto;
436
0
      break;
437
438
0
    default:
439
0
      if (r_type >= ARRAY_SIZE (iq2000_elf_howto_table))
440
0
  {
441
    /* xgettext:c-format */
442
0
    _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
443
0
            abfd, r_type);
444
0
    bfd_set_error (bfd_error_bad_value);
445
0
    return false;
446
0
  }
447
0
      cache_ptr->howto = & iq2000_elf_howto_table [r_type];
448
0
      break;
449
0
    }
450
0
  return true;
451
0
}
452
453
/* Look through the relocs for a section during the first phase.
454
   Since we don't do .gots or .plts, we just need to consider the
455
   virtual table relocs for gc.  */
456
457
static bool
458
iq2000_elf_check_relocs (bfd *abfd,
459
       struct bfd_link_info *info,
460
       asection *sec,
461
       const Elf_Internal_Rela *relocs)
462
0
{
463
0
  Elf_Internal_Shdr *symtab_hdr;
464
0
  struct elf_link_hash_entry **sym_hashes;
465
0
  const Elf_Internal_Rela *rel;
466
0
  const Elf_Internal_Rela *rel_end;
467
0
  bool changed = false;
468
469
0
  if (bfd_link_relocatable (info))
470
0
    return true;
471
472
0
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
473
0
  sym_hashes = elf_sym_hashes (abfd);
474
475
0
  rel_end = relocs + sec->reloc_count;
476
0
  for (rel = relocs; rel < rel_end; rel++)
477
0
    {
478
0
      struct elf_link_hash_entry *h;
479
0
      unsigned long r_symndx;
480
481
0
      r_symndx = ELF32_R_SYM (rel->r_info);
482
0
      if (r_symndx < symtab_hdr->sh_info)
483
0
  h = NULL;
484
0
      else
485
0
  {
486
0
    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
487
0
    while (h->root.type == bfd_link_hash_indirect
488
0
     || h->root.type == bfd_link_hash_warning)
489
0
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
490
0
  }
491
492
0
      switch (ELF32_R_TYPE (rel->r_info))
493
0
  {
494
    /* This relocation describes the C++ object vtable
495
       hierarchy.  Reconstruct it for later use during GC.  */
496
0
  case R_IQ2000_GNU_VTINHERIT:
497
0
    if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
498
0
      return false;
499
0
    break;
500
501
    /* This relocation describes which C++ vtable entries
502
       are actually used.  Record for later use during GC.  */
503
0
  case R_IQ2000_GNU_VTENTRY:
504
0
    if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
505
0
      return false;
506
0
    break;
507
508
0
  case R_IQ2000_32:
509
    /* For debug section, change to special harvard-aware relocations.  */
510
0
    if (startswith (sec->name, ".debug")
511
0
        || startswith (sec->name, ".stab")
512
0
        || startswith (sec->name, ".eh_frame"))
513
0
      {
514
0
        ((Elf_Internal_Rela *) rel)->r_info
515
0
    = ELF32_R_INFO (ELF32_R_SYM (rel->r_info), R_IQ2000_32_DEBUG);
516
0
        changed = true;
517
0
      }
518
0
    break;
519
0
  }
520
0
    }
521
522
0
  if (changed)
523
    /* Note that we've changed relocs, otherwise if !info->keep_memory
524
       we'll free the relocs and lose our changes.  */
525
0
    elf_section_data (sec)->relocs = (Elf_Internal_Rela *) relocs;
526
527
0
  return true;
528
0
}
529
530

531
/* Relocate a IQ2000 ELF section.
532
   There is some attempt to make this function usable for many architectures,
533
   both USE_REL and USE_RELA ['twould be nice if such a critter existed],
534
   if only to serve as a learning tool.
535
536
   The RELOCATE_SECTION function is called by the new ELF backend linker
537
   to handle the relocations for a section.
538
539
   The relocs are always passed as Rela structures; if the section
540
   actually uses Rel structures, the r_addend field will always be
541
   zero.
542
543
   This function is responsible for adjusting the section contents as
544
   necessary, and (if using Rela relocs and generating a relocatable
545
   output file) adjusting the reloc addend as necessary.
546
547
   This function does not have to worry about setting the reloc
548
   address or the reloc symbol index.
549
550
   LOCAL_SYMS is a pointer to the swapped in local symbols.
551
552
   LOCAL_SECTIONS is an array giving the section in the input file
553
   corresponding to the st_shndx field of each local symbol.
554
555
   The global hash table entry for the global symbols can be found
556
   via elf_sym_hashes (input_bfd).
557
558
   When generating relocatable output, this function must handle
559
   STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
560
   going to be the section symbol corresponding to the output
561
   section, which means that the addend must be adjusted
562
   accordingly.  */
563
564
static int
565
iq2000_elf_relocate_section (bfd *         output_bfd ATTRIBUTE_UNUSED,
566
           struct bfd_link_info *  info,
567
           bfd *         input_bfd,
568
           asection *        input_section,
569
           bfd_byte *        contents,
570
           Elf_Internal_Rela *     relocs,
571
           Elf_Internal_Sym *      local_syms,
572
           asection **       local_sections)
573
0
{
574
0
  Elf_Internal_Shdr *   symtab_hdr;
575
0
  struct elf_link_hash_entry ** sym_hashes;
576
0
  Elf_Internal_Rela *   rel;
577
0
  Elf_Internal_Rela *   relend;
578
579
0
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
580
0
  sym_hashes = elf_sym_hashes (input_bfd);
581
0
  relend     = relocs + input_section->reloc_count;
582
583
0
  for (rel = relocs; rel < relend; rel ++)
584
0
    {
585
0
      reloc_howto_type *     howto;
586
0
      unsigned long      r_symndx;
587
0
      Elf_Internal_Sym *     sym;
588
0
      asection *       sec;
589
0
      struct elf_link_hash_entry * h;
590
0
      bfd_vma        relocation;
591
0
      bfd_reloc_status_type    r;
592
0
      const char *       name = NULL;
593
0
      int        r_type;
594
595
0
      r_type = ELF32_R_TYPE (rel->r_info);
596
597
0
      if (   r_type == R_IQ2000_GNU_VTINHERIT
598
0
    || r_type == R_IQ2000_GNU_VTENTRY)
599
0
  continue;
600
601
0
      r_symndx = ELF32_R_SYM (rel->r_info);
602
603
0
      howto  = iq2000_elf_howto_table + ELF32_R_TYPE (rel->r_info);
604
0
      h      = NULL;
605
0
      sym    = NULL;
606
0
      sec    = NULL;
607
608
0
      if (r_symndx < symtab_hdr->sh_info)
609
0
  {
610
0
    asection *osec;
611
612
0
    sym = local_syms + r_symndx;
613
0
    osec = sec = local_sections [r_symndx];
614
0
    if ((sec->flags & SEC_MERGE)
615
0
        && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
616
      /* This relocation is relative to a section symbol that is
617
         going to be merged.  Change it so that it is relative
618
         to the merged section symbol.  */
619
0
      rel->r_addend = _bfd_elf_rel_local_sym (output_bfd, sym, &sec,
620
0
                rel->r_addend);
621
622
0
    relocation = (sec->output_section->vma
623
0
      + sec->output_offset
624
0
      + sym->st_value);
625
626
0
    name = bfd_elf_string_from_elf_section
627
0
      (input_bfd, symtab_hdr->sh_link, sym->st_name);
628
0
    name = name == NULL ? bfd_section_name (osec) : name;
629
0
  }
630
0
      else
631
0
  {
632
0
    bool unresolved_reloc;
633
0
    bool warned, ignored;
634
635
0
    RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
636
0
           r_symndx, symtab_hdr, sym_hashes,
637
0
           h, sec, relocation,
638
0
           unresolved_reloc, warned, ignored);
639
640
0
    name = h->root.root.string;
641
0
  }
642
643
0
      if (sec != NULL && discarded_section (sec))
644
0
  RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
645
0
           rel, 1, relend, R_IQ2000_NONE,
646
0
           howto, 0, contents);
647
648
0
      if (bfd_link_relocatable (info))
649
0
  continue;
650
651
0
      switch (r_type)
652
0
  {
653
0
  case R_IQ2000_HI16:
654
0
    r = iq2000_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
655
0
    break;
656
657
0
  case R_IQ2000_OFFSET_16:
658
0
    r = iq2000_elf_relocate_offset16 (input_bfd, rel, contents, relocation,
659
0
              input_section->output_section->vma
660
0
              + input_section->output_offset
661
0
              + rel->r_offset);
662
0
    break;
663
664
0
  case R_IQ2000_PC16:
665
0
    rel->r_addend -= 4;
666
    /* Fall through.  */
667
668
0
  default:
669
0
    r = iq2000_final_link_relocate (howto, input_bfd, input_section,
670
0
           contents, rel, relocation);
671
0
    break;
672
0
  }
673
674
0
      if (r != bfd_reloc_ok)
675
0
  {
676
0
    const char * msg = (const char *) NULL;
677
678
0
    switch (r)
679
0
      {
680
0
      case bfd_reloc_overflow:
681
0
        (*info->callbacks->reloc_overflow)
682
0
    (info, (h ? &h->root : NULL), name, howto->name,
683
0
     (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
684
0
        break;
685
686
0
      case bfd_reloc_undefined:
687
0
        (*info->callbacks->undefined_symbol)
688
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
689
0
        break;
690
691
0
      case bfd_reloc_outofrange:
692
0
        msg = _("internal error: out of range error");
693
0
        break;
694
695
0
      case bfd_reloc_notsupported:
696
0
        msg = _("internal error: unsupported relocation error");
697
0
        break;
698
699
0
      case bfd_reloc_dangerous:
700
0
        msg = _("internal error: dangerous relocation");
701
0
        break;
702
703
0
      default:
704
0
        msg = _("internal error: unknown error");
705
0
        break;
706
0
      }
707
708
0
    if (msg)
709
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
710
0
           input_section, rel->r_offset);
711
0
  }
712
0
    }
713
714
0
  return true;
715
0
}
716

717
718
/* Return the section that should be marked against GC for a given
719
   relocation.  */
720
721
static asection *
722
iq2000_elf_gc_mark_hook (asection *sec,
723
       struct bfd_link_info *info,
724
       struct elf_reloc_cookie *cookie,
725
       struct elf_link_hash_entry *h,
726
       unsigned int symndx)
727
0
{
728
0
  if (h != NULL)
729
0
    switch (ELF32_R_TYPE (cookie->rel->r_info))
730
0
      {
731
0
      case R_IQ2000_GNU_VTINHERIT:
732
0
      case R_IQ2000_GNU_VTENTRY:
733
0
  return NULL;
734
0
      }
735
736
0
  return _bfd_elf_gc_mark_hook (sec, info, cookie, h, symndx);
737
0
}
738
739

740
/* Return the MACH for an e_flags value.  */
741
742
static int
743
elf32_iq2000_machine (bfd *abfd)
744
12
{
745
12
  switch (elf_elfheader (abfd)->e_flags & EF_IQ2000_CPU_MASK)
746
12
    {
747
6
    case EF_IQ2000_CPU_IQ10:
748
6
      return bfd_mach_iq10;
749
750
4
    case EF_IQ2000_CPU_IQ2000:
751
6
    default:
752
6
      return bfd_mach_iq2000;
753
12
    }
754
12
}
755
756

757
/* Function to set the ELF flag bits.  */
758
759
static bool
760
iq2000_elf_set_private_flags (bfd *abfd, flagword flags)
761
0
{
762
0
  elf_elfheader (abfd)->e_flags = flags;
763
0
  elf_flags_init (abfd) = true;
764
0
  return true;
765
0
}
766
767
/* Merge backend specific data from an object
768
   file to the output object file when linking.  */
769
770
static bool
771
iq2000_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
772
0
{
773
0
  bfd *obfd = info->output_bfd;
774
0
  flagword old_flags, old_partial;
775
0
  flagword new_flags, new_partial;
776
0
  bool error = false;
777
0
  char new_opt[80];
778
0
  char old_opt[80];
779
780
0
  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
781
0
    return true;
782
783
0
  new_opt[0] = old_opt[0] = '\0';
784
0
  new_flags = elf_elfheader (ibfd)->e_flags;
785
0
  old_flags = elf_elfheader (obfd)->e_flags;
786
787
0
  if (!elf_flags_init (obfd))
788
0
    {
789
      /* First call, no flags set.  */
790
0
      elf_flags_init (obfd) = true;
791
0
      elf_elfheader (obfd)->e_flags = new_flags;
792
0
    }
793
794
0
  else if (new_flags != old_flags)
795
0
    {
796
      /* Warn if different cpu is used, but allow a
797
   specific cpu to override the generic cpu.  */
798
0
      new_partial = (new_flags & EF_IQ2000_CPU_MASK);
799
0
      old_partial = (old_flags & EF_IQ2000_CPU_MASK);
800
801
0
      if (new_partial != old_partial)
802
0
  {
803
0
    switch (new_partial)
804
0
      {
805
0
      case EF_IQ2000_CPU_IQ10:
806
0
        strcat (new_opt, " -m10");
807
0
        break;
808
809
0
      default:
810
0
      case EF_IQ2000_CPU_IQ2000:
811
0
        strcat (new_opt, " -m2000");
812
0
        break;
813
0
      }
814
815
0
    switch (old_partial)
816
0
      {
817
0
      case EF_IQ2000_CPU_IQ10:
818
0
        strcat (old_opt, " -m10");
819
0
        break;
820
821
0
      default:
822
0
      case EF_IQ2000_CPU_IQ2000:
823
0
        strcat (old_opt, " -m2000");
824
0
        break;
825
0
      }
826
0
  }
827
828
      /* Print out any mismatches from above.  */
829
0
      if (new_opt[0])
830
0
  {
831
0
    error = true;
832
0
    _bfd_error_handler
833
      /* xgettext:c-format */
834
0
      (_("%pB: compiled with %s and linked with modules compiled with %s"),
835
0
       ibfd, new_opt, old_opt);
836
0
  }
837
838
0
      new_flags &= ~ EF_IQ2000_ALL_FLAGS;
839
0
      old_flags &= ~ EF_IQ2000_ALL_FLAGS;
840
841
      /* Warn about any other mismatches.  */
842
0
      if (new_flags != old_flags)
843
0
  {
844
0
    error = true;
845
846
0
    _bfd_error_handler
847
      /* xgettext:c-format */
848
0
      (_("%pB: uses different e_flags (%#x) fields than previous modules (%#x)"),
849
0
       ibfd, new_flags, old_flags);
850
0
  }
851
0
    }
852
853
0
  if (error)
854
0
    bfd_set_error (bfd_error_bad_value);
855
856
0
  return !error;
857
0
}
858
859

860
static bool
861
iq2000_elf_print_private_bfd_data (bfd *abfd, void * ptr)
862
0
{
863
0
  FILE *file = (FILE *) ptr;
864
0
  flagword flags;
865
866
0
  BFD_ASSERT (abfd != NULL && ptr != NULL);
867
868
  /* Print normal ELF private data.  */
869
0
  _bfd_elf_print_private_bfd_data (abfd, ptr);
870
871
0
  flags = elf_elfheader (abfd)->e_flags;
872
0
  fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
873
874
0
  switch (flags & EF_IQ2000_CPU_MASK)
875
0
    {
876
0
    case EF_IQ2000_CPU_IQ10:
877
0
      fprintf (file, " -m10");
878
0
      break;
879
0
    case EF_IQ2000_CPU_IQ2000:
880
0
      fprintf (file, " -m2000");
881
0
      break;
882
0
    default:
883
0
      break;
884
0
    }
885
886
0
  fputc ('\n', file);
887
0
  return true;
888
0
}
889
890
static
891
bool
892
iq2000_elf_object_p (bfd *abfd)
893
12
{
894
12
  bfd_default_set_arch_mach (abfd, bfd_arch_iq2000,
895
12
           elf32_iq2000_machine (abfd));
896
  return true;
897
12
}
898
899

900
#define ELF_ARCH    bfd_arch_iq2000
901
#define ELF_MACHINE_CODE  EM_IQ2000
902
#define ELF_MAXPAGESIZE   0x1000
903
904
#define TARGET_BIG_SYM    iq2000_elf32_vec
905
#define TARGET_BIG_NAME   "elf32-iq2000"
906
907
#define elf_info_to_howto_rel     NULL
908
#define elf_info_to_howto     iq2000_info_to_howto_rela
909
#define elf_backend_relocate_section    iq2000_elf_relocate_section
910
#define elf_backend_gc_mark_hook    iq2000_elf_gc_mark_hook
911
#define elf_backend_check_relocs    iq2000_elf_check_relocs
912
#define elf_backend_object_p      iq2000_elf_object_p
913
#define elf_backend_rela_normal     1
914
915
#define elf_backend_can_gc_sections   1
916
917
#define bfd_elf32_bfd_reloc_type_lookup   iq2000_reloc_type_lookup
918
#define bfd_elf32_bfd_reloc_name_lookup iq2000_reloc_name_lookup
919
#define bfd_elf32_bfd_set_private_flags   iq2000_elf_set_private_flags
920
#define bfd_elf32_bfd_merge_private_bfd_data  iq2000_elf_merge_private_bfd_data
921
#define bfd_elf32_bfd_print_private_bfd_data  iq2000_elf_print_private_bfd_data
922
923
#include "elf32-target.h"