elf_object.cc revision 454
1/* 2 * Copyright (c) 2003 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <string> 30 31#include "base/loader/elf_object.hh" 32 33#include "mem/functional_mem/functional_memory.hh" 34#include "base/loader/symtab.hh" 35 36#include "base/trace.hh" // for DPRINTF 37 38 39using namespace std; 40 41ObjectFile * 42ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) 43{ 44 Elf *elf; 45 GElf_Ehdr ehdr; 46 47 48 /* check that header matches library version */ 49 assert(elf_version(EV_CURRENT) != EV_NONE); 50 51 /* get a pointer to elf structure */ 52 elf = elf_memory((char*)data,len); 53 /* will only fail if fd is invalid */ 54 assert(elf != NULL); 55 56 /* Check that we actually have a elf file */ 57 if(gelf_getehdr(elf, &ehdr) ==0) 58 { 59 DPRINTFR(Loader, "Not ELF\n"); 60 elf_end(elf); 61 return NULL; 62 } 63 else 64 { 65 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 66 panic("32 bit ELF Binary, Not Supported"); 67 if (ehdr.e_machine != EM_ALPHA) 68 panic("Non Alpha Binary, Not Supported"); 69 70 elf_end(elf); 71 72 return new ElfObject(fname, fd, len, data, 73 ObjectFile::Alpha, ObjectFile::Linux); 74 } 75} 76 77 78ElfObject::ElfObject(const string &_filename, int _fd, 79 size_t _len, uint8_t *_data, 80 Arch _arch, OpSys _opSys) 81 : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys) 82 83{ 84 85 Elf *elf; 86 GElf_Ehdr ehdr; 87 88 /* check that header matches library version */ 89 assert(elf_version(EV_CURRENT) != EV_NONE); 90 91 /* get a pointer to elf structure */ 92 elf = elf_memory((char*)fileData,len); 93 /* will only fail if fd is invalid */ 94 assert(elf != NULL); 95 96 /* Check that we actually have a elf file */ 97 if(gelf_getehdr(elf, &ehdr) ==0) 98 { 99 panic("Not ELF, shouldn't be here"); 100 } 101 102 103 entry = ehdr.e_entry; 104 elf_end(elf); 105 106 /* We will actually read the sections when we need to load them*/ 107} 108 109 110bool 111ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys) 112{ 113 Elf *elf; 114 int sec_idx = 1; /* there is a 0 but it is nothing, go figure*/ 115 Elf_Scn *section; 116 GElf_Shdr shdr; 117 GElf_Ehdr ehdr; 118 uint8_t *zero_mem; 119 uint8_t *section_data; 120 121 Addr address; 122 char *sec_name; 123 124 125 126 /* check that header matches library version */ 127 assert(elf_version(EV_CURRENT) != EV_NONE); 128 129 130 /* get a pointer to elf structure */ 131 elf = elf_memory((char*)fileData,len); 132 133 assert(elf != NULL); 134 135 /* Check that we actually have a elf file */ 136 if(gelf_getehdr(elf, &ehdr) ==0) 137 { 138 panic("Not ELF, shouldn't be here"); 139 } 140 141 142 143 /* Get the first section */ 144 section = elf_getscn(elf, sec_idx); 145 146 /* While there are no more sections */ 147 while (section != NULL) 148 { 149 gelf_getshdr(section, &shdr); 150 151 152 if (shdr.sh_flags & SHF_ALLOC) 153 { 154 /* we should load this */ 155 DPRINTF(Loader,"Name: %20s Address: 0x%016llx Size: 0x%08llx Offset: 0x%08llx Flags:0x%08llx %s\n", 156 elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name), shdr.sh_addr, 157 shdr.sh_size, shdr.sh_offset, shdr.sh_flags, shdr.sh_flags & SHF_ALLOC ? "ALLOC" : ""); 158 sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 159 160 section_data = fileData + shdr.sh_offset; 161 162 if(sec_name) 163 { 164 if (strcmp(sec_name, ".text")==0) 165 { 166 text.baseAddr = shdr.sh_addr; 167 text.size = shdr.sh_size; 168 } 169 if (strcmp(sec_name, ".data")==0) 170 { 171 data.baseAddr = shdr.sh_addr; 172 data.size = shdr.sh_size; 173 } 174 if (strcmp(sec_name, ".bss")==0) 175 { 176 bss.baseAddr = shdr.sh_addr; 177 bss.size = shdr.sh_size; 178 179 /* If this is the .bss section it must be 0, so just 180 to be extra causious, lets allocate some memory 181 bzero it, and write that */ 182 zero_mem = (uint8_t*)malloc(shdr.sh_size); 183 memset(zero_mem, 0, shdr.sh_size); 184 section_data = zero_mem; 185 } 186 } 187 if(shdr.sh_size != 0) 188 { 189 if (loadPhys) 190 { 191 address = shdr.sh_addr &= (ULL(1) << 40) - 1; 192 mem->prot_write(address, section_data, shdr.sh_size); 193 } 194 else 195 { 196 mem->prot_write(shdr.sh_addr, section_data, shdr.sh_size); 197 } 198 } 199 200 } 201 202 ++sec_idx; 203 section = elf_getscn(elf, sec_idx); 204 } 205 free(zero_mem); 206 207 elf_end(elf); 208 209 return true; 210} 211 212 213bool 214ElfObject::loadGlobalSymbols(SymbolTable *symtab) 215{ 216 Elf *elf; 217 int sec_idx = 1; /* there is a 0 but it is nothing, go figure*/ 218 Elf_Scn *section; 219 GElf_Shdr shdr; 220 Elf_Data *data; 221 int count, ii; 222 bool found = false; 223 GElf_Sym sym; 224 225 if (!symtab) 226 return false; 227 228 /* check that header matches library version */ 229 assert(elf_version(EV_CURRENT) != EV_NONE); 230 231 /* get a pointer to elf structure */ 232 elf = elf_memory((char*)fileData,len); 233 234 assert(elf != NULL); 235 236 237 /* Get the first section */ 238 section = elf_getscn(elf, sec_idx); 239 240 /* While there are no more sections */ 241 while (section != NULL) 242 { 243 gelf_getshdr(section, &shdr); 244 245 246 if(shdr.sh_type == SHT_SYMTAB) 247 { 248 found = true; 249 data = elf_getdata(section, NULL); 250 count = shdr.sh_size / shdr.sh_entsize; 251 DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 252 253 /* loop through all the symbols, only loading global ones*/ 254 for (ii = 0; ii < count; ++ii) 255 { 256 gelf_getsym(data, ii, &sym); 257 if ((GELF_ST_BIND(sym.st_info) & STB_GLOBAL) && 258 ((GELF_ST_TYPE(sym.st_info) == STT_FUNC) || (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE))) 259 { 260 symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name)); 261 } 262 } 263 } 264 ++sec_idx; 265 section = elf_getscn(elf, sec_idx); 266 } 267 268 elf_end(elf); 269 270 return found; 271} 272 273bool 274ElfObject::loadLocalSymbols(SymbolTable *symtab) 275{ 276 277 Elf *elf; 278 int sec_idx = 1; /* there is a 0 but it is nothing, go figure*/ 279 Elf_Scn *section; 280 GElf_Shdr shdr; 281 Elf_Data *data; 282 int count, ii; 283 bool found = false; 284 GElf_Sym sym; 285 286 if (!symtab) 287 return false; 288 289 /* check that header matches library version */ 290 assert(elf_version(EV_CURRENT) != EV_NONE); 291 292 /* get a pointer to elf structure */ 293 elf = elf_memory((char*)fileData,len); 294 295 assert(elf != NULL); 296 297 298 /* Get the first section */ 299 section = elf_getscn(elf, sec_idx); 300 301 /* While there are no more sections */ 302 while (section != NULL) 303 { 304 gelf_getshdr(section, &shdr); 305 306 307 if(shdr.sh_type == SHT_SYMTAB) 308 { 309 found = true; 310 data = elf_getdata(section, NULL); 311 count = shdr.sh_size / shdr.sh_entsize; 312 DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 313 314 /* loop through all the symbols, only loading global ones*/ 315 for (ii = 0; ii < count; ++ii) 316 { 317 gelf_getsym(data, ii, &sym); 318 if (GELF_ST_BIND(sym.st_info) & STB_LOCAL) 319 { 320 symtab->insert(sym.st_value, elf_strptr(elf, shdr.sh_link, sym.st_name)); 321 } 322 } 323 } 324 ++sec_idx; 325 section = elf_getscn(elf, sec_idx); 326 } 327 328 elf_end(elf); 329 330 return found; 331} 332