2022-04-26 04:16:05 +00:00
|
|
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
|
|
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
|
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
|
|
│ Copyright 2022 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/calls/calls.h"
|
2023-06-15 00:02:57 +00:00
|
|
|
#include "libc/dce.h"
|
2023-07-02 17:19:16 +00:00
|
|
|
#include "libc/elf/def.h"
|
2022-04-26 04:16:05 +00:00
|
|
|
#include "libc/elf/scalar.h"
|
|
|
|
#include "libc/elf/struct/ehdr.h"
|
2022-05-24 17:19:39 +00:00
|
|
|
#include "libc/elf/struct/phdr.h"
|
2022-04-26 04:16:05 +00:00
|
|
|
#include "libc/elf/struct/shdr.h"
|
|
|
|
#include "libc/elf/struct/sym.h"
|
2022-05-24 17:19:39 +00:00
|
|
|
#include "libc/elf/struct/verdaux.h"
|
|
|
|
#include "libc/elf/struct/verdef.h"
|
2023-10-03 02:25:19 +00:00
|
|
|
#include "libc/intrin/getauxval.h"
|
2022-09-13 06:10:38 +00:00
|
|
|
#include "libc/intrin/strace.h"
|
2022-04-26 04:16:05 +00:00
|
|
|
#include "libc/runtime/runtime.h"
|
2023-06-10 16:15:19 +00:00
|
|
|
#include "libc/str/str.h"
|
2022-04-26 04:16:05 +00:00
|
|
|
#include "libc/sysv/consts/auxv.h"
|
|
|
|
|
2023-06-15 00:02:57 +00:00
|
|
|
// needed to avoid asan restrictions on strcmp
|
|
|
|
static int StrCmp(const char *l, const char *r) {
|
|
|
|
size_t i = 0;
|
|
|
|
while (l[i] == r[i] && r[i])
|
|
|
|
++i;
|
|
|
|
return (l[i] & 255) - (r[i] & 255);
|
|
|
|
}
|
|
|
|
|
2022-05-24 17:19:39 +00:00
|
|
|
static inline int CheckDsoSymbolVersion(Elf64_Verdef *vd, int sym,
|
|
|
|
const char *name, char *strtab) {
|
|
|
|
Elf64_Verdaux *aux;
|
|
|
|
for (;; vd = (Elf64_Verdef *)((char *)vd + vd->vd_next)) {
|
|
|
|
if (!(vd->vd_flags & VER_FLG_BASE) &&
|
|
|
|
(vd->vd_ndx & 0x7fff) == (sym & 0x7fff)) {
|
|
|
|
aux = (Elf64_Verdaux *)((char *)vd + vd->vd_aux);
|
2023-06-15 00:02:57 +00:00
|
|
|
return !StrCmp(name, strtab + aux->vda_name);
|
2022-05-24 17:19:39 +00:00
|
|
|
}
|
|
|
|
if (!vd->vd_next) {
|
|
|
|
return 0;
|
2022-04-26 04:16:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-10-03 02:25:19 +00:00
|
|
|
* Returns address of "Virtual Dynamic Shared Object" function on Linux.
|
2022-04-26 04:16:05 +00:00
|
|
|
*/
|
2022-05-24 17:19:39 +00:00
|
|
|
void *__vdsosym(const char *version, const char *name) {
|
|
|
|
void *p;
|
|
|
|
size_t i;
|
2022-04-26 04:16:05 +00:00
|
|
|
Elf64_Ehdr *ehdr;
|
2022-05-24 17:19:39 +00:00
|
|
|
Elf64_Phdr *phdr;
|
|
|
|
char *strtab = 0;
|
|
|
|
size_t *dyn, base;
|
|
|
|
Elf64_Sym *symtab = 0;
|
|
|
|
uint16_t *versym = 0;
|
|
|
|
Elf_Symndx *hashtab = 0;
|
|
|
|
Elf64_Verdef *verdef = 0;
|
2023-10-03 02:25:19 +00:00
|
|
|
struct AuxiliaryValue av;
|
2022-05-24 17:19:39 +00:00
|
|
|
|
2023-10-03 02:25:19 +00:00
|
|
|
av = __getauxval(AT_SYSINFO_EHDR);
|
|
|
|
if (!av.isfound) {
|
|
|
|
KERNTRACE("__vdsosym() → missing AT_SYSINFO_EHDR");
|
2022-05-24 17:19:39 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-10-03 02:25:19 +00:00
|
|
|
ehdr = (void *)av.value;
|
2022-05-24 17:19:39 +00:00
|
|
|
phdr = (void *)((char *)ehdr + ehdr->e_phoff);
|
|
|
|
for (base = -1, dyn = 0, i = 0; i < ehdr->e_phnum;
|
|
|
|
i++, phdr = (void *)((char *)phdr + ehdr->e_phentsize)) {
|
|
|
|
switch (phdr->p_type) {
|
|
|
|
case PT_LOAD:
|
|
|
|
// modern linux uses the base address zero, but elders
|
|
|
|
// e.g. rhel7 uses the base address 0xffffffffff700000
|
|
|
|
base = (size_t)ehdr + phdr->p_offset - phdr->p_vaddr;
|
|
|
|
break;
|
|
|
|
case PT_DYNAMIC:
|
|
|
|
dyn = (void *)((char *)ehdr + phdr->p_offset);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dyn || base == -1) {
|
|
|
|
KERNTRACE("__vdsosym() → missing program headers");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; dyn[i]; i += 2) {
|
|
|
|
p = (void *)(base + dyn[i + 1]);
|
|
|
|
switch (dyn[i]) {
|
|
|
|
case DT_STRTAB:
|
|
|
|
strtab = p;
|
|
|
|
break;
|
|
|
|
case DT_SYMTAB:
|
|
|
|
symtab = p;
|
|
|
|
break;
|
|
|
|
case DT_HASH:
|
|
|
|
hashtab = p;
|
|
|
|
break;
|
|
|
|
case DT_VERSYM:
|
|
|
|
versym = p;
|
|
|
|
break;
|
|
|
|
case DT_VERDEF:
|
|
|
|
verdef = p;
|
|
|
|
break;
|
2022-04-26 04:16:05 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-24 17:19:39 +00:00
|
|
|
if (!strtab || !symtab || !hashtab) {
|
|
|
|
KERNTRACE("__vdsosym() → tables not found");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!verdef) {
|
|
|
|
versym = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < hashtab[1]; i++) {
|
|
|
|
if (ELF64_ST_TYPE(symtab[i].st_info) != STT_FUNC &&
|
|
|
|
ELF64_ST_TYPE(symtab[i].st_info) != STT_OBJECT &&
|
|
|
|
ELF64_ST_TYPE(symtab[i].st_info) != STT_NOTYPE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (ELF64_ST_BIND(symtab[i].st_info) != STB_GLOBAL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!symtab[i].st_shndx) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-06-15 00:02:57 +00:00
|
|
|
if (StrCmp(name, strtab + symtab[i].st_name)) {
|
2022-05-24 17:19:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (versym && !CheckDsoSymbolVersion(verdef, versym[i], version, strtab)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return (void *)(base + symtab[i].st_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
KERNTRACE("__vdsosym() → symbol not found");
|
2022-04-26 04:16:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|