OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [target-reloc.h] - Blame information for rev 127

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
// target-reloc.h -- target specific relocation support  -*- C++ -*-
2
 
3
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
// Written by Ian Lance Taylor <iant@google.com>.
5
 
6
// This file is part of gold.
7
 
8
// This program is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU General Public License as published by
10
// the Free Software Foundation; either version 3 of the License, or
11
// (at your option) any later version.
12
 
13
// This program is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
// GNU General Public License for more details.
17
 
18
// You should have received a copy of the GNU General Public License
19
// along with this program; if not, write to the Free Software
20
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
// MA 02110-1301, USA.
22
 
23
#ifndef GOLD_TARGET_RELOC_H
24
#define GOLD_TARGET_RELOC_H
25
 
26
#include "elfcpp.h"
27
#include "symtab.h"
28
#include "object.h"
29
#include "reloc.h"
30
#include "reloc-types.h"
31
 
32
namespace gold
33
{
34
 
35
// This function implements the generic part of reloc scanning.  The
36
// template parameter Scan must be a class type which provides two
37
// functions: local() and global().  Those functions implement the
38
// machine specific part of scanning.  We do it this way to
39
// avoid making a function call for each relocation, and to avoid
40
// repeating the generic code for each target.
41
 
42
template<int size, bool big_endian, typename Target_type, int sh_type,
43
         typename Scan>
44
inline void
45
scan_relocs(
46
    Symbol_table* symtab,
47
    Layout* layout,
48
    Target_type* target,
49
    Sized_relobj_file<size, big_endian>* object,
50
    unsigned int data_shndx,
51
    const unsigned char* prelocs,
52
    size_t reloc_count,
53
    Output_section* output_section,
54
    bool needs_special_offset_handling,
55
    size_t local_count,
56
    const unsigned char* plocal_syms)
57
{
58
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
59
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
60
  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
61
  Scan scan;
62
 
63
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
64
    {
65
      Reltype reloc(prelocs);
66
 
67
      if (needs_special_offset_handling
68
          && !output_section->is_input_address_mapped(object, data_shndx,
69
                                                      reloc.get_r_offset()))
70
        continue;
71
 
72
      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
73
      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
74
      unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
75
 
76
      if (r_sym < local_count)
77
        {
78
          gold_assert(plocal_syms != NULL);
79
          typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
80
                                                      + r_sym * sym_size);
81
          unsigned int shndx = lsym.get_st_shndx();
82
          bool is_ordinary;
83
          shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
84
          if (is_ordinary
85
              && shndx != elfcpp::SHN_UNDEF
86
              && !object->is_section_included(shndx)
87
              && !symtab->is_section_folded(object, shndx))
88
            {
89
              // RELOC is a relocation against a local symbol in a
90
              // section we are discarding.  We can ignore this
91
              // relocation.  It will eventually become a reloc
92
              // against the value zero.
93
              //
94
              // FIXME: We should issue a warning if this is an
95
              // allocated section; is this the best place to do it?
96
              // 
97
              // FIXME: The old GNU linker would in some cases look
98
              // for the linkonce section which caused this section to
99
              // be discarded, and, if the other section was the same
100
              // size, change the reloc to refer to the other section.
101
              // That seems risky and weird to me, and I don't know of
102
              // any case where it is actually required.
103
 
104
              continue;
105
            }
106
          scan.local(symtab, layout, target, object, data_shndx,
107
                     output_section, reloc, r_type, lsym);
108
        }
109
      else
110
        {
111
          Symbol* gsym = object->global_symbol(r_sym);
112
          gold_assert(gsym != NULL);
113
          if (gsym->is_forwarder())
114
            gsym = symtab->resolve_forwards(gsym);
115
 
116
          scan.global(symtab, layout, target, object, data_shndx,
117
                      output_section, reloc, r_type, gsym);
118
        }
119
    }
120
}
121
 
122
// Behavior for relocations to discarded comdat sections.
123
 
