Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/elf32-iq2000.c
Line
Count
Source (jump to first uncovered line)
1
/* IQ2000-specific support for 32-bit ELF.
2
   Copyright (C) 2003-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, 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, howto, 0, contents);
646
647
0
      if (bfd_link_relocatable (info))
648
0
  continue;
649
650
0
      switch (r_type)
651
0
  {
652
0
  case R_IQ2000_HI16:
653
0
    r = iq2000_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
654
0
    break;
655
656
0
  case R_IQ2000_OFFSET_16:
657
0
    r = iq2000_elf_relocate_offset16 (input_bfd, rel, contents, relocation,
658
0
              input_section->output_section->vma
659
0
              + input_section->output_offset
660
0
              + rel->r_offset);
661
0
    break;
662
663
0
  case R_IQ2000_PC16:
664
0
    rel->r_addend -= 4;
665
    /* Fall through.  */
666
667
0
  default:
668
0
    r = iq2000_final_link_relocate (howto, input_bfd, input_section,
669
0
           contents, rel, relocation);
670
0
    break;
671
0
  }
672
673
0
      if (r != bfd_reloc_ok)
674
0
  {
675
0
    const char * msg = (const char *) NULL;
676
677
0
    switch (r)
678
0
      {
679
0
      case bfd_reloc_overflow:
680
0
        (*info->callbacks->reloc_overflow)
681
0
    (info, (h ? &h->root : NULL), name, howto->name,
682
0
     (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
683
0
        break;
684
685
0
      case bfd_reloc_undefined:
686
0
        (*info->callbacks->undefined_symbol)
687
0
    (info, name, input_bfd, input_section, rel->r_offset, true);
688
0
        break;
689
690
0
      case bfd_reloc_outofrange:
691
0
        msg = _("internal error: out of range error");
692
0
        break;
693
694
0
      case bfd_reloc_notsupported:
695
0
        msg = _("internal error: unsupported relocation error");
696
0
        break;
697
698
0
      case bfd_reloc_dangerous:
699
0
        msg = _("internal error: dangerous relocation");
700
0
        break;
701
702
0
      default:
703
0
        msg = _("internal error: unknown error");
704
0
        break;
705
0
      }
706
707
0
    if (msg)
708
0
      (*info->callbacks->warning) (info, msg, name, input_bfd,
709
0
           input_section, rel->r_offset);
710
0
  }
711
0
    }
712
713
0
  return true;
714
0
}
715

716
717
/* Return the section that should be marked against GC for a given
718
   relocation.  */
719
720
static asection *
721
iq2000_elf_gc_mark_hook (asection *sec,
722
       struct bfd_link_info *info,
723
       Elf_Internal_Rela *rel,
724
       struct elf_link_hash_entry *h,
725
       Elf_Internal_Sym *sym)
726
0
{
727
0
  if (h != NULL)
728
0
    switch (ELF32_R_TYPE (rel->r_info))
729
0
      {
730
0
      case R_IQ2000_GNU_VTINHERIT:
731
0
      case R_IQ2000_GNU_VTENTRY:
732
0
  return NULL;
733
0
      }
734
735
0
  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
736
0
}
737
738

739
/* Return the MACH for an e_flags value.  */
740
741
static int
742
elf32_iq2000_machine (bfd *abfd)
743
946
{
744
946
  switch (elf_elfheader (abfd)->e_flags & EF_IQ2000_CPU_MASK)
745
946
    {
746
465
    case EF_IQ2000_CPU_IQ10:
747
465
      return bfd_mach_iq10;
748
749
0
    case EF_IQ2000_CPU_IQ2000:
750
481
    default:
751
481
      return bfd_mach_iq2000;
752
946
    }
753
946
}
754
755

756
/* Function to set the ELF flag bits.  */
757
758
static bool
759
iq2000_elf_set_private_flags (bfd *abfd, flagword flags)
760
0
{
761
0
  elf_elfheader (abfd)->e_flags = flags;
762
0
  elf_flags_init (abfd) = true;
763
0
  return true;
764
0
}
765
766
/* Merge backend specific data from an object
767
   file to the output object file when linking.  */
