diff --git a/.gitignore b/.gitignore index 20c4f52cd37860e6d124bf4859c9c795d2db5e53..46ab415ae35f647b721eda5cf475f7cb7b1fc5ed 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,6 @@ pythonenv* /clang/utils/analyzer/projects/*/RefScanBuildResults # automodapi puts generated documentation files here. /lldb/docs/python_api/ + + +musl_copy_* \ No newline at end of file diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 565ea795ac0e940da16a2fdc31a23e3490016b36..3c6fe62e1aaf38939e6688587f951c809c1ee3cf 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -205,12 +205,6 @@ 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 0a1a4a5535df82e8d3d7df7c22a9cc6af8adddd4..817008253fc0ef55018041afd38b414ada9542bf 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -137,18 +137,6 @@ 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 1fc4a677a10c21c26a73e5fc0ff928cbb1795858..82236453157fa3b6be86233a917bb24afc2f3a79 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -134,22 +134,11 @@ 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 787687db26d0bf6197ed965cf8cac761dbf93f06..c4153201a1a04632b1d23e23f89d646642e66003 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -807,13 +807,7 @@ 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 32a9e88f6711daddcefbaacc197901647bc5307f..c489cb2979f1835b2310484fbbcf4fd044ee228a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -281,15 +281,6 @@ 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 @@ -6543,24 +6534,6 @@ 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); @@ -6571,12 +6544,6 @@ 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); @@ -6585,6 +6552,9 @@ 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 36294dbcc6aee4c1dbfc9263e2863343aaee1cf5..b7fc9444cc66b326c833d2779d928339d027fc32 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.cpp @@ -28,15 +28,11 @@ 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) { @@ -74,25 +70,8 @@ void LibIgnore::OnLibraryLoaded(const char *name) { Die(); } loaded = true; - 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 + if (lib->loaded) continue; -#endif - } VReport(1, "Matched called_from_lib suppression '%s' against library" " '%s'\n", @@ -101,16 +80,7 @@ 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); @@ -118,75 +88,14 @@ 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()) @@ -208,7 +117,6 @@ 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 8bf9459741f235905b9784f1c600104f09633b21..18e4d83ed77fb8d3a9db0f12e974b308fc3ac948 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_libignore.h @@ -20,9 +20,7 @@ #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 { @@ -50,32 +48,17 @@ class LibIgnore { // Checks whether the provided PC belongs to an instrumented module. bool IsPcInstrumented(uptr pc) const; -#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: + 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 { @@ -107,13 +90,7 @@ private: 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; } @@ -127,56 +104,12 @@ 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 7d1315255005f08b30826e3aff8368d0768a174b..2d72a21b711ec049888dac9a574f9267d9428387 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -11,7 +11,6 @@ // sanitizer_libc.h. //===----------------------------------------------------------------------===// -#include "sanitizer_interface_internal.h" // OHOS_LOCAL #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ @@ -2291,56 +2290,7 @@ 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 4f330ffa10b0581f8886bc1f6617e19866d38105..785c399d02384e18d68e315ac1bad499742bccf6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -645,148 +645,12 @@ 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 81febbdca4347d703e4b91c2d964c421cd2e3008..66ace37d4d6256f8efb7db99c34df2164e0c5ad1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -450,8 +450,9 @@ #define SANITIZER_INTERCEPT_FCLOSE SI_POSIX #ifndef SANITIZER_INTERCEPT_DLOPEN_DLCLOSE -#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \ - (SI_FREEBSD || SI_NETBSD || (SI_LINUX_NOT_ANDROID) || SI_MAC || SI_SOLARIS) +// OHOS_LOCAL +#define SANITIZER_INTERCEPT_DLOPEN_DLCLOSE \ + (SI_FREEBSD || SI_NETBSD || (SI_LINUX_NOT_ANDROID && !SI_OHOS) || 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 af3c9a2de500458cfa37c4c7ced45703bcf28262..e71268eea1fbc15f19dd7e8fb8c293a5fcc0e8b8 100644 --- a/compiler-rt/lib/tsan/rtl/CMakeLists.txt +++ b/compiler-rt/lib/tsan/rtl/CMakeLists.txt @@ -11,17 +11,6 @@ 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) @@ -153,8 +142,7 @@ if(APPLE) RTSanitizerCommonSymbolizer RTUbsan CFLAGS ${TSAN_RTL_CFLAGS} - #OHOS_LOCAL - LINK_FLAGS ${TSAN_DYNAMIC_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} + LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS} ${WEAK_SYMBOL_LINK_FLAGS} LINK_LIBS ${TSAN_LINK_LIBS} objc PARENT_TARGET tsan) add_compiler_rt_object_libraries(RTTsan_dynamic @@ -276,8 +264,7 @@ else() ADDITIONAL_HEADERS ${TSAN_HEADERS} CFLAGS ${TSAN_RTL_DYNAMIC_CFLAGS} LINK_LIBS ${TSAN_DYNAMIC_LINK_LIBS} - #OHOS_LOCAL - LINK_FLAGS ${TSAN_DYNAMIC_LINK_FLAGS} + LINK_FLAGS ${SANITIZER_COMMON_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 0846c2af100c8c9cc0b408fcbbddcdda9021a2e7..731d776cc893e7a82b57c35178b834ff56751724 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_flags.inc +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.inc @@ -42,9 +42,6 @@ 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 " @@ -75,8 +72,7 @@ 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.") -// OHOS_LOCAL -TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_APPLE || SANITIZER_OHOS ? true : false, +TSAN_FLAG(bool, ignore_noninstrumented_modules, SANITIZER_APPLE ? 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 6b0e255f6db302e1c44fed6e18428f10f0e0ef15..825814f54d824a1c24b169c041682d712029e957 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -2391,20 +2391,7 @@ 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 89960059d42a954b4131f8ff38d39f1cb57ffc72..71874aad8dc5e84a730390108eb2e627c96c99fb 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp @@ -107,9 +107,6 @@ 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 f3702a52f6c517a43530b44ae5a481d5ae5c4286..5b4c7a0e4bdb1af84e7a9e74acd4b23a92849d1a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -456,8 +456,6 @@ 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 @@ -505,7 +503,6 @@ 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(); @@ -517,28 +514,14 @@ static void *BackgroundThread(void *arg) { } static void StartBackgroundThread() { - // 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 + ctx->background_thread = internal_start_thread(&BackgroundThread, 0); } #ifndef __mips__ static void StopBackgroundThread() { - // 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 + atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed); + internal_join_thread(ctx->background_thread); + ctx->background_thread = 0; } #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 706b12a841e1b8da8cecc41b64dfa6a88a11b4ca..444f210390cc9a00b7b981d4eb43eb38d3133e7d 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp @@ -652,9 +652,6 @@ 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); @@ -682,11 +679,6 @@ 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 4dadd579ff3a81b2098ddf64ba69b5ef87ef0d0e..117a761af91fc876eb3a4926516286c47c363a39 100644 --- a/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp @@ -1,9 +1,6 @@ // 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 7cfc708aebc21dfd47227ac530a6d87a54bc91c6..3037b232926ee05e7c4e927da96a4b7b2a563136 100644 --- a/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/init_fini_sections.cpp @@ -1,7 +1,4 @@ // 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 4905e15162242a92574dd0954ed3ea19a3699d5f..7f37727b2eeb10cb5501a43733d3990be91784b5 100644 --- a/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/rlimit_mmap_test.cpp @@ -1,10 +1,5 @@ // 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 eec592c8fbee02f08ba05422587d4d7feaee9315..8fed52092be8377e0f2c12d9414df41312e2ea55 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 +// XFAIL: android && !ohos_family // // 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 d34e8db9e3e7030dd1eae829639a3737d65124f8..cb613f53577a7fd0580f594f03ec3a4351c37674 100644 --- a/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cpp +++ b/compiler-rt/test/asan/TestCases/Posix/mmap_limit_mb.cpp @@ -10,10 +10,6 @@ // // 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 79a4c9cefb0c817252a23bdcd7d319159d2d0629..27436a1ad3d962c1adadc7722bc3e14c1e2a697a 100644 --- a/compiler-rt/test/asan/TestCases/Posix/readv.cpp +++ b/compiler-rt/test/asan/TestCases/Posix/readv.cpp @@ -23,13 +23,7 @@ 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 a806a0c7badfd07292e2aac7c1678156c2728308..1e574d99fe00c6967f256674a494f6fb6bc8ea72 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 && !ohos_family +// XFAIL: android // 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 3a4181e618bac05e2023c089e1204e623eac4fc8..563c1458c966e40b37902153536d181019af62a7 100644 --- a/compiler-rt/test/asan/TestCases/large_func_test.cpp +++ b/compiler-rt/test/asan/TestCases/large_func_test.cpp @@ -29,8 +29,6 @@ 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]++; @@ -55,9 +53,7 @@ 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}} - // OHOS_LOCAL - // CHECK-OHOS: {{ #0 0x.* in operator new}} - // CHECK-NEXT: {{ #1 0x.* in main .*large_func_test.cpp:}}[[@LINE-12]] + // CHECK-NEXT: {{ #1 0x.* in main .*large_func_test.cpp:}}[[@LINE-10]] 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 f06048de064f1bed84abb3f72affe94e95986056..4d0c055368bb0c5e202cdd1f040c34b833077525 100644 --- a/compiler-rt/test/asan/TestCases/use-after-delete.cpp +++ b/compiler-rt/test/asan/TestCases/use-after-delete.cpp @@ -21,9 +21,7 @@ int main() { // CHECK-Windows:{{ #0 0x.* in operator delete\[\]}} // CHECK-FreeBSD:{{ #0 0x.* in operator delete\[\]}} // CHECK-Darwin: {{ #0 0x.* in .*_Zda}} - // OHOS_LOCAL - // CHECK-OHOS: {{ #0 0x.* in operator delete\[\]}} - // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-16]] + // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-14]] // CHECK: {{previously allocated by thread T0 here:}} // CHECK-Linux: {{ #0 0x.* in operator new\[\]}} @@ -31,9 +29,7 @@ int main() { // CHECK-Windows:{{ #0 0x.* in operator new\[\]}} // CHECK-FreeBSD:{{ #0 0x.* in operator new\[\]}} // CHECK-Darwin: {{ #0 0x.* in .*_Zna}} - // OHOS_LOCAL - // CHECK-OHOS: {{ #0 0x.* in operator new\[\]}} - // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-27]] + // CHECK-NEXT: {{ #1 0x.* in main .*use-after-delete.cpp:}}[[@LINE-23]] // 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 3fb929e3b16a2d6560fd2dacac1da72da0cee875..cbe84170c61e52b1c3440280d8408e5f6789e4f4 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', 'OHOS']: # OHOS_LOCAL + if config.host_os in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: 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 dbe446a6848369cd2d27786479e8b8c70eb5ab76..b84161f8b99c3a11efe3593dd209f9eeefd278da 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, timeout=300) + return subprocess.check_output(command, stderr=subprocess.STDOUT) 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 a6e7596d2178f8b47680224fbb1c7ff0556d9036..1bdd8ea337710d995397a2a96746c638b3e00bb7 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,15 +26,12 @@ 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' if 'abort_on_error=1' is not set, + # for all sanitizers we need 'abort_on_error=0', # 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 @@ -45,7 +42,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 and set_abort_on_error: + if san_opt: 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 deleted file mode 100644 index 5a8f885b6d554adc0598e8e792636b793179650f..0000000000000000000000000000000000000000 --- a/compiler-rt/test/tsan/dlopen_ns.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// 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 646f71b013c64bde14a82ac0fdb25dc77f72d8f3..cf645cdfa9141f80c7b81e85e5fed9214635cc83 100644 --- a/compiler-rt/test/tsan/force_background_thread.cpp +++ b/compiler-rt/test/tsan/force_background_thread.cpp @@ -1,9 +1,7 @@ // RUN: %clangxx_tsan -O1 %s -o %t -// 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 +// 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 // 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 62c9302d25cd574116d00176a55d78ffed5a4bd9..027ba7bac26a12c9a93f16c29ad4a424248cbdb1 100644 --- a/compiler-rt/test/tsan/getline_nohang.cpp +++ b/compiler-rt/test/tsan/getline_nohang.cpp @@ -3,10 +3,6 @@ // 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 deleted file mode 100644 index 6129d7c390067edc6ec43f4bd461cd01f61b02e5..0000000000000000000000000000000000000000 --- a/compiler-rt/test/tsan/ignore-noninstrumented.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// 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 deleted file mode 100644 index 74d5cafc5df601694c0df8a9db8824299f8c8a54..0000000000000000000000000000000000000000 --- a/compiler-rt/test/tsan/ignore_dlclose.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// 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 01139519e491b466917945723d9c5501551eefec..2b17dee501418bb40489f11d7654bcefd2540120 100644 --- a/compiler-rt/test/tsan/ignore_lib1.cpp +++ b/compiler-rt/test/tsan/ignore_lib1.cpp @@ -16,6 +16,10 @@ // 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 05b7c2ed915a766a7546d65b4da6d5f70a268b6a..24b7f5e66a3e8972769dc6ff894026ef944ad09d 100644 --- a/compiler-rt/test/tsan/ignore_lib2.cpp +++ b/compiler-rt/test/tsan/ignore_lib2.cpp @@ -6,6 +6,10 @@ // 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 76ea0709a69a71c7518eb94c98428f60a0b2aee4..b13229184141e15d1aa2003a135c89b2938d32c5 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 -// The expected log will not be printed because ohos libignore support dlclose. +// dlopen not intercepted on OHOS // UNSUPPORTED: ohos_family #ifndef LIB diff --git a/compiler-rt/test/tsan/ignore_lib4.cpp b/compiler-rt/test/tsan/ignore_lib4.cpp index 06241c7b89f3024dd26e83a1507ff5b7a9e117bf..00bde34639d0f9441de755a8ad07aa50ac68bfdf 100644 --- a/compiler-rt/test/tsan/ignore_lib4.cpp +++ b/compiler-rt/test/tsan/ignore_lib4.cpp @@ -13,6 +13,10 @@ // 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 a71d560ab913c1e6855fb5bee3b6c46b6b7383db..9ae3f7bcbb9546368dff938a474472cdbdc35971 100644 --- a/compiler-rt/test/tsan/ignore_lib5.cpp +++ b/compiler-rt/test/tsan/ignore_lib5.cpp @@ -21,6 +21,10 @@ // 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 4f0bf242800efb00c19e6188a4c6f20ace34d3b9..ddd4d21642fa558a66763c25c00e152c699d1e1e 100644 --- a/compiler-rt/test/tsan/lit.cfg.py +++ b/compiler-rt/test/tsan/lit.cfg.py @@ -29,9 +29,6 @@ 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/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index b23684819a23967127a1cf2e3f5fea57d9733731..810ff3f5d9d9854c2e505c2aee7217c46119f5ee 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -44,6 +44,8 @@ public: uint32_t getThunkSectionSpacing() const override; bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; bool usesOnlyLowPageBits(RelType type) const override; + void deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const override; // ADLT void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override; @@ -79,6 +81,20 @@ AArch64::AArch64() { RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { + if (config->adlt) + switch (type) { + case R_AARCH64_GLOB_DAT: + case R_AARCH64_JUMP_SLOT: + case R_AARCH64_RELATIVE: + return R_ABS; + case R_AARCH64_TLSDESC: + return R_TLSDESC; + case R_AARCH64_TLS_TPREL64: + return R_TPREL; + default: + break; + } + switch (type) { case R_AARCH64_ABS16: case R_AARCH64_ABS32: @@ -335,8 +351,84 @@ static void writeSMovWImm(uint8_t *loc, uint32_t imm) { write32le(loc, inst | ((imm & 0xFFFF) << 5)); } +static void adltRelocateDebugMessage(StringRef title, uint8_t *loc, + const Relocation &rel, uint64_t &val) { + lld::outs() << title + << " loc: " << loc /*<< " loc val: " << Twine::utohexstr(*loc)*/ + << " rel expr: " << rel.expr + << " rel type: " << lld::toString(rel.type) << " rel offset: 0x" + << Twine::utohexstr(rel.offset) << " rel addend: 0x" + << Twine::utohexstr(rel.addend) + << " val: 0x" << Twine::utohexstr(val) + << " rel sym: " << (rel.sym ? rel.sym->getName() : "null!"); + + if (rel.sym && rel.sym->isDefined()) { + auto d = cast(rel.sym); + lld::outs() << ": section " << d->section->name + << ", value 0x" << Twine::utohexstr(d->value); + } + lld::outs() << '\n'; +} + +void AArch64::deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const { + bool isDebug = false; + if (isDebug) + adltRelocateDebugMessage("[AArch64::deRelocate]: ", loc, rel, *val); + + auto orClear32le = [&]() { + write32le(loc, read32le(loc) & ~((1 << 26) -1)); + }; + + auto orClearAArch64Imm = [&]() { + write32le(loc, read32le(loc) & ~(0xFFF << 10)); + }; + + switch (rel.type) { + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_MOVW_UABS_G0_NC: + case R_AARCH64_MOVW_UABS_G1_NC: + case R_AARCH64_MOVW_UABS_G2_NC: + case R_AARCH64_MOVW_UABS_G3: + case R_AARCH64_TSTBR14: + orClear32le(); + break; + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: + case R_AARCH64_LD64_GOTPAGE_LO15: + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case R_AARCH64_TLSDESC_ADD_LO12: + orClearAArch64Imm(); + break; + } +} + void AArch64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { + bool isDebug = false; + if (config->adlt) { + deRelocate(loc, rel, &val); + } + if (config->adlt && isDebug) + adltRelocateDebugMessage("[AArch64::relocate]: ", loc, rel, val); + switch (rel.type) { case R_AARCH64_ABS16: case R_AARCH64_PREL16: @@ -366,6 +458,8 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, checkInt(loc, val, 33, rel); LLVM_FALLTHROUGH; case R_AARCH64_ADR_PREL_PG_HI21_NC: + if (config->adlt && *(uint32_t*)loc == 0xd503201f) // ignore nop + break; write32AArch64Addr(loc, val >> 12); break; case R_AARCH64_ADR_PREL_LO21: diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index d6babe9f74c256bcf7f16f29389bf7b6712413c2..cd768db8a7ffcf1b04be33e2cac6d7e32418a787 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -34,6 +34,7 @@ class BinaryFile; class BitcodeFile; class ELFFileBase; class SharedFile; +struct PhdrEntry; // OHOS_LOCAL class InputSectionBase; class Symbol; @@ -220,6 +221,10 @@ struct Configuration { std::vector> shuffleSections; bool singleRoRx; bool shared; + // OHOS_LOCAL begin + bool adlt = false; + bool adltTrace = false; + // OHOS_LOCAL end bool symbolic; bool isStatic = false; bool sysvHash = false; @@ -384,6 +389,7 @@ struct Ctx { SmallVector> memoryBuffers; SmallVector objectFiles; SmallVector sharedFiles; + SmallVector sharedFilesExtended; SmallVector binaryFiles; SmallVector bitcodeFiles; SmallVector lazyBitcodeFiles; @@ -397,11 +403,25 @@ struct Ctx { // A tuple of (reference, extractedFile, sym). Used by --why-extract=. SmallVector, 0> whyExtractRecords; + // Store duplicate symbols (only defined). + typedef llvm::DenseMap eSymsCntMap; + llvm::DenseSet eSymsHist; // A mapping from a symbol to an InputFile referencing it backward. Used by // --warn-backrefs. llvm::DenseMap> backwardReferences; + + // OHOS_LOCAL begin + struct AdltCtx { + llvm::SetVector commonProgramHeaders; + bool withCfi = false; + // From input .rela.dyn, .rela.plt: + // Keep input library indexes that are needed for got/plt symbol + llvm::DenseMap> + gotPltInfo; // sym, soFile->orderIdx array; + } adlt; + // OHOS_LOCAL end }; // The only instance of Ctx struct. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index abcc8a984a65905cc2b62a84903015a86b588c7b..2f1fcf79c29a66633f79bb853ee9e25837943069 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -274,8 +274,12 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) { // the directory part is ignored. Note that path may be a temporary and // cannot be stored into SharedFile::soName. path = mbref.getBufferIdentifier(); - files.push_back( - make(mbref, withLOption ? path::filename(path) : path)); + if (config->adlt) + files.push_back(createSharedFileExtended( + mbref, withLOption ? path::filename(path) : path)); + else + files.push_back( + make(mbref, withLOption ? path::filename(path) : path)); return; case file_magic::bitcode: files.push_back(make(mbref, "", 0, inLib)); @@ -843,7 +847,8 @@ static std::pair getPackDynRelocs(opt::InputArgList &args) { static void readCallGraph(MemoryBufferRef mb) { // Build a map from symbol name to section DenseMap map; - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getSymbols()) map[sym->getName()] = sym; @@ -922,6 +927,7 @@ processCallGraphRelocations(SmallVector &symbolIndices, template static void readCallGraphsFromObjectFiles() { SmallVector symbolIndices; ArrayRef cgProfile; + // ADLT TODO for (auto file : ctx->objectFiles) { auto *obj = cast>(file); if (!processCallGraphRelocations(symbolIndices, cgProfile, obj)) @@ -1086,6 +1092,8 @@ static void readConfigs(opt::InputArgList &args) { else if (arg->getOption().matches(OPT_Bsymbolic)) config->bsymbolic = BsymbolicKind::All; } + config->adlt = args.hasArg(OPT_adlt); + config->adltTrace = args.hasArg(OPT_adlt_trace); config->checkSections = args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); config->chroot = args.getLastArgValue(OPT_chroot); @@ -1101,7 +1109,7 @@ static void readConfigs(opt::InputArgList &args) { config->dwoDir = args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq); config->dynamicLinker = getDynamicLinker(args); config->ehFrameHdr = - args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); + args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, config->adlt); config->emitLLVM = args.hasArg(OPT_plugin_opt_emit_llvm, false); config->emitRelocs = args.hasArg(OPT_emit_relocs); config->callGraphProfileSort = args.hasFlag( @@ -1217,7 +1225,7 @@ static void readConfigs(opt::InputArgList &args) { config->searchPaths = args::getStrings(args, OPT_library_path); config->sectionStartMap = getSectionStartMap(args); - config->shared = args.hasArg(OPT_shared); + config->shared = config->adlt ? true : args.hasArg(OPT_shared); config->singleRoRx = !args.hasFlag(OPT_rosegment, OPT_no_rosegment, true); config->soName = args.getLastArgValue(OPT_soname); config->sortSection = getSortSection(args); @@ -1818,7 +1826,8 @@ static void excludeLibs(opt::InputArgList &args) { sym->versionId = VER_NDX_LOCAL; }; - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) visit(file); for (BitcodeFile *file : ctx->bitcodeFiles) @@ -2014,7 +2023,8 @@ static void writeDependencyFile() { // symbols of type CommonSymbol. static void replaceCommonSymbols() { llvm::TimeTraceScope timeScope("Replace common symbols"); - for (ELFFileBase *file : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) { if (!file->hasCommonSyms) continue; for (Symbol *sym : file->getGlobalSymbols()) { @@ -2090,7 +2100,8 @@ static void findKeepUniqueSections(opt::InputArgList &args) { // Visit the address-significance table in each object file and mark each // referenced symbol as address-significant. - for (InputFile *f : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (InputFile *f : files) { auto *obj = cast>(f); ArrayRef syms = obj->getSymbols(); if (obj->addrsigSec) { @@ -2344,7 +2355,8 @@ static void redirectSymbols(ArrayRef wrapped) { return; // Update pointers in input files. - parallelForEach(ctx->objectFiles, [&](ELFFileBase *file) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + parallelForEach(files, [&](ELFFileBase *file) { for (Symbol *&sym : file->getMutableGlobalSymbols()) if (Symbol *s = map.lookup(sym)) sym = s; @@ -2379,7 +2391,8 @@ static uint32_t getAndFeatures() { return 0; uint32_t ret = -1; - for (ELFFileBase *f : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *f : files) { uint32_t features = f->andFeatures; checkAndReportMissingFeature( @@ -2462,6 +2475,46 @@ static void postParseObjectFile(ELFFileBase *file) { } } +static void postParseSharedFileForAdlt(ELFFileBase *file) { + switch (config->ekind) { + case ELF32LEKind: + cast>(file)->postParseForAdlt(); + break; + case ELF32BEKind: + cast>(file)->postParseForAdlt(); + break; + case ELF64LEKind: + cast>(file)->postParseForAdlt(); + break; + case ELF64BEKind: + cast>(file)->postParseForAdlt(); + break; + default: + llvm_unreachable(""); + } +} + +static bool isSectionValidForAdlt(int fileIdx, InputSectionBase *s) { + if (!s || s == &InputSection::discarded) + return false; + uint32_t type = s->type; + StringRef name = s->name; + + bool isBaseType = type == SHT_NOBITS || type == SHT_NOTE || + type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY; + // TODO: fix .debug_info relocation + bool isNeededProgBits = + type == SHT_PROGBITS && + !(name.startswith(".got.plt") || name.startswith(".plt") || name.startswith(".got") || + name.startswith(".eh_frame_hdr"));// || name.startswith(".debug_")); + bool ret = isBaseType || isNeededProgBits; + + bool isDebug = false; + if (ret && isDebug) + lld::outs() << "[isSectionValidForAdlt]: " << name << "\n"; + return ret; +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. void LinkerDriver::link(opt::InputArgList &args) { @@ -2513,6 +2566,17 @@ void LinkerDriver::link(opt::InputArgList &args) { for (StringRef name : config->undefined) addUnusedUndefined(name)->referenced = true; + // Fill eSymsHist for defined syms. This will help to find duplicates. + if (config->adlt) { + Ctx::eSymsCntMap eSymsHist; + for (auto *file : files) + buildSymsHist(file, eSymsHist); + for (auto eSym : eSymsHist) + if (eSym.second > 1) + ctx->eSymsHist.insert(eSym.first); + eSymsHist.clear(); + } + // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. This process might // add files to the link, via autolinking, these files are always @@ -2531,8 +2595,9 @@ void LinkerDriver::link(opt::InputArgList &args) { // producing a shared library. // We also need one if any shared libraries are used and for pie executables // (probably because the dynamic linker needs it). - config->hasDynSymTab = - !ctx->sharedFiles.empty() || config->isPic || config->exportDynamic; + config->hasDynSymTab = (config->adlt ? !ctx->sharedFilesExtended.empty() + : !ctx->sharedFiles.empty()) || + config->isPic || config->exportDynamic; // Some symbols (such as __ehdr_start) are defined lazily only when there // are undefined symbols for them, so we add these to trigger that logic. @@ -2587,6 +2652,9 @@ void LinkerDriver::link(opt::InputArgList &args) { // No more lazy bitcode can be extracted at this point. Do post parse work // like checking duplicate symbols. + if (config->adlt) + parallelForEach(ctx->sharedFilesExtended, postParseSharedFileForAdlt); + parallelForEach(ctx->objectFiles, initializeLocalSymbols); parallelForEach(ctx->objectFiles, postParseObjectFile); parallelForEach(ctx->bitcodeFiles, @@ -2654,6 +2722,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // With this the symbol table should be complete. After this, no new names // except a few linker-synthesized ones will be added to the symbol table. const size_t numObjsBeforeLTO = ctx->objectFiles.size(); + const size_t numSoBeforeLTO = ctx->sharedFilesExtended.size(); invokeELFT(compileBitcodeFiles, skipLinkedOutput); // Symbol resolution finished. Report backward reference problems, @@ -2670,6 +2739,11 @@ void LinkerDriver::link(opt::InputArgList &args) { // compileBitcodeFiles may have produced lto.tmp object files. After this, no // more file will be added. + if (config->adlt) { + auto newSharedFiles = + makeArrayRef(ctx->sharedFilesExtended).slice(numSoBeforeLTO); + parallelForEach(newSharedFiles, postParseSharedFileForAdlt); + } auto newObjectFiles = makeArrayRef(ctx->objectFiles).slice(numObjsBeforeLTO); parallelForEach(newObjectFiles, initializeLocalSymbols); parallelForEach(newObjectFiles, postParseObjectFile); @@ -2693,6 +2767,13 @@ void LinkerDriver::link(opt::InputArgList &args) { // Now that we have a complete list of input files. // Beyond this point, no new files are added. // Aggregate all input sections into one place. + if (config->adlt) + for (auto it : llvm::enumerate(ctx->sharedFilesExtended)) + for (InputSectionBase *s : it.value()->getSections()) + if (isSectionValidForAdlt(it.index(), s)) + inputSections.push_back(s); + + for (InputFile *f : ctx->objectFiles) for (InputSectionBase *s : f->getSections()) if (s && s != &InputSection::discarded) diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp index 51f3dc3a056e139ae3c92a47d6300a280f72a384..0145d9b9ba0cfdfe59b380ae2365f56c40b0d396 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -64,6 +64,13 @@ static void handleColorDiagnostics(opt::InputArgList &args) { error("unknown option: --color-diagnostics=" + s); } +static void handleAdltOption(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_adlt); + if (!arg) + return; + // slld::outs() << "adlt is active\n"; +} + static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { StringRef s = arg->getValue(); @@ -120,6 +127,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef argv) { args = this->ParseArgs(vec, missingIndex, missingCount); handleColorDiagnostics(args); + handleAdltOption(args); if (missingCount) error(Twine(args.getArgString(missingIndex)) + ": missing argument"); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 473809b05e9c2a3f5ac86a32d0e0f97376e219b7..3da64f63804d9ac89712a84a0ed987b199fb8fbe 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -158,6 +158,18 @@ static bool isCompatible(InputFile *file) { return false; } +template +static void doBuildSymsHist(InputFile *file, Ctx::eSymsCntMap &eSymsHist) { + if (!isCompatible(file)) + return; + if (auto *f = dyn_cast>(file)) + f->buildSymsHist(eSymsHist); +} + +void elf::buildSymsHist(InputFile *file, Ctx::eSymsCntMap &eSymsHist) { + invokeELFT(doBuildSymsHist, file, eSymsHist); +} + template static void doParseFile(InputFile *file) { if (!isCompatible(file)) return; @@ -184,6 +196,14 @@ template static void doParseFile(InputFile *file) { message(toString(file)); // .so file + if (config->adlt) + if (auto *f = dyn_cast>(file)) { + f->orderIdx = ctx->sharedFilesExtended.size(); + ctx->sharedFilesExtended.push_back(cast(file)); + f->parseForAdlt(); + return; + } + if (auto *f = dyn_cast(file)) { f->parse(); return; @@ -393,6 +413,11 @@ StringRef ObjFile::getShtGroupSignature(ArrayRef sections, return CHECK(sym.getName(this->stringTable), this); } +template +StringRef ObjFile::getUniqueName(StringRef origName) const { + return origName; +} + template bool ObjFile::shouldMerge(const Elf_Shdr &sec, StringRef name) { // On a regular link we don't merge sections if -O0 (default is -O1). This @@ -509,6 +534,11 @@ static void handleSectionGroup(ArrayRef sections, prev->nextInSectionGroup = head; } +template +ArrayRef ObjFile::getShndxTable() { + return shndxTable; +} + template void ObjFile::initializeSections(bool ignoreComdats, const llvm::object::ELFFile &obj) { @@ -548,6 +578,13 @@ void ObjFile::initializeSections(bool ignoreComdats, this->sections[i] = &InputSection::discarded; continue; } + auto secName = check(obj.getSectionName(sec, shstrtab)); + if (config->adlt && sec.sh_type == SHT_NULL) { + auto name = getUniqueName(secName); + this->sections[i] = createInputSection(i, sec, name); + this->sections[i]->address = sec.sh_addr; + this->sections[i]->size = sec.sh_size; + } switch (sec.sh_type) { case SHT_GROUP: { @@ -569,9 +606,14 @@ void ObjFile::initializeSections(bool ignoreComdats, symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this) .second; if (keepGroup) { - if (config->relocatable) - this->sections[i] = createInputSection( - i, sec, check(obj.getSectionName(sec, shstrtab))); + if (config->relocatable) { + auto name = config->adlt ? getUniqueName(secName) : secName; + this->sections[i] = createInputSection(i, sec, name); + if (config->adlt) { + this->sections[i]->address = sec.sh_addr; + this->sections[i]->size = sec.sh_size; + } + } selectedGroups.push_back(entries); continue; } @@ -598,8 +640,12 @@ void ObjFile::initializeSections(bool ignoreComdats, ctx->hasSympart.store(true, std::memory_order_relaxed); LLVM_FALLTHROUGH; default: - this->sections[i] = - createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab))); + auto name = config->adlt ? getUniqueName(secName) : secName; + this->sections[i] = createInputSection(i, sec, name); + if (config->adlt) { + this->sections[i]->address = sec.sh_addr; + this->sections[i]->size = sec.sh_size; + } } } @@ -789,7 +835,7 @@ template static uint32_t readAndFeatures(const InputSection &sec) { ArrayRef data = sec.rawData; auto reportFatal = [&](const uint8_t *place, const char *msg) { fatal(toString(sec.file) + ":(" + sec.name + "+0x" + - Twine::utohexstr(place - sec.rawData.data()) + "): " + msg); + utohexstr(place - sec.rawData.data()) + "): " + msg); }; while (!data.empty()) { // Read one NOTE record. @@ -995,11 +1041,24 @@ InputSectionBase *ObjFile::createInputSection(uint32_t idx, if (name == ".eh_frame" && !config->relocatable) return make(*this, sec, name); - if ((sec.sh_flags & SHF_MERGE) && shouldMerge(sec, name)) + const bool doNotMerge = config->adlt && name.startswith(".rodata"); + if ((sec.sh_flags & SHF_MERGE) && !doNotMerge && shouldMerge(sec, name)) return make(*this, sec, name); + return make(*this, sec, name); } +template +void ObjFile::buildSymsHist(Ctx::eSymsCntMap &eSymsHist) { + ArrayRef eSyms = this->getELFSyms(); + for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) { + if (!eSyms[i].isDefined()) + continue; + StringRef name = CHECK(eSyms[i].getName(stringTable), this); + eSymsHist[CachedHashStringRef(name)]++; + } +} + // Initialize this->Symbols. this->Symbols is a parallel array as // its corresponding ELF symbol table. template @@ -1011,8 +1070,15 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { // Some entries have been filled by LazyObjFile. for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) - if (!symbols[i]) - symbols[i] = symtab.insert(CHECK(eSyms[i].getName(stringTable), this)); + if (!symbols[i]) { + StringRef name = CHECK(eSyms[i].getName(stringTable), this); + if (config->adlt && eSyms[i].isDefined() && + ctx->eSymsHist.count(CachedHashStringRef(name)) != 0) { + ctx->adlt.withCfi = ctx->adlt.withCfi || name == "__cfi_check"; + name = this->getUniqueName(name); + } + symbols[i] = symtab.insert(name); + } // Perform symbol resolution on non-local symbols. SmallVector undefineds; @@ -1028,10 +1094,21 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { uint8_t stOther = eSym.st_other; uint8_t type = eSym.getType(); uint64_t value = eSym.st_value; + if (config->adlt && secIdx != SHN_ABS) { + auto p = obj.getSection(secIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *eSec = *p; + if (type != STT_TLS) + value -= eSec->sh_addr; + } uint64_t size = eSym.st_size; Symbol *sym = symbols[i]; sym->isUsedInRegularObj = true; + if (config->adlt) + sym->exportDynamic = true; if (LLVM_UNLIKELY(eSym.st_shndx == SHN_COMMON)) { if (value == 0 || value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + sym->getName() + @@ -1060,6 +1137,8 @@ void ObjFile::initializeSymbols(const object::ELFFile &obj) { eSym.getType()}); sym->isUsedInRegularObj = true; sym->referenced = true; + if (config->adlt) + sym->exportDynamic = true; } } @@ -1095,9 +1174,16 @@ template void ObjFile::initializeLocalSymbols() { if (eSym.st_shndx == SHN_UNDEF || sec == &InputSection::discarded) new (symbols[i]) Undefined(this, name, STB_LOCAL, eSym.st_other, type, /*discardedSecIdx=*/secIdx); - else + else { + auto p = this->getObj().getSection(secIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *eSec = *p; + auto value = config->adlt ? eSym.st_value - eSec->sh_addr : eSym.st_value; new (symbols[i]) Defined(this, name, STB_LOCAL, eSym.st_other, type, - eSym.st_value, eSym.st_size, sec); + value, eSym.st_size, sec); + } symbols[i]->isUsedInRegularObj = true; } } @@ -1160,6 +1246,14 @@ template void ObjFile::postParse() { if (sym.binding == STB_WEAK || binding == STB_WEAK) continue; std::lock_guard lock(mu); + if (config->adlt) { + auto *f = cast>(this); + bool isDebug = false; + if (isDebug) { + lld::outs() << "Put to duplicates for: " << archiveName << "\n"; + f->traceSymbol(sym); + } + } ctx->duplicates.push_back({&sym, this, sec, eSym.st_value}); } } @@ -1290,6 +1384,36 @@ std::vector SharedFile::parseVerneed(const ELFFile &obj, return verneeds; } +template +std::vector SharedFileExtended::parseVerneed(const ELFFile &obj, + const typename ELFT::Shdr *sec) { + if (!sec) + return {}; + std::vector verneeds; + ArrayRef data = CHECK(obj.getSectionContents(*sec), this); + const uint8_t *verneedBuf = data.begin(); + for (unsigned i = 0; i != sec->sh_info; ++i) { + if (verneedBuf + sizeof(typename ELFT::Verneed) > data.end()) + fatal(toString(this) + " has an invalid Verneed"); + auto *vn = reinterpret_cast(verneedBuf); + const uint8_t *vernauxBuf = verneedBuf + vn->vn_aux; + for (unsigned j = 0; j != vn->vn_cnt; ++j) { + if (vernauxBuf + sizeof(typename ELFT::Vernaux) > data.end()) + fatal(toString(this) + " has an invalid Vernaux"); + auto *aux = reinterpret_cast(vernauxBuf); + if (aux->vna_name >= this->stringTable.size()) + fatal(toString(this) + " has a Vernaux with an invalid vna_name"); + uint16_t version = aux->vna_other & VERSYM_VERSION; + if (version >= verneeds.size()) + verneeds.resize(version + 1); + verneeds[version] = aux->vna_name; + vernauxBuf += aux->vna_next; + } + verneedBuf += vn->vn_next; + } + return verneeds; +} + // We do not usually care about alignments of data in shared object // files because the loader takes care of it. However, if we promote a // DSO symbol to point to .bss due to copy relocation, we need to keep @@ -1497,6 +1621,549 @@ template void SharedFile::parse() { } } +template +void SharedFileExtended::resolveDuplicatesForAdlt() { + auto pred = [&](DuplicateSymbol dup) { + auto sym = dup.sym; + if (!sym->isDefined()) + return true; + + auto d = cast(sym); + return !d->section && !d->getOutputSection(); + }; + static std::mutex mu; + { + std::lock_guard lock(mu); + llvm::erase_if(ctx->duplicates, pred); + } + + if (ctx->duplicates.empty()) + return; + + { + std::lock_guard lock(mu); + for (DuplicateSymbol &dup : ctx->duplicates) + warn("duplicate: " + dup.file->getName() + ": " + dup.section->name + + ": " + dup.sym->getName()); + ctx->duplicates.clear(); + } +} + +template +SharedFileExtended::SharedFileExtended(MemoryBufferRef mb, + StringRef soName) + : ObjFile(mb, soName), soName(soName), + simpleSoName(path::stem(soName)) { + const_cast(this->fileKind) = InputFile::SharedKind; +} + +template void SharedFileExtended::parseForAdlt() { + this->parse(); + parseDynamics(); + parseElfSymTab(); + + bool isDebug = false; // debug hint + if (!isDebug) + return; + + const ELFFile obj = this->getObj(); + ArrayRef objSections = this->template getELFShdrs(); + + lld::outs() << "Parse symbols from .symtab:\n"; + auto p = obj.getSection(symTabSecIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *elfSymTab = *p; + StringRef strTable = *obj.getStringTableForSymtab(*elfSymTab); + + auto eSyms = *obj.symbols(elfSymTab); + this->symbols.resize(this->symbols.size() + eSyms.size()); + for (const Elf_Sym &sym : eSyms) { + if (!sym.isDefined()) + continue; + + auto rawSec = obj.getSection(sym.st_shndx); + if (rawSec.takeError()) + continue; + if (isDebug) + traceElfSymbol(sym, strTable); + } + if (isDebug) + lld::outs() << '\n'; + + lld::outs() << "Parse offsets of some sections:\n"; + for (const Elf_Shdr &sec : objSections) { + auto name = check(obj.getSectionName(sec)); + if (name == ".init_array" || name == ".fini_array" || name == ".data" || + name == ".data.rel.ro" || name == ".bss.rel.ro" || name == ".bss") + traceElfSection(sec); + } + lld::outs() << '\n'; +} + +template void SharedFileExtended::postParseForAdlt() { + this->initializeLocalSymbols(); + this->postParse(); + resolveDuplicatesForAdlt(); +} + +template +StringRef SharedFileExtended::addAdltPostfix(StringRef input) const { + if (input.empty()) return input; + auto suffix = Twine("__") + Twine::utohexstr(this->orderIdx); + return saver().save(input + suffix); +} + +template +bool SharedFileExtended::addAdltPostfix(Symbol *s) { + StringRef newName = addAdltPostfix(s->getName()); + if (s->getName() == newName) + return false; + s->setName(newName); + return true; +} + +template +StringRef SharedFileExtended::getUniqueName(StringRef origName) const { + return addAdltPostfix(origName); +} + +// TODO: optimize 2 lookups +template +bool SharedFileExtended::saveSymbol(const Defined& d) const { + auto found = elf::symtab->find(d.getName()); + if (found) + return false; + in.symTab->addSymbol(elf::symtab->addSymbol(d)); + return true; +} + +template +Defined *SharedFileExtended::findSectionSymbol(uint64_t offset) const { + bool isDebug = false; + /*if (offset == 0x7738) // debug hint + isDebug = true;*/ + llvm::SmallVector candidates; + for (auto *sym : this->allSymbols) { + if (!sym || !sym->isSection()) + continue; + assert(sym->isDefined()); + Defined *d = cast(sym); + uint64_t low = d->section->address; + uint64_t high = low + d->section->size; + + if (isDebug) + lld::outs() << "offset: 0x" + utohexstr(offset) + + " sect name: " + d->section->name + "low 0x" + + utohexstr(low) + " high: 0x" + utohexstr(high) + "\n"; + bool isGood = (offset >= low) && (offset < high); + if (!isGood) + continue; + candidates.push_back(d); + } + if (candidates.empty()) // no suitable items found + return nullptr; + + llvm::sort(candidates, [offset](Defined *d1, Defined *d2) { + auto a1 = d1->section->address; + auto a2 = d2->section->address; + return (offset - a1 < offset - a2); + }); + + auto d = *candidates.begin(); + if (isDebug) + traceSymbol(*d, "found section sym: "); + return d; +} + +template +InputSectionBase * +SharedFileExtended::findInputSection(StringRef name) const { + for (InputSectionBase *sec : this->sections) + if (sec && sec->name == name) + return sec; + return nullptr; +} + +template +InputSectionBase * +SharedFileExtended::findInputSection(uint64_t offset) const { + llvm::SmallVector candidates; + for (InputSectionBase *sec : this->sections) { + if (!sec) + continue; + if (sec->address == offset) + return sec; + uint64_t low = sec->address; + uint64_t high = low + sec->size; + bool isGood = (offset >= low) && (offset < high); + if (!isGood) + continue; + candidates.push_back(sec); + } + if (candidates.empty()) // no suitable items found + return nullptr; + + auto lessAddr = [&](auto *s1, auto *s2) { return s1->address < s2->address; }; + auto i = candidates.begin(); + auto e = candidates.end(); + auto ret = std::min_element(i, e, lessAddr); + return *ret; +} + +template +bool SharedFileExtended::isDynamicSection(InputSectionBase &sec) const { + return sec.type == llvm::ELF::SHT_NULL || sec.name.startswith(".got.plt"); +} + +template +Defined *SharedFileExtended::findDefinedSymbol( + uint64_t offset, llvm::function_ref extraCond) const { + bool isDebug = false; + /*if (offset == 0x7738) // debug hint + isDebug = true;*/ + auto predRange = [=](Symbol *sym) { + if (!sym || sym->isUndefined()) + return false; + + Defined *d = cast(sym); + if (d->file != this) + return false; + + bool goodVal = d->section->address + d->value == offset; + return goodVal && extraCond(d); + }; + + auto i = this->allSymbols.begin(); + auto e = this->allSymbols.end(); + auto ret = std::find_if(i, e, predRange); + if (ret != e) { // item was found + Defined *d = cast(*ret); + if (isDebug) + traceSymbol(*d, d->isSection() ? "found section sym: " + : "found defined sym: "); + return d; + } + + auto *sectionSym = findSectionSymbol(offset); + if (isDebug && sectionSym) + traceSymbol(*sectionSym, "found section sym: "); + return sectionSym; +} + +template +StringRef +SharedFileExtended::getShStrTab(ArrayRef elfSections) { + return CHECK(this->getObj().getSectionStringTable(elfSections), this); +} + +template +void SharedFileExtended::traceElfSymbol(const Elf_Sym &sym, + StringRef strTable) const { + const ELFFile obj = this->getObj(); + auto rawSec = obj.getSection(sym.st_shndx); + auto parsedSec = + !rawSec.takeError() ? *obj.getSection(sym.st_shndx) : nullptr; + lld::outs() << "File: " << soName << " symName: " << *sym.getName(strTable) + << " val: 0x" << utohexstr(sym.st_value) << " sec of sym: " + << (parsedSec ? *obj.getSectionName(*parsedSec) : "unknown!") + << " sym type: 0x" << utohexstr(sym.getType()) + << " sym binding: 0x" << utohexstr(sym.getBinding()) << '\n'; +} + +template +void SharedFileExtended::traceElfSection(const Elf_Shdr &sec) const { + const ELFFile obj = this->getObj(); + + auto secName = *obj.getSectionName(sec); + lld::outs() << "File: " << soName << " sec: " << secName << " sec addr: 0x" + << utohexstr(sec.sh_addr) << " sec offs: 0x" + << utohexstr(sec.sh_offset) << " sec ent size: 0x" + << utohexstr(sec.sh_entsize) << '\n'; +} + +template +void SharedFileExtended::traceSymbol(const Symbol &sym, + StringRef title) const { + lld::outs() << "File: " << soName << ": " + title + << " symName: " << sym.getName() << " exportDynamic: 0x" + << utohexstr(sym.exportDynamic); + if (!sym.isDefined()) { + lld::outs() << '\n'; + return; + } + auto &d = cast(sym); + lld::outs() << " val: 0x" << utohexstr(d.value) + << " sec of sym: " << (d.section ? d.section->name : "unknown!") + << " sym type: 0x" << utohexstr(d.type) << " sym binding: 0x" + << utohexstr(d.binding) << '\n'; +} + +template +void SharedFileExtended::traceSection(const SectionBase &sec, + StringRef title) const { + lld::outs() << "File: " << soName << ": " + title << " sec: " << sec.name + << " sec addr: 0x" << utohexstr(sec.address) << " sec offs: 0x" + << utohexstr(sec.getOffset(0)) << " sec ent size: 0x" + << utohexstr(sec.entsize) << '\n'; +} + +template +Symbol &SharedFileExtended::getDynamicSymbol(uint32_t symbolIndex) const { + return *this->symbols[symbolIndex]; +} + +template +Symbol &SharedFileExtended::getSymbolADLT(uint32_t symbolIndex, + bool fromDynamic) const { + Symbol &sym = fromDynamic ? getDynamicSymbol(symbolIndex) + : getSymbolFromElfSymTab(symbolIndex); + + StringRef name = sym.getName(); + if (name.empty()) + return sym; + + /*if (name.contains("__emutls_v.TLS_data1")) // debug hint + lld::outs() << "debug getSymbolADLT(): " << name << "\n";*/ + + // check SymbolTable + auto res = elf::symtab->find(name); + if (res && (res->exportDynamic || res->versionId)) + return *res; + + // check SymbolTableBaseSection + auto found = llvm::find_if( + in.symTab->getSymbols(), [&](const SymbolTableEntry &entry) { + return entry.sym->getName() == name; + }); + // add a local sym if it was not previously added + if (found == in.symTab->getSymbols().end()) + in.symTab->addSymbol(&sym); + return sym; +} + +template void SharedFileExtended::parseDynamics() { + const ELFFile obj = this->getObj(); + ArrayRef sections = this->template getELFShdrs(); + + ArrayRef dynamicTags; + const Elf_Shdr *versymSec = nullptr; + const Elf_Shdr *verdefSec = nullptr; + const Elf_Shdr *verneedSec = nullptr; + + // parse external lib deps + int secIdx = 0; + for (const Elf_Shdr &sec : sections) { + switch (sec.sh_type) { + case SHT_DYNAMIC: + dynamicTags = + CHECK(obj.template getSectionContentsAsArray(sec), this); + break; + case SHT_DYNSYM: + dynSymSecIdx = secIdx; + break; + case SHT_SYMTAB: + symTabSecIdx = secIdx; + break; + case SHT_SYMTAB_SHNDX: + symTabShndxSecIdx = secIdx; + break; + case SHT_GNU_versym: + versymSec = &sec; + break; + case SHT_GNU_verdef: + verdefSec = &sec; + break; + case SHT_GNU_verneed: + verneedSec = &sec; + break; + } + auto secName = check(this->getObj().getSectionName(sec)); + if (secName == ".got.plt") + gotPltSecIdx = secIdx; + secIdx++; + } + + if (versymSec && this->numELFSyms == 0) { + error("SHT_GNU_versym should be associated with symbol table"); + return; + } + + // Search for a DT_SONAME tag to initialize this->soName. + for (const Elf_Dyn &dyn : dynamicTags) { + if (dyn.d_tag == DT_NEEDED) { + uint64_t val = dyn.getVal(); + if (val >= this->stringTable.size()) + fatal(toString(this) + ": invalid DT_NEEDED entry"); + dtNeeded.push_back(this->stringTable.data() + val); + } else if (dyn.d_tag == DT_SONAME) { + uint64_t val = dyn.getVal(); + if (val >= this->stringTable.size()) + fatal(toString(this) + ": invalid DT_SONAME entry"); + soName = this->stringTable.data() + val; + } + } + + verdefs = parseVerdefs(obj.base(), verdefSec); + std::vector verneeds = parseVerneed(obj, verneedSec); + + // Parse ".gnu.version" section which is a parallel array for the symbol + // table. If a given file doesn't have a ".gnu.version" section, we use + // VER_NDX_GLOBAL. + size_t size = this->numELFSyms - this->firstGlobal; + std::vector versyms(size, VER_NDX_GLOBAL); + if (versymSec) { + ArrayRef versym = + CHECK(obj.template getSectionContentsAsArray(*versymSec), + this) + .slice(this->firstGlobal); + for (size_t i = 0; i < size; ++i) + versyms[i] = versym[i].vs_index; + } + + // System libraries can have a lot of symbols with versions. Using a + // fixed buffer for computing the versions name (foo@ver) can save a + // lot of allocations. + SmallString<0> versionedNameBuffer; + + // Add symbols to the symbol table. + SymbolTable &symtab = *elf::symtab; + ArrayRef syms = this->template getGlobalELFSyms(); + for (size_t i = 0, e = syms.size(); i != e; ++i) { + const Elf_Sym &sym = syms[i]; + + // ELF spec requires that all local symbols precede weak or global + // symbols in each symbol table, and the index of first non-local symbol + // is stored to sh_info. If a local symbol appears after some non-local + // symbol, that's a violation of the spec. + StringRef name = CHECK(sym.getName(this->stringTable), this); + if (sym.getBinding() == STB_LOCAL) { + warn("found local symbol '" + name + + "' in global part of symbol table in file " + toString(this)); + continue; + } + + uint16_t idx = versyms[i] & ~VERSYM_HIDDEN; + if (sym.isUndefined()) { + // For unversioned undefined symbols, VER_NDX_GLOBAL makes more sense but + // as of binutils 2.34, GNU ld produces VER_NDX_LOCAL. + if (idx != VER_NDX_LOCAL && idx != VER_NDX_GLOBAL) { + if (idx >= verneeds.size()) { + error("corrupt input file: version need index " + Twine(idx) + + " for symbol " + name + " is out of bounds\n>>> defined in " + + toString(this)); + continue; + } + StringRef verName = this->stringTable.data() + verneeds[idx]; + versionedNameBuffer.clear(); + name = saver().save( + (name + "@" + verName).toStringRef(versionedNameBuffer)); + } + Symbol *s = symtab.addSymbol( + Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); + s->exportDynamic = true; + if (s->isUndefined() && sym.getBinding() != STB_WEAK && + config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) + requiredSymbols.push_back(s); + continue; + } + // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly + // assigns VER_NDX_LOCAL to this section global symbol. Here is a + // workaround for this bug. + if (config->emachine == EM_MIPS && idx == VER_NDX_LOCAL && + name == "_gp_disp") + continue; + + uint32_t alignment = getAlignment(sections, sym); + if (!(versyms[i] & VERSYM_HIDDEN)) { + auto *s = symtab.addSymbol( + SharedSymbol{*this, name, sym.getBinding(), sym.st_other, + sym.getType(), sym.st_value, sym.st_size, alignment}); + if (s->file == this) + s->verdefIndex = idx; + } + + // Also add the symbol with the versioned name to handle undefined symbols + // with explicit versions. + if (idx == VER_NDX_GLOBAL) + continue; + + if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) { + error("corrupt input file: version definition index " + Twine(idx) + + " for symbol " + name + " is out of bounds\n>>> defined in " + + toString(this)); + continue; + } + + StringRef verName = + this->stringTable.data() + + reinterpret_cast(verdefs[idx])->getAux()->vda_name; + versionedNameBuffer.clear(); + name = (name + "@" + verName).toStringRef(versionedNameBuffer); + auto *s = symtab.addSymbol( + SharedSymbol{*this, saver().save(name), sym.getBinding(), sym.st_other, + sym.getType(), sym.st_value, sym.st_size, alignment}); + if (s->file == this) + s->verdefIndex = idx; + } +} + +template void SharedFileExtended::parseElfSymTab() { + const ELFFile obj = this->getObj(); + ArrayRef eSections = this->template getELFShdrs(); + + // Find a symbol table. + const Elf_Shdr *eSymtabSec = findSection(eSections, SHT_SYMTAB); + if (!eSymtabSec) + return; + + eFirstGlobal = eSymtabSec->sh_info; + + ArrayRef eSyms = CHECK(obj.symbols(eSymtabSec), this); + auto numESyms = uint32_t(eSyms.size()); + auto eStringTable = CHECK(obj.getStringTableForSymtab(*eSymtabSec, eSections), this); + this->allSymbols.resize(numESyms); + + for (size_t i = 0; i < numESyms; i++) { + const Elf_Sym &eSym = eSyms[i]; + StringRef name(eStringTable.data() + eSym.st_name); + auto bind = eSym.getBinding(); + auto type = eSym.getType(); + auto other = eSym.st_other; + if (eSym.isDefined()) { + auto secIdx = eSym.st_shndx; + if (LLVM_UNLIKELY(secIdx == SHN_XINDEX)) + secIdx = check( + getExtendedSymbolTableIndex(eSym, i, this->getShndxTable())); + else if (secIdx >= SHN_LORESERVE) + secIdx = 0; + auto p = obj.getSection(secIdx); + if (p.takeError()) { + fatal("getSection failed: " + llvm::toString(p.takeError())); + } + const Elf_Shdr *eSec = *p; + InputSectionBase *sec = this->sections[secIdx]; + auto val = eSym.st_value; + if (type != STT_TLS) + val -= eSec->sh_addr; + auto dynSym = llvm::find_if(this->symbols, [=](const Symbol *s) { + return s && s->getName() == name; + }); + bool isInDynSym = dynSym != this->symbols.end(); + if (!isInDynSym) + name = addAdltPostfix(name); + /*if (name == "TLS_data1") // debug hint + lld::outs() << name << '\n'; */ + this->allSymbols[i] = + make(this, name, bind, other, type, val, eSym.st_size, sec); + } else { + this->allSymbols[i] = make(this, name, bind, other, type, + /*discardedSecIdx=*/i); + } + } +} + static ELFKind getBitcodeELFKind(const Triple &t) { if (t.isLittleEndian()) return t.isArch64Bit() ? ELF64LEKind : ELF32LEKind; @@ -1733,6 +2400,27 @@ ELFFileBase *elf::createObjFile(MemoryBufferRef mb, StringRef archiveName, return f; } +ELFFileBase *elf::createSharedFileExtended(MemoryBufferRef mb, StringRef soName) { + ELFFileBase *f; + switch (getELFKind(mb, soName)) { + case ELF32LEKind: + f = make>(mb, soName); + break; + case ELF32BEKind: + f = make>(mb, soName); + break; + case ELF64LEKind: + f = make>(mb, soName); + break; + case ELF64BEKind: + f = make>(mb, soName); + break; + default: + llvm_unreachable("getELFKind"); + } + return f; +} + template void ObjFile::parseLazy() { const ArrayRef eSyms = this->getELFSyms(); SymbolTable &symtab = *elf::symtab; @@ -1785,3 +2473,8 @@ template void SharedFile::parse(); template void SharedFile::parse(); template void SharedFile::parse(); template void SharedFile::parse(); + +template class elf::SharedFileExtended; +template class elf::SharedFileExtended; +template class elf::SharedFileExtended; +template class elf::SharedFileExtended; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index a24e664a7e168392a24bde93756705132adef115..65152c33727952018484e56c456d731edfe508f5 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -38,6 +38,7 @@ namespace elf { class InputSection; class Symbol; +struct PhdrEntry; // OHOS_LOCAL // If --reproduce is specified, all input files are written to this tar archive. extern std::unique_ptr tar; @@ -46,6 +47,7 @@ extern std::unique_ptr tar; llvm::Optional readFile(StringRef path); // Add symbols in File to the symbol table. +void buildSymsHist(InputFile *file, Ctx::eSymsCntMap &eSymsHist); void parseFile(InputFile *file); // The root class of input files. @@ -76,18 +78,31 @@ public: // Returns sections. It is a runtime error to call this function // on files that don't have the notion of sections. ArrayRef getSections() const { - assert(fileKind == ObjKind || fileKind == BinaryKind); + if (config->adlt) + assert(fileKind == SharedKind); + else + assert(fileKind == ObjKind || fileKind == BinaryKind); return sections; } // Returns object file symbols. It is a runtime error to call this // function on files of other types. ArrayRef getSymbols() const { - assert(fileKind == BinaryKind || fileKind == ObjKind || - fileKind == BitcodeKind); + if (config->adlt) + assert(fileKind == SharedKind); + else + assert(fileKind == BinaryKind || fileKind == ObjKind || + fileKind == BitcodeKind); return symbols; } + // ADLT beg + ArrayRef getAllSymbols() const { return allSymbols; } + + SmallVector allSymbols; + // ADLT end + + // Get filename to use for linker script processing. StringRef getNameForScript() const; @@ -161,6 +176,7 @@ private: class ELFFileBase : public InputFile { public: ELFFileBase(Kind k, MemoryBufferRef m); + virtual ~ELFFileBase() {} static bool classof(const InputFile *f) { return f->isElf(); } template llvm::object::ELFFile getObj() const { @@ -169,7 +185,7 @@ public: StringRef getStringTable() const { return stringTable; } - ArrayRef getLocalSymbols() { + virtual ArrayRef getLocalSymbols() { if (symbols.empty()) return {}; return llvm::makeArrayRef(symbols).slice(1, firstGlobal - 1); @@ -224,6 +240,7 @@ public: ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) { this->archiveName = archiveName; } + virtual ~ObjFile() {} void parse(bool ignoreComdats = false); void parseLazy(); @@ -231,7 +248,7 @@ public: StringRef getShtGroupSignature(ArrayRef sections, const Elf_Shdr &sec); - Symbol &getSymbol(uint32_t symbolIndex) const { + virtual Symbol &getSymbol(uint32_t symbolIndex) const { if (symbolIndex >= this->symbols.size()) fatal(toString(this) + ": invalid symbol index"); return *this->symbols[symbolIndex]; @@ -247,6 +264,8 @@ public: llvm::Optional getDILineInfo(InputSectionBase *, uint64_t); llvm::Optional> getVariableLoc(StringRef name); + ArrayRef getShndxTable(); + // Name of source file obtained from STT_FILE symbol value, // or empty string if there is no such symbol in object file // symbol table. @@ -274,9 +293,13 @@ public: // Get cached DWARF information. DWARFCache *getDwarf(); + void buildSymsHist(Ctx::eSymsCntMap &eSymsHist); void initializeLocalSymbols(); void postParse(); +protected: + virtual StringRef getUniqueName(StringRef origName) const; + private: void initializeSections(bool ignoreComdats, const llvm::object::ELFFile &obj); @@ -364,6 +387,118 @@ private: const typename ELFT::Shdr *sec); }; + +// ADLT +template +class SharedFileExtended : public ObjFile { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + +public: + SharedFileExtended(MemoryBufferRef mb, StringRef soName); + + static bool classof(const InputFile *f) { + return f->kind() == InputFile::SharedKind; + } + + void parseForAdlt(); + void postParseForAdlt(); + + StringRef addAdltPostfix(StringRef input) const; + bool addAdltPostfix(Symbol *s); + + bool saveSymbol(const Defined& d) const; + + Defined *findSectionSymbol(uint64_t offset) const; + Defined *findDefinedSymbol( + uint64_t offset, + llvm::function_ref extraCond = [](Defined *) { + return true; + }) const; + + InputSectionBase *findInputSection(StringRef name) const; + InputSectionBase *findInputSection(uint64_t offset) const; + bool isDynamicSection(InputSectionBase &sec) const; + + template + Symbol &getRelocTargetSymADLT(const RelT &rel, InputSectionBase &sec) const { + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + return getSymbolADLT(symIndex, isDynamicSection(sec)); + } + + ArrayRef getLocalSymbols() override { + if (this->allSymbols.empty()) + return {}; + return llvm::makeArrayRef(this->allSymbols).slice(1, eFirstGlobal - 1); + } + + Symbol &getDynamicSymbol(uint32_t symbolIndex) const; + Symbol &getSymbolADLT(uint32_t symbolIndex, bool fromDynamic) const; + + Symbol &getSymbolFromElfSymTab(uint32_t symbolIndex) const { + if (symbolIndex >= this->allSymbols.size()) + fatal(toString(this) + ": invalid symbol index"); + return *this->allSymbols[symbolIndex]; + } + + void traceElfSymbol(const Elf_Sym &sym, StringRef strTable) const; + void traceElfSection(const Elf_Shdr &sec) const; + + void traceSymbol(const Symbol &sym, StringRef title = "") const; + void traceSection(const SectionBase &sec, StringRef title = "") const; + +public: + // the input order of the file as it presented in ADLT image + size_t orderIdx; + int dynSymSecIdx = 0; + int symTabSecIdx = 0; + int symTabShndxSecIdx = 0; + int eFirstGlobal = 0; + int gotPltSecIdx = 0; + + // .symtab's start of local symbols owned by library + llvm::Optional sharedLocalSymbolIndex; + // .symtab's start of global symbols owned by library + llvm::Optional sharedGlobalSymbolIndex; + + // Output information data: + llvm::SetVector programHeaders; + + // From input .rela.dyn, .rela.plt: + llvm::SetVector dynRelIndexes; + llvm::SetVector pltRelIndexes; + + // SharedFile compability layer: + // This is actually a vector of Elf_Verdef pointers. + SmallVector verdefs; + // If the output file needs Elf_Verneed data structures for this file, this is + // a vector of Elf_Vernaux version identifiers that map onto the entries in + // Verdefs, otherwise it is empty. + SmallVector vernauxs; + static unsigned vernauxNum; + SmallVector dtNeeded; + StringRef soName; + StringRef simpleSoName; + // Used for --as-needed + // bool isNeeded; + // Non-weak undefined symbols which are not yet resolved when the SO is + // parsed. Only filled for `--no-allow-shlib-undefined`. + SmallVector requiredSymbols; + +protected: + virtual StringRef getUniqueName(StringRef origName) const override; + +private: + void parseDynamics(); // SharedFile compability + void parseElfSymTab(); // ObjectFile compability + + void resolveDuplicatesForAdlt(); + + StringRef getShStrTab(ArrayRef elfSections); + + std::vector parseVerneed(const llvm::object::ELFFile &obj, + const typename ELFT::Shdr *sec); +}; + class BinaryFile : public InputFile { public: explicit BinaryFile(MemoryBufferRef m) : InputFile(BinaryKind, m) {} @@ -374,6 +509,8 @@ public: ELFFileBase *createObjFile(MemoryBufferRef mb, StringRef archiveName = "", bool lazy = false); +ELFFileBase *createSharedFileExtended(MemoryBufferRef mb, StringRef soName = ""); + std::string replaceThinLTOSuffix(StringRef path); } // namespace elf diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 8fe36eca6a4be91295854af2af08b9f50e2712d0..0eb2968413bddb05fb4888a7c749490fe14e98ac 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -347,8 +347,11 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { for (const RelTy &rel : rels) { RelType type = rel.getType(config->isMips64EL); - const ObjFile *file = getFile(); - Symbol &sym = file->getRelocTargetSym(rel); + const ObjFile *file = + config->adlt ? getSharedFile() : getFile(); + Symbol &sym = config->adlt + ? getSharedFile()->getRelocTargetSymADLT(rel, *sec) + : file->getRelocTargetSym(rel); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -844,7 +847,19 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend += target.getImplicitAddend(bufLoc, type); - Symbol &sym = getFile()->getRelocTargetSym(rel); + Symbol &sym = config->adlt ? getSharedFile()->getSymbolFromElfSymTab( + rel.getSymbol(config->isMips64EL)) + : getFile()->getRelocTargetSym(rel); + if (config->adlt) { // TODO improve + switch (type) { + case R_AARCH64_RELATIVE: + case R_AARCH64_GLOB_DAT: + case R_AARCH64_JUMP_SLOT: + return; + default: + break; + } + } RelExpr expr = target.getRelExpr(type, sym, bufLoc); if (expr == R_NONE) continue; @@ -948,7 +963,9 @@ static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) { template void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { - if ((flags & SHF_EXECINSTR) && LLVM_UNLIKELY(getFile()->splitStack)) + if (flags & SHF_EXECINSTR && + (config->adlt ? LLVM_UNLIKELY(getSharedFile()->splitStack) + : LLVM_UNLIKELY(getFile()->splitStack))) adjustSplitStackFunctionPrologues(buf, bufEnd); if (flags & SHF_ALLOC) { @@ -985,6 +1002,8 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { if (auto *sec = dyn_cast(this)) secAddr += sec->outSecOff; const uint64_t addrLoc = secAddr + offset; + /*if (config->adlt && addrLoc == 68600) // debug hint + lld::outs() << "addrLoc 0x" << utohexstr(addrLoc) << "\n";*/ const uint64_t targetVA = SignExtend64(getRelocTargetVA(file, rel.type, rel.addend, addrLoc, *rel.sym, rel.expr), diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index d1b889750bbd485e85dc0a97841cda1d8473c9ab..b9f4541e77a9a43fd3b67b711ff0af755ea1882d 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -28,6 +28,7 @@ class Defined; struct Partition; class SyntheticSection; template class ObjFile; +template class SharedFileExtended; class OutputSection; extern std::vector partitions; @@ -74,6 +75,9 @@ public: uint32_t type; uint32_t link; uint32_t info; + uint64_t address = 0; // store input sec addr for ADLT + uint64_t size = 0; // store input sec size for ADLT + OutputSection *getOutputSection(); const OutputSection *getOutputSection() const { @@ -133,6 +137,11 @@ public: return cast_or_null>(file); } + template + SharedFileExtended *getSharedFile() const { + return cast_or_null>(file); + } + // Used by --optimize-bb-jumps and RISC-V linker relaxation temporarily to // indicate the number of bytes which is not counted in the size. This should // be reset to zero after uses. @@ -392,7 +401,7 @@ private: template void copyShtGroup(uint8_t *buf); }; -static_assert(sizeof(InputSection) <= 160, "InputSection is too big"); +static_assert(sizeof(InputSection) <= 180, "InputSection is too big"); inline bool isDebugSection(const InputSectionBase &sec) { return (sec.flags & llvm::ELF::SHF_ALLOC) == 0 && diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 51c505d159d53a811172e360a0a2065ea49a5c25..68729e4ebc4bfc88515e33cfd1f49e3a2a6fc1d2 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -104,7 +104,9 @@ static StringRef getOutputSectionName(const InputSectionBase *s) { {".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", ".gcc_except_table", ".init_array", ".fini_array", ".tbss", ".tdata", ".ARM.exidx", ".ARM.extab", ".ctors", ".dtors", ".ohos.randomdata"}) // OHOS_LOCAL - if (isSectionPrefix(v, s->name)) + if (config->adlt && s->name.startswith(v)) + return s->name; + else if (isSectionPrefix(v, s->name)) return v; return s->name; diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index 893511929a3a50aa3b7e21a2b4821aa596be1e6d..51353287c90e540f36549841479d11cc440673a0 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -55,7 +55,8 @@ static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma, // Returns a list of all symbols that we want to print out. static std::vector getSymbols() { std::vector v; - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *b : file->getSymbols()) if (auto *dr = dyn_cast(b)) if (!dr->isSection() && dr->section && dr->section->isLive() && @@ -224,7 +225,8 @@ static void writeMapFile(raw_fd_ostream &os) { static void writeCref(raw_fd_ostream &os) { // Collect symbols and files. MapVector> map; - for (ELFFileBase *file : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) { for (Symbol *sym : file->getSymbols()) { if (isa(sym)) map[sym].insert(file); diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 12a23390e663b1defc3243f38876a5bdf7c0c1ad..61be1e13287f75665e3d681fa601a22e04a428bb 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -345,7 +345,8 @@ template void MarkLive::mark() { // to from __start_/__stop_ symbols because there will only be one set of // symbols for the whole program. template void MarkLive::moveToMain() { - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *s : file->getSymbols()) if (auto *d = dyn_cast(s)) if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 4e6c20f5c7f6014f4f23ed17b0962212966989c6..8342d7be88d1227c58bfd179274f4d0f0cdb0c19 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -375,6 +375,10 @@ defm section_start: Eq<"section-start", "Set address of section">, def shared: F<"shared">, HelpText<"Build a shared object">; +def adlt: F<"adlt">, HelpText<"Build adlt library">; + +def adlt_trace: F<"adlt-trace">, HelpText<"Enable ADLT trace logs">; + defm soname: Eq<"soname", "Set DT_SONAME">; defm sort_section: diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 277c57505bb2f920b51068b7def01c75081ad01c..7984401410256df7c663c07ff5d144a63cc9947e 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -100,7 +100,8 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, ErrorPlace errPlace = getErrorPlace(loc); std::string hint; if (rel.sym && !rel.sym->isSection()) - hint = "; references " + lld::toString(*rel.sym); + hint = "; references " + lld::toString(*rel.sym) + + (config->adlt ? ": raw-name: " + rel.sym->getName().str() + " " : ""); if (!errPlace.srcLoc.empty()) hint += "\n>>> referenced by " + errPlace.srcLoc; if (rel.sym && !rel.sym->isSection()) @@ -110,6 +111,11 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, hint += "; consider recompiling with -fdebug-types-section to reduce size " "of debug sections"; + if (config->adlt) { + auto offset = errPlace.isec->address + rel.offset; // debug hint: put bkpt here + hint += " [ADLT] Offset: 0x" + utohexstr(offset) + "\n"; + } + errorOrWarn(errPlace.loc + "relocation " + lld::toString(rel.type) + " out of range: " + v.str() + " is not in [" + Twine(min).str() + ", " + Twine(max).str() + "]" + hint); @@ -455,6 +461,13 @@ private: void processAux(RelExpr expr, RelType type, uint64_t offset, Symbol &sym, int64_t addend) const; template void scanOne(RelTy *&i); + + // ADLT + template + void processForADLT(const RelTy &rel, Relocation *r, bool fromDynamic); + + template + void tracePushRelocADLT(InputSectionBase &isec, Relocation &r) const; }; } // namespace @@ -1291,10 +1304,171 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym, return 0; } +template +static void trackDynRelocAdlt(SharedFileExtended *soFile) { + soFile->dynRelIndexes.insert(mainPart->relaDyn->relocs.size() - 1); +} + +template +static void trackGotPltAdlt(Symbol *sym, SharedFileExtended *soFile) { + ctx->adlt.gotPltInfo[sym].push_back(soFile->orderIdx); +} + +// ADLT BEGIN +template +void RelocationScanner::tracePushRelocADLT(InputSectionBase &isec, + Relocation &r) const { + auto file = sec.getSharedFile(); + auto fullOffset = isec.address + r.offset; + lld::outs() << "[ADLT] Before push: [0x" + utohexstr(fullOffset) + + "] type: " + toString(r.type) + + " expr: " + std::to_string(r.expr) + " offset: 0x" + + utohexstr(r.offset) + " addend: 0x" + utohexstr(r.addend) + + ".\n"; + lld::outs() << "section where: "; + file->traceSection(isec); + + lld::outs() << "r->sym: "; + file->traceSymbol(*r.sym); + lld::outs() << "\n"; +} + +template +void RelocationScanner::processForADLT(const RelTy &rel, Relocation *r, + bool fromDynamic) { + auto file = sec.getSharedFile(); + bool isDebug = false; + + /*if (r->offset == 0x21F) // debug hint + isDebug = true; + /*if (r->type == R_AARCH64_ABS64 && + r->sym->getName() == "__emutls_t.TLS_data1") + isDebug = true;*/ + + // parse offset (where) + InputSectionBase *secWhere = file->findInputSection(r->offset); + assert(secWhere && "not found!"); + + // process offset + r->offset -= fromDynamic ? secWhere->address : sec.address; + assert(r->type); + + if (isDebug) + tracePushRelocADLT(*secWhere, *r); + + // resolve relocs + switch (r->type) { + // dyn relocs + case R_AARCH64_RELATIVE: { + Defined *d = file->findDefinedSymbol(r->addend); + assert(d && "R_AARCH64_RELATIVE: r->sym not found by addend!"); + r->sym = d; + r->addend -= d->section->address + d->value; + addRelativeReloc(*secWhere, r->offset, *r->sym, r->addend, r->expr, + r->type); + trackDynRelocAdlt(file); + return; + } + case R_AARCH64_GLOB_DAT: + assert(r->sym->exportDynamic); + if (!r->sym->needsGot) + r->sym->needsGot = 1; + trackGotPltAdlt(r->sym, file); + return; + case R_AARCH64_JUMP_SLOT: + assert(r->sym->exportDynamic); + if (r->sym->isUndefined() && !r->sym->needsPlt) + r->sym->needsPlt = 1; + trackGotPltAdlt(r->sym, file); + return; + // abs relocs + case R_AARCH64_ABS32: + sec.relocations.push_back(*r); + return; + case R_AARCH64_ABS64: + if (fromDynamic) { + assert(r->sym->exportDynamic); + sec.getPartition().relaDyn->addSymbolReloc(target.symbolicRel, *secWhere, + r->offset, *r->sym, r->addend, + r->type); + trackDynRelocAdlt(file); + return; + } + sec.relocations.push_back(*r); + return; + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_PREL32: + case R_AARCH64_PREL64: + processAux(r->expr, r->type, r->offset, *r->sym, r->addend); + return; + // plt relocs + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_CONDBR19: + case R_AARCH64_TSTBR14: + if (r->sym->isDefined()) + r->expr = R_PC; // prev: R_PLT_PC + sec.relocations.push_back(*r); + return; + // got relocs + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_ADR_PREL_PG_HI21: + sec.relocations.push_back(*r); // TODO: optimize GOT + return; + case R_AARCH64_ADR_GOT_PAGE: + if (r->sym->isDefined() && !r->sym->needsGot) { + if (isDebug) + lld::outs() << "[ADLT] R_AARCH64_ADR_GOT_PAGE: sym not in GOT! "; + r->expr = R_PC; // prev: R_AARCH64_GOT_PAGE_PC || R_AARCH64_GOT_PAGE || + // R_GOT || R_GOT_PC + // TODO: replace reloc R_AARCH64_ADR_GOT_PAGE + sec.relocations.push_back(*r); + return; + } + LLVM_FALLTHROUGH; + case R_AARCH64_LD64_GOT_LO12_NC: + case R_AARCH64_LD64_GOTPAGE_LO15: + processAux(r->expr, r->type, r->offset, *r->sym, r->addend); + return; + // tls relocs + case R_AARCH64_TLSDESC: + if (fromDynamic && !r->sym->needsTlsDesc) + r->sym->needsTlsDesc = 1; + trackDynRelocAdlt(file); + return; + case R_AARCH64_TLSDESC_CALL: + case R_AARCH64_TLS_TPREL64: + case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case R_AARCH64_TLSDESC_ADR_PAGE21: + case R_AARCH64_TLSDESC_LD64_LO12: + case R_AARCH64_TLSDESC_ADD_LO12: + case R_AARCH64_TLSLE_ADD_TPREL_HI12: + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + handleTlsRelocation(r->type, *r->sym, sec, r->offset, r->addend, r->expr); + return; + default: + fatal("[ADLT] Unhandled " + toString(fromDynamic ? "dynamic " : "") + + "reloc: " + toString(r->type)); + break; + } +} +// ADLT END + template void RelocationScanner::scanOne(RelTy *&i) { const RelTy &rel = *i; uint32_t symIndex = rel.getSymbol(config->isMips64EL); - Symbol &sym = sec.getFile()->getSymbol(symIndex); + bool fromDynamic = false; + if (config->adlt) + fromDynamic = sec.getSharedFile()->isDynamicSection(sec); + Symbol &sym = + config->adlt + ? sec.getSharedFile()->getSymbolADLT(symIndex, fromDynamic) + : sec.getFile()->getSymbol(symIndex); RelType type; // Deal with MIPS oddity. @@ -1312,7 +1486,7 @@ template void RelocationScanner::scanOne(RelTy *&i) { // Error if the target symbol is undefined. Symbol index 0 may be used by // marker relocations, e.g. R_*_NONE and R_ARM_V4BX. Don't error on them. - if (sym.isUndefined() && symIndex != 0 && + if (symIndex != 0 && sym.isUndefined() && maybeReportUndefined(cast(sym), sec, offset)) return; @@ -1326,6 +1500,12 @@ template void RelocationScanner::scanOne(RelTy *&i) { // Read an addend. int64_t addend = computeAddend(rel, expr, sym.isLocal()); + if (config->adlt) { + Relocation r = {expr, type, offset, addend, &sym}; + processForADLT(rel, &r, fromDynamic); + return; + } + if (config->emachine == EM_PPC64) { // We can separate the small code model relocations into 2 categories: // 1) Those that access the compiler generated .toc sections. @@ -1536,6 +1716,11 @@ void RelocationScanner::scan(ArrayRef rels) { template void elf::scanRelocations(InputSectionBase &s) { RelocationScanner scanner(s); + if (config->adlt) { + bool isDebug = false; + if (isDebug) + lld::outs() << s.file->getName().str() + ": " + s.name.str() + '\n'; + } const RelsOrRelas rels = s.template relsOrRelas(); if (rels.areRelocsRel()) scanner.template scan(rels.rels); @@ -1622,18 +1807,35 @@ static bool handleNonPreemptibleIfunc(Symbol &sym) { return true; } +template static void addGotPltIndexAdlt(Symbol *s, bool isPlt) { + auto &vec = ctx->adlt.gotPltInfo[s]; + for (auto &it : vec) { + auto *soFile = cast>(ctx->sharedFilesExtended[it]); + auto &entries = isPlt ? in.relaPlt->relocs : mainPart->relaDyn->relocs; + auto &output = isPlt ? soFile->pltRelIndexes : soFile->dynRelIndexes; + output.insert(entries.size() - 1); + } +} + void elf::postScanRelocations() { auto fn = [](Symbol &sym) { if (handleNonPreemptibleIfunc(sym)) return; if (!sym.needsDynReloc()) return; - sym.allocateAux(); + if (!sym.allocateAux()) + return; - if (sym.needsGot) + if (sym.needsGot) { addGotEntry(sym); - if (sym.needsPlt) + if (config->adlt) + invokeELFT(addGotPltIndexAdlt, &sym, false); + } + if (sym.needsPlt) { addPltEntry(*in.plt, *in.gotPlt, *in.relaPlt, target->pltRel, sym); + if (config->adlt) + invokeELFT(addGotPltIndexAdlt, &sym, true); + } if (sym.needsCopy) { if (sym.isObject()) { invokeELFT(addCopyRelSymbol, cast(sym)); @@ -1667,6 +1869,7 @@ void elf::postScanRelocations() { mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible( target->tlsDescRel, *in.got, in.got->getTlsDescOffset(sym), sym, target->tlsDescRel); + invokeELFT(addGotPltIndexAdlt, &sym, false); } if (sym.needsTlsGd) { in.got->addDynTlsEntry(sym); @@ -1720,7 +1923,8 @@ void elf::postScanRelocations() { // Local symbols may need the aforementioned non-preemptible ifunc and GOT // handling. They don't need regular PLT. - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) fn(*sym); } @@ -2168,7 +2372,6 @@ bool ThunkCreator::createThunks(uint32_t pass, // original target so another Thunk can be generated. if (pass > 0 && normalizeExistingThunk(rel, src)) continue; - if (!target->needsThunk(rel.expr, rel.type, isec->file, src, *rel.sym, rel.addend)) continue; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 657c19a00ba364cf3bd429141fe53d097f3decc2..d65ebd486dd24632333cd9b9a7acc5ce6da07d4d 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -307,10 +307,12 @@ public: return needsCopy || needsGot || needsPlt || needsTlsDesc || needsTlsGd || needsTlsGdToIe || needsGotDtprel || needsTlsIe; } - void allocateAux() { - assert(auxIdx == uint32_t(-1)); + bool allocateAux() { + if (auxIdx != uint32_t(-1)) + return false; auxIdx = symAux.size(); symAux.emplace_back(); + return true; } bool isSection() const { return type == llvm::ELF::STT_SECTION; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f298b83bda0e4f00b253c28a201d7a1b69a759a0..61d52dc894b5ce2f046fd3a6d075277386f7b8bc 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1397,9 +1397,22 @@ DynamicSection::computeContents() { addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH, part.dynStrTab->addString(config->rpath)); - for (SharedFile *file : ctx->sharedFiles) - if (file->isNeeded) - addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); + if (config->adlt) { + for (InputFile *file : ctx->sharedFilesExtended) { + auto *f = cast>(file); + for (size_t i = 0; i < f->dtNeeded.size(); i++) { + auto tag = DT_NEEDED; + auto val = part.dynStrTab->addString(f->dtNeeded[i]); + if (llvm::find(entries, std::pair{tag, val}) == + entries.end()) + addInt(tag, val); + } + } + addInt(DT_SONAME, part.dynStrTab->addString(config->outputFile)); + } else + for (SharedFile *file : ctx->sharedFiles) + if (file->isNeeded) + addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); if (isMain) { if (!config->soName.empty()) @@ -1536,17 +1549,40 @@ DynamicSection::computeContents() { addInSec(DT_HASH, *part.hashTab); if (isMain) { - if (Out::preinitArray) { - addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr); - addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size); - } - if (Out::initArray) { - addInt(DT_INIT_ARRAY, Out::initArray->addr); - addInt(DT_INIT_ARRAYSZ, Out::initArray->size); - } - if (Out::finiArray) { - addInt(DT_FINI_ARRAY, Out::finiArray->addr); - addInt(DT_FINI_ARRAYSZ, Out::finiArray->size); + if (config->adlt) { + auto findSection = [](StringRef name, unsigned partition = 1) { + for (SectionCommand *cmd : script->sectionCommands) + if (auto *osd = dyn_cast(cmd)) + if (osd->osec.name == name && osd->osec.partition == partition) + return &osd->osec; + return (OutputSection *)nullptr; + }; + for (InputFile *file : ctx->sharedFilesExtended) { + auto *f = cast>(file); + auto initArray = findSection(f->addAdltPostfix(".init_array")); + auto finiArray = findSection(f->addAdltPostfix(".fini_array")); + if (initArray) { + addInt(DT_INIT_ARRAY, initArray->addr); + addInt(DT_INIT_ARRAYSZ, initArray->size); + } + if (finiArray) { + addInt(DT_FINI_ARRAY, finiArray->addr); + addInt(DT_FINI_ARRAYSZ, finiArray->size); + } + } + } else { + if (Out::preinitArray) { + addInt(DT_PREINIT_ARRAY, Out::preinitArray->addr); + addInt(DT_PREINIT_ARRAYSZ, Out::preinitArray->size); + } + if (Out::initArray) { + addInt(DT_INIT_ARRAY, Out::initArray->addr); + addInt(DT_INIT_ARRAYSZ, Out::initArray->size); + } + if (Out::finiArray) { + addInt(DT_FINI_ARRAY, Out::finiArray->addr); + addInt(DT_FINI_ARRAYSZ, Out::finiArray->size); + } } if (Symbol *b = symtab->find(config->init)) @@ -2207,6 +2243,11 @@ void SymbolTableBaseSection::sortSymTabSymbols() { size_t numLocals = e - symbols.begin(); getParent()->info = numLocals + 1; + if (config->adlt && this->type == SHT_SYMTAB) { + invokeELFT(sortSymTabSymbolsInAdlt, numLocals); + return; + } + // We want to group the local symbols by file. For that we rebuild the local // part of the symbols vector. We do not need to care about the STT_FILE // symbols, they are already naturally placed first in each group. That @@ -2222,6 +2263,50 @@ void SymbolTableBaseSection::sortSymTabSymbols() { *i++ = entry; } +template +void SymbolTableBaseSection::sortSymTabSymbolsInAdlt(size_t numLocals) { + auto localEnd = symbols.begin() + numLocals; + + using SortKey = std::tuple; + auto makeKey = [](const SymbolTableEntry& ent) -> SortKey { + const InputFile* file = ent.sym->file; + if(auto* soext = dyn_cast_or_null>(file)) { + return {static_cast(soext->orderIdx), file}; + } + return {-1, file}; + }; + + for (InputFile* file : ctx->sharedFilesExtended) { + auto* soext = cast>(file); + soext->sharedLocalSymbolIndex = llvm::None; + soext->sharedGlobalSymbolIndex = llvm::None; + } + + // sort local symbols + llvm::stable_sort(llvm::make_range(symbols.begin(), localEnd), + [makeKey](const SymbolTableEntry& lhs, const SymbolTableEntry& rhs) { + return makeKey(lhs) <= makeKey(rhs); + }); + + // sort global symbols + llvm::stable_sort(llvm::make_range(localEnd, symbols.end()), + [makeKey](const SymbolTableEntry& lhs, const SymbolTableEntry& rhs) { + return makeKey(lhs) <= makeKey(rhs); + }); + + // extract file boundaries for local symbols + for (auto iter = symbols.begin(); iter != localEnd; ++iter) + if (auto* soext = dyn_cast_or_null>(iter->sym->file)) + if (!soext->sharedLocalSymbolIndex) + soext->sharedLocalSymbolIndex = std::distance(symbols.begin(), iter); + + // extract file boundaries for global symbols + for (auto iter = localEnd; iter != symbols.end(); ++iter) + if (auto* soext = dyn_cast_or_null>(iter->sym->file)) + if (!soext->sharedGlobalSymbolIndex) + soext->sharedGlobalSymbolIndex = std::distance(symbols.begin(), iter); +} + void SymbolTableBaseSection::addSymbol(Symbol *b) { // Adding a local symbol to a .dynsym is a bug. assert(this->type != SHT_DYNSYM || !b->isLocal()); @@ -3410,7 +3495,8 @@ template void elf::splitSections() { llvm::TimeTraceScope timeScope("Split sections"); // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - parallelForEach(ctx->objectFiles, [](ELFFileBase *file) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + parallelForEach(files, [](ELFFileBase *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) continue; @@ -3912,6 +3998,8 @@ void InStruct::reset() { strTab.reset(); symTab.reset(); symTabShndx.reset(); + adltData.reset(); + adltStrTab.reset(); } constexpr char kMemtagAndroidNoteName[] = "Android"; @@ -3958,6 +4046,450 @@ size_t PackageMetadataNote::getSize() const { alignTo(config->packageMetadata.size() + 1, 4); } + +// OHOS_LOCAL begin +namespace lld { namespace elf { namespace adlt { + +static_assert( + sizeof(adlt_semver_t) == sizeof(Elf64_Half), + ".adlt semantic version is designed to occupy uint16_t" +); + +static_assert( + sizeof(adlt_dt_needed_index_t) == sizeof(Elf64_Off), + "adlt_dt_needed_index_t have to be an offset with intrused flags" +); + +static_assert( + sizeof(adlt_cross_section_ref_t) == 16, + "adlt_cross_section_ref_t size is 16 bytes" +); + +static_assert( + sizeof(adlt_cross_section_array_t) == 24, + "adlt_cross_section_ref_t size is 24 bytes" +); + +static_assert( + sizeof(adlt_hash_type_t) == sizeof(Elf64_Byte), + "String hash type enum should occupy only one byte" +); + +static_assert( + sizeof(adlt_blob_array_t) == 16, + "blob array reference occupies 16 bytes in PSOD" +); + +static_assert(sizeof(adltBlobStartMark) == 4, + "0xad17 consist of 4 bytes" +); + +static_assert(sizeof(adlt_section_header_t) == 56, + "please update version if header has been changed" +); + +static_assert(sizeof(adlt_psod_t) == 160, + "please udpate version if adlt_psod_t layout or content changed" +); + + +template +AdltSection::AdltSection(StringTableSection& strTabSec) + : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".adlt") + , strTabSec(strTabSec) +{ + assert(config->adlt); +} + +template +void AdltSection::finalizeContents() { + soInputs.clear(); + soInputs.reserve(ctx->sharedFilesExtended.size()); + for (InputFile* file : ctx->sharedFilesExtended) { + auto* soext = cast>(file); + soInputs.push_back(makeSoData(soext)); + } + + assert((soInputs.size() < 1<<16) && + "the number of input libs exeeds ELF limit on number of sections"); + const Elf64_Half soNum = soInputs.size(); + + common = makeCommonData(); + + std::memset(&header, 0, sizeof(header)); + header = adlt_section_header_t{ + adltSchemaVersion, // .schemaVersion + sizeof(adlt_section_header_t), // .schemaHeaderSize + sizeof(adlt_psod_t), // .schemaPSODSize + soNum, // .sharedObjectsNum + ADLT_HASH_TYPE_GNU_HASH, // .stringHashType + getBlobStartOffset(), // .blobStart + estimateBlobSize(), // .blobSize + 0, // .overallMappedSize, known on writeTo + adlt_blob_u16_array_t{}, // .phIndexes, filled in writeTo + }; + + buildSonameIndex(); + linkInternalDtNeeded(); + extractInitFiniArray(); +} + +template +void AdltSection::buildSonameIndex() { + for (const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + auto res = sonameToIndexMap.try_emplace( + CachedHashStringRef(soData.soName.ref), it.index()); + if (!res.second) { + warn(Twine(".adlt-section: duplicated soname: ") + soData.soName.ref + + " at pos=" + Twine(it.index()) + + " collided with pos=" + Twine(res.first->second)); + } + } +} + +template +void AdltSection::linkInternalDtNeeded() { + for (auto it : llvm::enumerate(soInputs)) { + auto& soData = it.value(); + for (auto& needed : soData.dtNeededs) { + auto cref = CachedHashStringRef(needed.str.ref); + auto res = sonameToIndexMap.find(cref); + if (res != sonameToIndexMap.end()) { + needed.psodIndex = res->second; + } + } + } +} + +template +OutputSection* AdltSection::findOutSection(StringRef name) { + if (name.empty()) return nullptr; + const unsigned partition = 1; + + for (SectionCommand* cmd : script->sectionCommands) { + if (auto* osd = dyn_cast(cmd)) + if (osd->osec.name == name && osd->osec.partition == partition) + return &osd->osec; + } + return nullptr; +} + +template +void AdltSection::extractInitFiniArray() { + for (auto& soData : soInputs) { + auto initArrayName = soData.initArrayName; + auto finiArrayName = soData.finiArrayName; + soData.initArraySec = findOutSection(initArrayName); + soData.finiArraySec = findOutSection(finiArrayName); + } +} + +template +size_t AdltSection::estimateOverallMappedSize() { + size_t totalMemsz = 0; + for (PhdrEntry* ph : mainPart->phdrs) + if (ph->p_type == PT_LOAD) + totalMemsz += ph->p_memsz; + return totalMemsz; +} + +template +typename AdltSection::CommonData +AdltSection::makeCommonData() { + return CommonData { + UINT32_MAX, // .symtabSecIndex, filled in writeTo + ctx->adlt.commonProgramHeaders.size(), // .programHeadersAllocated + {}, // .phIndexes filled in writeTo + }; +} + +template +typename AdltSection::SoData +AdltSection::makeSoData(const SharedFileExtended* soext) { + assert(soext); + SoData data = {}; + StringRef soname = soext->soName; + data.soName = SectionString{soname, strTabSec.addString(soname)}; + + for (const auto& neededName: soext->dtNeeded) { + data.dtNeededs.push_back({ + SectionString{neededName, strTabSec.addString(neededName)}, + {}, // unknown now, filled by linkInternalDtNeeded + }); + } + + data.initArrayName = soext->addAdltPostfix(".init_array"); + data.finiArrayName = soext->addAdltPostfix(".fini_array"); + + data.relaDynIndx = soext->dynRelIndexes.getArrayRef(); + data.relaPltIndx = soext->pltRelIndexes.getArrayRef(); + + data.programHeadersAllocated = soext->programHeaders.size(); + data.programHeaders = soext->programHeaders.getArrayRef(); + + return data; +} + +template +Elf64_Xword AdltSection::calculateHash(StringRef str) const { + switch(static_cast(header.stringHashType)) { + case ADLT_HASH_TYPE_NONE: + return 0x0; + case ADLT_HASH_TYPE_GNU_HASH: + return hashGnu(str); + case ADLT_HASH_TYPE_SYSV_HASH: + return hashSysV(str); + case ADLT_HASH_TYPE_DEBUG_CONST: + return 0xdeadbeef1337c0de; + default: + llvm_unreachable(".adlt hash type not implemented"); + } +} + +template +adlt_psod_t AdltSection::serialize(const SoData& soData) const { + return adlt_psod_t { + soData.soName.strtabOff, // .soName + calculateHash(soData.soName.ref), // .soNameHash + soData.initArraySec ? adlt_cross_section_array_t{ // .initArray + soData.initArraySec->sectionIndex, + 0x0, // .init_array function addresses are located at the start + soData.initArraySec->size, // size + } : adlt_cross_section_array_t{}, + soData.finiArraySec ? adlt_cross_section_array_t{ // .finiArray + soData.finiArraySec->sectionIndex, + 0x0, // .fini_array function addresses are located at the start + soData.finiArraySec->size, // size + } : adlt_cross_section_array_t{}, + adlt_blob_array_t {}, // .dtNeeded, filled in writeTo + adlt_cross_section_ref_t { + soData.sharedLocalIndex ? common.symtabSecIndex : UINT32_MAX, + soData.sharedLocalIndex.value_or(0), + }, // .sharedLocalSymbolIndex + adlt_cross_section_ref_t { + soData.sharedGlobalIndex ? common.symtabSecIndex : UINT32_MAX, + soData.sharedGlobalIndex.value_or(0), + }, // .sharedGlobalSymbolIndex + adlt_blob_u16_array_t {}, // .phIndexes, filled in writeTo + adlt_blob_u32_array_t {}, // .relaDynIndx, filled in writeTo + adlt_blob_u32_array_t {}, // .relaPltIndx, filled in writeTo + }; +} + +template +Elf64_Off AdltSection::getBlobStartOffset() const { + return sizeof(adlt_section_header_t) + sizeof(adlt_psod_t) * soInputs.size(); +} + +template +size_t AdltSection::estimateBlobSize() const { + size_t blobSize = sizeof(adltBlobStartMark); + + blobSize += sizeof(uint16_t) * common.programHeadersAllocated; + + for (const auto& soData: soInputs) { + blobSize += sizeof(adlt_dt_needed_index_t) * soData.dtNeededs.size(); + blobSize += sizeof(uint16_t) * soData.programHeadersAllocated; + blobSize += sizeof(uint32_t) * soData.relaDynIndx.size(); + blobSize += sizeof(uint32_t) * soData.relaPltIndx.size(); + }; + + return blobSize; +} + +template +template +adlt_blob_array_t AdltSection::writeArray( + uint8_t* buff, size_t offset, const SmallVector& data) { + if (data.empty()) return {0x0, 0}; + + const size_t to_write = data.size_in_bytes(); + memcpy(buff + offset, data.data(), to_write); + + return {offset, to_write}; +} + +template +template +adlt_blob_array_t AdltSection::writeArray( + uint8_t* buff, size_t offset, const ArrayRef& data) { + if (data.empty()) return {0x0, 0}; + + const size_t to_write = data.size() * sizeof(T); + memcpy(buff + offset, data.data(), to_write); + + return {offset, to_write}; +} + + +template +adlt_blob_array_t AdltSection::writeDtNeeded( + uint8_t* buff, size_t offset, const DtNeededsVec& neededVec) { + if (neededVec.empty()) return {0x0, 0}; + + SmallVector needIndexes; + needIndexes.reserve(neededVec.size()); + for (const auto& need_data : neededVec) { + needIndexes.push_back(adlt_dt_needed_index_t{ + need_data.psodIndex.has_value(), // .hasInternalPSOD + need_data.psodIndex.value_or(0), // .PSODindex + need_data.str.strtabOff, // .sonameOffset + }); + } + + return writeArray(buff, offset, needIndexes); +} + +template +void AdltSection::extractProgramHeaderIndexes() { + phdrsIndexes.clear(); + for (const auto& it : llvm::enumerate(mainPart->phdrs)) { + phdrsIndexes[it.value()] = static_cast(it.index()); + }; + + for (const PhdrEntry* phentry : ctx->adlt.commonProgramHeaders) { + auto it = phdrsIndexes.find(phentry); + if (it != phdrsIndexes.end()) { + common.phIndexes.push_back(it->second); + } + } + + assert(common.phIndexes.size() <= common.programHeadersAllocated); + if (common.phIndexes.size() != common.programHeadersAllocated) { + warn(Twine(".adlt section: overallocated common ph-indexes") + + " allocated=" + Twine(common.programHeadersAllocated) + + " actual=" + Twine(common.phIndexes.size()) + ); + } +} + +template +void AdltSection::finalizeOnWrite() { + // require optimizing Writer::removeEmptyPTLoad been called + extractProgramHeaderIndexes(); + // require Writer::setPhdrs previously been called + header.overallMappedSize = estimateOverallMappedSize(); + + if (OutputSection* osec = findOutSection(".symtab")) { + common.symtabSecIndex = osec->sectionIndex; + } + + for (auto& it: llvm::enumerate(soInputs)) { + finalizeOnWrite(it.index(), it.value()); + } +} + +template +void AdltSection::finalizeOnWrite(size_t idx, SoData& soData) { + auto* soext = cast>(ctx->sharedFilesExtended[idx]); + + // require SymbolTableBaseSection::sortSymTabSymbolsInAdlt for .symtab called + soData.sharedLocalIndex = soext->sharedLocalSymbolIndex; + soData.sharedGlobalIndex = soext->sharedGlobalSymbolIndex; + + // phIndexes may shift if called before Writer::removeEmptyPTLoad + soData.phIndexes.clear(); + for (const PhdrEntry* phentry : soData.programHeaders) { + auto it = phdrsIndexes.find(phentry); + if (it != phdrsIndexes.end()) { + soData.phIndexes.push_back(it->second); + } + } + + assert(soData.phIndexes.size() <= soData.programHeadersAllocated); + if (soData.phIndexes.size() != soData.programHeadersAllocated) { + warn(Twine(".adlt section: overallocated ph-indexes for psod-") + Twine(idx) + + " allocated=" + Twine(soData.programHeadersAllocated) + + " actual=" + Twine(soData.phIndexes.size()) + ); + } +} + +template +void AdltSection::writeTo(uint8_t* buf) { + // TODO: take care of endianness, use write32 / write64 etc. + finalizeOnWrite(); + + // pre-serialized SoData, enriched with offsets during blob writing + SmallVector psods; + for (const auto& it: llvm::enumerate(soInputs)) { + const SoData& soData = it.value(); + psods.push_back(serialize(soData)); + } + + // serialize blob data + { + uint8_t* const blobBuf = buf + header.blobStart; + size_t blobOff = 0; + memcpy(blobBuf + blobOff, &adltBlobStartMark, sizeof(adltBlobStartMark)); + blobOff += sizeof(adltBlobStartMark); + + // common header-related data + { + header.phIndexes = writeArray(blobBuf, blobOff, common.phIndexes); + blobOff += header.phIndexes.size; + } + + // psod-related data + for(const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + auto& psod = psods[it.index()]; + + psod.dtNeeded = writeDtNeeded(blobBuf, blobOff, soData.dtNeededs); + blobOff += psod.dtNeeded.size; + + psod.phIndexes = writeArray(blobBuf, blobOff, soData.phIndexes); + blobOff += psod.phIndexes.size; + } + + // group up relaDyn and relaPlt idxs, it tends to be size-consuming + for(const auto& it : llvm::enumerate(soInputs)) { + const auto& soData = it.value(); + auto& psod = psods[it.index()]; + + psod.relaDynIndx = writeArray(blobBuf, blobOff, soData.relaDynIndx); + blobOff += psod.relaDynIndx.size; + + psod.relaPltIndx = writeArray(blobBuf, blobOff, soData.relaPltIndx); + blobOff += psod.relaPltIndx.size; + } + + // finalize header.blobSize + assert((blobOff <= header.blobSize) && + ".adlt-section: blob output exeeds its initial estimation"); + header.blobSize = blobOff; + } + + // header + { + memcpy(buf, &header, sizeof(header)); + } + + // PSODs + { + uint8_t* const psods_buf = buf + sizeof(header); + size_t psods_off = 0; + for (const auto& it: llvm::enumerate(soInputs)) { + adlt_psod_t& psod = psods[it.index()]; + memcpy(psods_buf + psods_off, &psod, sizeof(adlt_psod_t)); + psods_off += sizeof(adlt_psod_t); + } + } +} + +template +size_t AdltSection::getSize() const { + assert(sizeof(adlt_section_header_t) + + sizeof(adlt_psod_t) * soInputs.size() + <= header.blobStart); + return header.blobStart + header.blobSize; +} + +}}} // namespace lld::elf::adlt +// OHOS_LOCAL end + + InStruct elf::in; std::vector elf::partitions; @@ -4046,3 +4578,8 @@ template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; template class elf::PartitionProgramHeadersSection; + +template class elf::adlt::AdltSection; +template class elf::adlt::AdltSection; +template class elf::adlt::AdltSection; +template class elf::adlt::AdltSection; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 83a2bd7d34dfd0efd99cb12b442793d340dcfec8..b51c85ce2ea810c1eab4d880926a0b39dc16e9a6 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -25,6 +25,7 @@ #include "InputSection.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/BinaryFormat/ADLTSection.h" // OHOS_LOCAL #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Threading.h" @@ -34,6 +35,7 @@ namespace elf { class Defined; struct PhdrEntry; class SymbolTableBaseSection; +template class SharedFileExtended; class SyntheticSection : public InputSection { public: @@ -643,6 +645,7 @@ public: protected: void sortSymTabSymbols(); + template void sortSymTabSymbolsInAdlt(size_t numLocals); // A vector of symbols and their string table offsets. SmallVector symbols; @@ -1220,6 +1223,110 @@ public: size_t getSize() const override; }; + +namespace adlt { + +using namespace llvm::adlt; + +template +class AdltSection final : public SyntheticSection { +public: + struct SectionString { + StringRef ref; + Elf64_Off strtabOff; // offset in strTabSec + }; + + // will be serialized to adlt_dt_needed_index_t + struct DtNeededData { + SectionString str; + llvm::Optional psodIndex; + }; + + using SectionStringVector = SmallVector; + using DtNeededsVec = SmallVector; + + // will be serialized to adlt_psod_t + struct SoData { + SectionString soName; + DtNeededsVec dtNeededs; + + StringRef initArrayName; + StringRef finiArrayName; + + OutputSection* initArraySec; + OutputSection* finiArraySec; + + llvm::Optional sharedLocalIndex; + llvm::Optional sharedGlobalIndex; + + size_t programHeadersAllocated; + ArrayRef programHeaders; + SmallVector phIndexes; + + ArrayRef relaDynIndx; + ArrayRef relaPltIndx; + }; + + // will be used to form some header data + struct CommonData { + uint32_t symtabSecIndex = UINT32_MAX; + size_t programHeadersAllocated; + SmallVector phIndexes; + }; + +public: + AdltSection(StringTableSection& strTabSec); + + void writeTo(uint8_t* buf) override; + size_t getSize() const override; + void finalizeContents() override; + + Elf64_Off getBlobStartOffset() const; + +private: + static OutputSection* findOutSection(StringRef name); + + void buildSonameIndex(); + void linkInternalDtNeeded(); + void extractInitFiniArray(); + size_t estimateOverallMappedSize(); + void extractProgramHeaderIndexes(); + Elf64_Xword calculateHash(StringRef str) const; + + CommonData makeCommonData(); + SoData makeSoData(const SharedFileExtended*); + adlt_psod_t serialize(const SoData&) const; + size_t estimateBlobSize() const; + + void finalizeOnWrite(); + void finalizeOnWrite(size_t idx, SoData& sodata); + + template + adlt_blob_array_t writeArray(uint8_t* buff, size_t offset, + const SmallVector& data); + + template + adlt_blob_array_t writeArray(uint8_t* buff, size_t offset, + const ArrayRef& data); + + adlt_blob_array_t writeDtNeeded(uint8_t* buff, size_t offset, + const DtNeededsVec& neededVec); + +private: + StringTableSection& strTabSec; + + adlt_section_header_t header = {}; + + CommonData common = {}; + SmallVector soInputs; + + llvm::DenseMap sonameToIndexMap; + llvm::DenseMap phdrsIndexes; +}; + +} // namespace adlt + + InputSection *createInterpSection(); MergeInputSection *createCommentSection(); template void splitSections(); @@ -1295,6 +1402,8 @@ struct InStruct { std::unique_ptr strTab; std::unique_ptr symTab; std::unique_ptr symTabShndx; + std::unique_ptr adltData; + std::unique_ptr adltStrTab; void reset(); }; diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 5ec2d85f64e83b6e7f25bfa4c6f702657e91a979..4ed885c2edd431369a679516d0c45a60214245b4 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -88,6 +88,9 @@ public: virtual bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const; + virtual void deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const {}; // ADLT + virtual void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const = 0; void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index e27e656d43c712b18ce1c8a63629382e589c840d..dd74a8bc98bfcf890e3e3ad8058adf58ce8c6cd8 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -116,6 +116,7 @@ static void removeEmptyPTLoad(SmallVector &phdrs) { for (OutputSection *sec : outputSections) if (removed.count(sec->ptLoad)) sec->ptLoad = nullptr; + phdrs.erase(it, phdrs.end()); } @@ -273,7 +274,9 @@ void elf::addReservedSymbols() { static OutputSection *findSection(StringRef name, unsigned partition = 1) { for (SectionCommand *cmd : script->sectionCommands) if (auto *osd = dyn_cast(cmd)) - if (osd->osec.name == name && osd->osec.partition == partition) + if ((config->adlt ? osd->osec.name.startswith(name) + : osd->osec.name == name) && + osd->osec.partition == partition) return &osd->osec; return nullptr; } @@ -310,6 +313,13 @@ template void elf::createSyntheticSections() { in.symTabShndx = std::make_unique(); } + if (config->adlt) { + in.adltStrTab = std::make_unique(".adlt.strtab", false); + in.adltData = std::make_unique>(*in.adltStrTab); + add(*in.adltStrTab); + add(*in.adltData); + } + in.bss = std::make_unique(".bss", 0, 1); add(*in.bss); @@ -628,7 +638,8 @@ template static void markUsedLocalSymbols() { // See MarkLive::resolveReloc(). if (config->gcSections) return; - for (ELFFileBase *file : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) { ObjFile *f = cast>(file); for (InputSectionBase *s : f->getSections()) { InputSection *isec = dyn_cast_or_null(s); @@ -699,7 +710,8 @@ template void Writer::copyLocalSymbols() { llvm::TimeTraceScope timeScope("Add local symbols"); if (config->copyRelocs && config->discard != DiscardPolicy::None) markUsedLocalSymbols(); - for (ELFFileBase *file : ctx->objectFiles) { + auto files = /*config->adlt ? ctx->sharedFilesExtended :*/ ctx->objectFiles; + for (ELFFileBase *file : files) { for (Symbol *b : file->getLocalSymbols()) { assert(b->isLocal() && "should have been caught in initializeSymbols()"); auto *dr = dyn_cast(b); @@ -829,6 +841,12 @@ static bool isRelroSection(const OutputSection *sec) { // ELF in spirit. But in reality many linker features depend on // magic section names. StringRef s = sec->name; + if (config->adlt) + return s.startswith(".data.rel.ro") || s.startswith(".bss.rel.ro") || + s.startswith(".ctors") || s.startswith(".dtors") || + s.startswith(".eh_frame") || s.startswith(".fini_array") || + s.startswith(".init_array") || s.startswith(".preinit_array"); + return s == ".data.rel.ro" || s == ".bss.rel.ro" || s == ".ctors" || s == ".dtors" || s == ".jcr" || s == ".eh_frame" || s == ".fini_array" || s == ".init_array" || @@ -1007,13 +1025,58 @@ static bool compareSections(const SectionCommand *aCmd, return false; } +// OHOS_LOCAL begin +namespace { + +InputSection* getInputSection(OutputSection* sec) { + if (!sec || !sec->hasInputSections || sec->commands.empty()) + return nullptr; + SectionCommand* cmd = sec->commands.front(); + InputSectionDescription* isd = cast(cmd); + return isd->sections.front(); +} + +template +void addPhdrToSharedFilesExtendedContext(InputFile* file, PhdrEntry* phdr) { + if (auto* soFile = dyn_cast>(file)) { + soFile->programHeaders.insert(phdr); + } +} + +} // namespace +// OHOS_LOCAL end + void PhdrEntry::add(OutputSection *sec) { lastSec = sec; if (!firstSec) firstSec = sec; + p_align = std::max(p_align, sec->alignment); + if (p_type == PT_LOAD) sec->ptLoad = this; + + // OHOS_LOCAL begin + if (config->adlt) { + if (ctx->adlt.withCfi && p_type == PT_LOAD) { + // check cfi.h: LIBRARY_ALIGNMENT and _BITS + constexpr uint32_t kCFILibraryAlignment = 1UL << 18; + firstSec->alignment = std::max(firstSec->alignment, kCFILibraryAlignment); + p_align = std::max(p_align, kCFILibraryAlignment); + } + + if (p_type == PT_LOAD || p_type == PT_TLS) { + auto* insec = getInputSection(sec); + // skip generated sections. + // TODO: fix .rodata_$ADLT_POSTFIX sections. + if (insec && insec->file) { + invokeELFT(addPhdrToSharedFilesExtendedContext, insec->file, this); + } else { + ctx->adlt.commonProgramHeaders.insert(this); + } + } + } + // OHOS_LOCAL end } // The beginning and the ending of .rel[a].plt section are marked @@ -1303,7 +1366,8 @@ static DenseMap buildSectionOrder() { for (Symbol *sym : symtab->symbols()) addSym(*sym); - for (ELFFileBase *file : ctx->objectFiles) + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (ELFFileBase *file : files) for (Symbol *sym : file->getLocalSymbols()) addSym(*sym); @@ -1719,7 +1783,8 @@ template void Writer::finalizeAddressDependentContent() { // block sections, input sections can shrink when the jump instructions at // the end of the section are relaxed. static void fixSymbolsAfterShrinking() { - for (InputFile *File : ctx->objectFiles) { + auto files = config->adlt ? ctx->sharedFilesExtended : ctx->objectFiles; + for (InputFile *File : files) { parallelForEach(File->getSymbols(), [&](Symbol *Sym) { auto *def = dyn_cast(Sym); if (!def) @@ -1847,6 +1912,45 @@ static void removeUnusedSyntheticSections() { }); } +template static void adltTraceRelocationIndexes() { + auto &relaDyn = mainPart->relaDyn; + assert(!relaDyn->relocs.empty() && "ADLT: relaDyn can't be empty!"); + assert(!in.relaPlt->relocs.empty() && "ADLT: relaPlt can't be empty!"); + + bool adltRelocsTrace = false; // debug hint + if (adltRelocsTrace) { + auto traceRelocInfo = [&](auto *relSec, auto &outIndexes) -> void { + bool isPlt = relSec == in.relaPlt.get(); + lld::outs() << (isPlt ? "Plt" : "Dyn") << " indexes: "; + for (auto &it : outIndexes) // simple print + lld::outs() << it << ' '; + lld::outs() << '\n'; + for (auto &it : outIndexes) // print relocs + if (DynamicReloc *rel = &relSec->relocs[it]) + lld::outs() << it << ": " << rel->inputSec->name << " + 0x" + << utohexstr(rel->offsetInSec) << "\t" + << toString(rel->type) << "\t" << rel->sym->getName() + << " + 0x" << utohexstr(rel->addend) << '\n'; + }; + lld::outs() << "[ADLT]\n"; + lld::outs() << "Dyn relocs (" << relaDyn->relocs.size() << ")\n"; + lld::outs() << "Plt relocs (" << in.relaPlt->relocs.size() << ")\n"; + for (auto *file : ctx->sharedFilesExtended) + if (auto *soFile = cast>(file)) { + lld::outs() << "[ADLT] " << soFile->soName << ":\n"; + traceRelocInfo(relaDyn.get(), soFile->dynRelIndexes); + traceRelocInfo(in.relaPlt.get(), soFile->pltRelIndexes); + } + } + for (auto *file : ctx->sharedFilesExtended) { + __attribute__((unused)) auto *soFile = cast>(file); + assert(!soFile->dynRelIndexes.empty() && + "ADLT: relaDyn indexes can't be empty!"); + assert(!soFile->pltRelIndexes.empty() && + "ADLT: relaPlt indexes can't be empty!"); + } +} + // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { Out::preinitArray = findSection(".preinit_array"); @@ -1937,9 +2041,29 @@ template void Writer::finalizeSections() { // determine if it needs special treatment, such as creating GOT, PLT, // copy relocations, etc. Note that relocations for non-alloc sections are // directly processed by InputSection::relocateNonAlloc. - for (InputSectionBase *sec : inputSections) - if (sec->isLive() && isa(sec) && (sec->flags & SHF_ALLOC)) - scanRelocations(*sec); + if (config->adlt) + for (auto &it : llvm::enumerate(ctx->sharedFilesExtended)) { + auto *soFile = cast>(it.value()); + auto sections = soFile->getSections(); + // scan .rela.dyn (base: SHT_NULL) + scanRelocations(*sections[0]); + // scan .rela.plt (base: .got.plt) + scanRelocations(*sections[soFile->gotPltSecIdx]); + // scan other sections + // excluding .rela.plt and .rela.dyn + auto gotPltIdx = static_cast(soFile->gotPltSecIdx); + auto isNotExcludedIdx = [&](auto idx) { + return idx != 0 && idx != gotPltIdx; + }; + for (auto &it : llvm::enumerate(soFile->getSections())) + if (InputSectionBase *sec = it.value()) + if (sec && sec->isLive() && isNotExcludedIdx(it.index())) + scanRelocations(*sec); + } + else + for (InputSectionBase *sec : inputSections) + if (sec->isLive() && isa(sec) && (sec->flags & SHF_ALLOC)) + scanRelocations(*sec); for (Partition &part : partitions) { for (EhInputSection *sec : part.ehFrame->sections) scanRelocations(*sec); @@ -2109,6 +2233,11 @@ template void Writer::finalizeSections() { finalizeSynthetic(in.ppc32Got2.get()); finalizeSynthetic(in.partIndex.get()); + if (config->adlt) { + finalizeSynthetic(in.adltData.get()); + finalizeSynthetic(in.adltStrTab.get()); + } + // Dynamic section must be the last one in this list and dynamic // symbol table section (dynSymTab) must be the first one. for (Partition &part : partitions) { @@ -2128,6 +2257,8 @@ template void Writer::finalizeSections() { finalizeSynthetic(part.verNeed.get()); finalizeSynthetic(part.dynamic.get()); } + if (config->adlt) // check ouput relocation indexes + adltTraceRelocationIndexes(); } if (!script->hasSectionsCommand && !config->relocatable) @@ -2291,12 +2422,22 @@ SmallVector Writer::createPhdrs(Partition &part) { return ret.back(); }; + // OHOS_LOCAL begin + auto getOwnerFileIdx = [](OutputSection* sec) -> llvm::Optional { + auto file = getInputSection(sec)->file; + if (!file) + return llvm::None; + return cast>(file)->orderIdx; + }; + // OHOS_LOCAL end + unsigned partNo = part.getNumber(); bool isMain = partNo == 1; // Add the first PT_LOAD segment for regular output sections. uint64_t flags = computeFlags(PF_R); PhdrEntry *load = nullptr; + llvm::Optional lastOwnerIdx = llvm::None; // OHOS_LOCAL // nmagic or omagic output does not have PT_PHDR, PT_INTERP, or the readonly // PT_LOAD. @@ -2312,6 +2453,10 @@ SmallVector Writer::createPhdrs(Partition &part) { if (OutputSection *cmd = findSection(".interp", partNo)) addHdr(PT_INTERP, cmd->getPhdrFlags())->add(cmd); + // PT_ADLT info. + if (OutputSection *adlt = findSection(".adlt", partNo)) + addHdr(PT_ADLT, adlt->getPhdrFlags())->add(adlt); + // Add the headers. We will remove them if they don't fit. // In the other partitions the headers are ordinary sections, so they don't // need to be added here. @@ -2371,8 +2516,19 @@ SmallVector Writer::createPhdrs(Partition &part) { uint64_t newFlags = computeFlags(sec->getPhdrFlags()); bool sameLMARegion = load && !sec->lmaExpr && sec->lmaRegion == load->firstSec->lmaRegion; + + // OHOS_LOCAL begin + // ALDT image sections have additional addribute: input file owner. + // The ownership contiguousity allows to map only related sections + // when processing program headers that + bool sameFileOwner = config->adlt && lastOwnerIdx == getOwnerFileIdx(sec); + if (config->adlt) + lastOwnerIdx = getOwnerFileIdx(sec); + // OHOS_LOCAL end + if (!(load && newFlags == flags && sec != relroEnd && sec->memRegion == load->firstSec->memRegion && + (!config->adlt || sameFileOwner) && (sameLMARegion || load->lastSec == Out::programHeaders))) { load = addHdr(PT_LOAD, newFlags); flags = newFlags; @@ -2384,9 +2540,13 @@ SmallVector Writer::createPhdrs(Partition &part) { // Add a TLS segment if any. PhdrEntry *tlsHdr = make(PT_TLS, PF_R); for (OutputSection *sec : outputSections) - if (sec->partition == partNo && sec->flags & SHF_TLS) + if (sec->partition == partNo && sec->flags & SHF_TLS) { + // It making TLS hdr for each TLS section, for adlt. + if (config->adlt) + tlsHdr = addHdr(PT_TLS, PF_R); tlsHdr->add(sec); - if (tlsHdr->firstSec) + } + if (!config->adlt && tlsHdr->firstSec) ret.push_back(tlsHdr); // Add an entry for .dynamic. @@ -2474,6 +2634,9 @@ template void Writer::fixSectionAlignments() { OutputSection *cmd = p->firstSec; if (!cmd) return; + if (config->adlt &&cmd->name == ".text") { + lld::outs() << "Writer::fixSectionAlignments()\n"; + } cmd->alignExpr = [align = cmd->alignment]() { return align; }; if (!cmd->addrExpr) { // Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid @@ -2611,6 +2774,11 @@ template void Writer::assignFileOffsets() { if (config->zSeparate != SeparateSegmentKind::None && lastRX && lastRX->lastSec == sec) off = alignToPowerOf2(off, config->maxPageSize); + bool debug = false; + if (debug) + lld::outs() << "assignFileOffsets() Sec: " << sec->name + << " Off: " << std::to_string(off) + << " Offset: " << std::to_string(sec->offset) << '\n'; } for (OutputSection *osec : outputSections) if (!(osec->flags & SHF_ALLOC)) { diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp index 3e87fd196e01e575dab7f1babb77e712f79b4c61..2896f5920db901855e2b3582e9b713be7077fd87 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) // OHOS_LOCAL + if (byte_size || *byte_size == 0) 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 26742b8c80eb7d521e0ab6af40e2f6a1653a8e31..bcac55f04b7d8c9aa4f6fcc051b5b74caa8ebb8c 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" || m_connect_addr == "127.0.0.1"; + return m_connect_addr == "localhost"; } namespace { diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp index 8f3f54a58472d247284600f267df8702e35a2ebd..0a6a7b208f404077663ba924762c22de4a8c1934 100644 --- a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp @@ -11,7 +11,6 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/UriParser.h" -#include "llvm/Support/Regex.h" #include "PlatformOHOSRemoteGDBServer.h" @@ -41,20 +40,20 @@ static Status ForwardPortWithHdc( device_id = hdc.GetDeviceID(); LLDB_LOGF(log, "Connected to OHOS device \"%s\"", device_id.c_str()); - 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); + 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); } - LLDB_LOGF(log, "Forwarding remote TCP port %d to local TCP port %d", - remote_port, local_port); + LLDB_LOGF(log, "Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name.str().c_str(), local_port); - if (remote_port == 0) - return Status("Invalid remote_port"); - - return hdc.SetPortForwarding(local_port, remote_port); + if (!socket_namespace) + return Status("Invalid socket namespace"); + + return hdc.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); } static Status DeleteForwardPortWithHdc(const std::string &connect_addr, @@ -139,21 +138,9 @@ 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" && !IsValidIPv4(hostname) && - !IsValidIPv6(hostname); + return hostname != "localhost" && !hostname.contains(':') && + !hostname.contains('.'); } Status PlatformOHOSRemoteGDBServer::ConnectRemote(Args &args) { @@ -262,7 +249,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 (!m_socket_namespace){ + if (remote_port != 0){ 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 a4ba2e16d3ed6b764d3359fd91e7d75d487d4645..cb130574d3f66f22a610c9dc7a4a3839dba2dbff 100644 --- a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h @@ -38,8 +38,6 @@ 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 4f4ceff1e6c3f9da51c886fef158b0495e8a91ce..b78b86f3496b6b89671c28e07302c31bf3e3d67e 100644 --- a/llvm-build/MakeLiblzma +++ b/llvm-build/MakeLiblzma @@ -17,7 +17,6 @@ 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 @@ -32,9 +31,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 -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 +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 else $(warning *** warning: TARGET_TRIPLE $(TARGET_TRIPLE) has not been set in rights) endif diff --git a/llvm-build/Makefile b/llvm-build/Makefile index ecb982228b0ecbb4d4dca3e65e1b2e9e62087551..79c3c413ccb9d1e63d0966881eb5d41a83f62458 100644 --- a/llvm-build/Makefile +++ b/llvm-build/Makefile @@ -92,7 +92,11 @@ endif endif ifeq ($(ARCH),aarch64) +ifeq ($(BUILD_DEBUG),true) +CFLAGS = -march=armv8 -g -gdwarf-4 -O0 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +else CFLAGS = -march=armv8 -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +endif else ifeq ($(ARCH),riscv64) CFLAGS = -march=rv64gc -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack @@ -225,7 +229,9 @@ musl_install_for_linux_user: musl_patch_for_linux_user make -sj install clean: + ifeq ($(BUILD_DEBUG),false) $(HIDE) rm -rf musl_copy_for_* linux_header_install_for_* + endif distclean: clean $(HIDE) rm -rf $(SYSROOTDIR)/lib $(SYSROOTDIR)/usr diff --git a/llvm-build/README.md b/llvm-build/README.md index 407b4b4c1871c8a6e602fbe357d1ea7e77433bef..39842b084ad58bbd436235f67588eb92f23ea0dd 100644 --- a/llvm-build/README.md +++ b/llvm-build/README.md @@ -91,6 +91,13 @@ build.py options: OH LLVM BOTH +--build-only # build only some targets, skip building windows, lldb-server and package step + lld + llvm-readelf + llvm-objdump + musl + compiler-rt + libcxx --enable-check-abi # Check libc++_shared.so ABI. If the ABI was changed then interrupt a build process and report an error. ```
diff --git a/llvm-build/build.py b/llvm-build/build.py index ee12969b8e24e5aed27446f043eecf5cbe131618..6e1574f9083c4547daeb569ac81666cf75947f2c 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -37,9 +37,12 @@ class BuildConfig(): def __init__(self): args = self.parse_args() + + assert not(args.no_build and args.build_only), "Error! --no-build and --build-only flags aren't compatible." + self.no_strip_libs = args.no_strip_libs self.do_build = not args.skip_build - self.do_package = not args.skip_package + self.do_package = not args.skip_package and not args.build_only self.build_name = args.build_name self.debug = args.debug self.target_debug = args.target_debug @@ -48,12 +51,17 @@ class BuildConfig(): self.build_instrumented = args.build_instrumented self.xunit_xml_output = args.xunit_xml_output self.enable_assertions = args.enable_assertions + self.build_gtest_libs = args.build_gtest_libs self.build_clean = args.build_clean self.need_libs = self.do_build and 'libs' not in args.no_build - self.need_lldb_server = self.do_build and 'lldb-server' not in args.no_build + self.need_lldb_server = self.do_build and 'lldb-server' not in args.no_build and not args.build_only self.build_python = args.build_python self.build_with_debug_info = args.build_with_debug_info + self.build_only = True if args.build_only else False + self.build_only_llvm = args.build_only["llvm"] if self.build_only else [] + self.build_only_libs = args.build_only["libs"] if self.build_only else [] + self.no_build_arm = args.skip_build or args.no_build_arm self.no_build_aarch64 = args.skip_build or args.no_build_aarch64 self.no_build_riscv64 = args.skip_build or args.no_build_riscv64 @@ -69,6 +77,7 @@ class BuildConfig(): self.enable_lzma_7zip = args.enable_lzma_7zip self.build_libs = args.build_libs self.build_libs_flags = args.build_libs_flags + self.adlt_debug_build = args.adlt_debug_build self.compression_format = args.compression_format self.enable_check_abi = args.enable_check_abi self.discover_paths() @@ -85,11 +94,10 @@ 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 @@ -130,6 +138,12 @@ class BuildConfig(): default=False, help='Apply assertions, some parameters are affected.') + parser.add_argument( + '--build-gtest-libs', + action='store_true', + default=False, + help='Build gtest libraries.') + parser.add_argument( '--build-name', default='dev', @@ -253,7 +267,7 @@ class BuildConfig(): action='store_true', default=False, help='Enable lldb performance monitoring') - + compression_formats = ['bz2', 'gz'] parser.add_argument( @@ -269,6 +283,12 @@ class BuildConfig(): default=False, help='Append -g to build flags in build_libs') + parser.add_argument( + '--adlt-debug-build', + action='store_true', + default=False, + help='Build adlt with debug flags') + parser.add_argument( '--enable-check-abi', nargs='?', @@ -354,6 +374,29 @@ class BuildConfig(): default=llvm_runtimes, help=f'Runtimes to build for host. Choices: {", ".join(llvm_runtimes)}') + llvm_components = ("lld", "llvm-readelf", "llvm-objdump") + libs_components = ("musl", "compiler-rt", "libcxx") + + class SeparatedListByCommaToDictAction(argparse.Action): + def __call__(self, parser, namespace, vals, option_string): + vals_dct = {"llvm": [], "libs": []} + for val in vals.split(','): + if val in llvm_components: + vals_dct["llvm"].append(val) + continue + elif val in libs_components: + vals_dct["libs"].append(val) + continue + else: + error = '\'{}\' invalid. Choose from {}, {}'.format(val, llvm_components, libs_components) + raise argparse.ArgumentError(self, error) + setattr(namespace, self.dest, vals_dct) + + parser.add_argument( + '--build-only', + action=SeparatedListByCommaToDictAction, + default=dict(), + help=f'Build only {", ".join(llvm_components)} llvm components and {", ".join(libs_components)} lib components.') return parser.parse_args() @@ -486,6 +529,11 @@ class BuildUtils(object): subprocess.check_call(cmd, *args, **kwargs) + def force_symlink(self, src, dst): + if os.path.exists(dst): + os.remove(dst) + os.symlink(src, dst) + def merge_out_path(self, *args): return os.path.abspath(os.path.join(self.build_config.OUT_PATH, *args)) @@ -604,15 +652,6 @@ 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): @@ -623,6 +662,7 @@ class LlvmCore(BuildUtils): build_dir, install_dir, build_name, + build_target=None, extra_defines=None, extra_env=None): @@ -653,6 +693,7 @@ class LlvmCore(BuildUtils): if extra_env is not None: env.update(extra_env) + install = not self.build_config.build_only llvm_project_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm')) self.invoke_cmake(llvm_project_path, @@ -662,8 +703,28 @@ class LlvmCore(BuildUtils): self.invoke_ninja(out_path=build_dir, env=env, - target=None, - install=True) + target=build_target, + install=install) + if not install: + self.llvm_python_install(build_dir, install_dir) + + def llvm_python_install(self, build_dir, install_dir): + target_dirs = ["bin", "include", "lib", "python3", "libexec", "share"] + for target_dir in target_dirs: + target_dir = f"{build_dir}/{target_dir}" + if not os.path.exists(target_dir): + continue + for (src_path, dirs, files) in os.walk(target_dir): + dst_path = src_path.replace(build_dir, install_dir) + for file in files: + src = os.path.join(src_path, file) + dst = os.path.join(dst_path, file) + if file.endswith(".cpp.o") or file == "cmake_install.cmake": + continue + if os.path.exists(dst) and os.stat(src) == os.stat(dst): + continue + os.makedirs(dst_path, exist_ok=True) + shutil.copy2(src, dst) def llvm_compile_darwin_defines(self, llvm_defines): if self.host_is_darwin(): @@ -682,13 +743,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(), f'liblzma.{self.build_config.LZMA_VERSION}.dylib') + llvm_defines['LIBLZMA_LIBRARIES'] = self.merge_out_path('lzma', 'lib', self.use_platform(), 'liblzma.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_libxml2_install_path(self.use_platform()), 'lib', f'libxml2.{self.build_config.LIBXML2_VERSION}.dylib') + llvm_defines['LIBXML2_LIBRARIES'] = os.path.join(self.get_prebuilts_dir('libxml2'), self.use_platform(), 'lib', f'libxml2.{self.build_config.LIBXML2_VERSION}.dylib') def llvm_compile_linux_defines(self, @@ -734,7 +795,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_libxml2_install_path(self.use_platform()), 'lib', f'libxml2.so.{self.build_config.LIBXML2_VERSION}') + llvm_defines['LIBXML2_LIBRARY'] = os.path.join(self.get_prebuilts_dir('libxml2'), 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) @@ -783,7 +844,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_libxml2_install_path(self.use_platform()), 'include', 'libxml2') + llvm_defines['LIBXML2_INCLUDE_DIR'] = os.path.join(self.get_prebuilts_dir('libxml2'), self.use_platform(), 'include', 'libxml2') if self.build_config.enable_monitoring: llvm_defines['LLDB_ENABLE_PERFORMANCE'] = 'ON' @@ -794,6 +855,7 @@ class LlvmCore(BuildUtils): debug_build=False, no_lto=False, build_instrumented=False, + build_target=None, xunit_xml_output=None): llvm_clang_install = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, @@ -851,6 +913,7 @@ class LlvmCore(BuildUtils): build_dir=llvm_path, install_dir=out_dir, build_name=build_name, + build_target=build_target, extra_defines=llvm_defines, extra_env=llvm_extra_env) @@ -890,7 +953,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'] = 'Debug' if self.build_config.debug else 'Release' + windows_defines['CMAKE_BUILD_TYPE'] = 'Release' windows_defines['LLVM_BUILD_RUNTIME'] = 'OFF' windows_defines['LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD'] = 'ON' windows_defines['LLVM_TOOL_OPENMP_BUILD'] = 'OFF' @@ -909,8 +972,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_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') + 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') if self.build_config.enable_monitoring: windows_defines['LLDB_ENABLE_PERFORMANCE'] = 'ON' @@ -937,11 +1000,9 @@ 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', @@ -952,7 +1013,6 @@ 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', @@ -1061,12 +1121,15 @@ class SysrootComposer(BuildUtils): self.get_python_dir(), 'bin', self.build_config.LLDB_PYTHON) llvm_gn_args = 'is_llvm_build=true startup_init_with_param_base=true use_thin_lto=false' subprocess.run([python_execute_dir, hb_build_py, 'build', '--product-name', product_name, '--target-cpu', - target_cpu, '--build-target', target_name, '--gn-args', + target_cpu, '--build-target', target_name, '--gn-args', gn_args, llvm_gn_args, '--deps-guard=false'], shell=False, stdout=subprocess.PIPE, cwd=self.build_config.REPOROOT_DIR) def build_musl_libs(self, product_name, target_cpu, target_name, ohos_lib_dir, sysroot_lib_dir, ld_musl_lib, gn_args=''): + if (self.build_config.debug): + gn_args = f"is_debug=true ohos_extra_cflags=-O0 {gn_args}" + self.run_hb_build(product_name, target_cpu, target_name, gn_args) libc_name = 'libc.so' crtplus_lib = self.merge_out_path('llvm_build', 'obj', 'out', 'llvm_build', 'obj', 'third_party', 'musl', @@ -1262,7 +1325,7 @@ class LlvmLibs(BuildUtils): ldflags.extend(ldflag) cflag = [ - '-fstack-protector-strong', + '-fstack-protector-strong', '--target=%s' % llvm_triple, '-ffunction-sections', '-fdata-sections', @@ -1318,6 +1381,8 @@ class LlvmLibs(BuildUtils): defines = self.base_cmake_defines() ldflags = [] cflags = [] + if self.build_config.adlt_debug_build: + cflags.append("-g -gdwarf-4 -O0") self.logger().info('Build libs for %s', llvm_triple) if self.build_config.target_debug: defines['CMAKE_BUILD_TYPE'] = 'Debug' @@ -1359,8 +1424,8 @@ class LlvmLibs(BuildUtils): self.build_lldb_tools(llvm_install, llvm_path, arch, llvm_triple, cflags, ldflags, defines) seen_arch_list.append(llvm_triple) - def build_libs_by_type(self, llvm_install, llvm_build, libs_type, is_first_time, is_ndk_install): - configs_list, cc, cxx, ar, llvm_config = self.libs_argument(llvm_install) + def build_libs_by_type(self, compiler_path, llvm_install, llvm_build, libs_type, is_first_time, is_ndk_install): + configs_list, cc, cxx, ar, llvm_config = self.libs_argument(compiler_path) for (arch, llvm_triple, extra_flags, multilib_suffix) in configs_list: if llvm_build != llvm_triple: @@ -1368,6 +1433,9 @@ class LlvmLibs(BuildUtils): defines = self.base_cmake_defines() ldflags = [] cflags = [] + if self.build_config.adlt_debug_build: + cflags.append("-g -gdwarf-4 -O0") + self.logger().info('Build %s libs for %s', libs_type, llvm_triple) out_path = self.merge_out_path('llvm_build') self.logger().info('Make %s libs for %s build_libs_flags: %s', libs_type, llvm_triple, self.build_config.build_libs_flags) @@ -1463,10 +1531,10 @@ class LlvmLibs(BuildUtils): rt_defines['LIBUNWIND_INSTALL_LIBRARY'] = 'OFF' else: rt_defines['LIBCXX_ABI_NAMESPACE'] = '__h' - + self.check_rm_tree(out_path) cmake_rt = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'runtimes')) - + self.invoke_cmake(cmake_rt, out_path, rt_defines, @@ -1694,13 +1762,6 @@ 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' @@ -1737,7 +1798,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'] = 'Debug' if self.build_config.target_debug else 'Release' + cmake_defines['CMAKE_BUILD_TYPE'] = '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') @@ -1805,14 +1866,13 @@ 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 = f'.{self.build_config.LZMA_VERSION}.dylib' + shlib_ext = '.dylib' if self.host_is_linux(): shlib_ext = '.so' lzma_file = os.path.join(liblzma_build_path, 'lib', target_triple, 'liblzma' + shlib_ext) @@ -1852,6 +1912,66 @@ class LlvmLibs(BuildUtils): self.llvm_package.copy_libedit_to_llvm(llvm_make) self.llvm_package.copy_libedit_to_llvm(llvm_install) + def copy_gtest_to_sysroot(self, build_dir): + build_lib_dir = os.path.join(build_dir, 'lib') + self.logger().info('LlvmPackage copy_gtest_to_sysroot from %s', build_lib_dir) + libs = [ "libLLVMSupport.so", "libLLVMDemangle.so", "libllvm_gtest.so" ] + sysroot_lib_dir = self.merge_out_path('sysroot', 'aarch64-linux-ohos', 'usr', 'lib') + + os.chdir(build_lib_dir) + for f in libs: + self.check_copy_file(f'{f}.15', sysroot_lib_dir) + os.chdir(sysroot_lib_dir) + self.force_symlink(f'{f}.15', f) + os.chdir(build_lib_dir) + + def build_gtest_defines(self, llvm_install): + sysroot = self.merge_out_path('sysroot', 'aarch64-linux-ohos', 'usr') + common_flags = f'--target=aarch64-linux-ohos -B{sysroot}/lib -L{sysroot}/lib' + libcxx = self.merge_out_path('llvm-install', 'include', 'libcxx-ohos', 'include', 'c++', 'v1') + libc = os.path.join(sysroot, "include") + + gtest_defines = {} + gtest_defines['BUILD_SHARED_LIBS'] = 'YES' + gtest_defines['CMAKE_BUILD_TYPE'] = 'Release' + gtest_defines['CMAKE_C_COMPILER'] = os.path.join(llvm_install, 'bin', 'clang') + gtest_defines['CMAKE_CXX_COMPILER'] = os.path.join(llvm_install, 'bin', 'clang++') + gtest_defines['LLVM_TABLEGEN'] = os.path.join(llvm_install, 'bin', 'llvm-tblgen') + gtest_defines['CMAKE_LINKER'] = os.path.join(llvm_install, 'bin', 'ld.lld') + gtest_defines['CMAKE_EXE_LINKER_FLAGS'] = f'{common_flags}' + gtest_defines['CMAKE_C_FLAGS'] = f'{common_flags} -I{libc}' + gtest_defines['CMAKE_CXX_FLAGS'] = f'{common_flags} -I{libcxx} -I{libc}' + + return gtest_defines + + def build_gtest(self, compiler_path, llvm_install): + gtest_defines = self.build_gtest_defines(compiler_path) + gtest_cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm')) + + gtest_build_path = self.merge_out_path('gtest') + + self.rm_cmake_cache(gtest_build_path) + + self.invoke_cmake(gtest_cmake_path, + gtest_build_path, + gtest_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=gtest_build_path, + env=dict(self.build_config.ORIG_ENV), + target=[ "LLVMSupport", "LLVMDemangle", "llvm_gtest" ], + install=False) + + self.copy_gtest_to_sysroot(gtest_build_path) + shutil.copytree( + os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm', 'utils', 'unittest', 'googlemock', 'include', 'gmock'), + os.path.join(llvm_install, 'include', 'gmock'), + dirs_exist_ok = True) + shutil.copytree( + os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm', 'utils', 'unittest', 'googletest', 'include', 'gtest'), + os.path.join(llvm_install, 'include', 'gtest'), + dirs_exist_ok = True) + def build_libxml2_defines(self): libxml2_defines = {} libxml2_defines['LIBXML2_WITH_PYTHON'] = 'OFF' @@ -1862,64 +1982,39 @@ class LlvmLibs(BuildUtils): return libxml2_defines - def build_libxml2(self, triple, llvm_make, llvm_install): - self.logger().info('Building libxml2 for %s', triple) - - 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]) + def build_libxml2(self, llvm_make, llvm_install): + self.logger().info('Building libxml2') - 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_defines = self.build_libxml2_defines() - defines = self.build_libxml2_defines() - defines['CMAKE_INSTALL_PREFIX'] = install_path + libxml2_cmake_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'out', ('libxml2-' + self.build_config.LIBXML2_VERSION))) - 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 + 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 - 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.rm_cmake_cache(libxml2_build_path) - self.invoke_cmake(cmake_path, - build_path, - defines, - dict(self.build_config.ORIG_ENV)) + self.invoke_cmake(libxml2_cmake_path, + libxml2_build_path, + libxml2_defines, + env=dict(self.build_config.ORIG_ENV)) - self.invoke_ninja(build_path, - dict(self.build_config.ORIG_ENV), - None, - True) + self.invoke_ninja(out_path=libxml2_build_path, + env=dict(self.build_config.ORIG_ENV), + target=None, + install=True) - 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) + self.llvm_package.copy_libxml2_to_llvm(llvm_make) + self.llvm_package.copy_libxml2_to_llvm(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.get_libxml2_build_path('windows-x86_64') - libxml2_install_path = self.get_libxml2_install_path('windows-x86_64') + libxml2_build_path = self.merge_out_path('libxml2-windows-build') + libxml2_install_path = os.path.join(self.get_prebuilts_dir('libxml2'), 'windows-x86_64') cflags = ['--target=x86_64-pc-windows-gnu'] cflags.extend(('-I', os.path.join(windows_sysroot, 'include'))) @@ -1946,7 +2041,8 @@ class LlvmLibs(BuildUtils): libxml2_defines['CMAKE_RC_FLAGS'] = ' '.join(rcflags) libxml2_defines['XML_INCLUDEDIR'] = os.path.join(windows_sysroot, 'include') - libxml2_cmake_path = self.get_libxml2_source_path() + libxml2_cmake_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'out', ('libxml2-' + self.build_config.LIBXML2_VERSION))) + self.invoke_cmake(libxml2_cmake_path, libxml2_build_path, libxml2_defines, @@ -2413,7 +2509,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, triple, install_dir): + def copy_libxml2_to_llvm(self, install_dir): self.logger().info('LlvmPackage copy_libxml2_to_llvm install_dir is %s', install_dir) libxml2_version = self.get_libxml2_version() @@ -2423,7 +2519,7 @@ class LlvmPackage(BuildUtils): if self.host_is_linux(): shlib_ext = f'.so.{libxml2_version}' - libxml2_lib_path = os.path.join(self.get_libxml2_install_path(triple), 'lib') + libxml2_lib_path = self.merge_out_path('libxml2') libxml2_src = os.path.join(libxml2_lib_path, 'libxml2%s' % shlib_ext) lib_dst_path = os.path.join(install_dir, 'lib') @@ -2524,7 +2620,6 @@ class LlvmPackage(BuildUtils): return - def main(): build_config = BuildConfig() build_utils = BuildUtils(build_config) @@ -2535,12 +2630,14 @@ def main(): args = build_config.parse_args() need_host = build_utils.host_is_darwin() or ('linux' not in args.no_build) - need_windows = build_utils.host_is_linux() and \ + need_windows = build_utils.host_is_linux() and not build_config.build_only and \ ('windows' not in args.no_build) llvm_install = build_utils.merge_out_path('llvm-install') llvm_make = build_utils.merge_out_path('llvm_make') windows64_install = build_utils.merge_out_path('windows-x86_64-install') + llvm_path = llvm_install if not build_config.build_only else \ + os.path.join(build_config.REPOROOT_DIR, 'prebuilts', 'clang', 'ohos', 'linux-x86_64', f'clang-{build_config.CLANG_VERSION}') configs = [] if not build_config.no_build_arm: @@ -2573,22 +2670,29 @@ def main(): build_config.build_libxml2 = False if build_config.build_libxml2: - llvm_libs.build_libxml2(build_utils.use_platform(), llvm_make, llvm_install) - - if build_config.do_build and need_host: + 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) + + if build_config.do_build and need_host and (build_config.build_only_llvm or not build_config.build_only): llvm_core.llvm_compile( build_config.build_name, llvm_install, build_config.debug, build_config.no_lto, build_config.build_instrumented, + build_config.build_only_llvm, build_config.xunit_xml_output) llvm_package.copy_python_to_host(llvm_make) llvm_package.copy_python_to_host(llvm_install) - llvm_core.set_clang_version(llvm_install) + llvm_core.set_clang_version(llvm_path) - if build_config.build_libs: + if build_config.build_libs and not build_config.build_only: libs_type = 'crts' if 'crts' in build_config.build_libs else 'runtimes' is_first_time = True if build_config.build_libs in ['crts_first_time', 'runtimes_libunwind'] else False is_ndk_install = True if build_config.build_libs == 'runtimes_libcxx_ndk' else False @@ -2597,7 +2701,7 @@ def main(): llvm_libs.build_libs_by_type(llvm_install, target, libs_type, is_first_time, is_ndk_install) return - if build_config.do_build and build_utils.host_is_linux(): + if build_config.do_build and build_utils.host_is_linux() and not build_config.build_only: sysroot_composer.setup_cmake_platform(llvm_install) llvm_libs.build_crt_libs(configs, llvm_install) @@ -2616,6 +2720,35 @@ def main(): print("Build is interrupted because of libCxx ABI changed") return + if build_config.build_only: + if "musl" in build_config.build_only_libs: + # change compiller path to prebuilds in clang.gni file + clang_gni = os.path.join(build_config.REPOROOT_DIR, "build", "config", "clang", "clang.gni") + clang_gni_tmp = f"{clang_gni}_tmp" + shutil.move(clang_gni, clang_gni_tmp) + with open(clang_gni_tmp, 'r') as f1: + data = f1.read() + with open(clang_gni, 'w') as f2: + data = data.replace("//out/llvm-install", "${toolchains_dir}/${host_platform_dir}/" + f"clang-{build_config.CLANG_VERSION}") + f2.write(data) + # build musl + for (arch, target) in configs: + sysroot_composer.build_musl_header(arch, target) + sysroot_composer.build_musl(arch, target) + # return original version of clang.gni + shutil.move(clang_gni_tmp, clang_gni) + + if "compiler-rt" in build_config.build_only_libs: + assert os.path.exists(os.path.join(build_config.REPOROOT_DIR, "out", "sysroot")), "Error! Compiler-rt require musl!" + for (_, target) in configs: + llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'crts', True, False) + llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'crts', False, False) + + if "libcxx" in build_config.build_only_libs: + assert os.path.exists(os.path.join(build_config.REPOROOT_DIR, "out", "sysroot")), "Error! Libcxx require musl!" + for (_, target) in configs: + llvm_libs.build_libs_by_type(llvm_path, llvm_install, target, 'runtimes', False, False) + windows_python_builder = None if build_config.do_build and need_windows: @@ -2656,6 +2789,8 @@ def main(): build_config.enable_assertions, build_config.build_name) + if build_config.build_gtest_libs: + llvm_libs.build_gtest(llvm_path, llvm_install) if build_config.do_package: if build_utils.host_is_linux(): diff --git a/llvm-build/env_prepare.sh b/llvm-build/env_prepare.sh index 6614f8c2fc6ffb7dc3d58d0447b451e1f9eafdbb..e2111ee61d6824945fabf5662921151df5c5cd9a 100755 --- a/llvm-build/env_prepare.sh +++ b/llvm-build/env_prepare.sh @@ -131,11 +131,13 @@ CLANG_DARWIN_BUILD=$(basename "$darwin_filename" .tar.bz2) if [ -d "${code_dir}/prebuilts/clang/ohos/linux-x86_64/${CLANG_LINUX_BUILD}" ]; then SET_CLANG_VERSION='15.0.4' mv "${code_dir}/prebuilts/clang/ohos/linux-x86_64/${CLANG_LINUX_BUILD}" "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-${SET_CLANG_VERSION}" + ln -s "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-${SET_CLANG_VERSION}" "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm" fi if [ -d "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/${CLANG_DARWIN_BUILD}" ]; then SET_CLANG_VERSION='15.0.4' mv "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/${CLANG_DARWIN_BUILD}" "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang-${SET_CLANG_VERSION}" + ln -s "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang-${SET_CLANG_VERSION}" "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/llvm" fi # try to detect version ... diff --git a/llvm/include/llvm/BinaryFormat/ADLTSection.h b/llvm/include/llvm/BinaryFormat/ADLTSection.h new file mode 100644 index 0000000000000000000000000000000000000000..073f24573768b362940f0f249d28de995a22ed26 --- /dev/null +++ b/llvm/include/llvm/BinaryFormat/ADLTSection.h @@ -0,0 +1,122 @@ +//===- ADLTSection.h - ADLT Section data types --------------------*- C -*-===// +// +// Copyright (C) 2024 Huawei Device Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_ADLTSECTION_H +#define LLVM_BINARYFORMAT_ADLTSECTION_H + +#ifdef __cplusplus +#include + +namespace llvm { +namespace adlt { + +#else // __cplusplus +#include +#endif // __cplusplus + +#ifndef _ELF_H +// part of #include +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef uint8_t Elf64_Byte; +#endif // _ELF_H + +typedef struct { + Elf64_Word secIndex; + Elf64_Off offset; // from section start +} adlt_cross_section_ref_t; + +typedef struct { + Elf64_Word secIndex; + Elf64_Off offset; // from section start + Elf64_Xword size; // size in bytes +} adlt_cross_section_array_t; + +typedef struct { + Elf64_Off offset; // relative to header.blobStart + Elf64_Xword size; // size in bytes, make convertions for data type +} adlt_blob_array_t; + +// plain-C has no strict typedefs, but aliases used to interpred underlying data +typedef adlt_blob_array_t adlt_blob_u8_array_t; // uint8_t[] +typedef adlt_blob_array_t adlt_blob_u16_array_t; // uint16_t[] +typedef adlt_blob_array_t adlt_blob_u32_array_t; // uint32_t[] +typedef adlt_blob_array_t adlt_blob_u64_array_t; // uint64_t[] + +typedef struct { + Elf64_Half major: 6; + Elf64_Half minor: 6; + Elf64_Half patch: 4; +} adlt_semver_t; + +// DT_NEEDED string index with embedded PSOD index if available +typedef struct { + Elf64_Off hasInternalPSOD : 1; // true if soname + Elf64_Off PSODindex : 16; // PSOD in the current ADLT image + Elf64_Off sonameOffset : 47; // string start in bound .adlt.strtab +} adlt_dt_needed_index_t; + +typedef enum { + ADLT_HASH_TYPE_NONE = 0, + ADLT_HASH_TYPE_GNU_HASH = 1, + ADLT_HASH_TYPE_SYSV_HASH = 2, + ADLT_HASH_TYPE_DEBUG_CONST = 0xfe, + ADLT_HASH_TYPE_MAX = 0xff, +} adlt_hash_type_enum_t; + +typedef uint8_t adlt_hash_type_t; + +// Serializable representation per-shared-object-data in .adlt section +typedef struct { + Elf64_Off soName; // offset in .adlt.strtab + Elf64_Xword soNameHash; // algorithm according to hdr.stringHashType value + adlt_cross_section_array_t initArray; + adlt_cross_section_array_t finiArray; + adlt_blob_array_t dtNeeded; // array of adlt_dt_needed_index_t[] elems + adlt_cross_section_ref_t sharedLocalSymbolIndex; + adlt_cross_section_ref_t sharedGlobalSymbolIndex; + adlt_blob_u16_array_t phIndexes; // program header indexes, typeof(e_phnum) + adlt_blob_u32_array_t relaDynIndx; // .rela.dyn dependent indexes, raw list + adlt_blob_u32_array_t relaPltIndx; // .rela.plt dependent indexes, raw list +} adlt_psod_t; + +typedef struct { + adlt_semver_t schemaVersion; // {major, minor, patch} + Elf64_Half schemaHeaderSize; // >= sizeof(adlt_section_header_t) if comp + Elf64_Half schemaPSODSize; // >= sizeof(adlt_psod_t) if compatible + Elf64_Half sharedObjectsNum; // number of PSOD entries + adlt_hash_type_t stringHashType; // contains adlt_hash_type_enum_t value + Elf64_Off blobStart; // offset of binary blob start relative to .adlt + Elf64_Xword blobSize; + Elf64_Xword overallMappedSize; // bytes, required to map the whole ADLT image + adlt_blob_u16_array_t phIndexes; // program header indexes, typeof(e_phnum) +} adlt_section_header_t; + +static const char adltBlobStartMark[4] = { 0xA, 0xD, 0x1, 0x7 }; + +static const adlt_semver_t adltSchemaVersion = {1, 1, 0}; + +#ifdef __cplusplus +} // namespace adlt +} // namespace llvm +#endif // __cplusplus + +#endif // LLVM_BINARYFORMAT_ADLTSECTION_H diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 556fe9c6a1a042caac23002459a5c12fefc438ef..c2a52a67bb5f052a189d7381bb1e2b9f4e1ff4c7 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1382,6 +1382,7 @@ enum { PT_OPENBSD_BOOTDATA = 0x65a41be6, // Section for boot arguments. PT_OHOS_RANDOMDATA = 0x6788FC60, // Fill with random data. OHOS_LOCAL + PT_ADLT = 0x6788FC61, // Adlt information. // ARM program header types. PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 68c635abf99c43ada159ed57acd1a2a4116d62b7..f0d1e092ad5515d0f982385f521285d28c0ecbb4 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -261,6 +261,9 @@ static void printProgramHeaders(const ELFFile &Obj, StringRef FileName) { outs() << " OHOS_RANDOMDATA "; break; // OHOS_LOCAL end + case ELF::PT_ADLT: + outs() << " ADLT "; + break; case ELF::PT_PHDR: outs() << " PHDR "; break; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index c9a239f785d2ebceeb33208d8eddf52032dae619..b6de5e52ee58c343f5df456beb94d65c157cb59a 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -29,6 +29,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/ADLTSection.h" #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MsgPackDocument.h" @@ -353,6 +354,8 @@ protected: void loadDynamicTable(); void parseDynamicTable(); + Expected> findAdlt(); + Expected getSymbolVersion(const Elf_Sym &Sym, bool &IsDefault) const; Expected, 0> *> getVersionMap() const; @@ -365,11 +368,14 @@ protected: DynRegionInfo DynSymTabShndxRegion; DynRegionInfo DynamicTable; StringRef DynamicStringTable; + StringRef AdltStringTable; const Elf_Hash *HashTable = nullptr; const Elf_GnuHash *GnuHashTable = nullptr; const Elf_Shdr *DotSymtabSec = nullptr; const Elf_Shdr *DotDynsymSec = nullptr; const Elf_Shdr *DotAddrsigSec = nullptr; + const Elf_Shdr *DotAdlt = nullptr; + const Elf_Shdr *DotAdltStrtab = nullptr; DenseMap> ShndxTables; Optional SONameOffset; Optional>> AddressToIndexMap; @@ -388,7 +394,9 @@ protected: Expected getSymbolSectionName(const Elf_Sym &Symbol, unsigned SectionIndex) const; std::string getStaticSymbolName(uint32_t Index) const; + StringRef getDynamicString(uint64_t Value, StringRef StringTable) const; StringRef getDynamicString(uint64_t Value) const; + StringRef getAdltDynamicString(uint64_t Value) const; void printSymbolsHelper(bool IsDynamic) const; std::string getDynamicEntry(uint64_t Type, uint64_t Value) const; @@ -572,6 +580,7 @@ public: void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printHashHistograms() override; + void printAdltSection() override; void printCGProfile() override; void printBBAddrMaps() override; void printAddrsig() override; @@ -676,6 +685,7 @@ public: void printVersionDefinitionSection(const Elf_Shdr *Sec) override; void printVersionDependencySection(const Elf_Shdr *Sec) override; void printHashHistograms() override; + void printAdltSection() override; void printCGProfile() override; void printBBAddrMaps() override; void printAddrsig() override; @@ -1416,6 +1426,7 @@ static StringRef segmentTypeToString(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); LLVM_READOBJ_ENUM_CASE(ELF, PT_OHOS_RANDOMDATA); // OHOS_LOCAL + LLVM_READOBJ_ENUM_CASE(ELF, PT_ADLT); // ADLT info default: return ""; } @@ -1705,6 +1716,45 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { } } +const EnumEntry AdltHashTypes[] = { + {"None", "NONE", llvm::adlt::ADLT_HASH_TYPE_NONE}, + {"GnuHash", "GNU_HASH", llvm::adlt::ADLT_HASH_TYPE_GNU_HASH}, + {"SysvHash", "SYSV_HASH", llvm::adlt::ADLT_HASH_TYPE_SYSV_HASH}, + {"Debug", "DEBUG", llvm::adlt::ADLT_HASH_TYPE_DEBUG_CONST}, +}; + +template +Expected> ELFDumper::findAdlt() { + // Try to locate .adlt section in the sections table + typename ELFT::ShdrRange Sections = cantFail(Obj.sections()); + for (const Elf_Shdr &Sec : Sections) { + if (DotAdlt && DotAdltStrtab) break; + + switch (Sec.sh_type) { + case ELF::SHT_STRTAB: + if (!DotAdltStrtab && getPrintableSectionName(Sec) == ".adlt.strtab") + DotAdltStrtab = &Sec; + break; + case ELF::SHT_PROGBITS: + if (!DotAdlt && getPrintableSectionName(Sec) == ".adlt") + DotAdlt = &Sec; + break; + } + } + + if (!DotAdlt) + return createError(".adlt section not found"); + if (!DotAdltStrtab) + return createError("has .adlt but .adlt.strtab section not found"); + + Expected StrTabOrErr = Obj.getStringTable(*DotAdltStrtab); + if (!StrTabOrErr) + return StrTabOrErr.takeError(); + AdltStringTable = *StrTabOrErr; + + return Obj.getSectionContents(*DotAdlt); +} + template std::pair ELFDumper::findDynamic() { @@ -2398,7 +2448,18 @@ std::string ELFDumper::getDynamicEntry(uint64_t Type, } template -StringRef ELFDumper::getDynamicString(uint64_t Value) const { +StringRef ELFDumper::getDynamicString(uint64_t Value) const { + return this->getDynamicString(Value, DynamicStringTable); +} + +template +StringRef ELFDumper::getAdltDynamicString(uint64_t Value) const { + return this->getDynamicString(Value, AdltStringTable); +} + +template +StringRef ELFDumper::getDynamicString( + uint64_t Value, StringRef DynamicStringTable) const { if (DynamicStringTable.empty() && !DynamicStringTable.data()) { reportUniqueWarning("string table was not found"); return ""; @@ -4822,6 +4883,10 @@ template void GNUELFDumper::printHashHistograms() { } } +template void GNUELFDumper::printAdltSection() { + OS << "GNUStyle::printAdltSection not implemented\n"; +} + template void GNUELFDumper::printCGProfile() { OS << "GNUStyle::printCGProfile not implemented\n"; } @@ -6954,6 +7019,202 @@ template void LLVMELFDumper::printHashHistograms() { W.startLine() << "Hash Histogram not implemented!\n"; } + +template void LLVMELFDumper::printAdltSection() { + using namespace llvm::adlt; + constexpr size_t kBinDumpLimit = sizeof(Elf64_Xword) * 0x80; + + Expected> ContentsOrErr = this->findAdlt(); + if (!ContentsOrErr) { + return this->reportUniqueWarning(ContentsOrErr.takeError()); + } + + ArrayRef adltRaw = ContentsOrErr.get(); + auto* header = reinterpret_cast(adltRaw.data()); + const auto& ver = header->schemaVersion; + + ArrayRef psodsRaw; + ArrayRef blob; + + if (psodsRaw.data() + psodsRaw.size() > blob.data()) + return this->reportUniqueWarning("invalid .adlt section: " + "PSOD and blob entries are overlapped"); + if (blob.data() + blob.size() > adltRaw.data() + adltRaw.size()) + return this->reportUniqueWarning("invalid .adlt section: " + "blob is out of section range"); + + DictScope DSec(W, "ADLT"); + + do { + DictScope DHeader(W, "Header"); + W.printVersion("schema-version", ver.major, ver.minor, ver.patch); + + if (ver.major > 1) { + this->reportUniqueWarning(Twine("schema version not supported yet") ); + return; + } + + W.printHex("schema-header-size", header->schemaHeaderSize); + W.printHex("schema-psod-size", header->schemaPSODSize); + W.printNumber("shared-objects-num", header->sharedObjectsNum); + W.printEnum("string-hash-type", header->stringHashType, makeArrayRef(AdltHashTypes)); + W.printHex("blob-start", header->blobStart); + W.printHex("blob-size", header->blobSize); + W.printHex("overall-mapped-size", header->overallMappedSize); + + psodsRaw = adltRaw.slice( + header->schemaHeaderSize, + header->sharedObjectsNum * header->schemaPSODSize); + blob = adltRaw.slice(header->blobStart, header->blobSize); + + if (psodsRaw.data() + psodsRaw.size() > blob.data()) + return this->reportUniqueWarning("invalid .adlt section: " + "PSOD and blob entries are overlapped"); + if (blob.data() + blob.size() > adltRaw.data() + adltRaw.size()) + return this->reportUniqueWarning("invalid .adlt section: " + "blob is out of section range"); + + if (ver.minor >= 1) { + DictScope PHEntry(W, "ph-indexes"); + const auto& arr = header->phIndexes; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + W.printBinary("raw", chunk); + ArrayRef phIdxs( + reinterpret_cast(chunk.data()), + chunk.size() / sizeof(uint16_t)); + W.printList("values", phIdxs); + } + } + } while(0); + + { + ListScope LPsods(W, "PSODs"); + + for (size_t psodIdx = 0; psodIdx < header->sharedObjectsNum; ++psodIdx) { + const adlt_psod_t& psod = *reinterpret_cast + (psodsRaw.data() + psodIdx * header->schemaPSODSize); + + auto psodName = Twine("psod-#") + Twine(psodIdx); + DictScope LEntry(W, psodName.str()); + + { + DictScope MetaEntry(W, "$-meta"); + auto psodSuffix = Twine("__") + Twine::utohexstr(psodIdx); + W.printNumber("$-order", psodIdx); + W.printString("$-symbol-suffix", psodSuffix.str()); + } + + W.printString("soname", this->getAdltDynamicString(psod.soName)); + W.printHex("soname-hash", psod.soNameHash); + { + DictScope IAEntry(W, "init-array"); + W.printHex("size", psod.initArray.size); + W.printNumber("sec-index", psod.initArray.secIndex); + W.printHex("offset", psod.initArray.offset); + } + { + DictScope IAEntry(W, "fini-array"); + W.printHex("size", psod.finiArray.size); + W.printNumber("sec-index", psod.finiArray.secIndex); + W.printHex("offset", psod.finiArray.offset); + } + { + DictScope DNEntry(W, "dt-needed"); + const auto& arr = psod.dtNeeded; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + W.printBinary("raw", chunk); + + ArrayRef deps( + reinterpret_cast(chunk.data()), + chunk.size() / sizeof(adlt_dt_needed_index_t)); + + ListScope NeedList(W, "needed-libs"); + for (const auto& need : deps) { + DictScope DepEntry(W, this->getAdltDynamicString(need.sonameOffset)); + W.printBoolean("is-internal", need.hasInternalPSOD); + if (need.hasInternalPSOD) + W.printNumber("psod-id", need.PSODindex); + } + } + } + { + DictScope SLEntry(W, "shared-local-symbol"); + const auto& csref = psod.sharedLocalSymbolIndex; + W.printNumber("sec-index", csref.secIndex); + W.printHex("offset", csref.offset); + } + { + DictScope SGEntry(W, "shared-global-symbol"); + const auto& csref = psod.sharedGlobalSymbolIndex; + W.printNumber("sec-index", csref.secIndex); + W.printHex("offset", csref.offset); + } + { + DictScope PHEntry(W, "ph-indexes"); + const auto& arr = psod.phIndexes; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + W.printBinary("raw", chunk); + ArrayRef phIdxs( + reinterpret_cast(chunk.data()), + chunk.size() / sizeof(uint16_t)); + W.printList("values", phIdxs); + } + } + { + DictScope RDEntry(W, "rela-dyn-idxs"); + const auto& arr = psod.relaDynIndx; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + if (chunk.size() > kBinDumpLimit) + W.printString("raw", ""); + else + W.printBinary("raw", chunk); + } + } + { + DictScope RPEntry(W, "rela-plt-idsx"); + const auto& arr = psod.relaPltIndx; + W.printHex("size", arr.size); + W.printHex("offset", arr.offset); + + const auto chunk = blob.slice(arr.offset, arr.size); + if (!chunk.empty()) { + if (chunk.size() > kBinDumpLimit) + W.printString("raw", ""); + else + W.printBinary("raw", chunk); + } + } + } + } + + { + DictScope DBlob(W, "Blob"); + W.printHex("start", header->blobStart); + W.printHex("size", header->blobSize); + + if (blob.size() > kBinDumpLimit * 50) + W.printString("raw", ""); + else + W.printBinaryBlock("raw", blob); + } +} + // Returns true if rel/rela section exists, and populates SymbolIndices. // Otherwise returns false. template diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h index 292efd2ae350a77cda3cc50fb0c1a7d1c6201f28..320e5972d479bee640e5e2292c7996424ca242e3 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -129,6 +129,7 @@ public: virtual void printVersionInfo() {} virtual void printGroupSections() {} virtual void printHashHistograms() {} + virtual void printAdltSection() {} virtual void printCGProfile() {} virtual void printBBAddrMaps() {} virtual void printAddrsig() {} diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td index 4687fc71245f8478e6f0f25b3fa2e5dcc16b3b77..012a16bb99ff7ae00d632f4b050cd51f2161da48 100644 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -55,6 +55,7 @@ def section_groups : FF<"section-groups", "Display section groups">, Group, Group; def hash_symbols : FF<"hash-symbols", "Display the dynamic symbols derived from the hash section">, Group; def hash_table : FF<"hash-table", "Display .hash section">, Group; +def adlt_section: FF<"adlt-section", "Display .adlt section in a pretty format">, Group; def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group; def notes : FF<"notes", "Display notes">, Group; def program_headers : FF<"program-headers", "Display program headers">, Group; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index e1ebbeb41f28b02e31ef3f28fbdfed6e687cff01..8c470a60ff9acad77cf08b3907d93a32ed82018c 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -125,6 +125,7 @@ static cl::boolOrDefault SectionMapping; static SmallVector SortKeys; // ELF specific options. +static bool AdltSection; static bool DynamicTable; static bool ELFLinkerOptions; static bool GnuHashTable; @@ -253,6 +254,7 @@ static void parseOptions(const opt::InputArgList &Args) { OutputStyleChoice + "'"); } } + opts::AdltSection = Args.hasArg(OPT_adlt_section); opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table); opts::HashSymbols = Args.hasArg(OPT_hash_symbols); opts::HashTable = Args.hasArg(OPT_hash_table); @@ -449,6 +451,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer, Dumper->printGroupSections(); if (opts::HashHistogram) Dumper->printHashHistograms(); + if (opts::AdltSection) + Dumper->printAdltSection(); if (opts::CGProfile) Dumper->printCGProfile(); if (opts::BBAddrMap)