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 229

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 159 khays
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 27 khays
// 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 159 khays
// Return true if we are should issue an error saying that SYM is an
173
// undefined symbol.  This is called if there is a relocation against
174
// SYM.
175
 
176
inline bool
177
issue_undefined_symbol_error(const Symbol* sym)
178
{
179
  // We only report global symbols.
180
  if (sym == NULL)
181
    return false;
182
 
183
  // We only report undefined symbols.
184
  if (!sym->is_undefined() && !sym->is_placeholder())
185
    return false;
186
 
187
  // We don't report weak symbols.
188
  if (sym->binding() == elfcpp::STB_WEAK)
189
    return false;
190
 
191
  // We don't report symbols defined in discarded sections.
192
  if (sym->is_defined_in_discarded_section())
193
    return false;
194
 
195
  // If the target defines this symbol, don't report it here.
196
  if (parameters->target().is_defined_by_abi(sym))
197
    return false;
198
 
199
  // See if we've been told to ignore whether this symbol is
200
  // undefined.
201
  const char* const u = parameters->options().unresolved_symbols();
202
  if (u != NULL)
203
    {
204
      if (strcmp(u, "ignore-all") == 0)
205
        return false;
206
      if (strcmp(u, "report-all") == 0)
207
        return true;
208
      if (strcmp(u, "ignore-in-object-files") == 0 && !sym->in_dyn())
209
        return false;
210
      if (strcmp(u, "ignore-in-shared-libs") == 0 && !sym->in_reg())
211
        return false;
212
    }
213
 
214
  // When creating a shared library, only report unresolved symbols if
215
  // -z defs was used.
216
  if (parameters->options().shared() && !parameters->options().defs())
217
    return false;
218
 
219
  // Otherwise issue a warning.
220
  return true;
221
}
222
 
223 27 khays
// This function implements the generic part of relocation processing.
224
// The template parameter Relocate must be a class type which provides
225
// a single function, relocate(), which implements the machine
226
// specific part of a relocation.
227
 
228
// SIZE is the ELF size: 32 or 64.  BIG_ENDIAN is the endianness of
229
// the data.  SH_TYPE is the section type: SHT_REL or SHT_RELA.
230
// RELOCATE implements operator() to do a relocation.
231
 
232
// PRELOCS points to the relocation data.  RELOC_COUNT is the number
233
// of relocs.  OUTPUT_SECTION is the output section.
234
// NEEDS_SPECIAL_OFFSET_HANDLING is true if input offsets need to be
235
// mapped to output offsets.
236
 
237
// VIEW is the section data, VIEW_ADDRESS is its memory address, and
238
// VIEW_SIZE is the size.  These refer to the input section, unless
239
// NEEDS_SPECIAL_OFFSET_HANDLING is true, in which case they refer to
240
// the output section.
241
 
242
// RELOC_SYMBOL_CHANGES is used for -fsplit-stack support.  If it is
243
// not NULL, it is a vector indexed by relocation index.  If that
244
// entry is not NULL, it points to a global symbol which used as the
245
// symbol for the relocation, ignoring the symbol index in the
246
// relocation.
247
 
248
template<int size, bool big_endian, typename Target_type, int sh_type,
249
         typename Relocate>
250
inline void
251
relocate_section(
252
    const Relocate_info<size, big_endian>* relinfo,
253
    Target_type* target,
254
    const unsigned char* prelocs,
255
    size_t reloc_count,
256
    Output_section* output_section,
257
    bool needs_special_offset_handling,
258
    unsigned char* view,
259
    typename elfcpp::Elf_types<size>::Elf_Addr view_address,
260
    section_size_type view_size,
261
    const Reloc_symbol_changes* reloc_symbol_changes)