124
enum Comdat_behavior
125
{
126
  CB_UNDETERMINED,   // Not yet determined -- need to look at section name.
127
  CB_PRETEND,        // Attempt to map to the corresponding kept section.
128
  CB_IGNORE,         // Ignore the relocation.
129
  CB_WARNING         // Print a warning.
130
};
131
 
132
// Decide what the linker should do for relocations that refer to discarded
133
// comdat sections.  This decision is based on the name of the section being
134
// relocated.
135
 
136
inline Comdat_behavior
137
get_comdat_behavior(const char* name)
138
{
139
  if (Layout::is_debug_info_section(name))
140
    return CB_PRETEND;
141
  if (strcmp(name, ".eh_frame") == 0
142
      || strcmp(name, ".gcc_except_table") == 0)
143
    return CB_IGNORE;
144
  return CB_WARNING;
145
}
146
 
147
// Give an error for a symbol with non-default visibility which is not
148
// defined locally.
149
 
150
inline void
151
visibility_error(const Symbol* sym)
152
{
153
  const char* v;
154
  switch (sym->visibility())
155
    {
156
    case elfcpp::STV_INTERNAL:
157
      v = _("internal");
158
      break;
159
    case elfcpp::STV_HIDDEN:
160
      v = _("hidden");
161
      break;
162
    case elfcpp::STV_PROTECTED:
163
      v = _("protected");
164
      break;
165
    default:
166
      gold_unreachable();
167
    }
168
  gold_error(_("%s symbol '%s' is not defined locally"),
169
             v, sym->name());
170
}
171
 
172
// This function implements the generic part of relocation processing.
173
// The template parameter Relocate must be a class type which provides
174
// a single function, relocate(), which implements the machine
175
// specific part of a relocation.
176
 
177
// SIZE is the ELF size: 32 or 64.  BIG_ENDIAN is the endianness of
178
// the data.  SH_TYPE is the section type: SHT_REL or SHT_RELA.
179
// RELOCATE implements operator() to do a relocation.
180
 
181
// PRELOCS points to the relocation data.  RELOC_COUNT is the number
182
// of relocs.  OUTPUT_SECTION is the output section.
183
// NEEDS_SPECIAL_OFFSET_HANDLING is true if input offsets need to be
184
// mapped to output offsets.
185
 
186
// VIEW is the section data, VIEW_ADDRESS is its memory address, and
187
// VIEW_SIZE is the size.  These refer to the input section, unless
188
// NEEDS_SPECIAL_OFFSET_HANDLING is true, in which case they refer to
189
// the output section.
190
 
191
// RELOC_SYMBOL_CHANGES is used for -fsplit-stack support.  If it is
192
// not NULL, it is a vector indexed by relocation index.  If that
193
// entry is not NULL, it points to a global symbol which used as the
194
// symbol for the relocation, ignoring the symbol index in the
195
// relocation.
196
 
197
template<int size, bool big_endian, typename Target_type, int sh_type,
198
         typename Relocate>
199
inline void
200
relocate_section(
201
    const Relocate_info<size, big_endian>* relinfo,
202
    Target_type* target,
203
    const unsigned char* prelocs,
204
    size_t reloc_count,
205
    Output_section* output_section,
206
    bool needs_special_offset_handling,
207
    unsigned char* view,
208
    typename elfcpp::Elf_types<size>::Elf_Addr view_address,
209
    section_size_type view_size,
210
    const Reloc_symbol_changes* reloc_symbol_changes)
