diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 3c6fe62e1aaf38939e6688587f951c809c1ee3cf..565ea795ac0e940da16a2fdc31a23e3490016b36 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -205,6 +205,12 @@ if(ANDROID) check_library_exists(log __android_log_write "" COMPILER_RT_HAS_LIBLOG) endif() +#OHOS_LOCAL begin +if(OHOS) + llvm_check_compiler_linker_flag(CXX "-Wl,-z,global" COMPILER_RT_HAS_Z_GLOBAL) +endif() +#OHOS_LOCAL end + # Architectures. # List of all architectures we can target. diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp index 817008253fc0ef55018041afd38b414ada9542bf..0a1a4a5535df82e8d3d7df7c22a9cc6af8adddd4 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -137,6 +137,18 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) CheckNoDeepBind(filename, flag); \ REAL(dlopen)(filename, flag); \ }) +// OHOS_LOCAL begin +#if SANITIZER_OHOS +#define COMMON_INTERCEPTOR_DLOPEN_IMPL(filename, flag, namespace, caller_addr, \ + extinfo) \ + ({ \ + if (flags()->strict_init_order) \ + StopInitOrderChecking(); \ + CheckNoDeepBind(filename, flag); \ + REAL(dlopen_impl)(filename, flag, namespace, caller_addr, extinfo); \ + }) +#endif +// OHOS_LOCAL end # define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() # define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) # define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp index 82236453157fa3b6be86233a917bb24afc2f3a79..1fc4a677a10c21c26a73e5fc0ff928cbb1795858 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -134,11 +134,22 @@ void RemoveANSIEscapeSequencesFromString(char *str) { *z = '\0'; } +#if SANITIZER_OHOS +// OHOS_LOCAL begin +void LoadedModule::set(const char *module_name, uptr base_address, bool instrumented) { + clear(); + full_name_ = internal_strdup(module_name); + base_address_ = base_address; + instrumented_ = instrumented; +} +#else void LoadedModule::set(const char *module_name, uptr base_address) { clear(); full_name_ = internal_strdup(module_name); base_address_ = base_address; } +// OHOS_LOCAL end +#endif void LoadedModule::set(const char *module_name, uptr base_address, ModuleArch arch, u8 uuid[kModuleUUIDSize], diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index c4153201a1a04632b1d23e23f89d646642e66003..787687db26d0bf6197ed965cf8cac761dbf93f06 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -807,7 +807,13 @@ class LoadedModule { internal_memset(uuid_, 0, kModuleUUIDSize); ranges_.clear(); } +#if SANITIZER_OHOS +// OHOS_LOCAL begin + void set(const char *module_name, uptr base_address, bool instrumented = false); +#else void set(const char *module_name, uptr base_address); +// OHOS_LOCAL end +#endif void set(const char *module_name, uptr base_address, ModuleArch arch, u8 uuid[kModuleUUIDSize], bool instrumented); void setUuid(const char *uuid, uptr size); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index c489cb2979f1835b2310484fbbcf4fd044ee228a..32a9e88f6711daddcefbaacc197901647bc5307f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -281,6 +281,15 @@ extern const short *_tolower_tab_; ({ CheckNoDeepBind(filename, flag); REAL(dlopen)(filename, flag); }) #endif +#if SANITIZER_OHOS +// OHOS_LOCAL begin +#ifndef COMMON_INTERCEPTOR_DLOPEN_IMPL +#define COMMON_INTERCEPTOR_DLOPEN_IMPL(filename, flag, namespace, caller_addr, extinfo) \ + ({ CheckNoDeepBind(filename, flag); REAL(dlopen_impl)(filename, flag, namespace, caller_addr, extinfo); }) +#endif +// OHOS_LOCAL end +#endif + #ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0; #endif @@ -6534,6 +6543,24 @@ INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) { #endif #if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE +// OHOS_LOCAL begin +#if SANITIZER_OHOS +INTERCEPTOR(void*, dlopen_impl, const char *filename, int flag, const char *ns, const void *caller_addr, + const void *extinfo) { + void *ctx; + COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen_impl, filename, flag, ns, caller_addr, extinfo); + if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0); + void *res = COMMON_INTERCEPTOR_DLOPEN_IMPL(filename, flag, ns, caller_addr, extinfo); + Symbolizer::GetOrInit()->InvalidateModuleList(); + COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res); + return res; +} + +#define INIT_DLOPEN_DLCLOSE \ + COMMON_INTERCEPT_FUNCTION(dlopen_impl); \ + COMMON_INTERCEPT_FUNCTION(dlclose); + +#else INTERCEPTOR(void*, dlopen, const char *filename, int flag) { void *ctx; COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag); @@ -6544,6 +6571,12 @@ INTERCEPTOR(void*, dlopen, const char *filename, int flag) { return res; } +#define INIT_DLOPEN_DLCLOSE \ + COMMON_INTERCEPT_FUNCTION(dlopen); \ + COMMON_INTERCEPT_FUNCTION(dlclose); +#endif +// OHOS_LOCAL end + INTERCEPTOR(int, dlclose, void *handle) { void *ctx; COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle); @@ -6552,9 +6585,6 @@ INTERCEPTOR(int, dlclose, void *handle) { COMMON_INTERCEPTOR_LIBRARY_UNLOADED(); return res; } -#define INIT_DLOPEN_DLCLOSE \ - COMMON_INTERCEPT_FUNCTION(dlopen); \ - COMMON_INTERCEPT_FUNCTION(dlclose); #else #define INIT_DLOPEN_DLCLOSE #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp index b7fc9444cc66b326c833d2779d928339d027fc32..36294dbcc6aee4c1dbfc9263e2863343aaee1cf5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp @@ -28,11 +28,15 @@ void LibIgnore::AddIgnoredLibrary(const char *name_templ) { kMaxLibs); Die(); } + VPrintf(2, "[Ignore] Add ignored library %s.\n", name_templ); // OHOS_LOCAL Lib *lib = &libs_[count_++]; lib->templ = internal_strdup(name_templ); lib->name = nullptr; lib->real_name = nullptr; lib->loaded = false; +#if SANITIZER_OHOS + lib->idx = 0; // OHOS_LOCAL +#endif } void LibIgnore::OnLibraryLoaded(const char *name) { @@ -70,8 +74,25 @@ void LibIgnore::OnLibraryLoaded(const char *name) { Die(); } loaded = true; - if (lib->loaded) + if (lib->loaded) { +#if SANITIZER_OHOS + // OHOS_LOCAL begin + if (ignored_code_ranges_[lib->idx].begin == range.beg) { + continue; + } + VReport(1, + "[Ignore] invalidate ignore code range 0x%zx-0x%zx from " + "library '%s' idx:0x%zx\n", + ignored_code_ranges_[lib->idx].begin, + ignored_code_ranges_[lib->idx].end, lib->name, lib->idx); + // It is possible because of dlclose. + atomic_store(&(ignored_code_ranges_[lib->idx].invalid), 1, + memory_order_release); + // OHOS_LOCAL end +#else continue; +#endif + } VReport(1, "Matched called_from_lib suppression '%s' against library" " '%s'\n", @@ -80,7 +101,16 @@ void LibIgnore::OnLibraryLoaded(const char *name) { lib->name = internal_strdup(mod.full_name()); const uptr idx = atomic_load(&ignored_ranges_count_, memory_order_relaxed); +#if SANITIZER_OHOS + lib->idx = idx; // OHOS_LOCAL +#endif CHECK_LT(idx, ARRAY_SIZE(ignored_code_ranges_)); + // OHOS_LOCAL + VReport(1, + "[Ignore] Adding ignore code range 0x%zx-0x%zx from library " + "'%s' idx:0x%zx\n", + ignored_code_ranges_[idx].begin, ignored_code_ranges_[idx].end, + lib->name, lib->idx); ignored_code_ranges_[idx].begin = range.beg; ignored_code_ranges_[idx].end = range.end; atomic_store(&ignored_ranges_count_, idx + 1, memory_order_release); @@ -88,14 +118,75 @@ void LibIgnore::OnLibraryLoaded(const char *name) { } } if (lib->loaded && !loaded) { +#if SANITIZER_OHOS + // OHOS_LOCAL begin + VReport(1, + "[Ignore] invalidate ignore code range 0x%zx-0x%zx from library " + "'%s' idx:0x%zx\n", + ignored_code_ranges_[lib->idx].begin, + ignored_code_ranges_[lib->idx].end, lib->name, lib->idx); + // Invalidate the address range when the library is unloaded. + lib->loaded = false; + atomic_store(&(ignored_code_ranges_[lib->idx].invalid), 1, + memory_order_release); + // OHOS_LOCAL end +#else Report("%s: library '%s' that was matched against called_from_lib" " suppression '%s' is unloaded\n", SanitizerToolName, lib->name, lib->templ); Die(); +#endif } } // Track instrumented ranges. +#if SANITIZER_OHOS + // OHOS_LOCAL begin + if (track_instrumented_libs_) { + for (const auto &mod : modules) { + for (const auto &range : mod.ranges()) { + if (!range.executable) + continue; + if (!mod.instrumented()) { + // Try to find if it overlap some instrumented ranges, if true, we + // should invalidate them, This is happen when we dlclose an + // instrumented module and reload an uninstrumented module. + auto InvalidateCallback = [&](uptr idx) -> void { + VReport(1, + "[Ignore] invalidate instrumented code range 0x%zx-0x%zx " + "from library '%s'\n", + instrumented_code_ranges_[idx].begin, + instrumented_code_ranges_[idx].end, mod.full_name()); + atomic_store(&(instrumented_code_ranges_[idx].invalid), 1, + memory_order_release); + }; + IterateOverlappingRanges(range.beg, range.end, InvalidateCallback); + continue; + } + // we need to check if whole range is instrumented, consider the + // following scenario: + // - instrumented module A is loaded at address[1-10] + // - instrumented module B is loaded at address[20-30] + // - unload A and B + // - instrumented module C is load at address[5-25] + // we need to make sure [10-20] will be instrumented so we should + // compare the whole range. + if (IsAddressRangeInstrumented(range.beg, range.end)) + continue; + VReport(1, "Adding instrumented range 0x%zx-0x%zx from library '%s'\n", + range.beg, range.end, mod.full_name()); + const uptr idx = + atomic_load(&instrumented_ranges_count_, memory_order_relaxed); + CHECK_LT(idx, ARRAY_SIZE(instrumented_code_ranges_)); + instrumented_code_ranges_[idx].begin = range.beg; + instrumented_code_ranges_[idx].end = range.end; + atomic_store(&instrumented_ranges_count_, idx + 1, + memory_order_release); + } + } + } + // OHOS_LOCAL end +#else if (track_instrumented_libs_) { for (const auto &mod : modules) { if (!mod.instrumented()) @@ -117,6 +208,7 @@ void LibIgnore::OnLibraryLoaded(const char *name) { } } } +#endif } void LibIgnore::OnLibraryUnloaded() { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h index 18e4d83ed77fb8d3a9db0f12e974b308fc3ac948..8bf9459741f235905b9784f1c600104f09633b21 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h @@ -20,7 +20,9 @@ #include "sanitizer_common.h" #include "sanitizer_atomic.h" #include "sanitizer_mutex.h" - +#if SANITIZER_OHOS +#include "sanitizer_vector.h" // OHOS_LOCAL +#endif namespace __sanitizer { class LibIgnore { @@ -48,17 +50,32 @@ class LibIgnore { // Checks whether the provided PC belongs to an instrumented module. bool IsPcInstrumented(uptr pc) const; - private: +#if SANITIZER_OHOS + bool IsAddressRangeInstrumented(uptr beg, uptr end) const; + + // Find all instrumented ranges which is overlapped by this range. + template + void IterateOverlappingRanges(uptr beg, uptr end, + Callback &callback) const; // OHOS_LOCAL +#endif + +private: struct Lib { char *templ; char *name; char *real_name; // target of symlink bool loaded; +#if SANITIZER_OHOS + uptr idx; // OHOS_LOCAL +#endif }; struct LibCodeRange { uptr begin; uptr end; +#if SANITIZER_OHOS + atomic_uint8_t invalid; // OHOS_LOCAL +#endif }; inline bool IsInRange(uptr pc, const LibCodeRange &range) const { @@ -90,7 +107,13 @@ class LibIgnore { inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const { const uptr n = atomic_load(&ignored_ranges_count_, memory_order_acquire); for (uptr i = 0; i < n; i++) { +#if SANITIZER_OHOS + if (IsInRange(pc, ignored_code_ranges_[i]) && + !atomic_load(&(ignored_code_ranges_[i].invalid), + memory_order_acquire)) { // OHOS_LOCAL +#else if (IsInRange(pc, ignored_code_ranges_[i])) { +#endif *pc_in_ignored_lib = true; return true; } @@ -104,12 +127,56 @@ inline bool LibIgnore::IsIgnored(uptr pc, bool *pc_in_ignored_lib) const { inline bool LibIgnore::IsPcInstrumented(uptr pc) const { const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire); for (uptr i = 0; i < n; i++) { +#if SANITIZER_OHOS + if (IsInRange(pc, instrumented_code_ranges_[i]) && + !atomic_load(&(instrumented_code_ranges_[i].invalid), + memory_order_acquire)) // OHOS_LOCAL +#else if (IsInRange(pc, instrumented_code_ranges_[i])) +#endif + return true; + } + return false; +} +#if SANITIZER_OHOS +// OHOS_LOCAL begin +inline bool LibIgnore::IsAddressRangeInstrumented(uptr beg, uptr end) const { + const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire); + for (uptr i = 0; i < n; i++) { + if ((beg == instrumented_code_ranges_[i].begin) && + (end == instrumented_code_ranges_[i].end) && + !atomic_load(&(instrumented_code_ranges_[i].invalid), + memory_order_acquire)) // OHOS_LOCAL return true; } return false; } +inline bool IsOverlapping(uptr beg1, uptr end1, uptr beg2, uptr end2) { + if (beg1 < end2 && beg2 < end1) { + return true; + } + return false; +} + +template +void LibIgnore::IterateOverlappingRanges(uptr beg, uptr end, + Callback &callback) const { + const uptr n = atomic_load(&instrumented_ranges_count_, memory_order_acquire); + for (uptr i = 0; i < n; i++) { + if (IsOverlapping(beg, end, instrumented_code_ranges_[i].begin, + instrumented_code_ranges_[i].end)) { + if (!atomic_load(&(instrumented_code_ranges_[i].invalid), + memory_order_acquire)) { + callback(i); + } + } + } + return; +} +// OHOS_LOCAL end +#endif + } // namespace __sanitizer #endif // SANITIZER_LIBIGNORE_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 2d72a21b711ec049888dac9a574f9267d9428387..7d1315255005f08b30826e3aff8368d0768a174b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -11,6 +11,7 @@ // sanitizer_libc.h. //===----------------------------------------------------------------------===// +#include "sanitizer_interface_internal.h" // OHOS_LOCAL #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ @@ -2290,7 +2291,56 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } +#if SANITIZER_OHOS +// OHOS_LOCAL begin +static bool ShouldCheckInterceptors() { + const char *sanitizer_names[] = {"AddressSanitizer", "ThreadSanitizer"}; + size_t count = sizeof(sanitizer_names) / sizeof(sanitizer_names[0]); + for (size_t i = 0; i < count; i++) { + if (internal_strcmp(sanitizer_names[i], SanitizerToolName) == 0) + return true; + } + return false; +} + +// We need to make sure that dlopen_impl interceptors really work. +// 1. Check sanitizer library has dlopen_impl symbol. +// 2. Check musl has dlopen_impl symbol. +// 3. Check first dlopen_impl symbol is located in sanitizer library. +static void VerifyInterceptorsWorking() { + if (!common_flags()->verify_interceptors || !ShouldCheckInterceptors()) + return; + + Dl_info info_dlopen_impl_default; + RAW_CHECK( + dladdr(dlsym(RTLD_DEFAULT, "dlopen_impl"), &info_dlopen_impl_default)); + + Dl_info info_dlopen_impl_next; + RAW_CHECK(dladdr(dlsym(RTLD_NEXT, "dlopen_impl"), &info_dlopen_impl_next)); + + Dl_info info_runtime; + RAW_CHECK(dladdr((void *)__sanitizer_report_error_summary, &info_runtime)); + + if (internal_strcmp(info_dlopen_impl_default.dli_fname, + info_runtime.dli_fname) != 0) { + Report( + "ERROR: Interceptor dlopen_impl are not working. This may be because " + "%s is " + "loaded too late (e.g. via dlopen). first dlopen_impl addr:%p file:%s " + "second dlopen_impl addr:%p file:%s.\n", + info_runtime.dli_fname, info_dlopen_impl_default.dli_saddr, + info_dlopen_impl_default.dli_fname, info_dlopen_impl_next.dli_saddr, + info_dlopen_impl_next.dli_fname); + RAW_CHECK("interceptors not installed" && 0); + } +} +// OHOS_LOCAL end +#endif + void InitializePlatformEarly() { +#if SANITIZER_OHOS && SANITIZER_INTERCEPT_DLOPEN_DLCLOSE + VerifyInterceptorsWorking(); // OHOS_LOCAL +#endif // Do nothing. } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index 785c399d02384e18d68e315ac1bad499742bccf6..4f330ffa10b0581f8886bc1f6617e19866d38105 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -645,12 +645,148 @@ struct DlIteratePhdrData { bool first; }; +#if SANITIZER_OHOS +// OHOS_LOCAL begin +class DynamicSegment { + ElfW(Addr) base_addr; + size_t symbol_count; + ElfW(Sym *) symbol_table; + const char *string_table; + + public: + DynamicSegment(ElfW(Addr) base_addr, ElfW(Addr) segment_addr) + : base_addr(base_addr), + symbol_count(0), + symbol_table(nullptr), + string_table(nullptr) { + initialize(segment_addr); + CHECK(symbol_count >= 0 && symbol_table && string_table); // OHOS_LOCAL + } + + size_t symbolCount() const { return symbol_count; } + + const char *getSymbolName(size_t index) const { + auto str_index = symbol_table[index].st_name; + return &string_table[str_index]; + } + + private: + // Elf_Addr -> dereferenceable pointer + template + Type *toPtr(ElfW(Addr) addr_or_offset) const { + bool offset = addr_or_offset < base_addr; + ElfW(Addr) ptr = offset ? (base_addr + addr_or_offset) : addr_or_offset; + return reinterpret_cast(ptr); + } + + void initialize(ElfW(Addr) segment_addr) { + auto *entry = toPtr(segment_addr); + for (; entry->d_tag != DT_NULL; entry++) { + auto addr = entry->d_un.d_ptr; + switch (entry->d_tag) { + case DT_HASH: + symbol_count = getSymbolCountFromHash(addr); + break; + case DT_GNU_HASH: + // DT_HASH takes precedence over DT_GNU_HASH + if (symbol_count > 0) + break; + symbol_count = getSymbolCountFromGnuHash(addr); + break; + case DT_SYMTAB: + CHECK_EQ(symbol_table, nullptr); + symbol_table = toPtr(addr); + break; + case DT_STRTAB: + CHECK_EQ(string_table, nullptr); + string_table = toPtr(addr); + break; + } + } + } + + size_t getSymbolCountFromHash(ElfW(Addr) hashtable_addr) const { + struct ht_header { + uint32_t bucket_count; + uint32_t chain_count; + }; + return toPtr(hashtable_addr)->chain_count; + } + + size_t getSymbolCountFromGnuHash(ElfW(Addr) hashtable_addr) const { + struct ht_header { + uint32_t bucket_count; + uint32_t symoffset; + uint32_t bloom_size; + uint32_t bloom_shift; + }; + auto header = toPtr(hashtable_addr); + auto word_size = FIRST_32_SECOND_64(sizeof(uint32_t), sizeof(uint64_t)); + auto buckets_addr = + hashtable_addr + sizeof(ht_header) + (word_size * header->bloom_size); + auto buckets = toPtr(buckets_addr); + auto chains_addr = + buckets_addr + (header->bucket_count * sizeof(buckets[0])); + auto chains = toPtr(chains_addr); + + // Locate the chain that handles the largest index bucket. + uint32_t last_symbol = 0; + for (uint32_t i = 0; i < header->bucket_count; i++) { + last_symbol = Max(buckets[i], last_symbol); + } + + // OHOS_LOCAL + if (!last_symbol) { + return 0; + } + + // Walk the bucket's chain to add the chain length to the total. + uint32_t chain_entry; + do { + chain_entry = chains[last_symbol - header->symoffset]; + last_symbol++; + } while ((chain_entry & 1) == 0); + + return last_symbol; + } +}; + +static bool IsModuleInstrumented(dl_phdr_info *info) { + // Iterate all headers of the library. + for (size_t header = 0; header < info->dlpi_phnum; header++) { + // We are only interested in dynamic segments. + if (info->dlpi_phdr[header].p_type != PT_DYNAMIC) + continue; + + auto base_addr = info->dlpi_addr; + auto segment_addr = info->dlpi_phdr[header].p_vaddr; + DynamicSegment segment(base_addr, segment_addr); + + // Iterate symbol table. + for (size_t i = 0; i < segment.symbolCount(); i++) { + auto *name = segment.getSymbolName(i); + if (internal_strcmp(name, "__tsan_init") == 0) + return true; + } + } + return false; +} +// OHOS_LOCAL end +#endif + static int AddModuleSegments(const char *module_name, dl_phdr_info *info, InternalMmapVectorNoCtor *modules) { if (module_name[0] == '\0') return 0; LoadedModule cur_module; +#if SANITIZER_OHOS +// OHOS_LOCAL begin + bool instrumented = IsModuleInstrumented(info); + cur_module.set(module_name, info->dlpi_addr, instrumented); +#else cur_module.set(module_name, info->dlpi_addr); +// OHOS_LOCAL end +#endif for (int i = 0; i < (int)info->dlpi_phnum; i++) { const Elf_Phdr *phdr = &info->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 66ace37d4d6256f8efb7db99c34df2164e0c5ad1..81febbdca4347d703e4b91c2d964c421cd2e3008 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -450,9 +450,8 @@ #define SANITIZER_INTERCEPT_FCLOSE SI_POSIX #ifndef SANITIZER_INTERCEPT_DLOPEN_DLCLOSE -// OHOS_LOCAL -#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \ - (SI_FREEBSD || SI_NETBSD || (SI_LINUX_NOT_ANDROID && !SI_OHOS) || SI_MAC || SI_SOLARIS) +#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \ + (SI_FREEBSD || SI_NETBSD || (SI_LINUX_NOT_ANDROID) || SI_MAC || SI_SOLARIS) #endif #define SANITIZER_INTERCEPT_GETPASS \ diff --git a/compiler-rt/lib/tsan/rtl/CMakeLists.txt b/compiler-rt/lib/tsan/rtl/CMakeLists.txt index e71268eea1fbc15f19dd7e8fb8c293a5fcc0e8b8..af3c9a2de500458cfa37c4c7ced45703bcf28262 100644 --- a/compiler-rt/lib/tsan/rtl/CMakeLists.txt +++ b/compiler-rt/lib/tsan/rtl/CMakeLists.txt @@ -11,6 +11,17 @@ set(TSAN_RTL_DYNAMIC_CFLAGS ${TSAN_RTL_CFLAGS}) list(REMOVE_ITEM TSAN_RTL_DYNAMIC_CFLAGS -fPIE) set(TSAN_DYNAMIC_LINK_LIBS ${SANITIZER_CXX_ABI_LIBRARIES} ${SANITIZER_COMMON_LINK_LIBS}) +#OHOS_LOCAL +set(TSAN_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) + +#OHOS_LOCAL begin +if(OHOS) +# Put tsan library in the global group so that libraries which don't depend on tsan can also find symbols from tsan. + if (COMPILER_RT_HAS_Z_GLOBAL) + list(APPEND TSAN_DYNAMIC_LINK_FLAGS -Wl,-z,global) + endif() +endif() +#OHOS_LOCAL end append_list_if(COMPILER_RT_HAS_LIBDL dl TSAN_DYNAMIC_LINK_LIBS) append_list_if(COMPILER_RT_HAS_LIBM m TSAN_DYNAMIC_LINK_LIBS) @@ -142,7 +153,8 @@ if(APPLE) RTSanitizerCommonSymbolizer RTUbsan CFLAGS ${TSAN_RTL_CFLAGS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} + #OHOS_LOCAL + LINK_FLAGS ${TSAN_DYNAMIC_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} LINK_LIBS ${TSAN_LINK_LIBS} objc PARENT_TARGET tsan) add_compiler_rt_object_libraries(RTTsan_dynamic @@ -264,7 +276,8 @@ else() ADDITIONAL_HEADERS ${TSAN_HEADERS} CFLAGS ${TSAN_RTL_DYNAMIC_CFLAGS} LINK_LIBS ${TSAN_DYNAMIC_LINK_LIBS} - LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} + #OHOS_LOCAL + LINK_FLAGS ${TSAN_DYNAMIC_LINK_FLAGS} PARENT_TARGET tsan) add_sanitizer_rt_symbols(clang_rt.tsan ARCHS ${arch} diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.inc b/compiler-rt/lib/tsan/rtl/tsan_flags.inc index 731d776cc893e7a82b57c35178b834ff56751724..0846c2af100c8c9cc0b408fcbbddcdda9021a2e7 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_flags.inc +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.inc @@ -42,6 +42,9 @@ TSAN_FLAG( TSAN_FLAG(bool, force_background_thread, false, "If set, eagerly launch a background thread for memory reclamation " "instead of waiting for a user call to pthread_create.") +// OHOS_LOCAL +TSAN_FLAG(bool, disable_background_thread, SANITIZER_OHOS ? true : false, + "If set, background thread will never be started, used where multithreading is not supported") TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.") TSAN_FLAG(int, atexit_sleep_ms, 1000, "Sleep in main thread before exiting for that many ms " @@ -72,7 +75,8 @@ TSAN_FLAG(bool, die_after_fork, true, TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.") TSAN_FLAG(bool, ignore_interceptors_accesses, SANITIZER_APPLE ? true : false, "Ignore reads and writes from all interceptors.") -TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_APPLE ? true : false, +// OHOS_LOCAL +TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_APPLE || SANITIZER_OHOS ? true : false, "Interceptors should only detect races when called from instrumented " "modules.") TSAN_FLAG(bool, shared_ptr_interceptor, true, diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 825814f54d824a1c24b169c041682d712029e957..6b0e255f6db302e1c44fed6e18428f10f0e0ef15 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -2391,7 +2391,20 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, ThreadIgnoreEnd(thr); \ res; \ }) - +// OHOS_LOCAL begin +#if SANITIZER_OHOS +#define COMMON_INTERCEPTOR_DLOPEN_IMPL(filename, flag, namespace, caller_addr, \ + extinfo) \ + ({ \ + CheckNoDeepBind(filename, flag); \ + ThreadIgnoreBegin(thr, 0); \ + void *res = \ + REAL(dlopen_impl)(filename, flag, namespace, caller_addr, extinfo); \ + ThreadIgnoreEnd(thr); \ + res; \ + }) +#endif +// OHOS_LOCAL end #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ libignore()->OnLibraryLoaded(filename) diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp index 71874aad8dc5e84a730390108eb2e627c96c99fb..89960059d42a954b4131f8ff38d39f1cb57ffc72 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp @@ -107,6 +107,9 @@ void CheckAndProtect() { break; Printf("FATAL: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n", segment.start, segment.end); +#if SANITIZER_OHOS + DumpProcessMap(); // OHOS_LOCAL +#endif Die(); } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp index 5b4c7a0e4bdb1af84e7a9e74acd4b23a92849d1a..f3702a52f6c517a43530b44ae5a481d5ae5c4286 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -456,6 +456,8 @@ static bool InitializeMemoryProfiler() { } static void *BackgroundThread(void *arg) { + VReport(1, "%s: Started BackgroundThread\n", + SanitizerToolName); // OHOS_LOCAL // This is a non-initialized non-user thread, nothing to see here. // We don't use ScopedIgnoreInterceptors, because we want ignores to be // enabled even when the thread function exits (e.g. during pthread thread @@ -503,6 +505,7 @@ static void *BackgroundThread(void *arg) { u64 last = atomic_load(&ctx->last_symbolize_time_ns, memory_order_relaxed); if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) { + VReport(1, "ThreadSanitizer: flushing symbolizer\n"); // OHOS_LOCAL Lock l(&ctx->report_mtx); ScopedErrorReportLock l2; SymbolizeFlush(); @@ -514,14 +517,28 @@ static void *BackgroundThread(void *arg) { } static void StartBackgroundThread() { - ctx->background_thread = internal_start_thread(&BackgroundThread, 0); + // OHOS_LOCAL begin + if (!flags()->disable_background_thread) { + ctx->background_thread = internal_start_thread(&BackgroundThread, 0); + } else { + // Appspawn does not allow the use of multi-threading so we don't start this + // thread. + return; + } + // OHOS_LOCAL end } #ifndef __mips__ static void StopBackgroundThread() { - atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed); - internal_join_thread(ctx->background_thread); - ctx->background_thread = 0; + // OHOS_LOCAL begin + if (!flags()->disable_background_thread) { + atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed); + internal_join_thread(ctx->background_thread); + ctx->background_thread = 0; + } else { + return; + } + // OHOS_LOCAL end } #endif #endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp index 444f210390cc9a00b7b981d4eb43eb38d3133e7d..706b12a841e1b8da8cecc41b64dfa6a88a11b4ca 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp @@ -652,6 +652,9 @@ bool OutputReport(ThreadState *thr, const ScopedReport &srep) { Lock lock(&ctx->fired_suppressions_mtx); FiredSuppression s = {srep.GetReport()->typ, pc_or_addr, supp}; ctx->fired_suppressions.push_back(s); + // OHOS_LOCAL + VPrintf(2, "[Suppression] Suppression hit type:%s file:%s pc:0x%zx.\n", + supp->type, supp->templ, pc_or_addr); } { bool suppressed = OnReport(rep, pc_or_addr != 0); @@ -679,6 +682,11 @@ bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace) { if (trace.trace[j] == s->pc_or_addr) { if (s->supp) atomic_fetch_add(&s->supp->hit_count, 1, memory_order_relaxed); + // OHOS_LOCAL + VPrintf( + 2, + "[Suppression] Fired suppression hit type:%s file:%s pc:0x%zx.\n", + s->supp->type, s->supp->templ, s->pc_or_addr); return true; } } diff --git a/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp b/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp index 117a761af91fc876eb3a4926516286c47c363a39..4dadd579ff3a81b2098ddf64ba69b5ef87ef0d0e 100644 --- a/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp @@ -1,6 +1,9 @@ // Test that gc-sections-friendly instrumentation of globals does not introduce // false negatives with the BFD linker. // RUN: %clangxx_asan -fuse-ld=bfd -Wl,-gc-sections -ffunction-sections -fdata-sections -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// +// OHOS_LOCAL +// UNSUPPORTED: ohos_family #include int main(int argc, char **argv) { diff --git a/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cpp b/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cpp index 3037b232926ee05e7c4e927da96a4b7b2a563136..7cfc708aebc21dfd47227ac530a6d87a54bc91c6 100644 --- a/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cpp @@ -1,4 +1,7 @@ // RUN: %clangxx_asan %s -o %t && %run %t | FileCheck %s +// +// OHOS_LOCAL +// UNSUPPORTED: ohos_family #include diff --git a/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cpp b/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cpp index 7f37727b2eeb10cb5501a43733d3990be91784b5..4905e15162242a92574dd0954ed3ea19a3699d5f 100644 --- a/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cpp @@ -1,5 +1,10 @@ // Check that we properly report mmap failure. // RUN: %clangxx_asan %s -o %t && not %run %t 2>&1 | FileCheck %s +// +// OHOS_LOCAL +// FIXME: timed out test +// XFAIL: ohos_family + #include #include #include diff --git a/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp b/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp index 8fed52092be8377e0f2c12d9414df41312e2ea55..eec592c8fbee02f08ba05422587d4d7feaee9315 100644 --- a/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp @@ -1,5 +1,5 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 -// XFAIL: android && !ohos_family +// XFAIL: android // // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 // Regression test for diff --git a/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cpp b/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cpp index cb613f53577a7fd0580f594f03ec3a4351c37674..d34e8db9e3e7030dd1eae829639a3737d65124f8 100644 --- a/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cpp +++ b/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cpp @@ -10,6 +10,10 @@ // // FIXME: Windows doesn't implement mmap_limit_mb. // XFAIL: windows-msvc +// +// OHOS_LOCAL +// FIXME: timed out test +// XFAIL: ohos_family #include #include diff --git a/compiler-rt/test/asan/TestCases/Posix/readv.cpp b/compiler-rt/test/asan/TestCases/Posix/readv.cpp index 27436a1ad3d962c1adadc7722bc3e14c1e2a697a..79a4c9cefb0c817252a23bdcd7d319159d2d0629 100644 --- a/compiler-rt/test/asan/TestCases/Posix/readv.cpp +++ b/compiler-rt/test/asan/TestCases/Posix/readv.cpp @@ -23,7 +23,13 @@ int main() { iov[0].iov_len = 5; iov[1].iov_base = buf + 10; iov[1].iov_len = 2000; +// OHOS_LOCAL begin +#if defined(__OHOS__) + int fd = open("/etc/resolv.conf", O_RDONLY); +#else int fd = open("/etc/hosts", O_RDONLY); +#endif +// OHOS_LOCAL end assert(fd > 0); readv(fd, iov, 2); // CHECK: WRITE of size 5 at diff --git a/compiler-rt/test/asan/TestCases/Posix/wait4.cpp b/compiler-rt/test/asan/TestCases/Posix/wait4.cpp index 1e574d99fe00c6967f256674a494f6fb6bc8ea72..a806a0c7badfd07292e2aac7c1678156c2728308 100644 --- a/compiler-rt/test/asan/TestCases/Posix/wait4.cpp +++ b/compiler-rt/test/asan/TestCases/Posix/wait4.cpp @@ -4,7 +4,7 @@ // RUN: %clangxx_asan -DWAIT4_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s -// XFAIL: android +// XFAIL: android && !ohos_family // UNSUPPORTED: darwin #include diff --git a/compiler-rt/test/asan/TestCases/large_func_test.cpp b/compiler-rt/test/asan/TestCases/large_func_test.cpp index 563c1458c966e40b37902153536d181019af62a7..3a4181e618bac05e2023c089e1204e623eac4fc8 100644 --- a/compiler-rt/test/asan/TestCases/large_func_test.cpp +++ b/compiler-rt/test/asan/TestCases/large_func_test.cpp @@ -29,6 +29,8 @@ static void LargeFunction(int *x, int zero) { // CHECK-Windows:{{#0 0x.* in LargeFunction.*large_func_test.cpp:}}[[@LINE-5]] // CHECK-FreeBSD:{{#0 0x.* in LargeFunction.*large_func_test.cpp:}}[[@LINE-6]] // CHECK-Darwin: {{#0 0x.* in .*LargeFunction.*large_func_test.cpp}}:[[@LINE-7]] + // OHOS_LOCAL + // CHECK-OHOS: {{#0 0x.* in LargeFunction.*large_func_test.cpp:}}[[@LINE-9]] x[10]++; x[11]++; @@ -53,7 +55,9 @@ int main(int argc, char **argv) { // CHECK-Windows:{{ #0 0x.* in operator new}} // CHECK-FreeBSD:{{ #0 0x.* in operator new}} // CHECK-Darwin: {{ #0 0x.* in .*_Zna}} - // CHECK-NEXT: {{ #1 0x.* in main .*large_func_test.cpp:}}[[@LINE-10]] + // OHOS_LOCAL + // CHECK-OHOS: {{ #0 0x.* in operator new}} + // CHECK-NEXT: {{ #1 0x.* in main .*large_func_test.cpp:}}[[@LINE-12]] int y = x[argc]; delete[] x; return y; diff --git a/compiler-rt/test/asan/TestCases/use-after-delete.cpp b/compiler-rt/test/asan/TestCases/use-after-delete.cpp index 4d0c055368bb0c5e202cdd1f040c34b833077525..f06048de064f1bed84abb3f72affe94e95986056 100644 --- a/compiler-rt/test/asan/TestCases/use-after-delete.cpp +++ b/compiler-rt/test/asan/TestCases/use-after-delete.cpp @@ -21,7 +21,9 @@ int main() { // CHECK-Windows:{{ #0 0x.* in operator delete\[\]}} // CHECK-FreeBSD:{{ #0 0x.* in operator delete\[\]}} // CHECK-Darwin: {{ #0 0x.* in .*_Zda}} - // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-14]] + // OHOS_LOCAL + // CHECK-OHOS: {{ #0 0x.* in operator delete\[\]}} + // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-16]] // CHECK: {{previously allocated by thread T0 here:}} // CHECK-Linux: {{ #0 0x.* in operator new\[\]}} @@ -29,7 +31,9 @@ int main() { // CHECK-Windows:{{ #0 0x.* in operator new\[\]}} // CHECK-FreeBSD:{{ #0 0x.* in operator new\[\]}} // CHECK-Darwin: {{ #0 0x.* in .*_Zna}} - // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-23]] + // OHOS_LOCAL + // CHECK-OHOS: {{ #0 0x.* in operator new\[\]}} + // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-27]] // CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes): diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py index cbe84170c61e52b1c3440280d8408e5f6789e4f4..3fb929e3b16a2d6560fd2dacac1da72da0cee875 100644 --- a/compiler-rt/test/asan/lit.cfg.py +++ b/compiler-rt/test/asan/lit.cfg.py @@ -131,7 +131,7 @@ config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) ) config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) ) config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) ) if config.asan_dynamic: - if config.host_os in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: + if config.host_os in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS', 'OHOS']: # OHOS_LOCAL shared_libasan_path = os.path.join(config.compiler_rt_libdir, "libclang_rt.asan{}.so".format(config.target_suffix)) elif config.host_os == 'Darwin': shared_libasan_path = os.path.join(config.compiler_rt_libdir, 'libclang_rt.asan_{}_dynamic.dylib'.format(config.apple_platform)) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py index b84161f8b99c3a11efe3593dd209f9eeefd278da..dbe446a6848369cd2d27786479e8b8c70eb5ab76 100755 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py @@ -14,7 +14,7 @@ def host_to_device_path(path): def hdc_output(args): command = hdc_constants.get_hdc_cmd_prefix() + args - return subprocess.check_output(command, stderr=subprocess.STDOUT) + return subprocess.check_output(command, stderr=subprocess.STDOUT, timeout=300) def hdc(args, attempts=1, check_stdout=''): if verbose: diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py index 1bdd8ea337710d995397a2a96746c638b3e00bb7..a6e7596d2178f8b47680224fbb1c7ff0556d9036 100755 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py @@ -26,12 +26,15 @@ def build_env(): sanitizers = ( 'HWASAN', 'ASAN', 'LSAN', 'MEMPROF', 'MSAN', 'TSAN', 'UBSAN', 'SCUDO' ) + set_abort_on_error=True for san in sanitizers: - # for all sanitizers we need 'abort_on_error=0', + # for all sanitizers we need 'abort_on_error=0' if 'abort_on_error=1' is not set, # so prepare key for them, to set value later opt_str = '%s_OPTIONS' % san if opt_str not in os.environ: os.environ[opt_str] = '' + elif 'abort_on_error=1' in os.environ[opt_str]: + set_abort_on_error=False # All sanitizers need external symbolizers for some tests # set them by default to llvm-symbolizer @@ -42,7 +45,7 @@ def build_env(): args.append('LD_LIBRARY_PATH=%s' % ( hdc_constants.TMPDIR,)) for (key, value) in os.environ.items(): san_opt = key.endswith('SAN_OPTIONS') - if san_opt: + if san_opt and set_abort_on_error: value += ':abort_on_error=0' if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or san_opt or key == 'LD_LIBRARY_PATH': if key in ['TSAN_OPTIONS', 'UBSAN_OPTIONS']: diff --git a/compiler-rt/test/tsan/dlopen_ns.cpp b/compiler-rt/test/tsan/dlopen_ns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a8f885b6d554adc0598e8e792636b793179650f --- /dev/null +++ b/compiler-rt/test/tsan/dlopen_ns.cpp @@ -0,0 +1,93 @@ +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O0 %s -DSHARED_LIB2 -fPIC -shared -fno-sanitize=thread -o %t-dir/lib_dlopen_ns_test.so +// RUN: %clangxx_tsan -O0 %s -DSHARED_LIB1 -DDLOPEN -fPIC -shared -shared-libsan -o %t-dir/lib_dlopen_ns_dep_shared_tsan_1.so +// RUN: %clangxx_tsan -O0 %s -DSHARED_LIB1 -fPIC -shared -shared-libsan -o %t-dir/lib_dlopen_ns_dep_shared_tsan_2.so + +// RUN: %clangxx_tsan -DTEST1 -shared-libsan -O1 %s %link_libcxx_tsan -o %t-dir/exe1 +// RUN: %run %t-dir/exe1 %t-dir 2>&1 | FileCheck %s --check-prefix=CHECK-DLOPEN-EXT + +// RUN: %clangxx_tsan -DTEST1 -DDLOPEN -shared-libsan -O1 %s %link_libcxx_tsan -o %t-dir/exe2 +// RUN: %run %t-dir/exe2 %t-dir 2>&1 | FileCheck %s --check-prefix=CHECK-DLOPEN + +// Test that dlopen works properly when interceptor dlopen_impl: +// Musl dlopen use the caller address to get a matched ns(namespace) and use it +// to search lib, we need to make sure that matched ns don't change, otherwise +// dlopen will be failed, make the ns of caller library different from the tsan +// library to test whether dlopen is ok. + +// REQUIRES: ohos_family + +#ifdef SHARED_LIB1 +#include +#include +#include +extern "C" __attribute__((noinline)) void *bar(const char *name) { + fprintf(stderr, "bar\n"); + // let lr in this lib. +#if defined(DLOPEN) + return dlopen(name, RTLD_NOW); +#else + return dlopen_ext(name, RTLD_NOW, nullptr); +#endif +} + +extern "C" __attribute__((noinline)) void *foo(const char *name) { + fprintf(stderr, "foo\n"); + return bar(name); +} + +#elif defined(SHARED_LIB2) +extern "C" void hello() { return; } +#else +#include +#include +#include +#include + +int main(int argc, char *argv[]) { +#if defined(DLOPEN) + std::string lib_caller = "lib_dlopen_ns_dep_shared_tsan_1.so"; +#else + std::string lib_caller = "lib_dlopen_ns_dep_shared_tsan_2.so"; +#endif + std::string lib_callee = "lib_dlopen_ns_test.so"; + std::string dir = std::string(dirname(argv[0])); + std::string ns_lib_path = dir + ":/system/lib64"; + Dl_namespace dlns; + dlns_init(&dlns, "test_ns"); + dlns_create(&dlns, ns_lib_path.c_str()); + + void *handle = dlopen_ns(&dlns, lib_caller.c_str(), RTLD_NOW); + if (!handle) { + fprintf(stderr, "dlopen_ns %s failed.\n", lib_caller.c_str()); + return 0; + } + + void *(*funcPtr)(const char *) = + (void *(*)(const char *))dlsym(handle, "foo"); + if (!funcPtr) { + fprintf(stderr, "dlsym %s failed.\n", "foo"); + return 0; + } + + void *res = funcPtr(lib_callee.c_str()); + if (!res) { + fprintf(stderr, "dlopen %s failed.\n", lib_callee.c_str()); + return 0; + } + fprintf(stderr, "DONE\n"); + return 0; +} + +// CHECK-CHECK-DLOPEN-NOT: failed +// CHECK-DLOPEN: foo +// CHECK-DLOPEN: bar +// CHECK-DLOPEN: DONE + +// CHECK-CHECK-DLOPEN-EXT-NOT: failed +// CHECK-DLOPEN-EXT: foo +// CHECK-DLOPEN-EXT: bar +// CHECK-DLOPEN-EXT: DONE +#endif \ No newline at end of file diff --git a/compiler-rt/test/tsan/force_background_thread.cpp b/compiler-rt/test/tsan/force_background_thread.cpp index cf645cdfa9141f80c7b81e85e5fed9214635cc83..646f71b013c64bde14a82ac0fdb25dc77f72d8f3 100644 --- a/compiler-rt/test/tsan/force_background_thread.cpp +++ b/compiler-rt/test/tsan/force_background_thread.cpp @@ -1,7 +1,9 @@ // RUN: %clangxx_tsan -O1 %s -o %t -// RUN: %deflake %env_tsan_opts=force_background_thread=0:verbosity=1:memory_limit_mb=1000 %run %t 2>&1 | FileCheck %s --implicit-check-not "memory flush check" -// RUN: %deflake %env_tsan_opts=force_background_thread=1:verbosity=1:memory_limit_mb=1000 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,THREAD -// RUN: %deflake %env_tsan_opts=force_background_thread=0:verbosity=1:memory_limit_mb=1000 %run %t 1 2>&1 | FileCheck %s --check-prefixes=CHECK,THREAD +// OHOS_LOCAL begin +// RUN: %deflake %env_tsan_opts=force_background_thread=0:verbosity=1:memory_limit_mb=1000:disable_background_thread=0 %run %t 2>&1 | FileCheck %s --implicit-check-not "memory flush check" +// RUN: %deflake %env_tsan_opts=force_background_thread=1:verbosity=1:memory_limit_mb=1000:disable_background_thread=0 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,THREAD +// RUN: %deflake %env_tsan_opts=force_background_thread=0:verbosity=1:memory_limit_mb=1000:disable_background_thread=0 %run %t 1 2>&1 | FileCheck %s --check-prefixes=CHECK,THREAD +// OHOS_LOCAL end // Fails with: objc[99984]: task_restartable_ranges_register failed (result 0x2e: (os/kern) service not supported) // UNSUPPORTED: darwin diff --git a/compiler-rt/test/tsan/getline_nohang.cpp b/compiler-rt/test/tsan/getline_nohang.cpp index 027ba7bac26a12c9a93f16c29ad4a424248cbdb1..62c9302d25cd574116d00176a55d78ffed5a4bd9 100644 --- a/compiler-rt/test/tsan/getline_nohang.cpp +++ b/compiler-rt/test/tsan/getline_nohang.cpp @@ -3,6 +3,10 @@ // Data race randomly triggered. // UNSUPPORTED: netbsd +// Musl try to visit all opening files and close it at exit, +// there will be potential deadlock if this file lock is held by getline on +// another thread. UNSUPPORTED: ohos_family + // Make sure TSan doesn't deadlock on a file stream lock at program shutdown. // See https://github.com/google/sanitizers/issues/454 #ifdef __FreeBSD__ diff --git a/compiler-rt/test/tsan/ignore-noninstrumented.cpp b/compiler-rt/test/tsan/ignore-noninstrumented.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6129d7c390067edc6ec43f4bd461cd01f61b02e5 --- /dev/null +++ b/compiler-rt/test/tsan/ignore-noninstrumented.cpp @@ -0,0 +1,86 @@ +// Check that ignore_noninstrumented_modules=1 suppresses reports originating +// from interceptors that are called from an un-instrumented library. + +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan %s -fPIC -shared -DLIBRARY -fno-sanitize=thread -o %t-dir/libignore_noninstrumented.so +// RUN: %clangxx_tsan %s -L%t-dir -lignore_noninstrumented -o %t + +// Check that without the flag, there are false positives. +// RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=ignore_noninstrumented_modules=0 %deflake %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE + +// With ignore_noninstrumented_modules=1, no races are reported. +// RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=ignore_noninstrumented_modules=1 %run %t 2>&1 | FileCheck %s --implicit-check-not='ThreadSanitizer' + +// With ignore_noninstrumented_modules=1, races in user's code are still reported. +// RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=ignore_noninstrumented_modules=1 %deflake %run %t race 2>&1 | FileCheck %s --check-prefix=CHECK-RACE + +// REQUIRES: ohos_family + +#include "test.h" + +#include + +#ifdef LIBRARY +namespace library { +#endif +char global_buf[64]; + +void *Thread1(void *arg) { + auto barrier_wait = (void (*)())arg; + barrier_wait(); + strcpy(global_buf, "hello world"); // NOLINT + return NULL; +} + +void *Thread2(void *arg) { + auto barrier_wait = (void (*)())arg; + strcpy(global_buf, "world hello"); // NOLINT + barrier_wait(); + return NULL; +} + +void Race(void (*barrier_wait)()) { + pthread_t t[2]; + pthread_create(&t[0], NULL, Thread1, (void *)barrier_wait); + pthread_create(&t[1], NULL, Thread2, (void *)barrier_wait); + pthread_join(t[0], NULL); + pthread_join(t[1], NULL); +} +#ifdef LIBRARY +} // namespace library +#endif + +#ifndef LIBRARY +namespace library { + void Race(void (*barrier_wait)()); +} + +// Pass pointer to this function to un-instrumented library, so it can access +// TSan-invisible barriers. +void my_barrier_wait() { + barrier_wait(&barrier); +} + +int main(int argc, char *argv[]) { + fprintf(stderr, "Hello world.\n"); + + // Race in un-instrumented library + barrier_init(&barrier, 2); + library::Race(my_barrier_wait); + + // Race in user code, if requested + if (argc > 1 && strcmp(argv[1], "race") == 0) { + barrier_init(&barrier, 2); + Race(my_barrier_wait); + } + + fprintf(stderr, "Done.\n"); +} + +#endif // LIBRARY + +// CHECK: Hello world. +// CHECK-RACE: SUMMARY: ThreadSanitizer: data race +// CHECK: Done. \ No newline at end of file diff --git a/compiler-rt/test/tsan/ignore_dlclose.cpp b/compiler-rt/test/tsan/ignore_dlclose.cpp new file mode 100644 index 0000000000000000000000000000000000000000..74d5cafc5df601694c0df8a9db8824299f8c8a54 --- /dev/null +++ b/compiler-rt/test/tsan/ignore_dlclose.cpp @@ -0,0 +1,223 @@ +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -fno-sanitize=thread -O0 -fno-builtin %s -DLIB -DEXPEND -fPIC -shared -o %t-dir/lib_noninstrumented_1.so +// RUN: %clangxx_tsan -fno-sanitize=thread -O0 -fno-builtin %s -DLIB -DEXPEND -fPIC -shared -o %t-dir/lib_noninstrumented_2.so +// RUN: %clangxx_tsan -O0 -fno-builtin %s -DLIB -fPIC -shared -o %t-dir/lib_instrumented_1.so +// RUN: %clangxx_tsan -O0 -fno-builtin %s -DLIB -fPIC -shared -o %t-dir/lib_instrumented_2.so + +// RUN: %clangxx_tsan -DTEST1 -O0 %s %link_libcxx_tsan -o %t-dir/exe1 +// RUN: %clangxx_tsan -DTEST2 -O0 %s %link_libcxx_tsan -o %t-dir/exe2 + +// RUN: %env_tsan_opts='ignore_noninstrumented_modules=0' %run %t-dir/exe1 2>&1 | FileCheck %s --check-prefix=CHECK-DLOPEN_EXT + +// RUN: %env_tsan_opts='ignore_noninstrumented_modules=1' %deflake %run %t-dir/exe2 instrumented_instrumented | FileCheck %s --check-prefix=CHECK-IGNORE-II +// RUN: %env_tsan_opts='ignore_noninstrumented_modules=1' %deflake %run %t-dir/exe2 instrumented_noninstrumented | FileCheck %s --check-prefix=CHECK-IGNORE-IN +// RUN: %env_tsan_opts='ignore_noninstrumented_modules=1' %deflake %run %t-dir/exe2 noninstrumented_instrumented | FileCheck %s --check-prefix=CHECK-IGNORE-NI +// RUN: %env_tsan_opts='ignore_noninstrumented_modules=1' %run %t-dir/exe2 noninstrumented_noninstrumented 2>&1 | FileCheck %s --check-prefix=CHECK-IGNORE-NN + +// RUN: echo "called_from_lib:lib_instrumented_1.so" > %t-dir/exe2.supp +// RUN: %env_tsan_opts='ignore_noninstrumented_modules=0:suppressions='%t-dir/exe2.supp'' %deflake %run %t-dir/exe2 instrumented_instrumented | FileCheck %s --check-prefix=CHECK-SUPPRESS + +// REQUIRES: ohos_family + +#ifndef LIB + +#include +#include +#include +#include +#include + +typedef void (*FUNC)(void); + +FUNC get_symbol_addr(std::string lib, std::string name, bool do_call) { + dl_extinfo extinfo = { + .flag = DL_EXT_RESERVED_ADDRESS_RECURSIVE, + }; + + void *h = dlopen_ext(lib.c_str(), RTLD_NOW, &extinfo); + if (!h) { + fprintf(stderr, "dlopen_ext %s failed.\n", lib.c_str()); + return nullptr; + } + + FUNC f = (void (*)())dlsym(h, name.c_str()); + if (!f) { + fprintf(stderr, "dlsym %s failed.\n", name.c_str()); + if (h) { + dlclose(h); + } + return nullptr; + } + + if (do_call) { + f(); + } + dlclose(h); + + return f; +} + +// Test we can reuse same addrress through dlopen_ext. +bool test1(std::string &dir) { + std::string lib1 = dir + "/lib_noninstrumented_1.so"; + std::string lib2 = dir + "/lib_noninstrumented_2.so"; + FUNC f1 = get_symbol_addr(lib1.c_str(), "libfunc1", 0); + FUNC f2 = get_symbol_addr(lib2.c_str(), "libfunc1", 0); + if (!f1 || !f2) { + fprintf(stderr, + "dlopen_ext with DL_EXT_RESERVED_ADDRESS_RECURSIVE failed " + "func1:%p, func2:%p\n", + f1, f2); + return false; + } else { + fprintf(stderr, + "dlopen_ext with DL_EXT_RESERVED_ADDRESS_RECURSIVE succeed " + "func1:%p, func2:%p\n", + f1, f2); + } + return true; +} + +bool test2(std::string &dir, char *type) { + std::string lib1; + std::string lib2; + + if (!strcmp(type, "instrumented_instrumented")) { + lib1 = dir + "/lib_instrumented_1.so"; + lib2 = dir + "/lib_instrumented_2.so"; + } + + if (!strcmp(type, "instrumented_noninstrumented")) { + lib1 = dir + "/lib_instrumented_1.so"; + lib2 = dir + "/lib_noninstrumented_1.so"; + } + + if (!strcmp(type, "noninstrumented_instrumented")) { + lib1 = dir + "/lib_noninstrumented_1.so"; + lib2 = dir + "/lib_instrumented_1.so"; + } + + if (!strcmp(type, "noninstrumented_noninstrumented")) { + lib1 = dir + "/lib_noninstrumented_1.so"; + lib2 = dir + "/lib_noninstrumented_2.so"; + } + + FUNC f1 = get_symbol_addr(lib1.c_str(), "libfunc1", 1); + FUNC f2 = get_symbol_addr(lib2.c_str(), "libfunc2", 1); + if (!f1 || !f2) { + fprintf(stderr, + "dlopen_ext with DL_EXT_RESERVED_ADDRESS_RECURSIVE failed " + "func1:%p, func2:%p\n", + f1, f2); + return false; + } else { + fprintf(stderr, + "dlopen_ext with DL_EXT_RESERVED_ADDRESS_RECURSIVE succeed " + "func1:%p, func2:%p\n", + f1, f2); + } + return true; +} + +int main(int argc, char *argv[]) { + std::string dir = std::string(dirname(argv[0])); +#if defined(TEST1) + test1(dir); +#endif + +#if defined(TEST2) + test2(dir, argv[1]); +#endif + + fprintf(stderr, "DONE\n"); + return 0; +} + +#else +#include +#include + +// Extend the code segment so that it can overlap with the instrumented module +// address. +#if defined(EXPEND) +template int func() { return func(); } +template <> int func<0>() { return 0; } +#endif + +static int Global1[4]; +static int Global2[4]; + +void *Thread1(void *a) { + memset(&Global1, 0, sizeof(Global1)); + return nullptr; +} + +void *Thread2(void *a) { + memset(&Global1, 1, sizeof(Global1)); + return nullptr; +} + +void *Thread3(void *a) { + memset(&Global2, 0, sizeof(Global2)); + return nullptr; +} + +void *Thread4(void *a) { + memset(&Global2, 1, sizeof(Global2)); + return nullptr; +} + +extern "C" void libfunc1() { +#if defined(EXPEND) + func<15>(); +#endif + fprintf(stderr, "mem1:%p.\n", &Global1); + pthread_t t[2]; + pthread_create(&t[0], nullptr, Thread1, nullptr); + pthread_create(&t[1], nullptr, Thread2, nullptr); + pthread_join(t[0], nullptr); + pthread_join(t[1], nullptr); +} + +extern "C" void libfunc2() { + fprintf(stderr, "mem2:%p.\n", &Global2); + pthread_t t[2]; + pthread_create(&t[0], nullptr, Thread3, nullptr); + pthread_create(&t[1], nullptr, Thread4, nullptr); + pthread_join(t[0], nullptr); + pthread_join(t[1], nullptr); +} +#endif + +// CHECK-DLOPEN_EXT: dlopen_ext with DL_EXT_RESERVED_ADDRESS_RECURSIVE succeed +// CHECK-DLOPEN_EXT: DONE + +// CHECK-IGNORE-II-NOT: failed +// CHECK-IGNORE-II: WARNING: ThreadSanitizer: data race +// CHECK-IGNORE-II: libfunc1 {{.*}}lib_instrumented_1.so{{.*}} +// CHECK-IGNORE-II: libfunc2 {{.*}}lib_instrumented_2.so{{.*}} +// CHECK-IGNORE-II: DONE + +// CHECK-IGNORE-IN-NOT: failed +// CHECK-IGNORE-IN: WARNING: ThreadSanitizer: data race +// CHECK-IGNORE-IN: libfunc1 {{.*}}lib_instrumented_1.so{{.*}} +// CHECK-IGNORE-IN-NOT: libfunc2 +// CHECK-IGNORE-IN: DONE + +// CHECK-IGNORE-NI-NOT: failed +// CHECK-IGNORE-NI: WARNING: ThreadSanitizer: data race +// CHECK-IGNORE-NI-NOT: libfunc1 +// CHECK-IGNORE-NI: libfunc2 {{.*}}lib_instrumented_1.so{{.*}} +// CHECK-IGNORE-NI: DONE + +// CHECK-IGNORE-NN-NOT: failed +// CHECK-IGNORE-NN-NOT: WARNING: ThreadSanitizer: data race +// CHECK-IGNORE-NN: DONE + +// CHECK-SUPPRESS-NOT: failed +// CHECK-SUPPRESS: WARNING: ThreadSanitizer: data race +// CHECK-SUPPRESS-NOT: libfunc1 +// CHECK-SUPPRESS: libfunc2 {{.*}}lib_instrumented_2.so{{.*}} +// CHECK-SUPPRESS: DONE \ No newline at end of file diff --git a/compiler-rt/test/tsan/ignore_lib1.cpp b/compiler-rt/test/tsan/ignore_lib1.cpp index 2b17dee501418bb40489f11d7654bcefd2540120..01139519e491b466917945723d9c5501551eefec 100644 --- a/compiler-rt/test/tsan/ignore_lib1.cpp +++ b/compiler-rt/test/tsan/ignore_lib1.cpp @@ -16,10 +16,6 @@ // FIXME: This test regularly fails on powerpc64 LE possibly starting with // r279664. Re-enable the test once the problem(s) have been fixed. -// OHOS_LOCAL -// dlopen not intercepted on OHOS -// UNSUPPORTED: ohos_family - #ifndef LIB #include diff --git a/compiler-rt/test/tsan/ignore_lib2.cpp b/compiler-rt/test/tsan/ignore_lib2.cpp index 24b7f5e66a3e8972769dc6ff894026ef944ad09d..05b7c2ed915a766a7546d65b4da6d5f70a268b6a 100644 --- a/compiler-rt/test/tsan/ignore_lib2.cpp +++ b/compiler-rt/test/tsan/ignore_lib2.cpp @@ -6,10 +6,6 @@ // RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable // RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t-dir/executable | FileCheck %s -// OHOS_LOCAL -// dlopen not intercepted on OHOS -// UNSUPPORTED: ohos_family - // Tests that called_from_lib suppression matched against 2 libraries // causes program crash (this is not supported). diff --git a/compiler-rt/test/tsan/ignore_lib3.cpp b/compiler-rt/test/tsan/ignore_lib3.cpp index b13229184141e15d1aa2003a135c89b2938d32c5..76ea0709a69a71c7518eb94c98428f60a0b2aee4 100644 --- a/compiler-rt/test/tsan/ignore_lib3.cpp +++ b/compiler-rt/test/tsan/ignore_lib3.cpp @@ -12,7 +12,7 @@ // REQUIRES: stable-runtime // OHOS_LOCAL -// dlopen not intercepted on OHOS +// The expected log will not be printed because ohos libignore support dlclose. // UNSUPPORTED: ohos_family #ifndef LIB diff --git a/compiler-rt/test/tsan/ignore_lib4.cpp b/compiler-rt/test/tsan/ignore_lib4.cpp index 00bde34639d0f9441de755a8ad07aa50ac68bfdf..06241c7b89f3024dd26e83a1507ff5b7a9e117bf 100644 --- a/compiler-rt/test/tsan/ignore_lib4.cpp +++ b/compiler-rt/test/tsan/ignore_lib4.cpp @@ -13,10 +13,6 @@ // is matched against 2 libraries". // UNSUPPORTED: aarch64 -// OHOS_LOCAL -// dlopen not intercepted on OHOS -// UNSUPPORTED: ohos_family - // Test longjmp in ignored lib. // It used to crash since we jumped out of ScopedInterceptor scope. diff --git a/compiler-rt/test/tsan/ignore_lib5.cpp b/compiler-rt/test/tsan/ignore_lib5.cpp index 9ae3f7bcbb9546368dff938a474472cdbdc35971..a71d560ab913c1e6855fb5bee3b6c46b6b7383db 100644 --- a/compiler-rt/test/tsan/ignore_lib5.cpp +++ b/compiler-rt/test/tsan/ignore_lib5.cpp @@ -21,10 +21,6 @@ // ReadProcMaps() on NetBSD does not handle >=1MB of memory layout information // UNSUPPORTED: netbsd -// OHOS_LOCAL -// dlopen not intercepted on OHOS -// UNSUPPORTED: ohos_family - #ifndef LIB #include diff --git a/compiler-rt/test/tsan/lit.cfg.py b/compiler-rt/test/tsan/lit.cfg.py index ddd4d21642fa558a66763c25c00e152c699d1e1e..4f0bf242800efb00c19e6188a4c6f20ace34d3b9 100644 --- a/compiler-rt/test/tsan/lit.cfg.py +++ b/compiler-rt/test/tsan/lit.cfg.py @@ -29,6 +29,9 @@ if config.host_os == 'Darwin': default_tsan_opts += ['ignore_noninstrumented_modules=0'] default_tsan_opts += ['ignore_interceptors_accesses=0'] +if config.host_os == 'OHOS': + default_tsan_opts += ['ignore_noninstrumented_modules=0'] + # Platform-specific default TSAN_OPTIONS for lit tests. default_tsan_opts_str = ':'.join(default_tsan_opts) if default_tsan_opts_str: diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp index 2896f5920db901855e2b3582e9b713be7077fd87..3e87fd196e01e575dab7f1babb77e712f79b4c61 100644 --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -471,7 +471,7 @@ static bool LoadValueFromConsecutiveGPRRegisters( llvm::Optional byte_size = value_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); - if (byte_size || *byte_size == 0) + if (!byte_size || *byte_size == 0) // OHOS_LOCAL return false; std::unique_ptr heap_data_up( diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp index bcac55f04b7d8c9aa4f6fcc051b5b74caa8ebb8c..26742b8c80eb7d521e0ab6af40e2f6a1653a8e31 100644 --- a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp @@ -143,7 +143,7 @@ void HdcClient::SetDeviceID(const std::string &device_id) { const std::string &HdcClient::GetDeviceID() const { return m_device_id; } bool HdcClient::IsServerLocal() { - return m_connect_addr == "localhost"; + return m_connect_addr == "localhost" || m_connect_addr == "127.0.0.1"; } namespace { diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp index 0a6a7b208f404077663ba924762c22de4a8c1934..8f3f54a58472d247284600f267df8702e35a2ebd 100644 --- a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp @@ -11,6 +11,7 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/UriParser.h" +#include "llvm/Support/Regex.h" #include "PlatformOHOSRemoteGDBServer.h" @@ -40,20 +41,20 @@ static Status ForwardPortWithHdc( device_id = hdc.GetDeviceID(); LLDB_LOGF(log, "Connected to OHOS device \"%s\"", device_id.c_str()); - if (remote_port != 0) { - LLDB_LOGF(log, "Forwarding remote TCP port %d to local TCP port %d", - remote_port, local_port); - return hdc.SetPortForwarding(local_port, remote_port); + if (socket_namespace) { + LLDB_LOGF(log, "Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name.str().c_str(), local_port); + return hdc.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); } - LLDB_LOGF(log, "Forwarding remote socket \"%s\" to local TCP port %d", - remote_socket_name.str().c_str(), local_port); + LLDB_LOGF(log, "Forwarding remote TCP port %d to local TCP port %d", + remote_port, local_port); - if (!socket_namespace) - return Status("Invalid socket namespace"); - - return hdc.SetPortForwarding(local_port, remote_socket_name, - *socket_namespace); + if (remote_port == 0) + return Status("Invalid remote_port"); + + return hdc.SetPortForwarding(local_port, remote_port); } static Status DeleteForwardPortWithHdc(const std::string &connect_addr, @@ -138,9 +139,21 @@ bool PlatformOHOSRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { return m_gdb_client_up->KillSpawnedProcess(pid); } +bool IsValidIPv4(llvm::StringRef ip) { + std::string pattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"; + llvm::Regex regex(pattern); + return regex.match(ip); +} + +bool IsValidIPv6(llvm::StringRef ip) { + std::string pattern = "^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"; + llvm::Regex regex(pattern); + return regex.match(ip); +} + bool PlatformOHOSRemoteGDBServer::IsHostnameDeviceID(llvm::StringRef hostname) { - return hostname != "localhost" && !hostname.contains(':') && - !hostname.contains('.'); + return hostname != "localhost" && !IsValidIPv4(hostname) && + !IsValidIPv6(hostname); } Status PlatformOHOSRemoteGDBServer::ConnectRemote(Args &args) { @@ -249,7 +262,7 @@ Status PlatformOHOSRemoteGDBServer::MakeConnectURL( ForwardPortWithHdc(m_connect_addr, local_port, remote_port, remote_socket_name, m_socket_namespace, m_device_id); if (error.Success()) { - if (remote_port != 0){ + if (!m_socket_namespace){ m_port_forwards[pid] = {local_port, remote_port}; } else{ diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h index cb130574d3f66f22a610c9dc7a4a3839dba2dbff..a4ba2e16d3ed6b764d3359fd91e7d75d487d4645 100644 --- a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h @@ -38,6 +38,8 @@ public: lldb_private::Target *target, lldb_private::Status &error) override; + // When 'hostname' is not ipv4, ipv6 or localhost, the function will return true. + // such as IsHostnameDeviceID("127.0.0.1:8080") return true. static bool IsHostnameDeviceID(llvm::StringRef hostname); protected: diff --git a/llvm-build/MakeLiblzma b/llvm-build/MakeLiblzma index b78b86f3496b6b89671c28e07302c31bf3e3d67e..4f4ceff1e6c3f9da51c886fef158b0495e8a91ce 100644 --- a/llvm-build/MakeLiblzma +++ b/llvm-build/MakeLiblzma @@ -17,6 +17,7 @@ TARGET_TRIPLE := CC := SRCS := 7zAlloc.c 7zArcIn.c 7zBuf2.c 7zBuf.c 7zCrc.c 7zCrcOpt.c 7zDec.c 7zFile.c 7zStream.c Aes.c AesOpt.c Alloc.c Bcj2.c Bra86.c Bra.c BraIA64.c CpuArch.c Delta.c LzFind.c Lzma2Dec.c Lzma2Enc.c Lzma86Dec.c Lzma86Enc.c LzmaDec.c LzmaEnc.c LzmaLib.c Ppmd7.c Ppmd7Dec.c Ppmd7Enc.c Sha256.c Sha256Opt.c Sort.c Xz.c XzCrc64.c XzCrc64Opt.c XzDec.c XzEnc.c XzIn.c SRC_PREFIX := +LIB_VERSION := ifeq ($(TARGET_TRIPLE),linux-x86_64) CFLAGS := --target=x86_64-unknown-linux-gnu -D_7ZIP_ST -Wall -Werror -Wno-empty-body -Wno-enum-conversion -Wno-logical-op-parentheses -Wno-self-assign -fPIC @@ -31,9 +32,9 @@ TARGET_A := liblzma.dll.a else ifeq ($(findstring darwin,$(TARGET_TRIPLE)),darwin) SDKROOT := $(shell xcrun --sdk macosx --show-sdk-path) -CFLAGS := -D_7ZIP_ST -Wall -Werror -Wno-empty-body -Wno-enum-conversion -Wno-logical-op-parentheses -Wno-self-assign -fPIC -LDFLAGS := -dynamiclib -fuse-ld=lld -Wl,-syslibroot,$(SDKROOT) -install_name @rpath/liblzma.dylib -TARGET := liblzma.dylib +CFLAGS := -D_7ZIP_ST -Wall -Werror -Wno-empty-body -Wno-enum-conversion -Wno-logical-op-parentheses -Wno-self-assign -fPIC -current_version $(LIB_VERSION) -compatibility_version $(LIB_VERSION) +LDFLAGS := -dynamiclib -fuse-ld=lld -Wl,-syslibroot,$(SDKROOT) -install_name @rpath/liblzma.$(LIB_VERSION).dylib +TARGET := liblzma.$(LIB_VERSION).dylib else $(warning *** warning: TARGET_TRIPLE $(TARGET_TRIPLE) has not been set in rights) endif diff --git a/llvm-build/build.py b/llvm-build/build.py index 2c289ce6d3f9c0bd15c53619311971b8a5848124..88209a79ff47da75652918bf6ecee81a791a1d1c 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -94,10 +94,11 @@ class BuildConfig(): self.CLANG_VERSION = prebuilts_clang_version self.MINGW_TRIPLE = 'x86_64-windows-gnu' self.build_libs_with_hb = self.build_libs_flags == 'OH' or self.build_libs_flags == 'BOTH' - + self.ARCHIVE_EXTENSION = '.tar.' + self.compression_format self.ARCHIVE_OPTION = '-c' + ('j' if self.compression_format == "bz2" else 'z') self.LIBXML2_VERSION = None + self.LZMA_VERSION = '22.0' logging.basicConfig(level=logging.INFO) self.host_projects = args.host_build_projects @@ -267,7 +268,7 @@ class BuildConfig(): action='store_true', default=False, help='Enable lldb performance monitoring') - + compression_formats = ['bz2', 'gz'] parser.add_argument( @@ -647,6 +648,15 @@ class BuildUtils(object): return None + def get_libxml2_source_path(self): + return self.merge_out_path('third_party', 'libxml2', ('libxml2-' + self.build_config.LIBXML2_VERSION)) + + def get_libxml2_install_path(self, triple): + return self.merge_out_path('third_party', 'libxml2', 'install', triple) + + def get_libxml2_build_path(self, triple): + return self.merge_out_path('third_party', 'libxml2', 'build', triple) + class LlvmCore(BuildUtils): def __init__(self, build_config): @@ -738,13 +748,13 @@ class LlvmCore(BuildUtils): llvm_defines['PANEL_LIBRARIES'] = ncurses_libs if self.build_config.enable_lzma_7zip: - llvm_defines['LIBLZMA_LIBRARIES'] = self.merge_out_path('lzma', 'lib', self.use_platform(), 'liblzma.dylib') + llvm_defines['LIBLZMA_LIBRARIES'] = self.merge_out_path('lzma', 'lib', self.use_platform(), f'liblzma.{self.build_config.LZMA_VERSION}.dylib') if self.build_config.build_libedit: llvm_defines['LibEdit_LIBRARIES'] = os.path.join(self.get_prebuilts_dir('libedit'), 'lib', 'libedit.0.dylib') if self.build_config.build_libxml2: - llvm_defines['LIBXML2_LIBRARIES'] = os.path.join(self.get_prebuilts_dir('libxml2'), self.use_platform(), 'lib', f'libxml2.{self.build_config.LIBXML2_VERSION}.dylib') + llvm_defines['LIBXML2_LIBRARIES'] = os.path.join(self.get_libxml2_install_path(self.use_platform()), 'lib', f'libxml2.{self.build_config.LIBXML2_VERSION}.dylib') def llvm_compile_linux_defines(self, @@ -790,7 +800,7 @@ class LlvmCore(BuildUtils): llvm_defines['LLVM_ENABLE_LTO'] = 'Thin' if self.build_config.build_libxml2: - llvm_defines['LIBXML2_LIBRARY'] = os.path.join(self.get_prebuilts_dir('libxml2'), self.use_platform(), 'lib', f'libxml2.so.{self.build_config.LIBXML2_VERSION}') + llvm_defines['LIBXML2_LIBRARY'] = os.path.join(self.get_libxml2_install_path(self.use_platform()), 'lib', f'libxml2.so.{self.build_config.LIBXML2_VERSION}') def llvm_compile_llvm_defines(self, llvm_defines, llvm_root, cflags, ldflags): llvm_defines['LLVM_ENABLE_PROJECTS'] = ';'.join(self.build_config.host_projects) @@ -839,7 +849,7 @@ class LlvmCore(BuildUtils): if self.build_config.build_libxml2: llvm_defines['LLDB_ENABLE_LIBXML2'] = 'ON' - llvm_defines['LIBXML2_INCLUDE_DIR'] = os.path.join(self.get_prebuilts_dir('libxml2'), self.use_platform(), 'include', 'libxml2') + llvm_defines['LIBXML2_INCLUDE_DIR'] = os.path.join(self.get_libxml2_install_path(self.use_platform()), 'include', 'libxml2') if self.build_config.enable_monitoring: llvm_defines['LLDB_ENABLE_PERFORMANCE'] = 'ON' @@ -948,7 +958,7 @@ class LlvmCore(BuildUtils): windows_defines['CMAKE_C_COMPILER'] = cc windows_defines['CMAKE_CXX_COMPILER'] = cxx windows_defines['CMAKE_SYSTEM_NAME'] = 'Windows' - windows_defines['CMAKE_BUILD_TYPE'] = 'Release' + windows_defines['CMAKE_BUILD_TYPE'] = 'Debug' if self.build_config.debug else 'Release' windows_defines['LLVM_BUILD_RUNTIME'] = 'OFF' windows_defines['LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD'] = 'ON' windows_defines['LLVM_TOOL_OPENMP_BUILD'] = 'OFF' @@ -967,8 +977,8 @@ class LlvmCore(BuildUtils): if self.build_config.build_libxml2: windows_defines['LLDB_ENABLE_LIBXML2'] = 'ON' - windows_defines['LIBXML2_INCLUDE_DIR'] = os.path.join(self.get_prebuilts_dir('libxml2'), 'windows-x86_64', 'include', 'libxml2') - windows_defines['LIBXML2_LIBRARY'] = os.path.join(self.get_prebuilts_dir('libxml2'), 'windows-x86_64', 'lib', 'libxml2.dll.a') + windows_defines['LIBXML2_INCLUDE_DIR'] = os.path.join(self.get_libxml2_install_path('windows-x86_64'), 'include', 'libxml2') + windows_defines['LIBXML2_LIBRARY'] = os.path.join(self.get_libxml2_install_path('windows-x86_64'), 'lib', 'libxml2.dll.a') if self.build_config.enable_monitoring: windows_defines['LLDB_ENABLE_PERFORMANCE'] = 'ON' @@ -995,9 +1005,11 @@ class LlvmCore(BuildUtils): ) ldflag = ['-fuse-ld=lld', + '-Wl,--gc-sections', '-stdlib=libc++', '--rtlib=compiler-rt', - '-lunwind', '-Wl,--dynamicbase', + '-lunwind', + '-Wl,--dynamicbase', '-Wl,--nxcompat', '-lucrt', '-lucrtbase', @@ -1008,6 +1020,7 @@ class LlvmCore(BuildUtils): cflag = ['-stdlib=libc++', '--target=x86_64-pc-windows-gnu', + '-fdata-sections', '-D_LARGEFILE_SOURCE', '-D_FILE_OFFSET_BITS=64', '-D_WIN32_WINNT=0x0600', @@ -1757,6 +1770,13 @@ class LlvmLibs(BuildUtils): lldb_defines['LIBLLDB_BUILD_STATIC'] = 'ON' lldb_target.append('lldb') + if self.build_config.build_libxml2: + self.build_libxml2(llvm_triple, None, llvm_install) + lldb_defines['LLDB_ENABLE_LIBXML2'] = 'ON' + libxml2_install_path = self.get_libxml2_install_path(llvm_triple) + lldb_defines['LIBXML2_INCLUDE_DIR'] = os.path.join(libxml2_install_path, 'include', 'libxml2') + lldb_defines['LIBXML2_LIBRARY'] = os.path.join(libxml2_install_path, 'lib', 'libxml2.a') + if self.build_config.lldb_timeout: lldb_defines['LLDB_ENABLE_TIMEOUT'] = 'True' @@ -1793,7 +1813,7 @@ class LlvmLibs(BuildUtils): cmake_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags) cmake_defines['CMAKE_C_FLAGS'] = ' '.join(cflags) cmake_defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags) - cmake_defines['CMAKE_BUILD_TYPE'] = 'Release' + cmake_defines['CMAKE_BUILD_TYPE'] = 'Debug' if self.build_config.target_debug else 'Release' cmake_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY' cmake_defines['CMAKE_INSTALL_PREFIX'] = install_dir cmake_defines['LLVM_CONFIG_PATH'] = os.path.join(toolchain_dir, 'bin', 'llvm-config') @@ -1861,13 +1881,14 @@ class LlvmLibs(BuildUtils): 'SRC_PREFIX=%s/' % src_dir, 'TARGET_TRIPLE=%s' % target_triple, 'INSTALL_DIR=%s' % liblzma_build_path, + 'LIB_VERSION=%s' % self.build_config.LZMA_VERSION, '-f', 'MakeLiblzma'] os.chdir(self.build_config.LLVM_BUILD_DIR) self.check_call(cmd) if self.host_is_darwin(): - shlib_ext = '.dylib' + shlib_ext = f'.{self.build_config.LZMA_VERSION}.dylib' if self.host_is_linux(): shlib_ext = '.so' lzma_file = os.path.join(liblzma_build_path, 'lib', target_triple, 'liblzma' + shlib_ext) @@ -1977,39 +1998,64 @@ class LlvmLibs(BuildUtils): return libxml2_defines - def build_libxml2(self, llvm_make, llvm_install): - self.logger().info('Building libxml2') + def build_libxml2(self, triple, llvm_make, llvm_install): + self.logger().info('Building libxml2 for %s', triple) - libxml2_defines = self.build_libxml2_defines() + cmake_path = self.get_libxml2_source_path() + if not os.path.exists(cmake_path): + package_path = os.path.join(self.build_config.REPOROOT_DIR, 'third_party', 'libxml2') + untar_py = os.path.join(package_path, 'install.py') + untar_path = self.merge_out_path('third_party', 'libxml2') + self.check_create_dir(untar_path) + subprocess.run(['python3', untar_py, '--gen-dir', untar_path, '--source-file', package_path]) - libxml2_cmake_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'out', ('libxml2-' + self.build_config.LIBXML2_VERSION))) + build_path = self.get_libxml2_build_path(triple) + install_path = self.get_libxml2_install_path(triple) + self.check_rm_tree(build_path) + self.check_rm_tree(install_path) - libxml2_build_path = self.merge_out_path('libxml2') - libxml2_install_path = os.path.join(self.get_prebuilts_dir('libxml2'), self.use_platform()) - libxml2_defines['CMAKE_INSTALL_PREFIX'] = libxml2_install_path + defines = self.build_libxml2_defines() + defines['CMAKE_INSTALL_PREFIX'] = install_path - self.rm_cmake_cache(libxml2_build_path) + if triple != self.use_platform(): + configs_list, cc, cxx, ar, llvm_config = self.libs_argument(llvm_install) + for (arch, llvm_triple, extra_flags, multilib_suffix) in configs_list: + if llvm_triple != triple or multilib_suffix != '': + continue - self.invoke_cmake(libxml2_cmake_path, - libxml2_build_path, - libxml2_defines, - env=dict(self.build_config.ORIG_ENV)) + ldflags = [] + cflags = [] + self.build_libs_defines(triple, defines, cc, cxx, ar, llvm_config, ldflags, cflags, extra_flags) + defines['CMAKE_C_FLAGS'] = ' '.join(cflags) + defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags) + defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + defines['CMAKE_LINKER'] = os.path.join(llvm_install, 'bin', 'ld.lld') + defines['CMAKE_SYSTEM_NAME'] = 'OHOS' + defines['CMAKE_CROSSCOMPILING'] = 'True' + defines['BUILD_SHARED_LIBS'] = 'OFF' + break + + self.invoke_cmake(cmake_path, + build_path, + defines, + dict(self.build_config.ORIG_ENV)) - self.invoke_ninja(out_path=libxml2_build_path, - env=dict(self.build_config.ORIG_ENV), - target=None, - install=True) + self.invoke_ninja(build_path, + dict(self.build_config.ORIG_ENV), + None, + True) - self.llvm_package.copy_libxml2_to_llvm(llvm_make) - self.llvm_package.copy_libxml2_to_llvm(llvm_install) + if triple == self.use_platform(): + self.llvm_package.copy_libxml2_to_llvm(triple, llvm_make) + self.llvm_package.copy_libxml2_to_llvm(triple, llvm_install) def build_libxml2_for_windows(self, windows64_install): self.logger().info('Building libxml2 for windows') windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE) windowstool_path = self.merge_out_path('llvm-install') - libxml2_build_path = self.merge_out_path('libxml2-windows-build') - libxml2_install_path = os.path.join(self.get_prebuilts_dir('libxml2'), 'windows-x86_64') + libxml2_build_path = self.get_libxml2_build_path('windows-x86_64') + libxml2_install_path = self.get_libxml2_install_path('windows-x86_64') cflags = ['--target=x86_64-pc-windows-gnu'] cflags.extend(('-I', os.path.join(windows_sysroot, 'include'))) @@ -2036,8 +2082,7 @@ class LlvmLibs(BuildUtils): libxml2_defines['CMAKE_RC_FLAGS'] = ' '.join(rcflags) libxml2_defines['XML_INCLUDEDIR'] = os.path.join(windows_sysroot, 'include') - libxml2_cmake_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'out', ('libxml2-' + self.build_config.LIBXML2_VERSION))) - + libxml2_cmake_path = self.get_libxml2_source_path() self.invoke_cmake(libxml2_cmake_path, libxml2_build_path, libxml2_defines, @@ -2504,7 +2549,7 @@ class LlvmPackage(BuildUtils): st = os.stat(os.path.join(bin_dir, sh_filename)) os.chmod(os.path.join(bin_dir, sh_filename), st.st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) - def copy_libxml2_to_llvm(self, install_dir): + def copy_libxml2_to_llvm(self, triple, install_dir): self.logger().info('LlvmPackage copy_libxml2_to_llvm install_dir is %s', install_dir) libxml2_version = self.get_libxml2_version() @@ -2514,7 +2559,7 @@ class LlvmPackage(BuildUtils): if self.host_is_linux(): shlib_ext = f'.so.{libxml2_version}' - libxml2_lib_path = self.merge_out_path('libxml2') + libxml2_lib_path = os.path.join(self.get_libxml2_install_path(triple), 'lib') libxml2_src = os.path.join(libxml2_lib_path, 'libxml2%s' % shlib_ext) lib_dst_path = os.path.join(install_dir, 'lib') @@ -2665,13 +2710,7 @@ def main(): build_config.build_libxml2 = False if build_config.build_libxml2: - libxml2_untar_py = os.path.join( - build_config.REPOROOT_DIR, 'third_party', 'libxml2', 'install.py') - if not os.path.exists(build_config.REPOROOT_DIR + '/out'): - os.makedirs(build_config.REPOROOT_DIR + '/out') - subprocess.run(['python3', libxml2_untar_py, '--gen-dir', build_config.REPOROOT_DIR + '/out', - '--source-file', build_config.REPOROOT_DIR + '/third_party/libxml2']) - llvm_libs.build_libxml2(llvm_make, llvm_install) + llvm_libs.build_libxml2(build_utils.use_platform(), llvm_make, llvm_install) if build_config.do_build and need_host and (build_config.build_only_llvm or not build_config.build_only): llvm_core.llvm_compile(