262
{
263
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
264
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
265
  Relocate relocate;
266
 
267
  Sized_relobj_file<size, big_endian>* object = relinfo->object;
268
  unsigned int local_count = object->local_symbol_count();
269
 
270
  Comdat_behavior comdat_behavior = CB_UNDETERMINED;
271
 
272
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
273
    {
274
      Reltype reloc(prelocs);
275
 
276
      section_offset_type offset =
277
        convert_to_section_size_type(reloc.get_r_offset());
278
 
279
      if (needs_special_offset_handling)
280
        {
281
          offset = output_section->output_offset(relinfo->object,
282
                                                 relinfo->data_shndx,
283
                                                 offset);
284
          if (offset == -1)
285
            continue;
286
        }
287
 
288
      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
289
      unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
290
      unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
291
 
292
      const Sized_symbol<size>* sym;
293
 
294
      Symbol_value<size> symval;
295
      const Symbol_value<size> *psymval;
296
      bool is_defined_in_discarded_section;
297
      unsigned int shndx;
298
      if (r_sym < local_count
299
          && (reloc_symbol_changes == NULL
300
              || (*reloc_symbol_changes)[i] == NULL))
301
        {
302
          sym = NULL;
303
          psymval = object->local_symbol(r_sym);
304
 
305
          // If the local symbol belongs to a section we are discarding,
306
          // and that section is a debug section, try to find the
307
          // corresponding kept section and map this symbol to its
308
          // counterpart in the kept section.  The symbol must not 
309
          // correspond to a section we are folding.
310
          bool is_ordinary;
311
          shndx = psymval->input_shndx(&is_ordinary);
312
          is_defined_in_discarded_section =
313
            (is_ordinary
314
             && shndx != elfcpp::SHN_UNDEF
315
             && !object->is_section_included(shndx)
316
             && !relinfo->symtab->is_section_folded(object, shndx));
317
        }
318
      else
319
        {
320
          const Symbol* gsym;
321
          if (reloc_symbol_changes != NULL
322
              && (*reloc_symbol_changes)[i] != NULL)
323
            gsym = (*reloc_symbol_changes)[i];
324
          else
325
            {
326
              gsym = object->global_symbol(r_sym);
327
              gold_assert(gsym != NULL);
328
              if (gsym->is_forwarder())
329
                gsym = relinfo->symtab->resolve_forwards(gsym);
330
            }
331
 
332
          sym = static_cast<const Sized_symbol<size>*>(gsym);
333
          if (sym->has_symtab_index() && sym->symtab_index() != -1U)
334
            symval.set_output_symtab_index(sym->symtab_index());
335
          else
336
            symval.set_no_output_symtab_entry();
337
          symval.set_output_value(sym->value());
338
          if (gsym->type() == elfcpp::STT_TLS)
339
            symval.set_is_tls_symbol();
340
          else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
341
            symval.set_is_ifunc_symbol();
342
          psymval = &symval;
343
 
344
          is_defined_in_discarded_section =
345
            (gsym->is_defined_in_discarded_section()
346
             && gsym->is_undefined());
347
          shndx = 0;
348
        }
349
 
350
      Symbol_value<size> symval2;
351
      if (is_defined_in_discarded_section)
352
        {
353
          if (comdat_behavior == CB_UNDETERMINED)
354
            {
355
              std::string name = object->section_name(relinfo->data_shndx);
356
              comdat_behavior = get_comdat_behavior(name.c_str());
357
            }
358
          if (comdat_behavior == CB_PRETEND)
359
            {
360
              // FIXME: This case does not work for global symbols.
361
              // We have no place to store the original section index.
362
              // Fortunately this does not matter for comdat sections,
363
              // only for sections explicitly discarded by a linker
364
              // script.
365
              bool found;
366
              typename elfcpp::Elf_types<size>::Elf_Addr value =
367
                object->map_to_kept_section(shndx, &found);
368
              if (found)
369
                symval2.set_output_value(value + psymval->input_value());
370
              else
371
                symval2.set_output_value(0);
372
            }
373
          else
374
            {
375
              if (comdat_behavior == CB_WARNING)
376
                gold_warning_at_location(relinfo, i, offset,
377
                                         _("relocation refers to discarded "
378
                                           "section"));
379
              symval2.set_output_value(0);
380
            }
381
          symval2.set_no_output_symtab_entry();
382
          psymval = &symval2;
383
        }
384
 
385
      if (!relocate.relocate(relinfo, target, output_section, i, reloc,
386
                             r_type, sym, psymval, view + offset,
387
                             view_address + offset, view_size))
388
        continue;
389
 
390
      if (offset < 0 || static_cast<section_size_type>(offset) >= view_size)
391
        {
392
          gold_error_at_location(relinfo, i, offset,
393
                                 _("reloc has bad offset %zu"),
394
                                 static_cast<size_t>(offset));
395
          continue;
396
        }
397
 
398 159 khays
      if (issue_undefined_symbol_error(sym))
399 27 khays
        gold_undefined_symbol_at_location(sym, relinfo, i, offset);
400
      else if (sym != NULL
401
               && sym->visibility() != elfcpp::STV_DEFAULT
402
               && (sym->is_undefined() || sym->is_from_dynobj()))
403
        visibility_error(sym);
404
 
405
      if (sym != NULL && sym->has_warning())
406
        relinfo->symtab->issue_warning(sym, relinfo, i, offset);
407
    }
408
}
409
 
