arch-power: Add multi-mode support
[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 determineByteOrder();
116
117 entry = ehdr.e_entry;
118 _programHeaderCount = ehdr.e_phnum;
119 _programHeaderSize = ehdr.e_phentsize;
120
121 // Go through all the segments in the program and record them.
122 for (int i = 0; i < ehdr.e_phnum; ++i) {
123 GElf_Phdr phdr;
124 if (gelf_getphdr(elf, i, &phdr) == 0) {
125 panic("gelf_getphdr failed for segment %d.", i);
126 }
127
128 if (phdr.p_type == PT_LOAD)
129 handleLoadableSegment(phdr, i);
130 if (phdr.p_type == PT_INTERP) {
131 // Make sure the interpreter is an valid ELF file.
132 auto interp_path = getInterpPath(phdr);
133 ObjectFile *obj = createObjectFile(interp_path);
134 interpreter = dynamic_cast<ElfObject *>(obj);
135 assert(interpreter != nullptr);
136 _symtab.insert(obj->symtab());
137 }
138 }
139
140 // should have found at least one loadable segment
141 warn_if(image.segments().empty(),
142 "No loadable segments in '%s'. ELF file corrupted?\n",
143 imageData->filename());
144
145 for (M5_VAR_USED auto &seg: image.segments())
146 DPRINTFR(Loader, "%s\n", seg);
147
148 // We will actually read the sections when we need to load them
149
150 // check that header matches library version
151 if (elf_version(EV_CURRENT) == EV_NONE)
152 panic("wrong elf version number!");
153
154 // Get the first section
155 int sec_idx = 1; // there is a 0 but it is nothing, go figure
156 Elf_Scn *section = elf_getscn(elf, sec_idx);
157
158 // While there are no more sections
159 while (section) {
160 GElf_Shdr shdr;
161 gelf_getshdr(section, &shdr);
162
163 if (shdr.sh_type == SHT_SYMTAB) {
164 Elf_Data *data = elf_getdata(section, nullptr);
165 int count = shdr.sh_size / shdr.sh_entsize;
166 DPRINTF(Loader, "Found Symbol Table, %d symbols present.", count);
167
168 // Loop through all the symbols.
169 for (int i = 0; i < count; ++i) {
170 GElf_Sym sym;
171 gelf_getsym(data, i, &sym);
172
173 char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
174 if (!sym_name || sym_name[0] == '$')
175 continue;
176
177 Loader::Symbol symbol;
178 symbol.address = sym.st_value;
179 symbol.name = sym_name;
180
181 switch (GELF_ST_BIND(sym.st_info)) {
182 case STB_GLOBAL:
183 symbol.binding = Loader::Symbol::Binding::Global;
184 break;
185 case STB_LOCAL:
186 symbol.binding = Loader::Symbol::Binding::Local;
187 break;
188 case STB_WEAK:
189 symbol.binding = Loader::Symbol::Binding::Weak;
190 break;
191 default:
192 continue;
193 }
194
195 if (_symtab.insert(symbol)) {
196 DPRINTF(Loader, "Symbol: %-40s value %#x.\n",
197 symbol.name, symbol.address);
198 }
199 }
200 }
201 ++sec_idx;
202 section = elf_getscn(elf, sec_idx);
203 }
204 }
205
206 std::string
207 ElfObject::getInterpPath(const GElf_Phdr &phdr) const
208 {
209 // This is the interpreter path as specified in the elf file
210 const std::string elf_path = (char *)imageData->data() + phdr.p_offset;
211 if (!interpDir.empty())
212 return interpDir + elf_path;
213 else
214 return elf_path;
215 }
216
217 void
218 ElfObject::determineArch()
219 {
220 auto &emach = ehdr.e_machine;
221 auto &eclass = ehdr.e_ident[EI_CLASS];
222 auto &edata = ehdr.e_ident[EI_DATA];
223
224 // Detect the architecture
225 if (emach == EM_SPARC64 || (emach == EM_SPARC && eclass == ELFCLASS64) ||
226 emach == EM_SPARCV9) {
227 arch = SPARC64;
228 } else if (emach == EM_SPARC32PLUS ||
229 (emach == EM_SPARC && eclass == ELFCLASS32)) {
230 arch = SPARC32;
231 } else if (emach == EM_MIPS && eclass == ELFCLASS32) {
232 arch = Mips;
233 if (edata != ELFDATA2LSB) {
234 fatal("The binary you're trying to load is compiled for big "
235 "endian MIPS. gem5\nonly supports little endian MIPS. "
236 "Please recompile your binary.\n");
237 }
238 } else if (emach == EM_X86_64 && eclass == ELFCLASS64) {
239 arch = X86_64;
240 } else if (emach == EM_386 && eclass == ELFCLASS32) {
241 arch = I386;
242 } else if (emach == EM_ARM && eclass == ELFCLASS32) {
243 arch = bits(ehdr.e_entry, 0) ? Thumb : Arm;
244 } else if (emach == EM_AARCH64 && eclass == ELFCLASS64) {
245 arch = Arm64;
246 } else if (emach == EM_RISCV) {
247 arch = (eclass == ELFCLASS64) ? Riscv64 : Riscv32;
248 } else if (emach == EM_PPC && eclass == ELFCLASS32) {
249 arch = Power;
250 } else if (emach == EM_PPC64 && eclass == ELFCLASS64) {
251 arch = Power64;
252 } else {
253 warn("Unknown architecture: %d\n", emach);
254 }
255 }
256
257 void
258 ElfObject::determineOpSys()
259 {
260 // For 64-bit Power, EI_OSABI and EI_ABIVERSION cannot be used to
261 // determine the ABI version used by the ELF object
262 if (ehdr.e_machine == EM_PPC64) {
263 switch (ehdr.e_flags & 0x3) {
264 case 0x1: opSys = LinuxPower64ABIv1; return;
265 case 0x2: opSys = LinuxPower64ABIv2; return;
266 default:
267 if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
268 opSys = LinuxPower64ABIv1;
269 if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
270 opSys = LinuxPower64ABIv2;
271 return;
272 }
273 }
274
275 // Detect the operating system
276 switch (ehdr.e_ident[EI_OSABI]) {
277 case ELFOSABI_LINUX:
278 opSys = Linux;
279 return;
280 case ELFOSABI_SOLARIS:
281 opSys = Solaris;
282 return;
283 case ELFOSABI_TRU64:
284 opSys = Tru64;
285 return;
286 case ELFOSABI_ARM:
287 opSys = LinuxArmOABI;
288 return;
289 case ELFOSABI_FREEBSD:
290 opSys = FreeBSD;
291 return;
292 default:
293 opSys = UnknownOpSys;
294 }
295
296 Elf_Scn *section = elf_getscn(elf, 1);
297 for (int sec_idx = 1; section; section = elf_getscn(elf, ++sec_idx)) {
298 GElf_Shdr shdr;
299 gelf_getshdr(section, &shdr);
300
301 char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
302 if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", e_str)) {
303 // we have found a ABI note section
304 // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
305 // 2 == solaris, 3 == freebsd
306 Elf_Data *raw_data = elf_rawdata(section, nullptr);
307 assert(raw_data && raw_data->d_buf);
308
309 uint32_t raw_abi = ((uint32_t *)raw_data->d_buf)[4];
310 bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB;
311 uint32_t os_abi = is_le ? htole(raw_abi) : htobe(raw_abi);
312
313 switch (os_abi) {
314 case 0:
315 opSys = Linux;
316 return;
317 case 1:
318 fatal("gem5 does not support the HURD ABI.\n");
319 case 2:
320 opSys = Solaris;
321 return;
322 case 3:
323 opSys = FreeBSD;
324 return;
325 }
326 }
327
328 if (!strcmp(".SUNW_version", e_str) || !strcmp(".stab.index", e_str)) {
329 opSys = Solaris;
330 return;
331 }
332 }
333 }
334
335 void
336 ElfObject::determineByteOrder()
337 {
338 auto edata = ehdr.e_ident[EI_DATA];
339 if (edata == ELFDATANONE)
340 panic("invalid ELF data encoding");
341 byteOrder = (edata == ELFDATA2MSB) ? ByteOrder::big : ByteOrder::little;
342 }
343
344 void
345 ElfObject::handleLoadableSegment(GElf_Phdr phdr, int seg_num)
346 {
347 auto name = std::to_string(seg_num);
348
349 if (phdr.p_memsz == 0) {
350 warn("Ignoring empty loadable segment %s", name);
351 return;
352 }
353
354 image.addSegment({ name, phdr.p_paddr, imageData,
355 phdr.p_offset, phdr.p_filesz });
356 Addr uninitialized = phdr.p_memsz - phdr.p_filesz;
357 if (uninitialized) {
358 // There may be parts of a segment which aren't included in the
359 // file. In those cases, we need to create a new segment with no
360 // data to take up the extra space. This should be zeroed when
361 // loaded into memory.
362 image.addSegment({ name + "(uninitialized)",
363 phdr.p_paddr + phdr.p_filesz, uninitialized });
364 }
365
366 const Addr file_start = phdr.p_offset;
367 const Addr file_end = file_start + phdr.p_filesz;
368
369 // If there is a program header table, figure out the virtual
370 // address of the header table in the final memory image. We use
371 // the program headers themselves to translate from a file offset
372 // to the address in the image.
373 if (file_start <= ehdr.e_phoff && file_end > ehdr.e_phoff)
374 _programHeaderTable = phdr.p_vaddr + (ehdr.e_phoff - file_start);
375 }
376
377 ElfObject::~ElfObject()
378 {
379 elf_end(elf);
380 }
381
382 void
383 ElfObject::getSections()
384 {
385 assert(!sectionNames.size());
386
387 // check that header matches library version
388 if (elf_version(EV_CURRENT) == EV_NONE)
389 panic("wrong elf version number!");
390
391 // get a pointer to elf structure
392 Elf *elf =
393 elf_memory((char *)const_cast<uint8_t *>(imageData->data()),
394 imageData->len());
395 assert(elf != NULL);
396
397 // Check that we actually have a elf file
398 GElf_Ehdr ehdr;
399 if (gelf_getehdr(elf, &ehdr) ==0) {
400 panic("Not ELF, shouldn't be here");
401 }
402
403 // Get the first section
404 int sec_idx = 1; // there is a 0 but it is nothing, go figure
405 Elf_Scn *section = elf_getscn(elf, sec_idx);
406
407 // While there are no more sections
408 while (section) {
409 GElf_Shdr shdr;
410 gelf_getshdr(section, &shdr);
411 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
412 section = elf_getscn(elf, ++sec_idx);
413 } // while sections
414
415 elf_end(elf);
416 }
417
418 bool
419 ElfObject::sectionExists(std::string sec)
420 {
421 if (!sectionNames.size())
422 getSections();
423
424 return sectionNames.find(sec) != sectionNames.end();
425 }
426
427
428 void
429 ElfObject::updateBias(Addr bias_addr)
430 {
431 // Record the bias.
432 ldBias = bias_addr;
433
434 // Patch the entry point with bias_addr.
435 entry += bias_addr;
436
437 // Patch segments with the bias_addr.
438 image.offset(bias_addr);
439 }
440
441 } // namespace Loader