768
769
static bool
770
iq2000_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
771
0
{
772
0
  bfd *obfd = info->output_bfd;
773
0
  flagword old_flags, old_partial;
774
0
  flagword new_flags, new_partial;
775
0
  bool error = false;
776
0
  char new_opt[80];
777
0
  char old_opt[80];
778
779
0
  new_opt[0] = old_opt[0] = '\0';
780
0
  new_flags = elf_elfheader (ibfd)->e_flags;
781
0
  old_flags = elf_elfheader (obfd)->e_flags;
782
783
0
  if (!elf_flags_init (obfd))
784
0
    {
785
      /* First call, no flags set.  */
786
0
      elf_flags_init (obfd) = true;
787
0
      elf_elfheader (obfd)->e_flags = new_flags;
788
0
    }
789
790
0
  else if (new_flags != old_flags)
791
0
    {
792
      /* Warn if different cpu is used, but allow a
793
   specific cpu to override the generic cpu.  */
794
0
      new_partial = (new_flags & EF_IQ2000_CPU_MASK);
795
0
      old_partial = (old_flags & EF_IQ2000_CPU_MASK);
796
797
0
      if (new_partial != old_partial)
798
0
  {
799
0
    switch (new_partial)
800
0
      {
801
0
      case EF_IQ2000_CPU_IQ10:
802
0
        strcat (new_opt, " -m10");
803
0
        break;
804
805
0
      default:
806
0
      case EF_IQ2000_CPU_IQ2000:
807
0
        strcat (new_opt, " -m2000");
808
0
        break;
809
0
      }
810
811
0
    switch (old_partial)
812
0
      {
813
0
      case EF_IQ2000_CPU_IQ10:
814
0
        strcat (old_opt, " -m10");
815
0
        break;
816
817
0
      default:
818
0
      case EF_IQ2000_CPU_IQ2000:
819
0
        strcat (old_opt, " -m2000");
820
0
        break;
821
0
      }
822
0
  }
823
824
      /* Print out any mismatches from above.  */
825
0
      if (new_opt[0])
826
0
  {
827
0
    error = true;
828
0
    _bfd_error_handler
829
      /* xgettext:c-format */
830
0
      (_("%pB: compiled with %s and linked with modules compiled with %s"),
831
0
       ibfd, new_opt, old_opt);
832
0
  }
833
834
0
      new_flags &= ~ EF_IQ2000_ALL_FLAGS;
835
0
      old_flags &= ~ EF_IQ2000_ALL_FLAGS;
836
837
      /* Warn about any other mismatches.  */
838
0
      if (new_flags != old_flags)
839
0
  {
840
0
    error = true;
841
842
0
    _bfd_error_handler
843
      /* xgettext:c-format */
844
0
      (_("%pB: uses different e_flags (%#x) fields than previous modules (%#x)"),
845
0
       ibfd, new_flags, old_flags);
846
0
  }
847
0
    }
848
849
0
  if (error)
850
0
    bfd_set_error (bfd_error_bad_value);
851
852
0
  return !error;
853
0
}
854
855

856
static bool
857
iq2000_elf_print_private_bfd_data (bfd *abfd, void * ptr)
858
7
{
859
7
  FILE *file = (FILE *) ptr;
860
7
  flagword flags;
861
862
7
  BFD_ASSERT (abfd != NULL && ptr != NULL);
863
864
  /* Print normal ELF private data.  */
865
7
  _bfd_elf_print_private_bfd_data (abfd, ptr);
866
867
7
  flags = elf_elfheader (abfd)->e_flags;
868
7
  fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
869
870
7
  switch (flags & EF_IQ2000_CPU_MASK)
871
7
    {
872
0
    case EF_IQ2000_CPU_IQ10:
873
0
      fprintf (file, " -m10");
874
0
      break;
875
0
    case EF_IQ2000_CPU_IQ2000:
876
0
      fprintf (file, " -m2000");
877
0
      break;
878
7
    default:
879
7
      break;
880
7
    }
881
882
7
  fputc ('\n', file);
883
7
  return true;
884
7
}
885
886
static
887
bool
888
iq2000_elf_object_p (bfd *abfd)
889
946
{
890
946
  bfd_default_set_arch_mach (abfd, bfd_arch_iq2000,
891
946
           elf32_iq2000_machine (abfd));
892
946
  return true;
893
946
}
894
895

896
#define ELF_ARCH    bfd_arch_iq2000
897
#define ELF_MACHINE_CODE  EM_IQ2000
898
#define ELF_MAXPAGESIZE   0x1000
899
900
#define TARGET_BIG_SYM    iq2000_elf32_vec
901
#define TARGET_BIG_NAME   "elf32-iq2000"
902
903
#define elf_info_to_howto_rel     NULL
904
#define elf_info_to_howto     iq2000_info_to_howto_rela
905
#define elf_backend_relocate_section    iq2000_elf_relocate_section
906
#define elf_backend_gc_mark_hook    iq2000_elf_gc_mark_hook
907
#define elf_backend_check_relocs    iq2000_elf_check_relocs
908
#define elf_backend_object_p      iq2000_elf_object_p
909
#define elf_backend_rela_normal     1
910
911
#define elf_backend_can_gc_sections   1
912
913
#define bfd_elf32_bfd_reloc_type_lookup   iq2000_reloc_type_lookup
914
#define bfd_elf32_bfd_reloc_name_lookup iq2000_reloc_name_lookup
915
#define bfd_elf32_bfd_set_private_flags   iq2000_elf_set_private_flags
916
#define bfd_elf32_bfd_merge_private_bfd_data  iq2000_elf_merge_private_bfd_data
917
#define bfd_elf32_bfd_print_private_bfd_data  iq2000_elf_print_private_bfd_data
918
919
#include "elf32-target.h"