410
// Apply an incremental relocation.
411
 
412
template<int size, bool big_endian, typename Target_type,
413
         typename Relocate>
414
void
415
apply_relocation(const Relocate_info<size, big_endian>* relinfo,
416
                 Target_type* target,
417
                 typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
418
                 unsigned int r_type,
419
                 typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
420
                 const Symbol* gsym,
421
                 unsigned char* view,
422
                 typename elfcpp::Elf_types<size>::Elf_Addr address,
423
                 section_size_type view_size)
424
{
425
  // Construct the ELF relocation in a temporary buffer.
426 166 khays
  const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
427 27 khays
  unsigned char relbuf[reloc_size];
428 166 khays
  elfcpp::Rela<size, big_endian> rel(relbuf);
429
  elfcpp::Rela_write<size, big_endian> orel(relbuf);
430 27 khays
  orel.put_r_offset(r_offset);
431 166 khays
  orel.put_r_info(elfcpp::elf_r_info<size>(0, r_type));
432 27 khays
  orel.put_r_addend(r_addend);
433
 
434
  // Setup a Symbol_value for the global symbol.
435 166 khays
  const Sized_symbol<size>* sym = static_cast<const Sized_symbol<size>*>(gsym);
436
  Symbol_value<size> symval;
437 27 khays
  gold_assert(sym->has_symtab_index() && sym->symtab_index() != -1U);
438
  symval.set_output_symtab_index(sym->symtab_index());
439
  symval.set_output_value(sym->value());
440
  if (gsym->type() == elfcpp::STT_TLS)
441
    symval.set_is_tls_symbol();
442
  else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
443
    symval.set_is_ifunc_symbol();
444
 
445
  Relocate relocate;
446
  relocate.relocate(relinfo, target, NULL, -1U, rel, r_type, sym, &symval,
447
                    view + r_offset, address + r_offset, view_size);
448
}
449
 
450
// This class may be used as a typical class for the
451
// Scan_relocatable_reloc parameter to scan_relocatable_relocs.  The
452
// template parameter Classify_reloc must be a class type which
453
// provides a function get_size_for_reloc which returns the number of
454
// bytes to which a reloc applies.  This class is intended to capture
455
// the most typical target behaviour, while still permitting targets
456
// to define their own independent class for Scan_relocatable_reloc.
457
 
