1 1.34 rillig /* $NetBSD: rumpuser_dl.c,v 1.34 2022/04/19 20:32:17 rillig Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 2009 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.1 pooka /* 29 1.1 pooka * Load all module link sets and feed symbol table to the kernel. 30 1.1 pooka * Called during rump bootstrap. 31 1.1 pooka */ 32 1.1 pooka 33 1.16 pooka /* 34 1.16 pooka * Solaris libelf.h doesn't support _FILE_OFFSET_BITS=64. Luckily, 35 1.16 pooka * for this module it doesn't matter. 36 1.16 pooka */ 37 1.17 pooka #if defined(__sun__) 38 1.17 pooka #define RUMPUSER_NO_FILE_OFFSET_BITS 39 1.16 pooka #endif 40 1.8 pooka #include "rumpuser_port.h" 41 1.8 pooka 42 1.8 pooka #if !defined(lint) 43 1.34 rillig __RCSID("$NetBSD: rumpuser_dl.c,v 1.34 2022/04/19 20:32:17 rillig Exp $"); 44 1.8 pooka #endif /* !lint */ 45 1.1 pooka 46 1.1 pooka #include <sys/types.h> 47 1.1 pooka #include <sys/time.h> 48 1.32 pgoyette #include <sys/evcnt.h> 49 1.32 pgoyette 50 1.8 pooka #include <assert.h> 51 1.1 pooka 52 1.1 pooka #include <dlfcn.h> 53 1.1 pooka #include <errno.h> 54 1.1 pooka #include <fcntl.h> 55 1.25 pooka #include <stdint.h> 56 1.1 pooka #include <stdio.h> 57 1.1 pooka #include <stdlib.h> 58 1.1 pooka #include <string.h> 59 1.1 pooka #include <unistd.h> 60 1.1 pooka 61 1.1 pooka #include <rump/rumpuser.h> 62 1.1 pooka 63 1.30 pooka #if defined(__ELF__) && defined(HAVE_DLINFO) 64 1.22 rmind #include <elf.h> 65 1.12 pooka #include <link.h> 66 1.12 pooka 67 1.1 pooka static size_t symtabsize = 0, strtabsize = 0; 68 1.1 pooka static size_t symtaboff = 0, strtaboff = 0; 69 1.1 pooka static uint8_t *symtab = NULL; 70 1.1 pooka static char *strtab = NULL; 71 1.1 pooka static unsigned char eident; 72 1.1 pooka 73 1.7 pooka /* nb5 compat */ 74 1.7 pooka #ifndef Elf_Symindx 75 1.7 pooka #define Elf_Symindx uint32_t 76 1.7 pooka #endif 77 1.7 pooka 78 1.1 pooka static void * 79 1.1 pooka reservespace(void *store, size_t *storesize, 80 1.1 pooka size_t storeoff, size_t required) 81 1.1 pooka { 82 1.1 pooka size_t chunk, newsize; 83 1.1 pooka 84 1.1 pooka assert(storeoff <= *storesize); 85 1.1 pooka chunk = *storesize - storeoff; 86 1.1 pooka 87 1.1 pooka if (chunk >= required) 88 1.1 pooka return store; 89 1.1 pooka 90 1.1 pooka newsize = *storesize + ((size_t)required - chunk); 91 1.1 pooka store = realloc(store, newsize); 92 1.1 pooka if (store == NULL) { 93 1.1 pooka return NULL; 94 1.1 pooka } 95 1.1 pooka *((uint8_t *)store + storeoff) = '\0'; 96 1.1 pooka *storesize = newsize; 97 1.1 pooka 98 1.1 pooka return store; 99 1.1 pooka } 100 1.1 pooka 101 1.1 pooka /* 102 1.1 pooka * Macros to make handling elf32/64 in the code a little saner. 103 1.1 pooka */ 104 1.1 pooka 105 1.1 pooka #define DYNn_GETMEMBER(base, n, thevar, result) \ 106 1.1 pooka do { \ 107 1.1 pooka if (eident == ELFCLASS32) { \ 108 1.9 pooka const Elf32_Dyn *dyn = base; \ 109 1.1 pooka /*LINTED*/ \ 110 1.1 pooka result = dyn[n].thevar; \ 111 1.1 pooka } else { \ 112 1.9 pooka const Elf64_Dyn *dyn = base; \ 113 1.1 pooka /*LINTED*/ \ 114 1.1 pooka result = dyn[n].thevar; \ 115 1.1 pooka } \ 116 1.34 rillig } while (0) 117 1.1 pooka 118 1.1 pooka #define SYMn_GETMEMBER(base, n, thevar, result) \ 119 1.1 pooka do { \ 120 1.1 pooka if (eident == ELFCLASS32) { \ 121 1.4 pooka const Elf32_Sym *sym = base; \ 122 1.1 pooka /*LINTED*/ \ 123 1.1 pooka result = sym[n].thevar; \ 124 1.1 pooka } else { \ 125 1.4 pooka const Elf64_Sym *sym = base; \ 126 1.1 pooka /*LINTED*/ \ 127 1.1 pooka result = sym[n].thevar; \ 128 1.1 pooka } \ 129 1.34 rillig } while (0) 130 1.1 pooka 131 1.1 pooka #define SYMn_SETMEMBER(base, n, thevar, value) \ 132 1.1 pooka do { \ 133 1.1 pooka if (eident == ELFCLASS32) { \ 134 1.1 pooka Elf32_Sym *sym = base; \ 135 1.1 pooka /*LINTED*/ \ 136 1.1 pooka sym[n].thevar = value; \ 137 1.1 pooka } else { \ 138 1.1 pooka Elf64_Sym *sym = base; \ 139 1.1 pooka /*LINTED*/ \ 140 1.1 pooka sym[n].thevar = value; \ 141 1.1 pooka } \ 142 1.34 rillig } while (0) 143 1.1 pooka 144 1.1 pooka #define SYM_GETSIZE() ((eident==ELFCLASS32)?sizeof(Elf32_Sym):sizeof(Elf64_Sym)) 145 1.1 pooka 146 1.8 pooka /* 147 1.8 pooka * On NetBSD, the dynamic section pointer values seem to be relative to 148 1.20 pooka * the address the dso is mapped at. On glibc, they seem to contain 149 1.8 pooka * the absolute address. I couldn't find anything definite from a quick 150 1.8 pooka * read of the standard and therefore I will not go and figure beyond ifdef. 151 1.20 pooka * On Solaris and DragonFly / FreeBSD, the main object works differently 152 1.20 pooka * ... uuuuh. 153 1.8 pooka */ 154 1.23 pooka #if defined(__GLIBC__) && !defined(__mips__) 155 1.8 pooka #define adjptr(_map_, _ptr_) ((void *)(_ptr_)) 156 1.19 pooka #elif defined(__sun__) || defined(__DragonFly__) || defined(__FreeBSD__) 157 1.13 pooka #define adjptr(_map_, _ptr_) \ 158 1.14 pooka (ismainobj ? (void *)(_ptr_) : (void *)(_map_->l_addr + (_ptr_))) 159 1.8 pooka #else 160 1.21 pooka /* NetBSD and some others, e.g. Linux + musl */ 161 1.8 pooka #define adjptr(_map_, _ptr_) ((void *)(_map_->l_addr + (_ptr_))) 162 1.8 pooka #endif 163 1.8 pooka 164 1.1 pooka static int 165 1.14 pooka getsymbols(struct link_map *map, int ismainobj) 166 1.1 pooka { 167 1.1 pooka char *str_base; 168 1.1 pooka void *syms_base = NULL; /* XXXgcc */ 169 1.4 pooka size_t curstrsize; 170 1.9 pooka const void *ed_base; 171 1.1 pooka uint64_t ed_tag; 172 1.4 pooka size_t cursymcount; 173 1.4 pooka unsigned i; 174 1.1 pooka 175 1.4 pooka if (map->l_addr) { 176 1.8 pooka if (memcmp((void *)map->l_addr, ELFMAG, SELFMAG) != 0) 177 1.4 pooka return ENOEXEC; 178 1.4 pooka eident = *(unsigned char *)(map->l_addr + EI_CLASS); 179 1.4 pooka if (eident != ELFCLASS32 && eident != ELFCLASS64) 180 1.4 pooka return ENOEXEC; 181 1.4 pooka } 182 1.1 pooka 183 1.4 pooka /* 184 1.4 pooka * ok, we probably have only the main object. instead of going 185 1.4 pooka * to disk and reading the ehdr, just try to guess the size. 186 1.4 pooka */ 187 1.4 pooka if (eident == 0) { 188 1.4 pooka if (/*CONSTCOND*/sizeof(void *) == 4) 189 1.4 pooka eident = ELFCLASS32; 190 1.4 pooka else 191 1.4 pooka eident = ELFCLASS64; 192 1.1 pooka } 193 1.1 pooka 194 1.4 pooka /* 195 1.4 pooka * Find symtab and strtab and their sizes. 196 1.4 pooka */ 197 1.1 pooka str_base = NULL; 198 1.4 pooka curstrsize = 0; 199 1.4 pooka cursymcount = 0; 200 1.1 pooka ed_base = map->l_ld; 201 1.4 pooka DYNn_GETMEMBER(ed_base, 0, d_tag, ed_tag); 202 1.4 pooka for (i = 0; ed_tag != DT_NULL;) { 203 1.1 pooka uintptr_t edptr; 204 1.1 pooka size_t edval; 205 1.6 njoly Elf_Symindx *hashtab; 206 1.1 pooka 207 1.1 pooka switch (ed_tag) { 208 1.1 pooka case DT_SYMTAB: 209 1.1 pooka DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr); 210 1.8 pooka syms_base = adjptr(map, edptr); 211 1.1 pooka break; 212 1.1 pooka case DT_STRTAB: 213 1.1 pooka DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr); 214 1.8 pooka str_base = adjptr(map, edptr); 215 1.1 pooka break; 216 1.1 pooka case DT_STRSZ: 217 1.1 pooka DYNn_GETMEMBER(ed_base, i, d_un.d_val, edval); 218 1.1 pooka curstrsize = edval; 219 1.1 pooka break; 220 1.4 pooka case DT_HASH: 221 1.4 pooka DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr); 222 1.8 pooka hashtab = (Elf_Symindx *)adjptr(map, edptr); 223 1.6 njoly cursymcount = hashtab[1]; 224 1.4 pooka break; 225 1.11 pooka #ifdef DT_GNU_HASH 226 1.11 pooka /* 227 1.11 pooka * DT_GNU_HASH is a bit more complicated than DT_HASH 228 1.11 pooka * in this regard since apparently there is no field 229 1.11 pooka * telling us the total symbol count. Instead, we look 230 1.31 msaitoh * for the last valid hash bucket and add its chain length 231 1.11 pooka * to the bucket's base index. 232 1.11 pooka */ 233 1.11 pooka case DT_GNU_HASH: { 234 1.11 pooka Elf32_Word nbuck, symndx, maskwords, maxchain = 0; 235 1.11 pooka Elf32_Word *gnuhash, *buckets, *ptr; 236 1.11 pooka int bi; 237 1.11 pooka 238 1.11 pooka DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr); 239 1.11 pooka gnuhash = (Elf32_Word *)adjptr(map, edptr); 240 1.11 pooka 241 1.11 pooka nbuck = gnuhash[0]; 242 1.11 pooka symndx = gnuhash[1]; 243 1.11 pooka maskwords = gnuhash[2]; 244 1.11 pooka 245 1.11 pooka /* 246 1.11 pooka * First, find the last valid bucket and grab its index 247 1.11 pooka */ 248 1.11 pooka if (eident == ELFCLASS64) 249 1.11 pooka maskwords *= 2; /* sizeof(*buckets) == 4 */ 250 1.11 pooka buckets = gnuhash + 4 + maskwords; 251 1.11 pooka for (bi = nbuck-1; bi >= 0; bi--) { 252 1.11 pooka if (buckets[bi] != 0) { 253 1.11 pooka maxchain = buckets[bi]; 254 1.11 pooka break; 255 1.11 pooka } 256 1.11 pooka } 257 1.11 pooka if (maxchain == 0 || maxchain < symndx) 258 1.11 pooka break; 259 1.11 pooka 260 1.11 pooka /* 261 1.11 pooka * Then, traverse the last chain and count symbols. 262 1.11 pooka */ 263 1.11 pooka 264 1.11 pooka cursymcount = maxchain; 265 1.11 pooka ptr = buckets + nbuck + (maxchain - symndx); 266 1.11 pooka do { 267 1.11 pooka cursymcount++; 268 1.11 pooka } while ((*ptr++ & 1) == 0); 269 1.11 pooka } 270 1.11 pooka break; 271 1.11 pooka #endif 272 1.4 pooka case DT_SYMENT: 273 1.4 pooka DYNn_GETMEMBER(ed_base, i, d_un.d_val, edval); 274 1.4 pooka assert(edval == SYM_GETSIZE()); 275 1.4 pooka break; 276 1.1 pooka default: 277 1.1 pooka break; 278 1.1 pooka } 279 1.1 pooka i++; 280 1.1 pooka DYNn_GETMEMBER(ed_base, i, d_tag, ed_tag); 281 1.4 pooka } 282 1.1 pooka 283 1.4 pooka if (str_base == NULL || syms_base == NULL || 284 1.4 pooka curstrsize == 0 || cursymcount == 0) { 285 1.4 pooka fprintf(stderr, "could not find strtab, symtab or their sizes " 286 1.1 pooka "in %s\n", map->l_name); 287 1.1 pooka return ENOEXEC; 288 1.1 pooka } 289 1.1 pooka 290 1.1 pooka /* 291 1.1 pooka * Make sure we have enough space for the contents of the symbol 292 1.1 pooka * and string tables we are currently processing. The total used 293 1.1 pooka * space will be smaller due to undefined symbols we are not 294 1.1 pooka * interested in. 295 1.1 pooka */ 296 1.4 pooka symtab = reservespace(symtab, &symtabsize, 297 1.4 pooka symtaboff, cursymcount * SYM_GETSIZE()); 298 1.1 pooka strtab = reservespace(strtab, &strtabsize, strtaboff, curstrsize); 299 1.1 pooka if (symtab == NULL || strtab == NULL) { 300 1.1 pooka fprintf(stderr, "failed to reserve memory"); 301 1.1 pooka return ENOMEM; 302 1.1 pooka } 303 1.1 pooka 304 1.1 pooka /* iterate over all symbols in current symtab */ 305 1.4 pooka for (i = 0; i < cursymcount; i++) { 306 1.4 pooka const char *cursymname; 307 1.1 pooka int shndx, name; 308 1.1 pooka uintptr_t value; 309 1.1 pooka void *csym; 310 1.1 pooka 311 1.1 pooka SYMn_GETMEMBER(syms_base, i, st_shndx, shndx); 312 1.1 pooka SYMn_GETMEMBER(syms_base, i, st_value, value); 313 1.1 pooka if (shndx == SHN_UNDEF || value == 0) 314 1.1 pooka continue; 315 1.1 pooka 316 1.1 pooka /* get symbol name */ 317 1.1 pooka SYMn_GETMEMBER(syms_base, i, st_name, name); 318 1.1 pooka cursymname = name + str_base; 319 1.4 pooka 320 1.4 pooka /* 321 1.4 pooka * Only accept symbols which are decidedly in 322 1.4 pooka * the rump kernel namespace. 323 1.4 pooka * XXX: quirks, but they wouldn't matter here 324 1.4 pooka */ 325 1.4 pooka if (strncmp(cursymname, "rump", 4) != 0 && 326 1.4 pooka strncmp(cursymname, "RUMP", 4) != 0 && 327 1.4 pooka strncmp(cursymname, "__", 2) != 0) { 328 1.4 pooka continue; 329 1.4 pooka } 330 1.4 pooka 331 1.1 pooka memcpy(symtab + symtaboff, 332 1.4 pooka (const uint8_t *)syms_base + i*SYM_GETSIZE(),SYM_GETSIZE()); 333 1.1 pooka 334 1.1 pooka /* 335 1.1 pooka * set name to point at new strtab, offset symbol value 336 1.1 pooka * with lib base address. 337 1.1 pooka */ 338 1.1 pooka csym = symtab + symtaboff; 339 1.1 pooka SYMn_SETMEMBER(csym, 0, st_name, strtaboff); 340 1.1 pooka SYMn_GETMEMBER(csym, 0, st_value, value); 341 1.1 pooka SYMn_SETMEMBER(csym, 0, st_value,(intptr_t)(value+map->l_addr)); 342 1.1 pooka symtaboff += SYM_GETSIZE(); 343 1.1 pooka 344 1.1 pooka strcpy(strtab + strtaboff, cursymname); 345 1.1 pooka strtaboff += strlen(cursymname)+1; 346 1.1 pooka } 347 1.1 pooka 348 1.1 pooka return 0; 349 1.1 pooka } 350 1.1 pooka 351 1.3 pooka static void 352 1.13 pooka process_object(void *handle, 353 1.33 pgoyette rump_modinit_fn domodinit, rump_compload_fn docompload, 354 1.33 pgoyette rump_evcntattach_fn doevcntattach) 355 1.1 pooka { 356 1.3 pooka const struct modinfo *const *mi_start, *const *mi_end; 357 1.13 pooka struct rump_component *const *rc, *const *rc_end; 358 1.1 pooka 359 1.32 pgoyette struct sysctllog; 360 1.32 pgoyette typedef void sysctl_setup_func(struct sysctllog **); 361 1.32 pgoyette sysctl_setup_func *const *sfp, *const *sfp_end; 362 1.32 pgoyette 363 1.32 pgoyette struct evcnt *const *evp, *const *evp_end; 364 1.32 pgoyette 365 1.3 pooka mi_start = dlsym(handle, "__start_link_set_modules"); 366 1.1 pooka mi_end = dlsym(handle, "__stop_link_set_modules"); 367 1.13 pooka if (mi_start && mi_end) 368 1.13 pooka domodinit(mi_start, (size_t)(mi_end-mi_start)); 369 1.1 pooka 370 1.13 pooka rc = dlsym(handle, "__start_link_set_rump_components"); 371 1.13 pooka rc_end = dlsym(handle, "__stop_link_set_rump_components"); 372 1.13 pooka if (rc && rc_end) { 373 1.13 pooka for (; rc < rc_end; rc++) 374 1.13 pooka docompload(*rc); 375 1.13 pooka assert(rc == rc_end); 376 1.13 pooka } 377 1.32 pgoyette 378 1.32 pgoyette /* handle link_set_sysctl_funcs */ 379 1.32 pgoyette sfp = dlsym(handle, "__start_link_set_sysctl_funcs"); 380 1.32 pgoyette sfp_end = dlsym(handle, "__stop_link_set_sysctl_funcs"); 381 1.32 pgoyette if (sfp && sfp_end) { 382 1.32 pgoyette for (; sfp < sfp_end; sfp++) 383 1.32 pgoyette (**sfp)(NULL); 384 1.32 pgoyette assert(sfp == sfp_end); 385 1.32 pgoyette } 386 1.32 pgoyette 387 1.32 pgoyette /* handle link_set_evcnts */ 388 1.32 pgoyette evp = dlsym(handle, "__start_link_set_evcnts"); 389 1.32 pgoyette evp_end = dlsym(handle, "__stop_link_set_evcnts"); 390 1.32 pgoyette if (evp && evp_end) { 391 1.32 pgoyette for (; evp < evp_end; evp++) 392 1.33 pgoyette doevcntattach(*evp); 393 1.32 pgoyette assert(evp == evp_end); 394 1.32 pgoyette } 395 1.1 pooka } 396 1.1 pooka 397 1.1 pooka /* 398 1.1 pooka * Get the linkmap from the dynlinker. Try to load kernel modules 399 1.1 pooka * from all objects in the linkmap. 400 1.1 pooka */ 401 1.1 pooka void 402 1.1 pooka rumpuser_dl_bootstrap(rump_modinit_fn domodinit, 403 1.33 pgoyette rump_symload_fn symload, rump_compload_fn compload, 404 1.33 pgoyette rump_evcntattach_fn doevcntattach) 405 1.1 pooka { 406 1.13 pooka struct link_map *map, *origmap, *mainmap; 407 1.13 pooka void *mainhandle; 408 1.1 pooka int error; 409 1.1 pooka 410 1.8 pooka mainhandle = dlopen(NULL, RTLD_NOW); 411 1.27 justin /* Will be null if statically linked so just return */ 412 1.27 justin if (mainhandle == NULL) 413 1.27 justin return; 414 1.13 pooka if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) { 415 1.1 pooka fprintf(stderr, "warning: rumpuser module bootstrap " 416 1.1 pooka "failed: %s\n", dlerror()); 417 1.1 pooka return; 418 1.1 pooka } 419 1.13 pooka origmap = mainmap; 420 1.13 pooka 421 1.1 pooka /* 422 1.26 pooka * Use a heuristic to determine if we are static linked. 423 1.26 pooka * A dynamically linked binary should always have at least 424 1.26 pooka * two objects: itself and ld.so. 425 1.26 pooka * 426 1.26 pooka * In a statically linked binary with glibc the linkmap 427 1.26 pooka * contains some "info" that leads to a segfault. Since we 428 1.26 pooka * can't really do anything useful in here without ld.so, just 429 1.26 pooka * simply bail and let the symbol references in librump do the 430 1.26 pooka * right things. 431 1.26 pooka */ 432 1.26 pooka if (origmap->l_next == NULL && origmap->l_prev == NULL) { 433 1.26 pooka dlclose(mainhandle); 434 1.26 pooka return; 435 1.26 pooka } 436 1.26 pooka 437 1.26 pooka /* 438 1.1 pooka * Process last->first because that's the most probable 439 1.1 pooka * order for dependencies 440 1.1 pooka */ 441 1.1 pooka for (; origmap->l_next; origmap = origmap->l_next) 442 1.1 pooka continue; 443 1.1 pooka 444 1.1 pooka /* 445 1.1 pooka * Build symbol table to hand to the rump kernel. Do this by 446 1.1 pooka * iterating over all rump libraries and collecting symbol 447 1.1 pooka * addresses and relocation info. 448 1.1 pooka */ 449 1.1 pooka error = 0; 450 1.1 pooka for (map = origmap; map && !error; map = map->l_prev) { 451 1.13 pooka if (strstr(map->l_name, "librump") != NULL || map == mainmap) 452 1.14 pooka error = getsymbols(map, map == mainmap); 453 1.1 pooka } 454 1.1 pooka 455 1.1 pooka if (error == 0) { 456 1.1 pooka void *trimmedsym, *trimmedstr; 457 1.1 pooka 458 1.1 pooka /* 459 1.1 pooka * Allocate optimum-sized memory for storing tables 460 1.1 pooka * and feed to kernel. If memory allocation fails, 461 1.1 pooka * just give the ones with extra context (although 462 1.1 pooka * I'm pretty sure we'll die moments later due to 463 1.1 pooka * memory running out). 464 1.1 pooka */ 465 1.1 pooka if ((trimmedsym = malloc(symtaboff)) != NULL) { 466 1.1 pooka memcpy(trimmedsym, symtab, symtaboff); 467 1.1 pooka } else { 468 1.1 pooka trimmedsym = symtab; 469 1.1 pooka symtab = NULL; 470 1.1 pooka } 471 1.1 pooka if ((trimmedstr = malloc(strtaboff)) != NULL) { 472 1.1 pooka memcpy(trimmedstr, strtab, strtaboff); 473 1.1 pooka } else { 474 1.1 pooka trimmedstr = strtab; 475 1.1 pooka strtab = NULL; 476 1.1 pooka } 477 1.1 pooka symload(trimmedsym, symtaboff, trimmedstr, strtaboff); 478 1.1 pooka } 479 1.1 pooka free(symtab); 480 1.1 pooka free(strtab); 481 1.1 pooka 482 1.1 pooka /* 483 1.13 pooka * Next, load modules and components. 484 1.13 pooka * 485 1.13 pooka * Simply loop through all objects, ones unrelated to rump kernels 486 1.13 pooka * will not contain link_set_rump_components (well, not including 487 1.13 pooka * "sabotage", but that needs to be solved at another level anyway). 488 1.1 pooka */ 489 1.13 pooka for (map = origmap; map; map = map->l_prev) { 490 1.13 pooka void *handle; 491 1.2 pooka 492 1.13 pooka if (map == mainmap) { 493 1.13 pooka handle = mainhandle; 494 1.13 pooka } else { 495 1.2 pooka handle = dlopen(map->l_name, RTLD_LAZY); 496 1.2 pooka if (handle == NULL) 497 1.2 pooka continue; 498 1.13 pooka } 499 1.33 pgoyette process_object(handle, domodinit, compload, doevcntattach); 500 1.13 pooka if (map != mainmap) 501 1.2 pooka dlclose(handle); 502 1.2 pooka } 503 1.2 pooka } 504 1.1 pooka #else 505 1.12 pooka /* 506 1.18 pooka * no dynamic linking supported 507 1.12 pooka */ 508 1.2 pooka void 509 1.13 pooka rumpuser_dl_bootstrap(rump_modinit_fn domodinit, 510 1.33 pgoyette rump_symload_fn symload, rump_compload_fn compload, 511 1.33 pgoyette rump_evcntattach_fn doevcntattach) 512 1.2 pooka { 513 1.12 pooka 514 1.18 pooka return; 515 1.2 pooka } 516 1.1 pooka #endif 517