37 #define PACKED __attribute__((packed)) 50 typedef void (*entry_point_t)(
const char *[],
char **);
51 typedef void (*init_fini_func_t)();
63 : filename(), path(), entry(0), mapped_file(0), mapped_file_sz(0),
64 relocated(
false), load_base(0), running(
false), debug(
false),
65 memory_regions(), phdrs(0), num_phdrs(0), shdrs(0), num_shdrs(0),
66 sh_symtab(0), sh_strtab(0), symtab(0), strtab(0), sh_shstrtab(0),
67 shstrtab(0), ph_dynamic(0), needed(0), dyn_symtab(0), dyn_strtab(0),
68 dyn_strtab_sz(0), rela(0), rel(0), rela_sz(0), rel_sz(0),
69 uses_rela(
false), got(0), plt_rela(0), plt_rel(0), init_func(0),
70 fini_func(0), plt_sz(0), hash(0), hash_buckets(0), hash_chains(0),
71 preloads(), objects(), parent(0)
79 const void *mapped_file;
80 size_t mapped_file_sz;
89 std::list<std::pair<void *, size_t>> memory_regions;
91 ElfProgramHeader_t *phdrs;
104 const char *shstrtab;
106 ElfProgramHeader_t *ph_dynamic;
108 std::list<std::string> needed;
111 const char *dyn_strtab;
112 size_t dyn_strtab_sz;
131 const ElfHash_t *hash;
132 const Elf_Word *hash_buckets;
133 const Elf_Word *hash_chains;
135 std::list<struct _object_meta *> preloads;
136 std::list<struct _object_meta *> objects;
138 struct _object_meta *parent;
141 #define IS_NOT_PAGE_ALIGNED(x) (((x) & (getpagesize() - 1)) != 0) 143 extern "C" void *pedigree_sys_request_mem(
size_t len);
146 const char *filename,
object_meta_t *meta,
bool envpath =
false);
148 bool loadSharedObjectHelper(
150 bool bRelocate =
true);
154 LookupPolicy policy = LocalFirst);
158 bool bGlobal =
true);
163 uintptr_t doThisRelocation(ElfRela_t rel,
object_meta_t *meta);
165 std::string symbolName(
168 std::string findObject(std::string name,
bool envpath);
170 extern "C" void *_libload_dlopen(
const char *file,
int mode);
171 extern "C" void *_libload_dlsym(
void *handle,
const char *name);
172 extern "C" int _libload_dlclose(
void *handle);
174 extern "C" uintptr_t _libload_resolve_symbol();
178 std::list<std::string> g_lSearchPaths;
180 std::set<std::string> g_LoadedObjects;
182 std::map<std::string, uintptr_t> g_LibLoadSymbols;
184 extern char __elf_start;
185 extern char __start_bss;
186 extern char __end_bss;
188 extern "C" void _init();
189 extern "C" void _fini();
190 extern "C" int _start(
const char *argv[],
const char *env[]);
192 size_t elfhash(
const char *name)
197 h = (h << 4) + *name++;
206 extern char **environ;
214 extern "C" int _libload_main(
const char *argv[],
const char *env[])
220 uintptr_t bssStart =
reinterpret_cast<uintptr_t
>(&__start_bss);
221 uintptr_t bssEnd =
reinterpret_cast<uintptr_t
>(&__end_bss);
223 &__start_bss, bssEnd - bssStart, PROT_READ | PROT_WRITE,
224 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_USERSVD, -1, 0);
229 int ret = _start(argv, env);
237 extern "C" int main(
int argc,
const char *argv[])
246 klog(LOG_INFO,
"libload.so starting...");
249 char *ld_libpath = getenv(
"LD_LIBRARY_PATH");
250 char *ld_preload = getenv(
"LD_PRELOAD");
251 char *ld_debug = getenv(
"LD_DEBUG");
253 g_lSearchPaths.push_back(std::string(
"root»/libraries"));
254 g_lSearchPaths.push_back(std::string(
"."));
257 g_LibLoadSymbols.insert(std::pair<std::string, uintptr_t>(
258 "_libload_dlopen", (uintptr_t) _libload_dlopen));
259 g_LibLoadSymbols.insert(std::pair<std::string, uintptr_t>(
260 "_libload_dlsym", (uintptr_t) _libload_dlsym));
261 g_LibLoadSymbols.insert(std::pair<std::string, uintptr_t>(
262 "_libload_dlopen", (uintptr_t) _libload_dlclose));
268 while ((entry = strtok(ld_libpath,
":")))
270 g_lSearchPaths.push_back(std::string(entry));
276 fprintf(stderr,
"libload.so: search path is\n");
277 for (std::list<std::string>::iterator it = g_lSearchPaths.begin();
278 it != g_lSearchPaths.end(); ++it)
280 printf(
" -> %s\n", it->c_str());
285 klog(LOG_INFO,
"libload.so loading main object");
289 if (!strcmp(argv[0],
"sh") || !strcmp(argv[0],
"/bin/sh"))
292 argv[0] = getenv(
"SHELL");
298 "libload: $SHELL is undefined and /bin/sh was requested");
304 klog(LOG_INFO,
"libload.so main object is %s", argv[0]);
310 meta->running =
false;
311 if (!loadObject(argv[0], meta,
true))
317 g_LoadedObjects.insert(meta->filename);
320 klog(LOG_INFO,
"libload.so loading preload, if one exists");
327 if (!loadObject(ld_preload, preload))
329 printf(
"Loading preload '%s' failed.\n", ld_preload);
333 preload->parent = meta;
334 meta->preloads.push_back(preload);
336 g_LoadedObjects.insert(preload->filename);
341 klog(LOG_INFO,
"libload.so loading dependencies");
345 if (meta->needed.size())
347 for (std::list<std::string>::iterator it = meta->needed.begin();
348 it != meta->needed.end(); ++it)
350 if (g_LoadedObjects.find(*it) == g_LoadedObjects.end())
351 loadSharedObjectHelper(it->c_str(), meta, NULL,
false);
356 klog(LOG_INFO,
"libload.so relocating dependencies");
360 for (std::list<struct _object_meta *>::iterator it = meta->preloads.begin();
361 it != meta->preloads.end(); ++it)
367 for (std::list<struct _object_meta *>::iterator it = meta->objects.begin();
368 it != meta->objects.end(); ++it)
374 klog(LOG_INFO,
"libload.so relocating main object");
381 meta->running =
true;
384 for (std::list<struct _object_meta *>::iterator it = meta->objects.begin();
385 it != meta->objects.end(); ++it)
387 if ((*it)->init_func)
391 LOG_INFO,
"libload.so running init_func for %s",
392 (*it)->filename.c_str());
394 init_fini_func_t init = (init_fini_func_t)(*it)->init_func;
402 init_fini_func_t init = (init_fini_func_t) meta->init_func;
405 LOG_INFO,
"libload.so running init_func for %s",
406 meta->filename.c_str());
412 for (std::list<struct _object_meta *>::iterator it = meta->objects.begin();
413 it != meta->objects.end(); ++it)
415 if ((*it)->fini_func)
417 init_fini_func_t fini = (init_fini_func_t)(*it)->fini_func;
425 init_fini_func_t fini = (init_fini_func_t) meta->fini_func;
432 klog(LOG_INFO,
"libload.so running entry point");
434 meta->entry(&argv[1], environ);
439 std::string findObject(std::string name,
bool envpath)
441 std::list<std::string>::iterator it = g_lSearchPaths.begin();
442 if (it != g_lSearchPaths.end())
444 std::string fixed_path;
447 if ((name[0] ==
'.') || (name[0] ==
'/') ||
448 (name.find(
"»") != std::string::npos))
460 klog(LOG_INFO,
"Trying %s", fixed_path.c_str());
464 int l = stat(fixed_path.c_str(), &st);
465 if ((l == 0) && S_ISREG(st.st_mode))
473 }
while (++it != g_lSearchPaths.end());
479 char *path = getenv(
"PATH");
484 const char *entry = strtok(path,
":");
489 g_lSearchPaths.push_back(std::string(entry));
492 std::string fixed_path(entry);
497 klog(LOG_INFO,
"Trying %s", fixed_path.c_str());
500 std::string result = findObject(fixed_path,
false);
502 if (result.compare(
"<not found>") != 0)
506 g_lSearchPaths.pop_back();
507 }
while ((entry = strtok(NULL,
":")));
512 return std::string(
"<not found>");
515 bool loadSharedObjectHelper(
520 bool bSuccess =
true;
521 if (!loadObject(filename,
object))
523 printf(
"Loading '%s' failed.\n", filename);
528 object->parent = parent;
529 parent->objects.push_back(
object);
530 g_LoadedObjects.insert(object->filename);
532 if (object->needed.size())
534 for (std::list<std::string>::iterator it = object->needed.begin();
535 it !=
object->needed.end(); ++it)
537 if (g_LoadedObjects.find(*it) == g_LoadedObjects.end())
540 bSuccess = loadSharedObjectHelper(
541 it->c_str(), parent, &child, bRelocate);
555 doRelocation(
object);
561 bool loadObject(
const char *filename,
object_meta_t *meta,
bool envpath)
563 meta->filename = filename;
564 meta->path = findObject(meta->filename, envpath);
566 klog(LOG_INFO,
"libload.so loading %s", filename);
570 int fd = open(meta->path.c_str(), O_RDONLY);
574 stderr,
"libload.so: couldn't load object '%s' (%s) (%s)\n",
575 filename, meta->path.c_str(), strerror(errno));
581 int n = read(fd, &header,
sizeof(header));
586 stderr,
"libload.so: couldn't read file header (%s)\n",
590 LOG_INFO,
"libload.so: couldn't read file header (%s)",
596 else if (n !=
sizeof(header))
599 fprintf(stderr,
"libload.so: read was not the correct size\n");
601 klog(LOG_INFO,
"libload.so: read was not the correct size");
608 if (header.ident[1] !=
'E' || header.ident[2] !=
'L' ||
609 header.ident[3] !=
'F' || header.ident[0] != 127)
612 fprintf(stderr,
"libload.so: bad ELF magic\n");
614 klog(LOG_INFO,
"libload.so: bad ELF magic");
622 if (!(header.ident[4] == 1 || header.ident[4] == 2))
625 fprintf(stderr,
"libload.so: not a valid ELF class\n");
627 klog(LOG_INFO,
"libload.so: not a valid ELF class");
634 meta->entry = (entry_point_t) header.entry;
641 meta->mapped_file_sz = st.st_size;
643 const char *pBuffer = (
const char *) mmap(
644 0, meta->mapped_file_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
645 if (pBuffer == MAP_FAILED)
648 fprintf(stderr,
"libload.so: could not mmap binary\n");
650 klog(LOG_INFO,
"libload.so: could not mmap binary");
656 meta->mapped_file = pBuffer;
658 meta->phdrs =
const_cast<ElfProgramHeader_t *
>(
659 reinterpret_cast<const ElfProgramHeader_t *
>(&pBuffer[header.phoff]));
660 meta->num_phdrs = header.phnum;
663 meta->num_shdrs = header.shnum;
665 if (header.type == ET_REL)
667 meta->relocated =
true;
669 else if (header.type == ET_EXEC || header.type == ET_DYN)
674 for (
size_t i = 0; i < header.phnum; ++i)
676 if (meta->phdrs[i].type != PT_LOAD)
680 (meta->phdrs[i].vaddr & ~(getpagesize() - 1)) == 0;
686 meta->sh_shstrtab = &meta->shdrs[header.shstrndx];
687 meta->shstrtab = &pBuffer[meta->sh_shstrtab->offset];
692 for (
int i = 0; i < header.shnum; i++)
694 const char *name = meta->shstrtab + meta->shdrs[i].name;
695 if (meta->shdrs[i].type == SHT_SYMTAB && !strcmp(name,
".symtab"))
697 meta->sh_symtab = &meta->shdrs[i];
699 else if (meta->shdrs[i].type == SHT_STRTAB && !strcmp(name,
".strtab"))
701 meta->sh_strtab = &meta->shdrs[i];
708 if (meta->sh_symtab != 0)
710 meta->symtab =
reinterpret_cast<const ElfSymbol_t *
>(
711 &pBuffer[meta->sh_symtab->offset]);
714 if (meta->sh_strtab != 0)
716 meta->strtab = &pBuffer[meta->sh_strtab->offset];
727 meta->load_base = meta->phdrs[0].vaddr & ~(getpagesize() - 1);
728 uintptr_t finalAddress = 0;
729 for (
size_t i = 0; i < header.phnum; ++i)
731 uintptr_t endAddr = meta->phdrs[i].vaddr + meta->phdrs[i].memsz;
732 finalAddress = std::max(finalAddress, endAddr);
734 size_t mapSize = finalAddress - meta->load_base;
735 if (mapSize & (getpagesize() - 1))
737 mapSize = (mapSize + getpagesize()) & ~(getpagesize() - 1);
740 void *p = pedigree_sys_request_mem(mapSize);
743 munmap(const_cast<char *>(pBuffer), meta->mapped_file_sz);
747 "libload.so: couldn't get memory for relocated object");
751 meta->load_base = (uintptr_t) p;
752 if (meta->load_base & (getpagesize() - 1))
755 (meta->load_base + getpagesize()) & ~(getpagesize() - 1);
759 for (
size_t shdx = 0; shdx < header.shnum; ++shdx)
761 meta->shdrs[shdx].addr += meta->load_base;
766 std::list<uintptr_t> tmp_needed;
768 for (
size_t i = 0; i < header.phnum; i++)
770 if (meta->phdrs[i].type == PT_DYNAMIC)
772 meta->ph_dynamic = &meta->phdrs[i];
775 meta->ph_dynamic->vaddr += meta->load_base;
778 const ElfDyn_t *dyn =
779 (
const ElfDyn_t *) &pBuffer[meta->phdrs[i].offset];
781 while (dyn->tag != DT_NULL)
786 tmp_needed.push_back(dyn->un.ptr);
792 meta->dyn_strtab = (
const char *) dyn->un.ptr;
795 meta->dyn_strtab_sz = dyn->un.val;
798 meta->rela = (ElfRela_t *) dyn->un.ptr;
801 meta->rel = (
ElfRel_t *) dyn->un.ptr;
804 meta->rela_sz = dyn->un.val;
807 meta->rel_sz = dyn->un.val;
810 meta->got = (uintptr_t *) dyn->un.ptr;
815 meta->plt_rela = (ElfRela_t *) dyn->un.ptr;
819 meta->plt_rel = (
ElfRel_t *) dyn->un.ptr;
823 meta->uses_rela = dyn->un.val == DT_RELA;
826 meta->plt_sz = dyn->un.val;
829 meta->init_func = dyn->un.val;
832 meta->fini_func = dyn->un.val;
838 else if (meta->phdrs[i].type == PT_LOAD)
842 meta->phdrs[i].vaddr += meta->load_base;
845 uintptr_t phdr_base = meta->phdrs[i].vaddr;
847 size_t pagesz = getpagesize();
849 size_t base_addend = phdr_base & (pagesz - 1);
850 phdr_base &= ~(pagesz - 1);
853 if (meta->phdrs[i].offset)
855 offset = meta->phdrs[i].offset - base_addend;
858 size_t mapsz = base_addend + meta->phdrs[i].filesz;
861 if ((msync((
void *) phdr_base, mapsz, MS_SYNC) != 0) &&
864 int mapflags = MAP_FIXED | MAP_PRIVATE;
867 mapflags |= MAP_USERSVD;
871 if ((meta->phdrs[i].flags & PF_W) == 0)
876 mapflags &= ~(MAP_PRIVATE);
880 if (meta->phdrs[i].memsz > meta->phdrs[i].filesz)
882 uintptr_t vaddr_start =
883 meta->phdrs[i].vaddr + meta->phdrs[i].filesz;
884 uintptr_t vaddr_end =
885 meta->phdrs[i].vaddr + meta->phdrs[i].memsz;
886 if ((vaddr_start & ~(getpagesize() - 1)) !=
887 (vaddr_end & ~(getpagesize() - 1)))
892 vaddr_start += getpagesize();
893 vaddr_start &= ~(getpagesize() - 1);
894 size_t totalLength = vaddr_end - vaddr_start;
896 totalLength = getpagesize();
898 (
void *) vaddr_start, totalLength,
899 PROT_READ | PROT_WRITE, mapflags | MAP_ANON, 0,
905 LOG_INFO,
"libload.so: mmap failed for " 906 "program header (anonymous " 911 meta->memory_regions.push_back(
912 std::pair<void *, size_t>(p, totalLength));
918 "libload.so: not mapping filesz section at %p",
924 (
void *) phdr_base, mapsz, PROT_READ | PROT_WRITE,
925 mapflags, map_fd, map_fd ? offset : 0);
932 "libload.so: mmap failed for program header");
936 meta->memory_regions.push_back(
937 std::pair<void *, size_t>(p, mapsz));
944 uintptr_t base_vaddr = meta->load_base;
947 if (meta->dyn_strtab)
948 meta->dyn_strtab += base_vaddr;
949 if (meta->dyn_symtab)
952 *) (((uintptr_t) meta->dyn_symtab) + base_vaddr);
955 (uintptr_t *) (((uintptr_t) meta->got) + base_vaddr);
958 (ElfRela_t *) (((uintptr_t) meta->rela) + base_vaddr);
960 meta->rel = (
ElfRel_t *) (((uintptr_t) meta->rel) + base_vaddr);
963 (ElfRela_t *) (((uintptr_t) meta->plt_rela) + base_vaddr);
966 (
ElfRel_t *) (((uintptr_t) meta->plt_rel) + base_vaddr);
968 meta->init_func += base_vaddr;
970 meta->fini_func += base_vaddr;
973 if (meta->dyn_strtab)
975 for (std::list<uintptr_t>::iterator it = tmp_needed.begin();
976 it != tmp_needed.end(); ++it)
978 std::string s(meta->dyn_strtab + *it);
979 meta->needed.push_back(s);
990 meta->hash_buckets = 0;
991 meta->hash_chains = 0;
992 for (
size_t i = 0; i < header.shnum; i++)
994 if (meta->shdrs[i].type == SHT_HASH)
996 uintptr_t vaddr = meta->shdrs[meta->shdrs[i].link].addr;
997 if (((uintptr_t) meta->dyn_symtab) == vaddr)
1000 (
const ElfHash_t *) &pBuffer[meta->shdrs[i].offset];
1001 meta->hash_buckets =
1003 *) &pBuffer[meta->shdrs[i].offset +
sizeof(ElfHash_t)];
1004 meta->hash_chains = (
const Elf_Word *) &pBuffer
1005 [meta->shdrs[i].offset +
sizeof(ElfHash_t) +
1006 (
sizeof(Elf_Word) * meta->hash->nbucket)];
1014 meta->got[1] = (uintptr_t) meta;
1015 meta->got[2] = (uintptr_t) _libload_resolve_symbol;
1035 for (std::list<object_meta_t *>::iterator it = meta->preloads.begin();
1036 it != meta->preloads.end(); ++it)
1038 if (lookupSymbol(
symbol, *it, sym,
false))
1042 std::string sname(
symbol);
1044 size_t hash = elfhash(
symbol);
1045 size_t y = meta->hash_buckets[hash % meta->hash->nbucket];
1046 if (y > meta->hash->nchain)
1054 sym = meta->dyn_symtab[y];
1055 if (symbolName(sym, meta) == sname)
1057 if (ST_BIND(sym.info) == STB_LOCAL)
1066 if (ST_BIND(sym.info) == STB_WEAK)
1073 y = meta->hash_chains[y];
1077 if ((bGlobal) && (y == 0))
1079 y = meta->hash_buckets[hash % meta->hash->nbucket];
1082 sym = meta->dyn_symtab[y];
1083 if (symbolName(sym, meta) == sname)
1085 if (ST_BIND(sym.info) == STB_GLOBAL)
1093 y = meta->hash_chains[y];
1100 if (ST_TYPE(sym.info) < 3)
1102 if (sym.shndx && meta->relocated)
1104 sym.value += meta->load_base;
1114 LookupPolicy policy)
1122 std::map<std::string, uintptr_t>::iterator it =
1123 g_LibLoadSymbols.find(std::string(
symbol));
1124 if (it != g_LibLoadSymbols.end())
1128 sym.value = it->second;
1134 while (ext_meta->parent)
1136 ext_meta = ext_meta->parent;
1140 for (std::list<object_meta_t *>::iterator it = ext_meta->preloads.begin();
1141 it != ext_meta->preloads.end(); ++it)
1143 if (lookupSymbol(
symbol, *it, sym,
false))
1148 if (policy != NotThisObject && policy != LocalLast)
1150 if (lookupSymbol(
symbol, meta, sym,
false,
false))
1155 if ((meta != ext_meta) && lookupSymbol(
symbol, ext_meta, sym,
false))
1159 for (std::list<object_meta_t *>::iterator it = ext_meta->objects.begin();
1160 it != ext_meta->objects.end(); ++it)
1165 if (lookupSymbol(
symbol, *it, sym,
false))
1172 if (policy == LocalLast)
1174 if (lookupSymbol(
symbol, meta, sym,
false,
false))
1179 for (std::list<object_meta_t *>::iterator it = ext_meta->objects.begin();
1180 it != ext_meta->objects.end(); ++it)
1185 if (lookupSymbol(
symbol, *it, sym,
true))
1192 if ((meta != ext_meta) && lookupSymbol(
symbol, ext_meta, sym,
true))
1196 if (policy != NotThisObject)
1198 if (lookupSymbol(
symbol, meta, sym,
true))
1210 return std::string(
"");
1212 else if (sym.name == 0)
1214 return std::string(
"");
1217 const char *strtab = meta->strtab;
1219 if (ST_TYPE(sym.info) == 3)
1221 strtab = meta->shstrtab;
1223 else if ((!bNoDynamic) && meta->dyn_strtab)
1225 strtab = meta->dyn_strtab;
1228 const char *name = strtab + sym.name;
1229 return std::string(name);
1236 for (
size_t i = 0; i < (meta->rel_sz /
sizeof(
ElfRel_t)); i++)
1238 doThisRelocation(meta->rel[i], meta);
1244 for (
size_t i = 0; i < (meta->rela_sz /
sizeof(ElfRela_t)); i++)
1246 doThisRelocation(meta->rela[i], meta);
1252 if (meta->relocated)
1254 uintptr_t base = meta->load_base;
1258 for (
size_t i = 0; i < (meta->plt_sz /
sizeof(
ElfRel_t)); i++)
1261 (uintptr_t *) (base + meta->plt_rel[i].offset);
1268 for (
size_t i = 0; i < (meta->plt_sz /
sizeof(ElfRela_t)); i++)
1271 (uintptr_t *) (base + meta->plt_rela[i].offset);
1278 for (
size_t i = 0; i < meta->num_phdrs; i++)
1280 if (meta->phdrs[i].type != PT_LOAD)
1284 int flags = PROT_READ;
1285 if (meta->phdrs[i].flags & PF_X)
1287 if (meta->phdrs[i].flags & PF_W)
1288 flags |= PROT_WRITE;
1289 if ((meta->phdrs[i].flags & PF_R) == 0)
1290 flags &= ~PROT_READ;
1293 size_t alignExtra = meta->phdrs[i].vaddr & (getpagesize() - 1);
1294 uintptr_t protectaddr = meta->phdrs[i].vaddr & ~(getpagesize() - 1);
1295 #ifdef DEBUG_LIBLOAD 1297 LOG_INFO,
"map %s %p -> %p [%p] %s%s%s", meta->filename.c_str(),
1298 meta->phdrs[i].vaddr, meta->phdrs[i].vaddr + meta->phdrs[i].memsz,
1299 meta->phdrs[i].offset, flags & PROT_READ ?
"r" :
"-",
1300 flags & PROT_WRITE ?
"w" :
"-", flags & PROT_EXEC ?
"x" :
"-");
1303 (
void *) protectaddr, meta->phdrs[i].memsz + alignExtra, flags);
1307 #define R_X86_64_NONE 0 1308 #define R_X86_64_64 1 1309 #define R_X86_64_PC32 2 1310 #define R_X86_64_GOT32 3 1311 #define R_X86_64_PLT32 4 1312 #define R_X86_64_COPY 5 1313 #define R_X86_64_GLOB_DAT 6 1314 #define R_X86_64_JUMP_SLOT 7 1315 #define R_X86_64_RELATIVE 8 1316 #define R_X86_64_GOTPCREL 9 1317 #define R_X86_64_32 10 1318 #define R_X86_64_32S 11 1319 #define R_X86_64_PC64 24 1320 #define R_X86_64_GOTOFF64 25 1321 #define R_X86_64_GOTPC32 26 1322 #define R_X86_64_GOT64 27 1323 #define R_X86_64_GOTPCREL64 28 1324 #define R_X86_64_GOTPC64 29 1325 #define R_X86_64_GOTPLT64 30 1326 #define R_X86_64_PLTOFF64 31 1328 #define R_386_NONE 0 1330 #define R_386_PC32 2 1331 #define R_386_GOT32 3 1332 #define R_386_PLT32 4 1333 #define R_386_COPY 5 1334 #define R_386_GLOB_DAT 6 1335 #define R_386_JMP_SLOT 7 1336 #define R_386_RELATIVE 8 1337 #define R_386_GOTOFF 9 1338 #define R_386_GOTPC 10 1343 if (meta->dyn_symtab)
1345 symtab = meta->dyn_symtab;
1348 const ElfSymbol_t *sym = &symtab[R_SYM(rel.info)];
1352 sh = &meta->shdrs[sym->shndx];
1355 uintptr_t B = meta->load_base;
1356 uintptr_t P = rel.offset;
1357 if (meta->relocated)
1362 uintptr_t A = *((uintptr_t *) P);
1365 std::string symbolname = symbolName(*sym, meta);
1366 size_t symbolSize =
sizeof(uintptr_t);
1369 if (symtab && ST_TYPE(sym->info) == 3)
1374 "symbol lookup for '%s' needed a section header, which wasn't " 1376 symbolname.c_str());
1381 else if (R_TYPE(rel.info) != R_386_RELATIVE)
1390 LookupPolicy policy = LocalFirst;
1391 if (R_TYPE(rel.info) == R_386_COPY)
1393 policy = NotThisObject;
1397 if (!findSymbol(symbolname.c_str(), meta, lookupsym, policy))
1400 "symbol lookup for '%s' (needed in '%s') failed.\n",
1401 symbolname.c_str(), meta->path.c_str());
1402 lookupsym.value = ~0UL;
1405 S = lookupsym.value;
1406 symbolSize = lookupsym.size;
1415 uint32_t result = A;
1416 switch (R_TYPE(rel.info))
1426 case R_386_JMP_SLOT:
1427 case R_386_GLOB_DAT:
1434 memcpy((
void *) P, (
void *) S, symbolSize);
1438 case R_386_RELATIVE:
1443 if (R_TYPE(rel.info) != R_386_COPY)
1445 *((uint32_t *) P) = result;
1450 uintptr_t doThisRelocation(ElfRela_t rel,
object_meta_t *meta)
1453 if (meta->dyn_symtab)
1455 symtab = meta->dyn_symtab;
1458 const ElfSymbol_t *sym = &symtab[R_SYM(rel.info)];
1462 sh = &meta->shdrs[sym->shndx];
1465 uintptr_t B = meta->load_base;
1466 uintptr_t P = rel.offset;
1467 if (meta->relocated)
1472 uintptr_t A = rel.addend;
1475 std::string symbolname = symbolName(*sym, meta);
1476 size_t symbolSize =
sizeof(uintptr_t);
1479 if (symtab && ST_TYPE(sym->info) == 3)
1484 "symbol lookup for '%s' needed a section header, which wasn't " 1486 symbolname.c_str());
1491 else if (R_TYPE(rel.info) != R_X86_64_RELATIVE)
1500 LookupPolicy policy = LocalFirst;
1501 if (R_TYPE(rel.info) == R_X86_64_COPY)
1503 policy = NotThisObject;
1507 if (!findSymbol(symbolname.c_str(), meta, lookupsym, policy))
1510 "symbol lookup for '%s' (needed in '%s') failed.\n",
1511 symbolname.c_str(), meta->path.c_str());
1512 lookupsym.value = ~0UL;
1515 S = lookupsym.value;
1516 symbolSize = lookupsym.size;
1521 if ((S == 0) && (R_TYPE(rel.info) != R_X86_64_RELATIVE))
1532 uintptr_t result = *((uintptr_t *) P);
1533 switch (R_TYPE(rel.info))
1541 result = (S + A - P) & 0xFFFFFFFF;
1547 memcpy((
void *) P, (
void *) S, symbolSize);
1551 case R_X86_64_JUMP_SLOT:
1552 case R_X86_64_GLOB_DAT:
1555 case R_X86_64_RELATIVE:
1564 result = (S + A) & 0xFFFFFFFF;
1569 "libload: unsupported relocation for '%s' in %s: %d",
1570 symbolname.c_str(), meta->filename.c_str(), R_TYPE(rel.info));
1573 if (R_TYPE(rel.info) != R_X86_64_COPY)
1575 *((uintptr_t *) P) = result;
1585 extern "C" uintptr_t _libload_dofixup(uintptr_t
id, uintptr_t
symbol)
1588 uintptr_t returnaddr = 0;
1593 xmm_t *fixup_xmm_save = (xmm_t *) memalign(16,
sizeof(xmm_t) * 8);
1594 #define XMM_SAVE(N) \ 1595 asm volatile("movdqa %%xmm" #N ", %0" : "=m"(fixup_xmm_save[N])); 1596 #define XMM_RESTORE(N) \ 1597 asm volatile("movdqa %0, %%xmm" #N ::"m"(fixup_xmm_save[N])); 1611 ElfRela_t rel = meta->plt_rela[symbol];
1615 if (meta->hash && (R_SYM(rel.info) > meta->hash->nchain))
1617 fprintf(stderr,
"symbol lookup failed (symbol not in hash table)\n");
1621 uintptr_t result = doThisRelocation(rel, meta);
1624 fprintf(stderr,
"symbol lookup failed (couldn't relocate)\n");
1637 free(fixup_xmm_save);
1645 void *_libload_dlopen(
const char *file,
int mode)
1649 std::set<std::string>::iterator it =
1650 g_LoadedObjects.find(std::string(file));
1651 if (it != g_LoadedObjects.end())
1654 fprintf(stderr,
"Not yet able to dlopen already-opened objects.\n");
1658 bool bLoad = loadSharedObjectHelper(file, g_MainObject, &result);
1661 fprintf(stderr,
"Loading object '%s' failed.\n", file);
1665 if (result->init_func)
1667 init_fini_func_t init = (init_fini_func_t) result->init_func;
1671 return (
void *) result;
1674 void *_libload_dlsym(
void *handle,
const char *name)
1682 bool bFound = findSymbol(name, obj, sym);
1688 return (
void *) sym.value;
1691 int _libload_dlclose(
void *handle)
xmm_t fixup_xmm_save[8] __attribute__((aligned(16)))