211
{
212
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
213
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
214
  Relocate relocate;
215
 
216
  Sized_relobj_file<size, big_endian>* object = relinfo->object;
217
  unsigned int local_count = object->local_symbol_count();
218
 
219
  Comdat_behavior comdat_behavior = CB_UNDETERMINED;
220
 
221
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
222
    {
223
      Reltype reloc(prelocs);
224
 
225
      section_offset_type offset =
226
        convert_to_section_size_type(reloc.get_r_offset());
227
 
228
      if (needs_special_offset_handling)
229
        {
230
          offset = output_section->output_offset(relinfo->object,
231
                                                 relinfo->data_shndx,
232
                                                 offset);
233
          if (offset == -1)
234
            continue;
235
        }
236
 
237
      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
238
      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
239
      unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
240
 
241
      const Sized_symbol<size>* sym;
242
 
243
      Symbol_value<size> symval;
244
      const Symbol_value<size> *psymval;
245
      bool is_defined_in_discarded_section;
246
      unsigned int shndx;
247
      if (r_sym < local_count
248
          && (reloc_symbol_changes == NULL
249
              || (*reloc_symbol_changes)[i] == NULL))
250
        {
251
          sym = NULL;
252
          psymval = object->local_symbol(r_sym);
253
 
254
          // If the local symbol belongs to a section we are discarding,
255
          // and that section is a debug section, try to find the
256
          // corresponding kept section and map this symbol to its
257
          // counterpart in the kept section.  The symbol must not 
258
          // correspond to a section we are folding.
259
          bool is_ordinary;
260
          shndx = psymval->input_shndx(&is_ordinary);
261
          is_defined_in_discarded_section =
262
            (is_ordinary
263
             && shndx != elfcpp::SHN_UNDEF
264
             && !object->is_section_included(shndx)
265
             && !relinfo->symtab->is_section_folded(object, shndx));
266
        }
267
      else
268
        {
269
          const Symbol* gsym;
270
          if (reloc_symbol_changes != NULL
271
              && (*reloc_symbol_changes)[i] != NULL)
272
            gsym = (*reloc_symbol_changes)[i];
273
          else
274
            {
275
              gsym = object->global_symbol(r_sym);
276
              gold_assert(gsym != NULL);
277
              if (gsym->is_forwarder())
278
                gsym = relinfo->symtab->resolve_forwards(gsym);
279
            }
280
 
281
          sym = static_cast<const Sized_symbol<size>*>(gsym);
282
          if (sym->has_symtab_index() && sym->symtab_index() != -1U)
283
            symval.set_output_symtab_index(sym->symtab_index());
284
          else
285
            symval.set_no_output_symtab_entry();
286
          symval.set_output_value(sym->value());
287
          if (gsym->type() == elfcpp::STT_TLS)
288
            symval.set_is_tls_symbol();
289
          else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
290
            symval.set_is_ifunc_symbol();
291
          psymval = &symval;
292
 
293
          is_defined_in_discarded_section =
294
            (gsym->is_defined_in_discarded_section()
295
             && gsym->is_undefined());
296
          shndx = 0;
297
        }
298
 
299
      Symbol_value<size> symval2;
300
      if (is_defined_in_discarded_section)
301
        {
302
          if (comdat_behavior == CB_UNDETERMINED)
303
            {
304
              std::string name = object->section_name(relinfo->data_shndx);
305
              comdat_behavior = get_comdat_behavior(name.c_str());
306
            }
307
          if (comdat_behavior == CB_PRETEND)
308
            {
309
              // FIXME: This case does not work for global symbols.
310
              // We have no place to store the original section index.
311
              // Fortunately this does not matter for comdat sections,
312
              // only for sections explicitly discarded by a linker
313
              // script.
314
              bool found;
315
              typename elfcpp::Elf_types<size>::Elf_Addr value =
316
                object->map_to_kept_section(shndx, &found);
317
              if (found)
318
                symval2.set_output_value(value + psymval->input_value());
319
              else
320
                symval2.set_output_value(0);
321
            }
322
          else
323
            {
324
              if (comdat_behavior == CB_WARNING)
325
                gold_warning_at_location(relinfo, i, offset,
326
                                         _("relocation refers to discarded "
327
                                           "section"));
328
              symval2.set_output_value(0);
329
            }
330
          symval2.set_no_output_symtab_entry();
331
          psymval = &symval2;
332
        }
333
 
334
      if (!relocate.relocate(relinfo, target, output_section, i, reloc,
335
                             r_type, sym, psymval, view + offset,
336
                             view_address + offset, view_size))
337
        continue;
338
 
339
      if (offset < 0 || static_cast<section_size_type>(offset) >= view_size)
340
        {
341
          gold_error_at_location(relinfo, i, offset,
342
                                 _("reloc has bad offset %zu"),
343
                                 static_cast<size_t>(offset));
344
          continue;
345
        }
346
 
347
      if (sym != NULL
348
          && (sym->is_undefined() || sym->is_placeholder())
349
          && sym->binding() != elfcpp::STB_WEAK
350
          && !is_defined_in_discarded_section
351
          && !target->is_defined_by_abi(sym)
352
          && (!parameters->options().shared()       // -shared
353
              || parameters->options().defs()))     // -z defs
354
        gold_undefined_symbol_at_location(sym, relinfo, i, offset);
355
      else if (sym != NULL
356
               && sym->visibility() != elfcpp::STV_DEFAULT
357
               && (sym->is_undefined() || sym->is_from_dynobj()))
358
        visibility_error(sym);
359
 
360
      if (sym != NULL && sym->has_warning())
361
        relinfo->symtab->issue_warning(sym, relinfo, i, offset);
362
    }
363
}
364
 
