diff options
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/msan/msan_dl.cpp')
| -rw-r--r-- | contrib/llvm-project/compiler-rt/lib/msan/msan_dl.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/msan/msan_dl.cpp b/contrib/llvm-project/compiler-rt/lib/msan/msan_dl.cpp new file mode 100644 index 000000000000..4f9ba52cf47d --- /dev/null +++ b/contrib/llvm-project/compiler-rt/lib/msan/msan_dl.cpp @@ -0,0 +1,65 @@ +//===-- msan_dl.cpp -------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of MemorySanitizer. +// +// Helper functions for unpoisoning results of dladdr and dladdr1. +//===----------------------------------------------------------------------===// + +#include "msan_dl.h" + +#include <dlfcn.h> +#include <elf.h> +#include <link.h> + +#include "msan_poisoning.h" + +namespace __msan { + +void UnpoisonDllAddrInfo(void *info) { + Dl_info *ptr = (Dl_info *)(info); + __msan_unpoison(ptr, sizeof(*ptr)); + if (ptr->dli_fname) + __msan_unpoison(ptr->dli_fname, internal_strlen(ptr->dli_fname) + 1); + if (ptr->dli_sname) + __msan_unpoison(ptr->dli_sname, internal_strlen(ptr->dli_sname) + 1); +} + +#if SANITIZER_GLIBC +void UnpoisonDllAddr1ExtraInfo(void **extra_info, int flags) { + if (flags == RTLD_DL_SYMENT) { + __msan_unpoison(extra_info, sizeof(void *)); + + ElfW(Sym) *s = *((ElfW(Sym) **)(extra_info)); + __msan_unpoison(s, sizeof(ElfW(Sym))); + } else if (flags == RTLD_DL_LINKMAP) { + __msan_unpoison(extra_info, sizeof(void *)); + + struct link_map *map = *((struct link_map **)(extra_info)); + + // Walk forward + for (auto *ptr = map; ptr; ptr = ptr->l_next) { + __msan_unpoison(ptr, sizeof(struct link_map)); + if (ptr->l_name) + __msan_unpoison(ptr->l_name, internal_strlen(ptr->l_name) + 1); + } + + if (!map) + return; + + // Walk backward + for (auto *ptr = map->l_prev; ptr; ptr = ptr->l_prev) { + __msan_unpoison(ptr, sizeof(struct link_map)); + if (ptr->l_name) + __msan_unpoison(ptr->l_name, internal_strlen(ptr->l_name) + 1); + } + } +} +#endif + +} // namespace __msan |
