summaryrefslogtreecommitdiff
path: root/src/base/loader/elf_object.cc
diff options
context:
space:
mode:
authorBrandon Potter <brandon.potter@amd.com>2016-03-17 10:34:27 -0700
committerBrandon Potter <brandon.potter@amd.com>2016-03-17 10:34:27 -0700
commit4a9dd1feb846e015303196ad5274a829a7c18525 (patch)
tree8822d5eb77832ca8986ddbfe145b593de32783cc /src/base/loader/elf_object.cc
parentde8077763e4d3f5b218d98eb9cf772a115725bf4 (diff)
downloadgem5-4a9dd1feb846e015303196ad5274a829a7c18525.tar.xz
base: add symbol support for dynamic libraries
Libraries are loaded into the process address space using the mmap system call. Conveniently, this happens to be a good time to update the process symbol table with the library's incoming symbols so we handle the table update from within the system call. This works just like an application's normal symbols. The only difference between a dynamic library and a main executable is when the symbol table update occurs. The symbol table update for an executable happens at program load time and is finished before the process ever begins executing. Since dynamic linking happens at runtime, the symbol loading happens after the library is first loaded into the process address space. The library binary is examined at this time for a symbol section and that section is parsed for symbol types with specific bindings (global, local, weak). Subsequently, these symbols are added to the table and are available for use by gem5 for things like trace generation. Checkpointing should work just as it did previously. The address space (and therefore the library) will be recorded and the symbol table will be entirely recorded. (It's not possible to do anything clever like checkpoint a program and then load the program back with different libraries with LD_LIBRARY_PATH, because the library becomes part of the address space after being loaded.)
Diffstat (limited to 'src/base/loader/elf_object.cc')
-rw-r--r--src/base/loader/elf_object.cc49
1 files changed, 37 insertions, 12 deletions
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
index fb5ec4c14..73c1c5dcd 100644
--- a/src/base/loader/elf_object.cc
+++ b/src/base/loader/elf_object.cc
@@ -396,7 +396,8 @@ ElfObject::ElfObject(const std::string &_filename, size_t _len,
bool
-ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask)
+ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask,
+ Addr base, Addr offset)
{
if (!symtab)
return false;
@@ -432,9 +433,11 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask)
if (GELF_ST_BIND(sym.st_info) == binding) {
char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
if (sym_name && sym_name[0] != '$') {
- DPRINTF(Loader, "Symbol: %-40s value %#x\n",
- sym_name, sym.st_value);
- symtab->insert(sym.st_value & mask, sym_name);
+ Addr value = sym.st_value - base + offset;
+ if (symtab->insert(value & mask, sym_name)) {
+ DPRINTF(Loader, "Symbol: %-40s value %#x\n",
+ sym_name, value);
+ }
}
}
}
@@ -449,23 +452,45 @@ ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask)
}
bool
-ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addr_mask)
+ElfObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset,
+ Addr addr_mask)
{
- return loadSomeSymbols(symtab, STB_GLOBAL, addr_mask);
+ return (loadGlobalSymbols(symtab, base, offset, addr_mask) &&
+ loadLocalSymbols(symtab, base, offset, addr_mask) &&
+ loadWeakSymbols(symtab, base, offset, addr_mask));
}
bool
-ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addr_mask)
+ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset,
+ Addr addr_mask)
{
- bool found_local = loadSomeSymbols(symtab, STB_LOCAL, addr_mask);
- bool found_weak = loadSomeSymbols(symtab, STB_WEAK, addr_mask);
- return found_local || found_weak;
+ if (interpreter) {
+ interpreter->loadSomeSymbols(symtab, STB_GLOBAL, addr_mask,
+ base, offset);
+ }
+ return loadSomeSymbols(symtab, STB_GLOBAL, addr_mask, base, offset);
}
bool
-ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr addr_mask)
+ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset,
+ Addr addr_mask)
{
- return loadSomeSymbols(symtab, STB_WEAK, addr_mask);
+ if (interpreter) {
+ interpreter->loadSomeSymbols(symtab, STB_LOCAL, addr_mask,
+ base, offset);
+ }
+ return loadSomeSymbols(symtab, STB_LOCAL, addr_mask, base, offset);
+}
+
+bool
+ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr base, Addr offset,
+ Addr addr_mask)
+{
+ if (interpreter) {
+ interpreter->loadSomeSymbols(symtab, STB_WEAK, addr_mask,
+ base, offset);
+ }
+ return loadSomeSymbols(symtab, STB_WEAK, addr_mask, base, offset);
}
bool