458
template<int sh_type, typename Classify_reloc>
459
class Default_scan_relocatable_relocs
460
{
461
 public:
462
  // Return the strategy to use for a local symbol which is not a
463
  // section symbol, given the relocation type.
464
  inline Relocatable_relocs::Reloc_strategy
465
  local_non_section_strategy(unsigned int r_type, Relobj*, unsigned int r_sym)
466
  {
467
    // We assume that relocation type 0 is NONE.  Targets which are
468
    // different must override.
469
    if (r_type == 0 && r_sym == 0)
470
      return Relocatable_relocs::RELOC_DISCARD;
471
    return Relocatable_relocs::RELOC_COPY;
472
  }
473
 
474
  // Return the strategy to use for a local symbol which is a section
475
  // symbol, given the relocation type.
476
  inline Relocatable_relocs::Reloc_strategy
477
  local_section_strategy(unsigned int r_type, Relobj* object)
478
  {
479
    if (sh_type == elfcpp::SHT_RELA)
480
      return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA;
481
    else
482
      {
483
        Classify_reloc classify;
484
        switch (classify.get_size_for_reloc(r_type, object))
485
          {
486
          case 0:
487
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0;
488
          case 1:
489
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1;
490
          case 2:
491
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2;
492
          case 4:
493
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4;
494
          case 8:
495
            return Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_8;
496
          default:
497
            gold_unreachable();
498
          }
499
      }
500
  }
501
 
502
  // Return the strategy to use for a global symbol, given the
503
  // relocation type, the object, and the symbol index.
504
  inline Relocatable_relocs::Reloc_strategy
505
  global_strategy(unsigned int, Relobj*, unsigned int)
506
  { return Relocatable_relocs::RELOC_COPY; }
507
};
508
 
509
// Scan relocs during a relocatable link.  This is a default
510
// definition which should work for most targets.
511
// Scan_relocatable_reloc must name a class type which provides three
512
// functions which return a Relocatable_relocs::Reloc_strategy code:
513
// global_strategy, local_non_section_strategy, and
514
// local_section_strategy.  Most targets should be able to use
515
// Default_scan_relocatable_relocs as this class.
516
 
517
template<int size, bool big_endian, int sh_type,
518
         typename Scan_relocatable_reloc>
519
void
520
scan_relocatable_relocs(
521
    Symbol_table*,
522
    Layout*,
523
    Sized_relobj_file<size, big_endian>* object,
524
    unsigned int data_shndx,
525
    const unsigned char* prelocs,
526
    size_t reloc_count,
527
    Output_section* output_section,
528
    bool needs_special_offset_handling,
529
    size_t local_symbol_count,
530
    const unsigned char* plocal_syms,
531
    Relocatable_relocs* rr)
532
{
533
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
534
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
535
  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
536
  Scan_relocatable_reloc scan;
537
 
538
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
539
    {
540
      Reltype reloc(prelocs);
541
 
542
      Relocatable_relocs::Reloc_strategy strategy;
543
 
544
      if (needs_special_offset_handling
545
          && !output_section->is_input_address_mapped(object, data_shndx,
546
                                                      reloc.get_r_offset()))
547
        strategy = Relocatable_relocs::RELOC_DISCARD;
548
      else
549
        {
550
          typename elfcpp::Elf_types<size>::Elf_WXword r_info =
551
            reloc.get_r_info();
552
          const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
553
          const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
554
 
555
          if (r_sym >= local_symbol_count)
556
            strategy = scan.global_strategy(r_type, object, r_sym);
557
          else
558
            {
559
              gold_assert(plocal_syms != NULL);
560
              typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
561
                                                          + r_sym * sym_size);
562
              unsigned int shndx = lsym.get_st_shndx();
563
              bool is_ordinary;
564
              shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
565
              if (is_ordinary
566
                  && shndx != elfcpp::SHN_UNDEF
567
                  && !object->is_section_included(shndx))
568
                {
569
                  // RELOC is a relocation against a local symbol
570
                  // defined in a section we are discarding.  Discard
571
                  // the reloc.  FIXME: Should we issue a warning?
572
                  strategy = Relocatable_relocs::RELOC_DISCARD;
573
                }
574
              else if (lsym.get_st_type() != elfcpp::STT_SECTION)
575
                strategy = scan.local_non_section_strategy(r_type, object,
576
                                                           r_sym);
577
              else
578
                {
579
                  strategy = scan.local_section_strategy(r_type, object);
580
                  if (strategy != Relocatable_relocs::RELOC_DISCARD)
581
                    object->output_section(shndx)->set_needs_symtab_index();
582
                }
583
 
584
              if (strategy == Relocatable_relocs::RELOC_COPY)
585
                object->set_must_have_output_symtab_entry(r_sym);
586
            }
587
        }
588
 
589
      rr->set_next_reloc_strategy(strategy);
590
    }