365
// Apply an incremental relocation.
366
 
367
template<int size, bool big_endian, typename Target_type,
368
         typename Relocate>
369
void
370
apply_relocation(const Relocate_info<size, big_endian>* relinfo,
371
                 Target_type* target,
372
                 typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
373
                 unsigned int r_type,
374
                 typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
375
                 const Symbol* gsym,
376
                 unsigned char* view,
377
                 typename elfcpp::Elf_types<size>::Elf_Addr address,
378
                 section_size_type view_size)
379
{
380
  // Construct the ELF relocation in a temporary buffer.
381
  const int reloc_size = elfcpp::Elf_sizes<64>::rela_size;
382
  unsigned char relbuf[reloc_size];
383
  elfcpp::Rela<64, false> rel(relbuf);
384
  elfcpp::Rela_write<64, false> orel(relbuf);
385
  orel.put_r_offset(r_offset);
386
  orel.put_r_info(elfcpp::elf_r_info<64>(0, r_type));
387
  orel.put_r_addend(r_addend);
388
 
389
  // Setup a Symbol_value for the global symbol.
390
  const Sized_symbol<64>* sym = static_cast<const Sized_symbol<64>*>(gsym);
391
  Symbol_value<64> symval;
392
  gold_assert(sym->has_symtab_index() && sym->symtab_index() != -1U);
393
  symval.set_output_symtab_index(sym->symtab_index());
394
  symval.set_output_value(sym->value());
395
  if (gsym->type() == elfcpp::STT_TLS)
396
    symval.set_is_tls_symbol();
397
  else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
398
    symval.set_is_ifunc_symbol();
399
 
400
  Relocate relocate;
401
  relocate.relocate(relinfo, target, NULL, -1U, rel, r_type, sym, &symval,
402
                    view + r_offset, address + r_offset, view_size);
403
}
404
 
405
// This class may be used as a typical class for the
406
// Scan_relocatable_reloc parameter to scan_relocatable_relocs.  The
407
// template parameter Classify_reloc must be a class type which
408
// provides a function get_size_for_reloc which returns the number of
409
// bytes to which a reloc applies.  This class is intended to capture
410
// the most typical target behaviour, while still permitting targets
411
// to define their own independent class for Scan_relocatable_reloc.
412
 
