/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ │ above copyright notice and this permission notice appear in all copies. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/atomic.h" #include "libc/calls/calls.h" #include "libc/cosmo.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/kprintf.h" #include "libc/intrin/promises.internal.h" #include "libc/runtime/runtime.h" #include "libc/runtime/symbols.internal.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/prot.h" __static_yoink("__get_symbol"); struct SymbolTableLoader __symtab; static struct SymbolTable *GetSymbolTableFromZip(void) { int fd; struct SymbolTable *res = 0; if ((fd = open("/zip/.symtab." _ARCH_NAME, O_RDONLY)) != -1 || (fd = open("/zip/.symtab", O_RDONLY)) != -1) { void *map; ssize_t size; if ((size = lseek(fd, 0, SEEK_END)) != -1 && (map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) != MAP_FAILED) { res = map; } close(fd); } return res; } static struct SymbolTable *GetSymbolTableFromElf(void) { const char *path; if ((path = FindDebugBinary())) { return OpenSymbolTable(path); } else { return 0; } } static void GetSymbolTableInit(void) { if (!PLEDGED(RPATH)) return; int e = errno; if ((__symtab.st = GetSymbolTableFromZip())) { __symtab.st->names = (uint32_t *)((char *)__symtab.st + __symtab.st->names_offset); __symtab.st->name_base = (char *)((char *)__symtab.st + __symtab.st->name_base_offset); } if (!__symtab.st) { __symtab.st = GetSymbolTableFromElf(); } errno = e; } /** * Returns symbol table singleton. * * This uses multiple strategies to find the symbol table. The first * strategy, depends on whether or not the following is linked: * * __static_yoink("zipos"); * * In that case, the symbol table may be read from `/zip/.symtab.ARCH` * or `/zip/.symtab` which are generated by `o//tool/build/symtab.com` * or `o//tool/build/apelink.com`. * * The second strategy is to look for the ELF executable for the current * program. If you're running a .com binary, it'll look for the .com.dbg * file. If it's running the .com.dbg or .elf file, then it'll just read * the symbols from itself. In other cases, you can explicitly specify a * debug symbol binary via the `COMDBG` environment variable. * * When using pledge() security, it's recommended that this function get * called *before* calling pledge() if it lacks the rpath promise, so it * can load the symbols into memory before the filesystem goes away. * * @return symbol table, or NULL if not found */ struct SymbolTable *GetSymbolTable(void) { cosmo_once(&__symtab.once, GetSymbolTableInit); return __symtab.st; }