aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/compiler-rt/lib/msan/msan_dl.cpp
diff options
context:
space:
mode:
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.cpp65
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