2 * Copyright (c) 2003 The Regents of The University of Michigan
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.
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.
31 #include "base/loader/elf_object.hh"
33 #include "mem/functional_mem/functional_memory.hh"
34 #include "base/loader/symtab.hh"
36 #include "base/trace.hh" // for DPRINTF
42 ElfObject::tryFile(const string
&fname
, int fd
, size_t len
, uint8_t *data
)
48 /* check that header matches library version */
49 assert(elf_version(EV_CURRENT
) != EV_NONE
);
51 /* get a pointer to elf structure */
52 elf
= elf_memory((char*)data
,len
);
53 /* will only fail if fd is invalid */
56 /* Check that we actually have a elf file */
57 if(gelf_getehdr(elf
, &ehdr
) ==0)
59 DPRINTFR(Loader
, "Not ELF\n");
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");
72 return new ElfObject(fname
, fd
, len
, data
,
73 ObjectFile::Alpha
, ObjectFile::Linux
);
78 ElfObject::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
)
88 /* check that header matches library version */
89 assert(elf_version(EV_CURRENT
) != EV_NONE
);
91 /* get a pointer to elf structure */
92 elf
= elf_memory((char*)fileData
,len
);
93 /* will only fail if fd is invalid */
96 /* Check that we actually have a elf file */
97 if(gelf_getehdr(elf
, &ehdr
) ==0)
99 panic("Not ELF, shouldn't be here");
103 entry
= ehdr
.e_entry
;
106 /* We will actually read the sections when we need to load them*/
111 ElfObject::loadSections(FunctionalMemory
*mem
, bool loadPhys
)
114 int sec_idx
= 1; /* there is a 0 but it is nothing, go figure*/
119 uint8_t *section_data
;
126 /* check that header matches library version */
127 assert(elf_version(EV_CURRENT
) != EV_NONE
);
130 /* get a pointer to elf structure */
131 elf
= elf_memory((char*)fileData
,len
);
135 /* Check that we actually have a elf file */
136 if(gelf_getehdr(elf
, &ehdr
) ==0)
138 panic("Not ELF, shouldn't be here");
143 /* Get the first section */
144 section
= elf_getscn(elf
, sec_idx
);
146 /* While there are no more sections */
147 while (section
!= NULL
)
149 gelf_getshdr(section
, &shdr
);
152 if (shdr
.sh_flags
& SHF_ALLOC
)
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
);
160 section_data
= fileData
+ shdr
.sh_offset
;
164 if (strcmp(sec_name
, ".text")==0)
166 text
.baseAddr
= shdr
.sh_addr
;
167 text
.size
= shdr
.sh_size
;
169 if (strcmp(sec_name
, ".data")==0)
171 data
.baseAddr
= shdr
.sh_addr
;
172 data
.size
= shdr
.sh_size
;
174 if (strcmp(sec_name
, ".bss")==0)
176 bss
.baseAddr
= shdr
.sh_addr
;
177 bss
.size
= shdr
.sh_size
;
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
;
187 if(shdr
.sh_size
!= 0)
191 address
= shdr
.sh_addr
&= (ULL(1) << 40) - 1;
192 mem
->prot_write(address
, section_data
, shdr
.sh_size
);
196 mem
->prot_write(shdr
.sh_addr
, section_data
, shdr
.sh_size
);
203 section
= elf_getscn(elf
, sec_idx
);
214 ElfObject::loadGlobalSymbols(SymbolTable
*symtab
)
217 int sec_idx
= 1; /* there is a 0 but it is nothing, go figure*/
228 /* check that header matches library version */
229 assert(elf_version(EV_CURRENT
) != EV_NONE
);
231 /* get a pointer to elf structure */
232 elf
= elf_memory((char*)fileData
,len
);
237 /* Get the first section */
238 section
= elf_getscn(elf
, sec_idx
);
240 /* While there are no more sections */
241 while (section
!= NULL
)
243 gelf_getshdr(section
, &shdr
);
246 if(shdr
.sh_type
== SHT_SYMTAB
)
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
);
253 /* loop through all the symbols, only loading global ones*/
254 for (ii
= 0; ii
< count
; ++ii
)
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
)))
260 symtab
->insert(sym
.st_value
, elf_strptr(elf
, shdr
.sh_link
, sym
.st_name
));
265 section
= elf_getscn(elf
, sec_idx
);
274 ElfObject::loadLocalSymbols(SymbolTable
*symtab
)
278 int sec_idx
= 1; /* there is a 0 but it is nothing, go figure*/
289 /* check that header matches library version */
290 assert(elf_version(EV_CURRENT
) != EV_NONE
);
292 /* get a pointer to elf structure */
293 elf
= elf_memory((char*)fileData
,len
);
298 /* Get the first section */
299 section
= elf_getscn(elf
, sec_idx
);
301 /* While there are no more sections */
302 while (section
!= NULL
)
304 gelf_getshdr(section
, &shdr
);
307 if(shdr
.sh_type
== SHT_SYMTAB
)
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
);
314 /* loop through all the symbols, only loading global ones*/
315 for (ii
= 0; ii
< count
; ++ii
)
317 gelf_getsym(data
, ii
, &sym
);
318 if (GELF_ST_BIND(sym
.st_info
) & STB_LOCAL
)
320 symtab
->insert(sym
.st_value
, elf_strptr(elf
, shdr
.sh_link
, sym
.st_name
));
325 section
= elf_getscn(elf
, sec_idx
);