1 | // target.cc -- target support for gold.
|
---|
2 |
|
---|
3 | // Copyright (C) 2009-2016 Free Software Foundation, Inc.
|
---|
4 | // Written by Doug Kwan <dougkwan@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 | #include "gold.h"
|
---|
24 | #include "elfcpp.h"
|
---|
25 | #include "dynobj.h"
|
---|
26 | #include "symtab.h"
|
---|
27 | #include "output.h"
|
---|
28 | #include "target.h"
|
---|
29 |
|
---|
30 | namespace gold
|
---|
31 | {
|
---|
32 |
|
---|
33 | // Return whether NAME is a local label name. This is used to implement the
|
---|
34 | // --discard-locals options and can be overridden by child classes to
|
---|
35 | // implement system-specific behaviour. The logic here is the same as that
|
---|
36 | // in _bfd_elf_is_local_label_name().
|
---|
37 |
|
---|
38 | bool
|
---|
39 | Target::do_is_local_label_name(const char* name) const
|
---|
40 | {
|
---|
41 | // Normal local symbols start with ``.L''.
|
---|
42 | if (name[0] == '.' && name[1] == 'L')
|
---|
43 | return true;
|
---|
44 |
|
---|
45 | // At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
|
---|
46 | // DWARF debugging symbols starting with ``..''.
|
---|
47 | if (name[0] == '.' && name[1] == '.')
|
---|
48 | return true;
|
---|
49 |
|
---|
50 | // gcc will sometimes generate symbols beginning with ``_.L_'' when
|
---|
51 | // emitting DWARF debugging output. I suspect this is actually a
|
---|
52 | // small bug in gcc (it calls ASM_OUTPUT_LABEL when it should call
|
---|
53 | // ASM_GENERATE_INTERNAL_LABEL, and this causes the leading
|
---|
54 | // underscore to be emitted on some ELF targets). For ease of use,
|
---|
55 | // we treat such symbols as local.
|
---|
56 | if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
|
---|
57 | return true;
|
---|
58 |
|
---|
59 | return false;
|
---|
60 | }
|
---|
61 |
|
---|
62 | // Implementations of methods Target::do_make_elf_object are almost identical
|
---|
63 | // except for the address sizes and endianities. So we extract this
|
---|
64 | // into a template.
|
---|
65 |
|
---|
66 | template<int size, bool big_endian>
|
---|
67 | inline Object*
|
---|
68 | Target::do_make_elf_object_implementation(
|
---|
69 | const std::string& name,
|
---|
70 | Input_file* input_file,
|
---|
71 | off_t offset,
|
---|
72 | const elfcpp::Ehdr<size, big_endian>& ehdr)
|
---|
73 | {
|
---|
74 | int et = ehdr.get_e_type();
|
---|
75 | // ET_EXEC files are valid input for --just-symbols/-R,
|
---|
76 | // and we treat them as relocatable objects.
|
---|
77 | if (et == elfcpp::ET_REL
|
---|
78 | || (et == elfcpp::ET_EXEC && input_file->just_symbols()))
|
---|
79 | {
|
---|
80 | Sized_relobj_file<size, big_endian>* obj =
|
---|
81 | new Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr);
|
---|
82 | obj->setup();
|
---|
83 | return obj;
|
---|
84 | }
|
---|
85 | else if (et == elfcpp::ET_DYN)
|
---|
86 | {
|
---|
87 | Sized_dynobj<size, big_endian>* obj =
|
---|
88 | new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr);
|
---|
89 | obj->setup();
|
---|
90 | return obj;
|
---|
91 | }
|
---|
92 | else
|
---|
93 | {
|
---|
94 | gold_error(_("%s: unsupported ELF file type %d"),
|
---|
95 | name.c_str(), et);
|
---|
96 | return NULL;
|
---|
97 | }
|
---|
98 | }
|
---|
99 |
|
---|
100 | // Make an ELF object called NAME by reading INPUT_FILE at OFFSET. EHDR
|
---|
101 | // is the ELF header of the object. There are four versions of this
|
---|
102 | // for different address sizes and endianities.
|
---|
103 |
|
---|
104 | #ifdef HAVE_TARGET_32_LITTLE
|
---|
105 | Object*
|
---|
106 | Target::do_make_elf_object(const std::string& name, Input_file* input_file,
|
---|
107 | off_t offset, const elfcpp::Ehdr<32, false>& ehdr)
|
---|
108 | {
|
---|
109 | return this->do_make_elf_object_implementation<32, false>(name, input_file,
|
---|
110 | offset, ehdr);
|
---|
111 | }
|
---|
112 | #endif
|
---|
113 |
|
---|
114 | #ifdef HAVE_TARGET_32_BIG
|
---|
115 | Object*
|
---|
116 | Target::do_make_elf_object(const std::string& name, Input_file* input_file,
|
---|
117 | off_t offset, const elfcpp::Ehdr<32, true>& ehdr)
|
---|
118 | {
|
---|
119 | return this->do_make_elf_object_implementation<32, true>(name, input_file,
|
---|
120 | offset, ehdr);
|
---|
121 | }
|
---|
122 | #endif
|
---|
123 |
|
---|
124 | #ifdef HAVE_TARGET_64_LITTLE
|
---|
125 | Object*
|
---|
126 | Target::do_make_elf_object(const std::string& name, Input_file* input_file,
|
---|
127 | off_t offset, const elfcpp::Ehdr<64, false>& ehdr)
|
---|
128 | {
|
---|
129 | return this->do_make_elf_object_implementation<64, false>(name, input_file,
|
---|
130 | offset, ehdr);
|
---|
131 | }
|
---|
132 | #endif
|
---|
133 |
|
---|
134 | #ifdef HAVE_TARGET_64_BIG
|
---|
135 | Object*
|
---|
136 | Target::do_make_elf_object(const std::string& name, Input_file* input_file,
|
---|
137 | off_t offset, const elfcpp::Ehdr<64, true>& ehdr)
|
---|
138 | {
|
---|
139 | return this->do_make_elf_object_implementation<64, true>(name, input_file,
|
---|
140 | offset, ehdr);
|
---|
141 | }
|
---|
142 | #endif
|
---|
143 |
|
---|
144 | Output_section*
|
---|
145 | Target::do_make_output_section(const char* name, elfcpp::Elf_Word type,
|
---|
146 | elfcpp::Elf_Xword flags)
|
---|
147 | {
|
---|
148 | return new Output_section(name, type, flags);
|
---|
149 | }
|
---|
150 |
|
---|
151 | // Default for whether a reloc is a call to a non-split function is
|
---|
152 | // whether the symbol is a function.
|
---|
153 |
|
---|
154 | bool
|
---|
155 | Target::do_is_call_to_non_split(const Symbol* sym, const unsigned char*,
|
---|
156 | const unsigned char*, section_size_type) const
|
---|
157 | {
|
---|
158 | return sym->type() == elfcpp::STT_FUNC;
|
---|
159 | }
|
---|
160 |
|
---|
161 | // Default conversion for -fsplit-stack is to give an error.
|
---|
162 |
|
---|
163 | void
|
---|
164 | Target::do_calls_non_split(Relobj* object, unsigned int, section_offset_type,
|
---|
165 | section_size_type, const unsigned char*, size_t,
|
---|
166 | unsigned char*, section_size_type,
|
---|
167 | std::string*, std::string*) const
|
---|
168 | {
|
---|
169 | static bool warned;
|
---|
170 | if (!warned)
|
---|
171 | {
|
---|
172 | gold_error(_("linker does not include stack split support "
|
---|
173 | "required by %s"),
|
---|
174 | object->name().c_str());
|
---|
175 | warned = true;
|
---|
176 | }
|
---|
177 | }
|
---|
178 |
|
---|
179 | // Return whether BYTES/LEN matches VIEW/VIEW_SIZE at OFFSET.
|
---|
180 |
|
---|
181 | bool
|
---|
182 | Target::match_view(const unsigned char* view, section_size_type view_size,
|
---|
183 | section_offset_type offset, const char* bytes,
|
---|
184 | size_t len) const
|
---|
185 | {
|
---|
186 | if (offset + len > view_size)
|
---|
187 | return false;
|
---|
188 | return memcmp(view + offset, bytes, len) == 0;
|
---|
189 | }
|
---|
190 |
|
---|
191 | // Set the contents of a VIEW/VIEW_SIZE to nops starting at OFFSET
|
---|
192 | // for LEN bytes.
|
---|
193 |
|
---|
194 | void
|
---|
195 | Target::set_view_to_nop(unsigned char* view, section_size_type view_size,
|
---|
196 | section_offset_type offset, size_t len) const
|
---|
197 | {
|
---|
198 | gold_assert(offset >= 0 && offset + len <= view_size);
|
---|
199 | if (!this->has_code_fill())
|
---|
200 | memset(view + offset, 0, len);
|
---|
201 | else
|
---|
202 | {
|
---|
203 | std::string fill = this->code_fill(len);
|
---|
204 | memcpy(view + offset, fill.data(), len);
|
---|
205 | }
|
---|
206 | }
|
---|
207 |
|
---|
208 | // Return address and size to plug into eh_frame FDEs associated with a PLT.
|
---|
209 | void
|
---|
210 | Target::do_plt_fde_location(const Output_data* plt, unsigned char*,
|
---|
211 | uint64_t* address, off_t* len) const
|
---|
212 | {
|
---|
213 | *address = plt->address();
|
---|
214 | *len = plt->data_size();
|
---|
215 | }
|
---|
216 |
|
---|
217 | // Class Sized_target.
|
---|
218 |
|
---|
219 | // Set the EI_OSABI field of the ELF header if requested.
|
---|
220 |
|
---|
221 | template<int size, bool big_endian>
|
---|
222 | void
|
---|
223 | Sized_target<size, big_endian>::do_adjust_elf_header(unsigned char* view,
|
---|
224 | int len)
|
---|
225 | {
|
---|
226 | elfcpp::ELFOSABI osabi = this->osabi();
|
---|
227 | if (osabi != elfcpp::ELFOSABI_NONE)
|
---|
228 | {
|
---|
229 | gold_assert(len == elfcpp::Elf_sizes<size>::ehdr_size);
|
---|
230 |
|
---|
231 | elfcpp::Ehdr<size, big_endian> ehdr(view);
|
---|
232 | unsigned char e_ident[elfcpp::EI_NIDENT];
|
---|
233 | memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT);
|
---|
234 |
|
---|
235 | e_ident[elfcpp::EI_OSABI] = osabi;
|
---|
236 |
|
---|
237 | elfcpp::Ehdr_write<size, big_endian> oehdr(view);
|
---|
238 | oehdr.put_e_ident(e_ident);
|
---|
239 | }
|
---|
240 | }
|
---|
241 |
|
---|
242 | #ifdef HAVE_TARGET_32_LITTLE
|
---|
243 | template
|
---|
244 | class Sized_target<32, false>;
|
---|
245 | #endif
|
---|
246 |
|
---|
247 | #ifdef HAVE_TARGET_32_BIG
|
---|
248 | template
|
---|
249 | class Sized_target<32, true>;
|
---|
250 | #endif
|
---|
251 |
|
---|
252 | #ifdef HAVE_TARGET_64_LITTLE
|
---|
253 | template
|
---|
254 | class Sized_target<64, false>;
|
---|
255 | #endif
|
---|
256 |
|
---|
257 | #ifdef HAVE_TARGET_64_BIG
|
---|
258 | template
|
---|
259 | class Sized_target<64, true>;
|
---|
260 | #endif
|
---|
261 |
|
---|
262 | } // End namespace gold.
|
---|