591
}
592
 
593
// Relocate relocs during a relocatable link.  This is a default
594
// definition which should work for most targets.
595
 
596
template<int size, bool big_endian, int sh_type>
597
void
598
relocate_for_relocatable(
599
    const Relocate_info<size, big_endian>* relinfo,
600
    const unsigned char* prelocs,
601
    size_t reloc_count,
602
    Output_section* output_section,
603
    typename elfcpp::Elf_types<size>::Elf_Addr offset_in_output_section,
604
    const Relocatable_relocs* rr,
605
    unsigned char* view,
606
    typename elfcpp::Elf_types<size>::Elf_Addr view_address,
607
    section_size_type view_size,
608
    unsigned char* reloc_view,
609
    section_size_type reloc_view_size)
610
{
611
  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
612
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
613
  typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write
614
    Reltype_write;
615
  const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
616
  const Address invalid_address = static_cast<Address>(0) - 1;
617
 
618
  Sized_relobj_file<size, big_endian>* const object = relinfo->object;
619
  const unsigned int local_count = object->local_symbol_count();
620
 
621
  unsigned char* pwrite = reloc_view;
622
 
623
  for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
624
    {
625
      Relocatable_relocs::Reloc_strategy strategy = rr->strategy(i);
626
      if (strategy == Relocatable_relocs::RELOC_DISCARD)
627
        continue;
628
 
629
      if (strategy == Relocatable_relocs::RELOC_SPECIAL)
630
        {
631
          // Target wants to handle this relocation.
632
          Sized_target<size, big_endian>* target =
633
            parameters->sized_target<size, big_endian>();
634
          target->relocate_special_relocatable(relinfo, sh_type, prelocs,
635
                                               i, output_section,
636
                                               offset_in_output_section,
637
                                               view, view_address,
638
                                               view_size, pwrite);
639
          pwrite += reloc_size;
640
          continue;
641
        }
642
      Reltype reloc(prelocs);
643
      Reltype_write reloc_write(pwrite);
644
 
645
      typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
646
      const unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
647
      const unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
648
 
649
      // Get the new symbol index.
650
 
651
      unsigned int new_symndx;
652
      if (r_sym < local_count)
653
        {
654
          switch (strategy)
655
            {
656
            case Relocatable_relocs::RELOC_COPY:
657
              if (r_sym == 0)
658
                new_symndx = 0;
659
              else
660
                {
661
                  new_symndx = object->symtab_index(r_sym);
662
                  gold_assert(new_symndx != -1U);
663
                }
664
              break;
665
 
666
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
667
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0:
668
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
669
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2:
670
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4:
671
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_8:
672 163 khays
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4_UNALIGNED:
673 27 khays
              {
674
                // We are adjusting a section symbol.  We need to find
675
                // the symbol table index of the section symbol for
676
                // the output section corresponding to input section
677
                // in which this symbol is defined.
678
                gold_assert(r_sym < local_count);
679
                bool is_ordinary;
680
                unsigned int shndx =
681
                  object->local_symbol_input_shndx(r_sym, &is_ordinary);
682
                gold_assert(is_ordinary);
683
                Output_section* os = object->output_section(shndx);
684
                gold_assert(os != NULL);
685
                gold_assert(os->needs_symtab_index());
686
                new_symndx = os->symtab_index();
687
              }
688
              break;
689
 
690
            default:
691
              gold_unreachable();
692
            }
693
        }
694
      else
695
        {
696
          const Symbol* gsym = object->global_symbol(r_sym);
697
          gold_assert(gsym != NULL);
698
          if (gsym->is_forwarder())
699
            gsym = relinfo->symtab->resolve_forwards(gsym);
700
 
701
          gold_assert(gsym->has_symtab_index());
702
          new_symndx = gsym->symtab_index();
703
        }
704
 
705
      // Get the new offset--the location in the output section where
706
      // this relocation should be applied.
707
 
708
      Address offset = reloc.get_r_offset();
709
      Address new_offset;
710
      if (offset_in_output_section != invalid_address)
711
        new_offset = offset + offset_in_output_section;
712
      else
713
        {
714
          section_offset_type sot_offset =
715
              convert_types<section_offset_type, Address>(offset);
716
          section_offset_type new_sot_offset =
717
              output_section->output_offset(object, relinfo->data_shndx,
718
                                            sot_offset);
719
          gold_assert(new_sot_offset != -1);
720
          new_offset = new_sot_offset;
721
        }
722
 
723
      // In an object file, r_offset is an offset within the section.
724
      // In an executable or dynamic object, generated by
725
      // --emit-relocs, r_offset is an absolute address.
726
      if (!parameters->options().relocatable())
727
        {
728
          new_offset += view_address;
729
          if (offset_in_output_section != invalid_address)
730
            new_offset -= offset_in_output_section;
731
        }
732
 
733
      reloc_write.put_r_offset(new_offset);
734
      reloc_write.put_r_info(elfcpp::elf_r_info<size>(new_symndx, r_type));
735
 
736
      // Handle the reloc addend based on the strategy.
737
 
738
      if (strategy == Relocatable_relocs::RELOC_COPY)
739
        {
740
          if (sh_type == elfcpp::SHT_RELA)
741
            Reloc_types<sh_type, size, big_endian>::
742
              copy_reloc_addend(&reloc_write,
743
                                &reloc);
744
        }
745
      else
746
        {
747
          // The relocation uses a section symbol in the input file.
748
          // We are adjusting it to use a section symbol in the output
749
          // file.  The input section symbol refers to some address in
750
          // the input section.  We need the relocation in the output
751
          // file to refer to that same address.  This adjustment to
752
          // the addend is the same calculation we use for a simple
753
          // absolute relocation for the input section symbol.
754
 
755
          const Symbol_value<size>* psymval = object->local_symbol(r_sym);
756
 
757
          unsigned char* padd = view + offset;
758
          switch (strategy)
759
            {
760
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
761
              {
762
                typename elfcpp::Elf_types<size>::Elf_Swxword addend;
763
                addend = Reloc_types<sh_type, size, big_endian>::
764
                           get_reloc_addend(&reloc);
765
                addend = psymval->value(object, addend);
766
                Reloc_types<sh_type, size, big_endian>::
767
                  set_reloc_addend(&reloc_write, addend);
768
              }
769
              break;
770
 
771
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_0:
772
              break;
773
 
774
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_1:
775
              Relocate_functions<size, big_endian>::rel8(padd, object,
776
                                                         psymval);
777
              break;
778
 
779
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_2:
780
              Relocate_functions<size, big_endian>::rel16(padd, object,
781
                                                          psymval);
782
              break;
783
 
784
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4:
785
              Relocate_functions<size, big_endian>::rel32(padd, object,
786
                                                          psymval);
787
              break;
788
 
789
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_8:
790
              Relocate_functions<size, big_endian>::rel64(padd, object,
791
                                                          psymval);
792
              break;
793
 
794 163 khays
            case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_4_UNALIGNED:
795
              Relocate_functions<size, big_endian>::rel32_unaligned(padd,
796
                                                                    object,
797
                                                                    psymval);
798
              break;
799
 
800 27 khays
            default:
801
              gold_unreachable();
802
            }
803
        }
804
 
805
      pwrite += reloc_size;
806
    }
807
 
808
  gold_assert(static_cast<section_size_type>(pwrite - reloc_view)
809
              == reloc_view_size);
810
}
811
 
812
} // End namespace gold.
813
 
814
#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.