413
template<int sh_type, typename Classify_reloc>
414
class Default_scan_relocatable_relocs
415
{
416
 public:
417
  // Return the strategy to use for a local symbol which is not a
418
  // section symbol, given the relocation type.
419
  inline Relocatable_relocs::Reloc_strategy
420
  local_non_section_strategy(unsigned int r_type, Relobj*, unsigned int r_sym)
421
  {
422
    // We assume that relocation type 0 is NONE.  Targets which are
423
    // different must override.
424
    if (r_type == 0 && r_sym == 0)
425
      return Relocatable_relocs::RELOC_DISCARD;
426
    return Relocatable_relocs::RELOC_COPY;
427
  }
428
 
429
  // Return the strategy to use for a local symbol which is a section
430
  // symbol, given the relocation type.
431
  inline Relocatable_relocs::Reloc_strategy
432
  local_section_strategy(unsigned int r_type, Relobj* object)
433
  {
434
    if (sh_type == elfcpp::SHT_RELA)
435
      return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
436
    else
437
      {
438
        Classify_reloc classify;
439
        switch (classify.get_size_for_reloc(r_type, object))
440
          {
441
          case 0:
442
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
443
          case 1:
444
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1;
445
          case 2:
446
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2;
447
          case 4:
448
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4;
449
          case 8:
450
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_8;
451
          default:
452
            gold_unreachable();
453
          }
454
      }
455
  }
456
 
457
  // Return the strategy to use for a global symbol, given the
458
  // relocation type, the object, and the symbol index.
459
  inline Relocatable_relocs::Reloc_strategy
460
  global_strategy(unsigned int, Relobj*, unsigned int)
461
  { return Relocatable_relocs::RELOC_COPY; }
462
};
463
 
464
// Scan relocs during a relocatable link.  This is a default
465
// definition which should work for most targets.
466
// Scan_relocatable_reloc must name a class type which provides three
467
// functions which return a Relocatable_relocs::Reloc_strategy code:
468
// global_strategy, local_non_section_strategy, and
469
// local_section_strategy.  Most targets should be able to use
470
// Default_scan_relocatable_relocs as this class.
471
 
472
template<int size, bool big_endian, int sh_type,
473
         typename Scan_relocatable_reloc>
474
void
475
scan_relocatable_relocs(
476
    Symbol_table*,
477
    Layout*,
478
    Sized_relobj_file<size, big_endian>* object,
479
    unsigned int data_shndx,
480
    const unsigned char* prelocs,
481
    size_t reloc_count,
482
    Output_section* output_section,
483
    bool needs_special_offset_handling,
484
    size_t local_symbol_count,
485
    const unsigned char* plocal_syms,
486
    Relocatable_relocs* rr)
487
{
488
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
489
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
490
  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
491
  Scan_relocatable_reloc scan;
492
 
493
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
494
    {
495
      Reltype reloc(prelocs);
496
 
497
      Relocatable_relocs::Reloc_strategy strategy;
498
 
499
      if (needs_special_offset_handling
500
          && !output_section->is_input_address_mapped(object, data_shndx,
501
                                                      reloc.get_r_offset()))
502
        strategy = Relocatable_relocs::RELOC_DISCARD;
503
      else
504
        {
505
          typename elfcpp::Elf_types<size>::Elf_WXword r_info =
506
            reloc.get_r_info();
507
          const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
508
          const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
509
 
510
          if (r_sym >= local_symbol_count)
511
            strategy = scan.global_strategy(r_type, object, r_sym);
512
          else
513
            {
514
              gold_assert(plocal_syms != NULL);
515
              typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
516
                                                          + r_sym * sym_size);
517
              unsigned int shndx = lsym.get_st_shndx();
518
              bool is_ordinary;
519
              shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
520
              if (is_ordinary
521
                  && shndx != elfcpp::SHN_UNDEF
522
                  && !object->is_section_included(shndx))
523
                {
524
                  // RELOC is a relocation against a local symbol
525
                  // defined in a section we are discarding.  Discard
526
                  // the reloc.  FIXME: Should we issue a warning?
527
                  strategy = Relocatable_relocs::RELOC_DISCARD;
528
                }
529
              else if (lsym.get_st_type() != elfcpp::STT_SECTION)
530
                strategy = scan.local_non_section_strategy(r_type, object,
531
                                                           r_sym);
532
              else
533
                {
534
                  strategy = scan.local_section_strategy(r_type, object);
535
                  if (strategy != Relocatable_relocs::RELOC_DISCARD)
536
                    object->output_section(shndx)->set_needs_symtab_index();
537
                }
538
 
539
              if (strategy == Relocatable_relocs::RELOC_COPY)
540
                object->set_must_have_output_symtab_entry(r_sym);
541
            }
542
        }
543
 
544
      rr->set_next_reloc_strategy(strategy);
545
    }
