1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
// target.h -- target support for gold -*- C++ -*-
// The abstract class Target is the interface for target specific
// support. It defines abstract methods which each target must
// implement. Typically there will be one target per processor, but
// in some cases it may be necessary to have subclasses.
// For speed and consistency we want to use inline functions to handle
// relocation processing. So besides implementations of the abstract
// methods, each target is expected to define a template
// specialization of the relocation functions.
#ifndef GOLD_TARGET_H
#define GOLD_TARGET_H
#include <cassert>
#include "elfcpp.h"
#include "symtab.h"
namespace gold
{
class Object;
template<int size, bool big_endian>
class Sized_object;
// The abstract class for target specific handling.
class Target
{
public:
virtual ~Target()
{ }
// Return the bit size that this target implements. This should
// return 32 or 64.
int
get_size() const
{ return this->pti_->size; }
// Return whether this target is big-endian.
bool
is_big_endian() const
{ return this->pti_->is_big_endian; }
// Machine code to store in e_machine field of ELF header.
elfcpp::EM
machine_code() const
{ return this->pti_->machine_code; }
// Whether this target has a specific make_symbol function.
bool
has_make_symbol() const
{ return this->pti_->has_make_symbol; }
// Whether this target has a specific resolve function.
bool
has_resolve() const
{ return this->pti_->has_resolve; }
// Return the default address to use for the text segment.
uint64_t
text_segment_address() const
{ return this->pti_->text_segment_address; }
// Return the ABI specified page size.
uint64_t
abi_pagesize() const
{ return this->pti_->abi_pagesize; }
// Return the common page size used on actual systems.
uint64_t
common_pagesize() const
{ return this->pti_->common_pagesize; }
protected:
// This struct holds the constant information for a child class. We
// use a struct to avoid the overhead of virtual function calls for
// simple information.
struct Target_info
{
// Address size (32 or 64).
int size;
// Whether the target is big endian.
bool is_big_endian;
// The code to store in the e_machine field of the ELF header.
elfcpp::EM machine_code;
// Whether this target has a specific make_symbol function.
bool has_make_symbol;
// Whether this target has a specific resolve function.
bool has_resolve;
// The default text segment address.
uint64_t text_segment_address;
// The ABI specified page size.
uint64_t abi_pagesize;
// The common page size used by actual implementations.
uint64_t common_pagesize;
};
Target(const Target_info* pti)
: pti_(pti)
{ }
private:
Target(const Target&);
Target& operator=(const Target&);
// The target information.
const Target_info* pti_;
};
// The abstract class for a specific size and endianness of target.
// Each actual target implementation class should derive from an
// instantiation of Sized_target.
template<int size, bool big_endian>
class Sized_target : public Target
{
public:
// Make a new symbol table entry for the target. This should be
// overridden by a target which needs additional information in the
// symbol table. This will only be called if has_make_symbol()
// returns true.
virtual Sized_symbol<size>*
make_symbol()
{ abort(); }
// Resolve a symbol for the target. This should be overridden by a
// target which needs to take special action. TO is the
// pre-existing symbol. SYM is the new symbol, seen in OBJECT.
virtual void
resolve(Symbol*, const elfcpp::Sym<size, big_endian>&, Object*)
{ abort(); }
// Relocate section data. SYMTAB is the symbol table. OBJECT is
// the object in which the section appears. SH_TYPE is the type of
// the relocation section, SHT_REL or SHT_RELA. PRELOCS points to
// the relocation information. RELOC_COUNT is the number of relocs.
// LOCAL_COUNT is the number of local symbols. The VALUES and
// GLOBAL_SYMS have symbol table information. VIEW is a view into
// the output file holding the section contents, VIEW_ADDRESS is the
// virtual address of the view, and VIEW_SIZE is the size of the
// view.
virtual void
relocate_section(const Symbol_table*, // symtab
Sized_object<size, big_endian>*, // object
unsigned int, // sh_type
const unsigned char*, // prelocs
size_t, // reloc_count
unsigned int, // local_count
const typename elfcpp::Elf_types<size>::Elf_Addr*, // values
Symbol**, // global_syms
unsigned char*, // view
typename elfcpp::Elf_types<size>::Elf_Addr, // view_address
off_t) // view_size
{ abort(); }
protected:
Sized_target(const Target::Target_info* pti)
: Target(pti)
{
assert(pti->size == size);
assert(pti->is_big_endian ? big_endian : !big_endian);
}
};
} // End namespace gold.
#endif // !defined(GOLD_TARGET_H)
|