/* * Get the linkmap from the dynlinker. Try to load kernel modules * from all objects in the linkmap. */ void rumpuser_dl_bootstrap(rump_modinit_fn domodinit, rump_symload_fn symload, rump_compload_fn compload) { struct link_map *map, *origmap, *mainmap; void *mainhandle; int error; mainhandle = dlopen(NULL, RTLD_NOW); if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) { fprintf(stderr, "warning: rumpuser module bootstrap " "failed: %s\n", dlerror()); return; } origmap = mainmap; /* * Process last->first because that's the most probable * order for dependencies */ for (; origmap->l_next; origmap = origmap->l_next) continue; /* * Build symbol table to hand to the rump kernel. Do this by * iterating over all rump libraries and collecting symbol * addresses and relocation info. */ error = 0; for (map = origmap; map && !error; map = map->l_prev) { if (strstr(map->l_name, "librump") != NULL || map == mainmap) error = getsymbols(map, map == mainmap); } if (error == 0) { void *trimmedsym, *trimmedstr; /* * Allocate optimum-sized memory for storing tables * and feed to kernel. If memory allocation fails, * just give the ones with extra context (although * I'm pretty sure we'll die moments later due to * memory running out). */ if ((trimmedsym = malloc(symtaboff)) != NULL) { memcpy(trimmedsym, symtab, symtaboff); } else { trimmedsym = symtab; symtab = NULL; } if ((trimmedstr = malloc(strtaboff)) != NULL) { memcpy(trimmedstr, strtab, strtaboff); } else { trimmedstr = strtab; strtab = NULL; } symload(trimmedsym, symtaboff, trimmedstr, strtaboff); } free(symtab); free(strtab); /* * Next, load modules and components. * * Simply loop through all objects, ones unrelated to rump kernels * will not contain link_set_rump_components (well, not including * "sabotage", but that needs to be solved at another level anyway). */ for (map = origmap; map; map = map->l_prev) { void *handle; if (map == mainmap) { handle = mainhandle; } else { handle = dlopen(map->l_name, RTLD_LAZY); if (handle == NULL) continue; } process_object(handle, domodinit, compload); if (map != mainmap) dlclose(handle); } }
/* * Get the linkmap from the dynlinker. Try to load kernel modules * from all objects in the linkmap. */ void rumpuser_dl_bootstrap(rump_modinit_fn domodinit, rump_symload_fn symload, rump_compload_fn compload) { struct link_map *map, *origmap, *mainmap; void *mainhandle; int error; mainhandle = dlopen(NULL, RTLD_NOW); /* Will be null if statically linked so just return */ if (mainhandle == NULL) return; if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) { fprintf(stderr, "warning: rumpuser module bootstrap " "failed: %s\n", dlerror()); return; } origmap = mainmap; /* * Use a heuristic to determine if we are static linked. * A dynamically linked binary should always have at least * two objects: itself and ld.so. * * In a statically linked binary with glibc the linkmap * contains some "info" that leads to a segfault. Since we * can't really do anything useful in here without ld.so, just * simply bail and let the symbol references in librump do the * right things. */ if (origmap->l_next == NULL && origmap->l_prev == NULL) { dlclose(mainhandle); return; } /* * Process last->first because that's the most probable * order for dependencies */ for (; origmap->l_next; origmap = origmap->l_next) continue; /* * Build symbol table to hand to the rump kernel. Do this by * iterating over all rump libraries and collecting symbol * addresses and relocation info. */ error = 0; for (map = origmap; map && !error; map = map->l_prev) { if (strstr(map->l_name, "librump") != NULL || map == mainmap) error = getsymbols(map, map == mainmap); } if (error == 0) { void *trimmedsym, *trimmedstr; /* * Allocate optimum-sized memory for storing tables * and feed to kernel. If memory allocation fails, * just give the ones with extra context (although * I'm pretty sure we'll die moments later due to * memory running out). */ if ((trimmedsym = malloc(symtaboff)) != NULL) { memcpy(trimmedsym, symtab, symtaboff); } else { trimmedsym = symtab; symtab = NULL; } if ((trimmedstr = malloc(strtaboff)) != NULL) { memcpy(trimmedstr, strtab, strtaboff); } else { trimmedstr = strtab; strtab = NULL; } symload(trimmedsym, symtaboff, trimmedstr, strtaboff); } free(symtab); free(strtab); /* * Next, load modules and components. * * Simply loop through all objects, ones unrelated to rump kernels * will not contain link_set_rump_components (well, not including * "sabotage", but that needs to be solved at another level anyway). */ for (map = origmap; map; map = map->l_prev) { void *handle; if (map == mainmap) { handle = mainhandle; } else { handle = dlopen(map->l_name, RTLD_LAZY); if (handle == NULL) continue; } process_object(handle, domodinit, compload); if (map != mainmap) dlclose(handle); } }