546
}
547
 
548
// Relocate relocs during a relocatable link.  This is a default
549
// definition which should work for most targets.
550
 
551
template<int size, bool big_endian, int sh_type>
552
void
553
relocate_for_relocatable(
554
    const Relocate_info<size, big_endian>* relinfo,
555
    const unsigned char* prelocs,
556
    size_t reloc_count,
557
    Output_section* output_section,
558
    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
559
    const Relocatable_relocs* rr,
560
    unsigned char* view,
561
    typename elfcpp::Elf_types<size>::Elf_Addr view_address,
562
    section_size_type view_size,
563
    unsigned char* reloc_view,
564
    section_size_type reloc_view_size)
565
{
566
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
567
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
568
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write
569
    Reltype_write;
570
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
571
  const Address invalid_address = static_cast<Address>(0) - 1;
572
 
573
  Sized_relobj_file<size, big_endian>* const object = relinfo->object;
574
  const unsigned int local_count = object->local_symbol_count();
575
 
576
  unsigned char* pwrite = reloc_view;
577
 
578
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
579
    {
580
      Relocatable_relocs::Reloc_strategy strategy = rr->strategy(i);
581
      if (strategy == Relocatable_relocs::RELOC_DISCARD)
582
        continue;
583
 
584
      if (strategy == Relocatable_relocs::RELOC_SPECIAL)
585
        {
586
          // Target wants to handle this relocation.
587
          Sized_target<size, big_endian>* target =
588
            parameters->sized_target<size, big_endian>();
589
          target->relocate_special_relocatable(relinfo, sh_type, prelocs,
590
                                               i, output_section,
591
                                               offset_in_output_section,
592
                                               view, view_address,
593
                                               view_size, pwrite);
594
          pwrite += reloc_size;
595
          continue;
596
        }
597
      Reltype reloc(prelocs);
598
      Reltype_write reloc_write(pwrite);
599
 
600
      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
601
      const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
602
      const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
603
 
604
      // Get the new symbol index.
605
 
606
      unsigned int new_symndx;
607
      if (r_sym < local_count)
608
        {
609
          switch (strategy)
610
            {
611
            case Relocatable_relocs::RELOC_COPY:
612
              if (r_sym == 0)
613
                new_symndx = 0;
614
              else
615
                {
616
                  new_symndx = object->symtab_index(r_sym);
617
                  gold_assert(new_symndx != -1U);
618
                }
619
              break;
620
 
621
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
622
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0:
623
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
624
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2:
625
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4:
626
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_8:
627
              {
628
                // We are adjusting a section symbol.  We need to find
629
                // the symbol table index of the section symbol for
630
                // the output section corresponding to input section
631
                // in which this symbol is defined.
632
                gold_assert(r_sym < local_count);
633
                bool is_ordinary;
634
                unsigned int shndx =
635
                  object->local_symbol_input_shndx(r_sym, &is_ordinary);
636
                gold_assert(is_ordinary);
637
                Output_section* os = object->output_section(shndx);
638
                gold_assert(os != NULL);
639
                gold_assert(os->needs_symtab_index());
640
                new_symndx = os->symtab_index();
641
              }
642
              break;
643
 
644
            default:
645
              gold_unreachable();
646
            }
647
        }
648
      else
649
        {
650
          const Symbol* gsym = object->global_symbol(r_sym);
651
          gold_assert(gsym != NULL);
652
          if (gsym->is_forwarder())
653
            gsym = relinfo->symtab->resolve_forwards(gsym);
654
 
655
          gold_assert(gsym->has_symtab_index());
656
          new_symndx = gsym->symtab_index();
657
        }
658
 
659
      // Get the new offset--the location in the output section where
660
      // this relocation should be applied.
661
 
662
      Address offset = reloc.get_r_offset();
663
      Address new_offset;
664
      if (offset_in_output_section != invalid_address)
665
        new_offset = offset + offset_in_output_section;
666
      else
667
        {
668
          section_offset_type sot_offset =
669
              convert_types<section_offset_type, Address>(offset);
670
          section_offset_type new_sot_offset =
671
              output_section->output_offset(object, relinfo->data_shndx,
672
                                            sot_offset);
673
          gold_assert(new_sot_offset != -1);
674
          new_offset = new_sot_offset;
675
        }
676
 
677
      // In an object file, r_offset is an offset within the section.
678
      // In an executable or dynamic object, generated by
679
      // --emit-relocs, r_offset is an absolute address.
680
      if (!parameters->options().relocatable())
681
        {
682
          new_offset += view_address;
683
          if (offset_in_output_section != invalid_address)
684
            new_offset -= offset_in_output_section;
685
        }
686
 
687
      reloc_write.put_r_offset(new_offset);
688
      reloc_write.put_r_info(elfcpp::elf_r_info<size>(new_symndx, r_type));
689
 
690
      // Handle the reloc addend based on the strategy.
691
 
692
      if (strategy == Relocatable_relocs::RELOC_COPY)
693
        {
694
          if (sh_type == elfcpp::SHT_RELA)
695
            Reloc_types<sh_type, size, big_endian>::
696
              copy_reloc_addend(&reloc_write,
697
                                &reloc);
698
        }
699
      else
700
        {
701
          // The relocation uses a section symbol in the input file.
702
          // We are adjusting it to use a section symbol in the output
703
          // file.  The input section symbol refers to some address in
704
          // the input section.  We need the relocation in the output
705
          // file to refer to that same address.  This adjustment to
706
          // the addend is the same calculation we use for a simple
707
          // absolute relocation for the input section symbol.
708
 
709
          const Symbol_value<size>* psymval = object->local_symbol(r_sym);
710
 
711
          unsigned char* padd = view + offset;
712
          switch (strategy)
713
            {
714
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
715
              {
716
                typename elfcpp::Elf_types<size>::Elf_Swxword addend;
717
                addend = Reloc_types<sh_type, size, big_endian>::
718
                           get_reloc_addend(&reloc);
719
                addend = psymval->value(object, addend);
720
                Reloc_types<sh_type, size, big_endian>::
721
                  set_reloc_addend(&reloc_write, addend);
722
              }
723
              break;
724
 
725
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0:
726
              break;
727
 
728
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
729
              Relocate_functions<size, big_endian>::rel8(padd, object,
730
                                                         psymval);
731
              break;
732
 
733
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2:
734
              Relocate_functions<size, big_endian>::rel16(padd, object,
735
                                                          psymval);
736
              break;
737
 
738
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4:
739
              Relocate_functions<size, big_endian>::rel32(padd, object,
740
                                                          psymval);
741
              break;
742
 
743
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_8:
744
              Relocate_functions<size, big_endian>::rel64(padd, object,
745
                                                          psymval);
746
              break;
747
 
748
            default:
749
              gold_unreachable();
750
            }
751
        }
752
 
753
      pwrite += reloc_size;
754
    }
755
 
756
  gold_assert(static_cast<section_size_type>(pwrite - reloc_view)
757
              == reloc_view_size);
758
}
759
 
760
} // End namespace gold.
761
 
762
#endif // !defined(GOLD_TARGET_RELOC_H)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.