tests: log_call is not returning any value
[gem5.git] / src / base / loader / elf_object.cc
1 /*
2 * Copyright (c) 2011-2013, 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include "base/loader/elf_object.hh"
42
43 #include <fcntl.h>
44 #include <sys/mman.h>
45 #include <sys/stat.h>
46 #include <sys/types.h>
47 #include <unistd.h>
48
49 #include <cassert>
50 #include <string>
51
52 #include "base/bitfield.hh"
53 #include "base/loader/symtab.hh"
54 #include "base/logging.hh"
55 #include "base/trace.hh"
56 #include "debug/Loader.hh"
57 #include "gelf.h"
58 #include "sim/byteswap.hh"
59
60 namespace Loader
61 {
62
63 ObjectFile *
64 ElfObjectFormat::load(ImageFileDataPtr ifd)
65 {
66 // check that header matches library version
67 if (elf_version(EV_CURRENT) == EV_NONE)
68 panic("wrong elf version number!");
69
70 ObjectFile *object = nullptr;
71
72 // get a pointer to elf structure
73 // Check that we actually have a elf file
74 Elf *elf =
75 elf_memory((char *)const_cast<uint8_t *>(ifd->data()), ifd->len());
76 assert(elf);
77
78 GElf_Ehdr ehdr;
79 if (gelf_getehdr(elf, &ehdr) == 0)
80 DPRINTFR(Loader, "Not ELF\n");
81 else
82 object = new ElfObject(ifd);
83
84 elf_end(elf);
85
86 return object;
87 }
88
89 namespace
90 {
91
92 ElfObjectFormat elfObjectFormat;
93 std::string interpDir;
94
95 } // anonymous namespace
96
97 void
98 setInterpDir(const std::string &dirname)
99 {
100 fatal_if(!interpDir.empty(),
101 "Error: setInterpDir has already been called once\n");
102 interpDir = dirname;
103 }
104
105 ElfObject::ElfObject(ImageFileDataPtr ifd) : ObjectFile(ifd)
106 {
107 // get a pointer to elf structure
108 elf = elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
109 imageData->len());
110 assert(elf);
111 gelf_getehdr(elf, &ehdr);
112
113 determineArch();
114 determineOpSys();
115
116 entry = ehdr.e_entry;
117 _programHeaderCount = ehdr.e_phnum;
118 _programHeaderSize = ehdr.e_phentsize;
119
120 // Go through all the segments in the program and record them.
121 for (int i = 0; i < ehdr.e_phnum; ++i) {
122 GElf_Phdr phdr;
123 if (gelf_getphdr(elf, i, &phdr) == 0) {
124 panic("gelf_getphdr failed for segment %d.", i);
125 }
126
127 if (phdr.p_type == PT_LOAD)
128 handleLoadableSegment(phdr, i);
129 if (phdr.p_type == PT_INTERP) {
130 // Make sure the interpreter is an valid ELF file.
131 auto interp_path = getInterpPath(phdr);
132 ObjectFile *obj = createObjectFile(interp_path);
133 interpreter = dynamic_cast<ElfObject *>(obj);
134 assert(interpreter != nullptr);
135 _symtab.insert(obj->symtab());
136 }
137 }
138
139 // should have found at least one loadable segment
140 warn_if(image.segments().empty(),
141 "No loadable segments in '%s'. ELF file corrupted?\n",
142 imageData->filename());
143
144 for (auto M5_VAR_USED &seg: image.segments())
145 DPRINTFR(Loader, "%s\n", seg);
146
147 // We will actually read the sections when we need to load them
148
149 // check that header matches library version
150 if (elf_version(EV_CURRENT) == EV_NONE)
151 panic("wrong elf version number!");
152
153 // Get the first section
154 int sec_idx = 1; // there is a 0 but it is nothing, go figure
155 Elf_Scn *section = elf_getscn(elf, sec_idx);
156
157 // While there are no more sections
158 while (section) {
159 GElf_Shdr shdr;
160 gelf_getshdr(section, &shdr);
161
162 if (shdr.sh_type == SHT_SYMTAB) {
163 Elf_Data *data = elf_getdata(section, nullptr);
164 int count = shdr.sh_size / shdr.sh_entsize;
165 DPRINTF(Loader, "Found Symbol Table, %d symbols present.", count);
166
167 // Loop through all the symbols.
168 for (int i = 0; i < count; ++i) {
169 GElf_Sym sym;
170 gelf_getsym(data, i, &sym);
171
172 char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
173 if (!sym_name || sym_name[0] == '$')
174 continue;
175
176 Loader::Symbol symbol;
177 symbol.address = sym.st_value;
178 symbol.name = sym_name;
179
180 switch (GELF_ST_BIND(sym.st_info)) {
181 case STB_GLOBAL:
182 symbol.binding = Loader::Symbol::Binding::Global;
183 break;
184 case STB_LOCAL:
185 symbol.binding = Loader::Symbol::Binding::Local;
186 break;
187 case STB_WEAK:
188 symbol.binding = Loader::Symbol::Binding::Weak;
189 break;
190 default:
191 continue;
192 }
193
194 if (_symtab.insert(symbol)) {
195 DPRINTF(Loader, "Symbol: %-40s value %#x.\n",
196 symbol.name, symbol.address);
197 }
198 }
199 }
200 ++sec_idx;
201 section = elf_getscn(elf, sec_idx);
202 }
203 }
204
205 std::string
206 ElfObject::getInterpPath(const GElf_Phdr &phdr) const
207 {
208 // This is the interpreter path as specified in the elf file
209 const std::string elf_path = (char *)imageData->data() + phdr.p_offset;
210 if (!interpDir.empty())
211 return interpDir + elf_path;
212 else
213 return elf_path;
214 }
215
216 void
217 ElfObject::determineArch()
218 {
219 auto &emach = ehdr.e_machine;
220 auto &eclass = ehdr.e_ident[EI_CLASS];
221 auto &edata = ehdr.e_ident[EI_DATA];
222
223 // Detect the architecture
224 if (emach == EM_SPARC64 || (emach == EM_SPARC && eclass == ELFCLASS64) ||
225 emach == EM_SPARCV9) {
226 arch = SPARC64;
227 } else if (emach == EM_SPARC32PLUS ||
228 (emach == EM_SPARC && eclass == ELFCLASS32)) {
229 arch = SPARC32;
230 } else if (emach == EM_MIPS && eclass == ELFCLASS32) {
231 arch = Mips;
232 if (edata != ELFDATA2LSB) {
233 fatal("The binary you're trying to load is compiled for big "
234 "endian MIPS. gem5\nonly supports little endian MIPS. "
235 "Please recompile your binary.\n");
236 }
237 } else if (emach == EM_X86_64 && eclass == ELFCLASS64) {
238 arch = X86_64;
239 } else if (emach == EM_386 && eclass == ELFCLASS32) {
240 arch = I386;
241 } else if (emach == EM_ARM && eclass == ELFCLASS32) {
242 arch = bits(ehdr.e_entry, 0) ? Thumb : Arm;
243 } else if (emach == EM_AARCH64 && eclass == ELFCLASS64) {
244 arch = Arm64;
245 } else if (emach == EM_RISCV) {
246 arch = (eclass == ELFCLASS64) ? Riscv64 : Riscv32;
247 } else if (emach == EM_PPC && eclass == ELFCLASS32) {
248 arch = Power;
249 if (edata != ELFDATA2MSB) {
250 fatal("The binary you're trying to load is compiled for "
251 "little endian Power.\ngem5 only supports big "
252 "endian Power. Please recompile your binary.\n");
253 }
254 } else if (emach == EM_PPC64) {
255 fatal("The binary you're trying to load is compiled for 64-bit "
256 "Power. M5\n only supports 32-bit Power. Please "
257 "recompile your binary.\n");
258 } else {
259 warn("Unknown architecture: %d\n", emach);
260 }
261 }
262
263 void
264 ElfObject::determineOpSys()
265 {
266 // Detect the operating system
267 switch (ehdr.e_ident[EI_OSABI]) {
268 case ELFOSABI_LINUX:
269 opSys = Linux;
270 return;
271 case ELFOSABI_SOLARIS:
272 opSys = Solaris;
273 return;
274 case ELFOSABI_TRU64:
275 opSys = Tru64;
276 return;
277 case ELFOSABI_ARM:
278 opSys = LinuxArmOABI;
279 return;
280 case ELFOSABI_FREEBSD:
281 opSys = FreeBSD;
282 return;
283 default:
284 opSys = UnknownOpSys;
285 }
286
287 Elf_Scn *section = elf_getscn(elf, 1);
288 for (int sec_idx = 1; section; section = elf_getscn(elf, ++sec_idx)) {
289 GElf_Shdr shdr;
290 gelf_getshdr(section, &shdr);
291
292 char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
293 if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", e_str)) {
294 // we have found a ABI note section
295 // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
296 // 2 == solaris, 3 == freebsd
297 Elf_Data *raw_data = elf_rawdata(section, nullptr);
298 assert(raw_data && raw_data->d_buf);
299
300 uint32_t raw_abi = ((uint32_t *)raw_data->d_buf)[4];
301 bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
302 uint32_t os_abi = is_le ? htole(raw_abi) : htobe(raw_abi);
303
304 switch (os_abi) {
305 case 0:
306 opSys = Linux;
307 return;
308 case 1:
309 fatal("gem5 does not support the HURD ABI.\n");
310 case 2:
311 opSys = Solaris;
312 return;
313 case 3:
314 opSys = FreeBSD;
315 return;
316 }
317 }
318
319 if (!strcmp(".SUNW_version", e_str) || !strcmp(".stab.index", e_str)) {
320 opSys = Solaris;
321 return;
322 }
323 }
324 }
325
326 void
327 ElfObject::handleLoadableSegment(GElf_Phdr phdr, int seg_num)
328 {
329 auto name = std::to_string(seg_num);
330
331 image.addSegment({ name, phdr.p_paddr, imageData,
332 phdr.p_offset, phdr.p_filesz });
333 Addr uninitialized = phdr.p_memsz - phdr.p_filesz;
334 if (uninitialized) {
335 // There may be parts of a segment which aren't included in the
336 // file. In those cases, we need to create a new segment with no
337 // data to take up the extra space. This should be zeroed when
338 // loaded into memory.
339 image.addSegment({ name + "(uninitialized)",
340 phdr.p_paddr + phdr.p_filesz, uninitialized });
341 }
342
343 const Addr file_start = phdr.p_offset;
344 const Addr file_end = file_start + phdr.p_filesz;
345
346 // If there is a program header table, figure out the virtual
347 // address of the header table in the final memory image. We use
348 // the program headers themselves to translate from a file offset
349 // to the address in the image.
350 if (file_start <= ehdr.e_phoff && file_end > ehdr.e_phoff)
351 _programHeaderTable = phdr.p_vaddr + (ehdr.e_phoff - file_start);
352 }
353
354 ElfObject::~ElfObject()
355 {
356 elf_end(elf);
357 }
358
359 void
360 ElfObject::getSections()
361 {
362 assert(!sectionNames.size());
363
364 // check that header matches library version
365 if (elf_version(EV_CURRENT) == EV_NONE)
366 panic("wrong elf version number!");
367
368 // get a pointer to elf structure
369 Elf *elf =
370 elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
371 imageData->len());
372 assert(elf != NULL);
373
374 // Check that we actually have a elf file
375 GElf_Ehdr ehdr;
376 if (gelf_getehdr(elf, &ehdr) ==0) {
377 panic("Not ELF, shouldn't be here");
378 }
379
380 // Get the first section
381 int sec_idx = 1; // there is a 0 but it is nothing, go figure
382 Elf_Scn *section = elf_getscn(elf, sec_idx);
383
384 // While there are no more sections
385 while (section) {
386 GElf_Shdr shdr;
387 gelf_getshdr(section, &shdr);
388 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
389 section = elf_getscn(elf, ++sec_idx);
390 } // while sections
391
392 elf_end(elf);
393 }
394
395 bool
396 ElfObject::sectionExists(std::string sec)
397 {
398 if (!sectionNames.size())
399 getSections();
400
401 return sectionNames.find(sec) != sectionNames.end();
402 }
403
404
405 void
406 ElfObject::updateBias(Addr bias_addr)
407 {
408 // Record the bias.
409 ldBias = bias_addr;
410
411 // Patch the entry point with bias_addr.
412 entry += bias_addr;
413
414 // Patch segments with the bias_addr.
415 image.offset(bias_addr);
416 }
417
418 } // namespace Loader