diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..7b91e1e2f440ad8877dc39552625f8751ab8f19d --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,8 @@ +variables: + TOOLCHAIN_MANIFEST: 'huawei/dev-open-harmonyos' + TOOLCHAIN_NAME: 'HOS-OS' + +include: + - project: 'rus-os-team/compilers/testing/automation/llvm-ci' + ref: 'master-opensource-llvm-15' + file: '/pipelines/llvm/ohos/main.yml' diff --git a/DesignOHOS.md b/DesignOHOS.md new file mode 100644 index 0000000000000000000000000000000000000000..7b1e6aad444bf7a08a1b80f430f692694828b494 --- /dev/null +++ b/DesignOHOS.md @@ -0,0 +1,38 @@ +Hi all, + +We would like to contribute a new triple for the operational system OpenHarmony [1,2]. + +OpenHarmony is an open-source project incubated and operated by the OpenAtom Foundation. It is an open-source operating system with a framework and platform applicable to smart devices in all scenarios of a fully-connected world. It aims to promote the development of the Internet of Everything (IoE). + +OpenHarmony supports the following types: + +- Mini system + +A mini system runs on the devices whose memory is greater than or equal to 128 KiB and that are equipped with MCU processors such as Arm Cortex-M and 32-bit RISC-V. This system provides multiple lightweight network protocols and graphics frameworks, and a wide range of read/write components for the IoT bus. Typical products include connection modules, sensors, and wearables for smart home. + +- Small system + +A small system runs on the devices whose memory is greater than or equal to 1 MiB and that are equipped with application processors such as Arm Cortex-A. This system provides higher security capabilities, standard graphics frameworks, and video encoding and decoding capabilities. Typical products include smart home IP cameras, electronic cat eyes, routers, and event data recorders (EDRs) for smart travel. + +- Standard system + +A standard system runs on the devices whose memory is greater than or equal to 128 MiB and that are equipped with application processors such as Arm Cortex-A. This system provides a complete application framework supporting the enhanced interaction, 3D GPU, hardware composer, diverse components, and rich animations. This system applies to high-end refrigerator displays. + +For more detail please refer [3] + +The patches implement all the parts required for code generation: + + LLVM triple: http://reviews.llvm.org/D17003 9 + Clang support: http://reviews.llvm.org/D17002 5 + +We are still actively developing the OS support and have many optimizations in mind. + +This OS already used on a real world devices like [4,5] etc + +Please leave code comments on the Phab patches, while discussing high-level comments about the triples and operational system on this thread. + +1. https://github.com/openharmony/docs +2. https://en.wikipedia.org/wiki/OpenHarmony +3. https://github.com/openharmony/docs/blob/master/en/OpenHarmony-Overview.md +4. https://support.hkvstar.com/file/Hi3516D.pdf +5. https://developer.huawei.com/consumer/cn/market/prod-detail?productId=d0df2ab0845547129b0eb8900ca57d65&shopId=ccee05f52ce04acdbe7ce91b9398a527 \ No newline at end of file diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 52eb375a7e14bb451291ed3f936040eb34f62422..f29396749305942a8de9a8512f7d211d4a1d312d 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2510,6 +2510,10 @@ Enable stack protectors for all functions Enable stack protectors for some functions vulnerable to stack smashing. Compared to -fstack-protector, this uses a stronger heuristic that includes functions containing arrays of any size (and any type), as well as any calls to alloca or the taking of an address from a local variable +.. option:: -fstack-protector-ret + +Enable stack protectors for all functions with return address check + .. option:: -fstack-size-section, -fno-stack-size-section Emit section containing metadata on function stack sizes diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d61f3583281d1dd55fb1f7ed665af1bd96869fce..68f0841c51bddbf8637506bdc4e41af65f3cf6d0 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -901,6 +901,7 @@ def Availability : InheritableAttr { .Case("maccatalyst", "macCatalyst") .Case("maccatalyst_app_extension", "macCatalyst (App Extension)") .Case("swift", "Swift") + .Case("ohos", "OpenHOS") .Default(llvm::StringRef()); } static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) { diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index ad366821f3cbff1153654f2bcad21381fa14313c..4faec655636cb98d9f24f6b5c0b3ba42a610bdcf 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -358,7 +358,7 @@ ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibil BENIGN_LANGOPT(SemanticInterposition , 1, 0, "semantic interposition") BENIGN_LANGOPT(HalfNoSemanticInterposition, 1, 0, "Like -fno-semantic-interposition but don't use local aliases") -ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, +ENUM_LANGOPT(StackProtector, StackProtectorMode, 3, SSPOff, "stack protector mode") ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized, "trivial automatic variable initialization") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 3a1c13dd725681f3d177809daa8bcfff160789a8..04677596490567521aecc4f0d0660c31e95da5b4 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -81,7 +81,7 @@ public: using RoundingMode = llvm::RoundingMode; enum GCMode { NonGC, GCOnly, HybridGC }; - enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq }; + enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq, SSPRet }; // Automatic variables live on the stack, and when trivial they're usually // uninitialized because it's undefined behavior to use them without diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 3cab37b21aaf3f4bee4daecb21bd90d3cb5cf069..1b96288ff225892e5ee755fe071ef1db1723f83f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2738,6 +2738,8 @@ defm split_stack : BoolFOption<"split-stack", PosFlag>; def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group, HelpText<"Enable stack protectors for all functions">; +def fstack_protector_ret : Flag<["-"], "fstack-protector-ret">, Group, + HelpText<"Enable stack protectors for all functions with return address check">; defm stack_clash_protection : BoolFOption<"stack-clash-protection", CodeGenOpts<"StackClashProtector">, DefaultFalse, PosFlag, NegFlag, @@ -2910,6 +2912,8 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group, def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group, HelpText<"Do not assume that any loop is finite.">, Flags<[CC1Option]>; +def fenable_merge_functions : Flag<["-"], "fenable-merge-functions">, Group, + HelpText<"Enables Merge Functions optimization">; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, @@ -6048,9 +6052,9 @@ def static_define : Flag<["-"], "static-define">, MarshallingInfoFlag>; def stack_protector : Separate<["-"], "stack-protector">, HelpText<"Enable stack protectors">, - Values<"0,1,2,3">, + Values<"0,1,2,3,4">, NormalizedValuesScope<"LangOptions">, - NormalizedValues<["SSPOff", "SSPOn", "SSPStrong", "SSPReq"]>, + NormalizedValues<["SSPOff", "SSPOn", "SSPStrong", "SSPReq", "SSPRet"]>, MarshallingInfoEnum, "SSPOff">; def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">, HelpText<"Lower bound for a buffer to be considered for stack protection">, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index f20ab164531b8274a4ac574699d99c644107ac94..4f9d52ad9be16732fbc829523fc02f91449e8597 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -482,7 +482,8 @@ public: // Returns /lib//. This is used by runtimes (such // as OpenMP) to find arch-specific libraries. - std::string getArchSpecificLibPath() const; + // OHOS specific: make this function virtual to override in OHOS.cpp + virtual std::string getArchSpecificLibPath() const; // Returns part of above. virtual StringRef getOSLibName() const; diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index cf8cec3b13c3a15fc469ee2f67acb1c593c62a42..3b1326ffc37e22bb499679f676bc6dc7f3b373c0 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -120,6 +120,8 @@ def FuchsiaAlpha : Package<"fuchsia">, ParentPackage; def WebKit : Package<"webkit">; def WebKitAlpha : Package<"webkit">, ParentPackage; +def OpenHarmony : Package<"openharmony">; + //===----------------------------------------------------------------------===// // Core Checkers. //===----------------------------------------------------------------------===// @@ -1734,3 +1736,17 @@ def UncountedLocalVarsChecker : Checker<"UncountedLocalVarsChecker">, Documentation; } // end alpha.webkit + +//===----------------------------------------------------------------------===// +// OpenHarmony checkers. +//===----------------------------------------------------------------------===// + +let ParentPackage = OpenHarmony in { +def UnixAPIArgsChecker : Checker<"UnixAPIArgs">, + HelpText<"Check for open unix api arguments">, + Documentation; + +def MemcpyChecker : Checker<"Memcpy">, + HelpText<"Check for memcpy_s api arguments">, + Documentation; +} diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 6685145ea6d2e4004d0a830215919f6034ec1e7b..b4b1af20a64d26132ab0cd41cff66ead60f49c3c 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -71,7 +71,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) { // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html. // This alignment guarantee also applies to Windows and Android. On Darwin // and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit systems. - if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid()) + if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid() || T.isOHOSFamily()) NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0; else if (T.isOSDarwin() || T.isOSOpenBSD()) NewAlign = 128; diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 2d6ef998485ae1404e561dc12f962ce1bef2996d..d2eac5cae7b6ae9cd9fe044a2e2ca317b00f52cd 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -146,7 +146,12 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::Fuchsia: return new FuchsiaTargetInfo(Triple, Opts); case llvm::Triple::Linux: - return new LinuxTargetInfo(Triple, Opts); + switch (Triple.getEnvironment()) { + default: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSTargetInfo(Triple, Opts); + } case llvm::Triple::NetBSD: return new NetBSDTargetInfo(Triple, Opts); case llvm::Triple::OpenBSD: @@ -186,7 +191,14 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::CloudABI: return new CloudABITargetInfo(Triple, Opts); case llvm::Triple::Linux: - return new LinuxTargetInfo(Triple, Opts); + switch (Triple.getEnvironment()) { + default: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSTargetInfo(Triple, Opts); + } + case llvm::Triple::LiteOS: + return new OHOSTargetInfo(Triple, Opts); case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo(Triple, Opts); case llvm::Triple::NetBSD: @@ -261,7 +273,12 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::mipsel: switch (os) { case llvm::Triple::Linux: - return new LinuxTargetInfo(Triple, Opts); + switch (Triple.getEnvironment()) { + default: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSTargetInfo(Triple, Opts); + } case llvm::Triple::RTEMS: return new RTEMSTargetInfo(Triple, Opts); case llvm::Triple::FreeBSD: @@ -421,7 +438,12 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::Fuchsia: return new FuchsiaTargetInfo(Triple, Opts); case llvm::Triple::Linux: - return new LinuxTargetInfo(Triple, Opts); + switch (Triple.getEnvironment()) { + default: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSTargetInfo(Triple, Opts); + } default: return new RISCV64TargetInfo(Triple, Opts); } @@ -559,6 +581,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new LinuxTargetInfo(Triple, Opts); case llvm::Triple::Android: return new AndroidX86_64TargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSX86_64TargetInfo(Triple, Opts); } } case llvm::Triple::DragonFly: diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index b2f61cff81c9586f0cf31cb0e3c938f9f258d761..fd005a6570fb545172ad11a51cbb5334bbc96f03 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -317,7 +317,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, default: if (IsNetBSD) setABI("apcs-gnu"); - else if (IsOpenBSD) + else if (IsOpenBSD || Triple.isOHOSFamily()) setABI("aapcs-linux"); else setABI("aapcs"); diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index a814f681b1468c7628daf6f5c9c6d723155821b0..878efbf48317c74f9ddc9648335e289ff087e79a 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -1013,6 +1013,68 @@ public: } }; +// OHOS target +template +class LLVM_LIBRARY_VISIBILITY OHOSTargetInfo : public OSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // Linux defines; list based off of gcc output + DefineStd(Builder, "unix", Opts); + + Builder.defineMacro("__ELF__"); + + // Generic OHOS target defines + if (Triple.isOHOSFamily()) { + Builder.defineMacro("__OHOS_FAMILY__", "1"); + + auto Version = Triple.getEnvironmentVersion(); + this->PlatformName = "ohos"; + this->PlatformMinVersion = Version; + Builder.defineMacro("__OHOS_Major__", Twine(Version.getMajor())); + if (auto Minor = Version.getMinor()) + Builder.defineMacro("__OHOS_Minor__", Twine(*Minor)); + if (auto Subminor = Version.getSubminor()) + Builder.defineMacro("__OHOS_Micro__", Twine(*Subminor)); + } + + if (Triple.isOpenHOS()) + Builder.defineMacro("__OHOS__"); + + if (Triple.isOSLinux()) { + DefineStd(Builder, "linux", Opts); + } else if (Triple.isOSLiteOS()) { + Builder.defineMacro("__LITEOS__"); + } + + if (Opts.POSIXThreads) + Builder.defineMacro("_REENTRANT"); + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + if (this->HasFloat128) + Builder.defineMacro("__FLOAT128__"); + } + +public: + OHOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo(Triple, Opts) { + this->WIntType = TargetInfo::UnsignedInt; + + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + this->HasFloat128 = true; + break; + } + } + + const char *getStaticInitSectionSpecifier() const override { + return ".text.startup"; + } +}; + } // namespace targets } // namespace clang #endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index ed0864aec6d2d2c986b994472a89f2dc08b23f8e..0d5d068741a5d5b7fd689ea93c1a6a66219775bb 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -943,6 +943,28 @@ public: LongDoubleFormat = &llvm::APFloat::IEEEquad(); } }; + +// x86_32 OHOS target +class LLVM_LIBRARY_VISIBILITY OHOSX86_32TargetInfo + : public OHOSTargetInfo { +public: + OHOSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OHOSTargetInfo(Triple, Opts) { + SuitableAlign = 32; + LongDoubleWidth = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } +}; + +// x86_64 OHOS target +class LLVM_LIBRARY_VISIBILITY OHOSX86_64TargetInfo + : public OHOSTargetInfo { +public: + OHOSX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OHOSTargetInfo(Triple, Opts) { + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + } +}; } // namespace targets } // namespace clang #endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index c1eb8a9757962a63d22dbe0681ea56b743404419..250272fb8d238ccef8ae55de2a8b24e04a150077 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/lib/CodeGen/ABIInfo.h @@ -85,6 +85,7 @@ namespace CodeGen { QualType Ty) const = 0; bool isAndroid() const; + bool isOHOSFamily() const; /// Emit the target dependent code to load a value of /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d87692face2a94eb2cfd28b757f3d431124f3afc..c67643c43a7d1d13591bb3ea8c47711bab317b47 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1951,6 +1951,8 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, B.addAttribute(llvm::Attribute::StackProtectStrong); else if (LangOpts.getStackProtector() == LangOptions::SSPReq) B.addAttribute(llvm::Attribute::StackProtectReq); + else if (LangOpts.getStackProtector() == LangOptions::SSPRet) + B.addAttribute(llvm::Attribute::StackProtectRet); } if (!D) { diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 36e10e4df4c192335533a6bc1103d055fc39579e..3e667abc6f1c269dfe25ddca83eff27807551828 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -231,6 +231,10 @@ const CodeGenOptions &ABIInfo::getCodeGenOpts() const { bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); } +bool ABIInfo::isOHOSFamily() const { + return getTarget().getTriple().isOHOSFamily(); +} + bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { return false; } @@ -5726,7 +5730,7 @@ ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty) const { uint64_t Size = getContext().getTypeSize(Ty); // Android promotes <2 x i8> to i16, not i32 - if (isAndroid() && (Size <= 16)) { + if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) { llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); return ABIArgInfo::getDirect(ResType); } @@ -6323,7 +6327,7 @@ public: case llvm::Triple::MuslEABIHF: return true; default: - return false; + return getTarget().getTriple().isOHOSFamily(); } } diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 18c9b2d042f6c6e27382a4c72119250533e93482..7be7f959e896f7c3eb6b0bc30b639607a090a51b 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -71,6 +71,7 @@ add_clang_library(clangDriver ToolChains/Myriad.cpp ToolChains/NaCl.cpp ToolChains/NetBSD.cpp + ToolChains/OHOS.cpp ToolChains/OpenBSD.cpp ToolChains/PS4CPU.cpp ToolChains/RISCVToolchain.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 3f29afd359718a1c21e9c9911f0e6ad5f1002a3a..cbd2ff494de91b77695f271efc6a7f434c79064d 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -40,6 +40,7 @@ #include "ToolChains/Myriad.h" #include "ToolChains/NaCl.h" #include "ToolChains/NetBSD.h" +#include "ToolChains/OHOS.h" #include "ToolChains/OpenBSD.h" #include "ToolChains/PPCFreeBSD.h" #include "ToolChains/PPCLinux.h" @@ -5999,7 +6000,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, Args); else if (Target.getArch() == llvm::Triple::ve) TC = std::make_unique(*this, Target, Args); - + else if (Target.isOHOSFamily()) + TC = std::make_unique(*this, Target, Args); else TC = std::make_unique(*this, Target, Args); break; @@ -6060,6 +6062,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::Hurd: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::LiteOS: + TC = std::make_unique(*this, Target, Args); + break; case llvm::Triple::ZOS: TC = std::make_unique(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index cf7e201b4972cc913a8e5d7f7468e04736fc65f3..b497c14b79023a06392a8eda128ba6604b363704 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -608,7 +608,7 @@ fp16_fml_fallthrough: Features.push_back("+fix-cortex-a53-835769"); else Features.push_back("-fix-cortex-a53-835769"); - } else if (Triple.isAndroid()) { + } else if (Triple.isAndroid() || Triple.isOHOSFamily()) { // Enabled A53 errata (835769) workaround by default on android Features.push_back("+fix-cortex-a53-835769"); } diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index a64909d9a6e77a126a249b083d674afaf73df2bb..1f199fcd8d834ce08d98043157460ae3559ecfce 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -276,6 +276,11 @@ void arm::setArchNameInTriple(const Driver &D, const ArgList &Args, void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args, llvm::Triple &Triple) { + if (Triple.isOSLiteOS()) { + Triple.setEnvironment(llvm::Triple::OpenHOS); + return; + } + bool isHardFloat = (arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard); @@ -295,6 +300,8 @@ void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args, Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF : llvm::Triple::MuslEABI); break; + case llvm::Triple::OpenHOS: + break; default: { arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple); if (DefaultABI != arm::FloatABI::Invalid && @@ -364,6 +371,8 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) { return FloatABI::SoftFP; default: + if (Triple.isOHOSFamily()) + return FloatABI::Soft; switch (Triple.getEnvironment()) { case llvm::Triple::GNUEABIHF: case llvm::Triple::MuslEABIHF: diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index de6e045a9447f30be80f50872bc881597f752d55..610ba635bc58b19abe3833444a0a0b10fb3c2599 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -138,7 +138,9 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("+reserve-x31"); // -mrelax is default, unless -mno-relax is specified. - if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) { + // lld does not support relocations used by -mrelax on RISC-V + bool DefaultMRelax = !Triple.isOpenHOS(); + if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, DefaultMRelax)) { Features.push_back("+relax"); // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing // into .debug_addr, which is currently not implemented. diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h index dc718e09ad43eafc593bdba52aa66f36ee479b73..95970f7421ca53901bced3ab8eda979ae2b89175 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.h +++ b/clang/lib/Driver/ToolChains/BareMetal.h @@ -39,7 +39,7 @@ protected: bool AddArch = true) const override; public: - bool useIntegratedAs() const override { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } bool isPIEDefault(const llvm::opt::ArgList &Args) const override { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3704ed8586682677882acb8e1b82bfc14b1d07a5..c4355b9d52ec60e4a42f0fd47b69e7bb3d0ada31 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3259,6 +3259,7 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, options::OPT_fstack_protector_all, + options::OPT_fstack_protector_ret, options::OPT_fstack_protector_strong, options::OPT_fstack_protector)) { if (A->getOption().matches(options::OPT_fstack_protector)) @@ -3266,6 +3267,8 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC, std::max<>(LangOptions::SSPOn, DefaultStackProtectorLevel); else if (A->getOption().matches(options::OPT_fstack_protector_strong)) StackProtectorLevel = LangOptions::SSPStrong; + else if (A->getOption().matches(options::OPT_fstack_protector_ret)) + StackProtectorLevel = LangOptions::SSPRet; else if (A->getOption().matches(options::OPT_fstack_protector_all)) StackProtectorLevel = LangOptions::SSPReq; } else { @@ -6264,6 +6267,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fstrict_flex_arrays_EQ); + if (Args.hasArg(options::OPT_fenable_merge_functions)) + CmdArgs.push_back(Args.MakeArgString("-fmerge-functions")); + Args.AddLastArg(CmdArgs, options::OPT_pthread); if (Args.hasFlag(options::OPT_mspeculative_load_hardening, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 443725f7d8a8df1aa5a809b9e70399217c6a4831..84946b9e6d258baf029eb686a86d111fd80e36e4 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -828,7 +828,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, CmdArgs.push_back(getAsNeededOption(TC, false)); // There's no libpthread or librt on RTEMS & Android. if (TC.getTriple().getOS() != llvm::Triple::RTEMS && - !TC.getTriple().isAndroid()) { + !TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) { CmdArgs.push_back("-lpthread"); if (!TC.getTriple().isOSOpenBSD()) CmdArgs.push_back("-lrt"); @@ -1243,6 +1243,18 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { } } + // OHOS-specific defaults for PIC/PIE + if (Triple.isOHOSFamily()) { + switch (Triple.getArch()) { + case llvm::Triple::aarch64: + PIC = true; // "-fpic" + break; + + default: + break; + } + } + // OpenBSD-specific defaults for PIE if (Triple.isOSOpenBSD()) { switch (ToolChain.getArch()) { @@ -1505,6 +1517,11 @@ static LibGccType getLibGccType(const ToolChain &TC, const Driver &D, static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args); + if (TC.getTriple().isOHOSFamily() && UNW != ToolChain::UNW_None) { + CmdArgs.push_back("-l:libunwind.a"); + return; + } + // Targets that don't use unwind libraries. if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) || TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() || diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 665cdc3132fb8fc69f0a33feffdd0a82a5510810..f8dfb189eaf6ae03a8f3caadc7a0648a3e646eaf 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -398,6 +398,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); const llvm::Triple::ArchType Arch = ToolChain.getArch(); + const bool isOHOSFamily = ToolChain.getTriple().isOHOSFamily(); const bool isAndroid = ToolChain.getTriple().isAndroid(); const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU(); const bool IsVE = ToolChain.getTriple().isVE(); @@ -448,7 +449,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Most Android ARM64 targets should enable the linker fix for erratum // 843419. Only non-Cortex-A53 devices are allowed to skip this flag. - if (Arch == llvm::Triple::aarch64 && isAndroid) { + if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) { std::string CPU = getCPUName(D, Args, Triple); if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53") CmdArgs.push_back("--fix-cortex-a53-843419"); @@ -641,7 +642,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--pop-state"); } - if (WantPthread && !isAndroid) + // We don't need libpthread neither for bionic nor for musl + if (WantPthread && !isAndroid && !isOHOSFamily) CmdArgs.push_back("-lpthread"); if (Args.hasArg(options::OPT_fsplit_stack)) @@ -2208,7 +2210,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "x86_64-redhat-linux", "x86_64-suse-linux", "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", "x86_64-slackware-linux", "x86_64-unknown-linux", - "x86_64-amazon-linux"}; + "x86_64-amazon-linux", "x86_64-linux-ohos"}; static const char *const X32Triples[] = {"x86_64-linux-gnux32", "x86_64-pc-linux-gnux32"}; static const char *const X32LibDirs[] = {"/libx32", "/lib"}; @@ -2229,7 +2231,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"}; static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"}; static const char *const MIPSELTriples[] = { - "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu"}; + "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu", + "mipsel-linux-ohos"}; static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"}; static const char *const MIPS64Triples[] = { diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64dcec7bb1f299c8b3c9a26f7e1da93866f06cec --- /dev/null +++ b/clang/lib/Driver/ToolChains/OHOS.cpp @@ -0,0 +1,421 @@ +//===--- OHOS.cpp - OHOS ToolChain Implementations --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "OHOS.h" +#include "Arch/ARM.h" +#include "CommonArgs.h" +#include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "llvm/Option/ArgList.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/ScopedPrinter.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; +using namespace clang::driver::tools::arm; + +using tools::addMultilibFlag; +using tools::addPathIfExists; + +static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags, + DetectedMultilibs &Result) { + MultilibSet Multilibs; + Multilibs.push_back(Multilib()); + // -mcpu=cortex-a7 + // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard + // -mfpu=neon-vfpv4 + Multilibs.push_back(Multilib("a7_soft", {}, {}, 1) + .flag("+mcpu=cortex-a7") + .flag("+mfloat-abi=soft")); + + Multilibs.push_back(Multilib("a7_softfp_neon-vfpv4", {}, {}, 1) + .flag("+mcpu=cortex-a7") + .flag("+mfloat-abi=softfp") + .flag("+mfpu=neon-vfpv4")); + + Multilibs.push_back(Multilib("a7_hard_neon-vfpv4", {}, {}, 1) + .flag("+mcpu=cortex-a7") + .flag("+mfloat-abi=hard") + .flag("+mfpu=neon-vfpv4")); + + if (Multilibs.select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = Multilibs; + return true; + } + return false; +} + +static bool findOHOSMultilibs(const Driver &D, + const ToolChain &TC, + const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + Multilib::flags_list Flags; + bool IsA7 = false; + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + IsA7 = A->getValue() == StringRef("cortex-a7"); + addMultilibFlag(IsA7, "mcpu=cortex-a7", Flags); + + bool IsMFPU = false; + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) + IsMFPU = A->getValue() == StringRef("neon-vfpv4"); + addMultilibFlag(IsMFPU, "mfpu=neon-vfpv4", Flags); + + tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args); + addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Soft), + "mfloat-abi=soft", Flags); + addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::SoftFP), + "mfloat-abi=softfp", Flags); + addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard), + "mfloat-abi=hard", Flags); + + return findOHOSMuslMultilibs(Flags, Result); +} + +std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const { + // For most architectures, just use whatever we have rather than trying to be + // clever. + switch (T.getArch()) { + default: + break; + + // We use the existence of '/lib/' as a directory to detect some + // common linux triples that don't quite match the Clang triple for both + // 32-bit and 64-bit targets. Multiarch fixes its install triples to these + // regardless of what the actual target triple is. + case llvm::Triple::arm: + case llvm::Triple::thumb: + return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos"; + case llvm::Triple::riscv32: + return "riscv32-liteos-ohos"; + case llvm::Triple::riscv64: + return "riscv64-linux-ohos"; + case llvm::Triple::mipsel: + return "mipsel-linux-ohos"; + case llvm::Triple::x86: + return "i686-linux-ohos"; + case llvm::Triple::x86_64: + return "x86_64-linux-ohos"; + case llvm::Triple::aarch64: + return "aarch64-linux-ohos"; + } + return T.str(); +} + +std::string OHOS::getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) const { + return getMultiarchTriple(TargetTriple); +} + +static std::string makePath(const std::initializer_list &IL) { + SmallString<128> P; + for (const auto &S : IL) + llvm::sys::path::append(P, S); + return static_cast(P.str()); +} + +/// OHOS Toolchain +OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + std::string SysRoot = computeSysRoot(); + + // Select the correct multilib according to the given arguments. + DetectedMultilibs Result; + findOHOSMultilibs(D, *this, Triple, "", Args, Result); + Multilibs = Result.Multilibs; + SelectedMultilib = Result.SelectedMultilib; + + getFilePaths().clear(); + std::string CandidateLibPath = getArchSpecificLibPath(); + if (getVFS().exists(CandidateLibPath)) + getFilePaths().push_back(CandidateLibPath); + + getLibraryPaths().clear(); + for (auto &Path : getRuntimePaths()) + if (getVFS().exists(Path)) + getLibraryPaths().push_back(Path); + + // OHOS sysroots contain a library directory for each supported OS + // version as well as some unversioned libraries in the usual multiarch + // directory. Support --target=aarch64-linux-ohosX.Y.Z or + // --target=aarch64-linux-ohosX.Y or --target=aarch64-linux-ohosX + path_list &Paths = getFilePaths(); + std::string SysRootLibPath = makePath({SysRoot, "usr", "lib"}); + std::string MultiarchTriple = getMultiarchTriple(getTriple()); + addPathIfExists(D, makePath({SysRootLibPath, SelectedMultilib.gccSuffix()}), + Paths); + addPathIfExists(D, + makePath({D.Dir, "..", "lib", MultiarchTriple, + SelectedMultilib.gccSuffix()}), + Paths); + + // For compatibility with arm-liteos sysroot + // FIXME: Remove this when we'll use arm-liteos sysroot produced by build.py. + addPathIfExists( + D, + makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}), + Paths); +} + +ToolChain::RuntimeLibType OHOS::GetRuntimeLibType( + const ArgList &Args) const { + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) { + StringRef Value = A->getValue(); + if (Value != "compiler-rt") + getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name) + << A->getAsString(Args); + } + + return ToolChain::RLT_CompilerRT; +} + +ToolChain::CXXStdlibType +OHOS::GetCXXStdlibType(const ArgList &Args) const { + if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { + StringRef Value = A->getValue(); + if (Value != "libc++") + getDriver().Diag(diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); + } + + return ToolChain::CST_Libcxx; +} + +void OHOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + const llvm::Triple &Triple = getTriple(); + std::string SysRoot = computeSysRoot(); + + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + // Check for configure-time C include directories. + StringRef CIncludeDirs(C_INCLUDE_DIRS); + if (CIncludeDirs != "") { + SmallVector dirs; + CIncludeDirs.split(dirs, ":"); + for (StringRef dir : dirs) { + StringRef Prefix = + llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : ""; + addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); + } + return; + } + + addExternCSystemInclude(DriverArgs, CC1Args, + SysRoot + "/usr/include/" + + getMultiarchTriple(Triple)); + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); +} + +void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: { + std::string IncPath = makePath({getDriver().Dir, "..", "include"}); + std::string IncTargetPath = + makePath({IncPath, getMultiarchTriple(getTriple()), "c++", "v1"}); + if (getVFS().exists(IncTargetPath)) { + addSystemInclude(DriverArgs, CC1Args, makePath({IncPath, "c++", "v1"})); + addSystemInclude(DriverArgs, CC1Args, IncTargetPath); + } + break; + } + + default: + llvm_unreachable("invalid stdlib name"); + } +} + +void OHOS::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + switch (GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); + break; + + case ToolChain::CST_Libstdcxx: + llvm_unreachable("invalid stdlib name"); + } +} + +std::string OHOS::computeSysRoot() const { + std::string SysRoot = + !getDriver().SysRoot.empty() + ? getDriver().SysRoot + : makePath({getDriver().getInstalledDir(), "..", "..", "sysroot"}); + if (!llvm::sys::fs::exists(SysRoot)) + return std::string(); + + std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())}); + return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot; +} + +ToolChain::path_list OHOS::getRuntimePaths() const { + SmallString<128> P; + path_list Paths; + const Driver &D = getDriver(); + const llvm::Triple &Triple = getTriple(); + + // First try the triple passed to driver as --target=. + P.assign(D.ResourceDir); + llvm::sys::path::append(P, "lib", D.getTargetTriple(), SelectedMultilib.gccSuffix()); + Paths.push_back(P.c_str()); + + // Second try the normalized triple. + P.assign(D.ResourceDir); + llvm::sys::path::append(P, "lib", Triple.str(), SelectedMultilib.gccSuffix()); + Paths.push_back(P.c_str()); + + // Third try the effective triple. + P.assign(D.ResourceDir); + std::string SysRoot = computeSysRoot(); + llvm::sys::path::append(P, "lib", getMultiarchTriple(Triple), + SelectedMultilib.gccSuffix()); + Paths.push_back(P.c_str()); + + return Paths; +} + +std::string OHOS::getDynamicLinker(const ArgList &Args) const { + const llvm::Triple &Triple = getTriple(); + const llvm::Triple::ArchType Arch = getArch(); + + assert(Triple.isMusl()); + std::string ArchName; + bool IsArm = false; + + switch (Arch) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + ArchName = "arm"; + IsArm = true; + break; + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + ArchName = "armeb"; + IsArm = true; + break; + default: + ArchName = Triple.getArchName().str(); + } + if (IsArm && + (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)) + ArchName += "hf"; + + return "/lib/ld-musl-" + ArchName + ".so.1"; +} + +std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component, + FileType Type) const { + SmallString<128> Path(getDriver().ResourceDir); + llvm::sys::path::append(Path, "lib", getMultiarchTriple(getTriple()), + SelectedMultilib.gccSuffix()); + const char *Prefix = + Type == ToolChain::FT_Object ? "" : "lib"; + const char *Suffix; + switch (Type) { + case ToolChain::FT_Object: + Suffix = ".o"; + break; + case ToolChain::FT_Static: + Suffix = ".a"; + break; + case ToolChain::FT_Shared: + Suffix = ".so"; + break; + } + llvm::sys::path::append( + Path, Prefix + Twine("clang_rt.") + Component + Suffix); + return static_cast(Path.str()); +} + +void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const { + CmdArgs.push_back("-z"); + CmdArgs.push_back("now"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("relro"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("max-page-size=4096"); + // .gnu.hash section is not compatible with the MIPS target + if (getArch() != llvm::Triple::mipsel) { + CmdArgs.push_back("--hash-style=gnu"); + // FIXME: gnu or both??? + CmdArgs.push_back("--hash-style=both"); + } +#ifdef ENABLE_LINKER_BUILD_ID + CmdArgs.push_back("--build-id"); +#endif + CmdArgs.push_back("--enable-new-dtags"); +} + +SanitizerMask OHOS::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::PointerCompare; + Res |= SanitizerKind::PointerSubtract; + Res |= SanitizerKind::Fuzzer; + Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::Memory; + Res |= SanitizerKind::Vptr; + Res |= SanitizerKind::SafeStack; + Res |= SanitizerKind::Scudo; + // TODO: kASAN for liteos ?? + // TODO: Support TSAN and HWASAN and update mask. + return Res; +} + +// TODO: Make a base class for Linux and OHOS and move this there. +void OHOS::addProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const { + // Add linker option -u__llvm_profile_runtime to cause runtime + // initialization module to be linked in. + if (needsProfileRT(Args)) + CmdArgs.push_back(Args.MakeArgString( + Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); + ToolChain::addProfileRTLibs(Args, CmdArgs); +} + +std::string OHOS::getArchSpecificLibPath() const { + llvm::Triple Triple = getTriple(); + return makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}); +} + +ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const { + if (const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ)) + return Generic_ELF::GetUnwindLibType(Args); + return GetDefaultUnwindLibType(); +} diff --git a/clang/lib/Driver/ToolChains/OHOS.h b/clang/lib/Driver/ToolChains/OHOS.h new file mode 100644 index 0000000000000000000000000000000000000000..1d826122e239739db26a5af03560fd6372171700 --- /dev/null +++ b/clang/lib/Driver/ToolChains/OHOS.h @@ -0,0 +1,97 @@ +//===--- OHOS.h - OHOS ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H + +#include "Linux.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY OHOS : public Generic_ELF { +public: + OHOS(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool HasNativeLLVMSupport() const override { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } + bool IsMathErrnoDefault() const override { return false; } + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Libcxx; + } + // Not add -funwind-tables by default + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override { + return false; + } + bool isPICDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { return true; } + bool isPICDefaultForced() const override { return false; } + bool useRelaxRelocations() const override { return false; } + UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override; + UnwindLibType GetDefaultUnwindLibType() const override { return UNW_CompilerRT; } + + RuntimeLibType + GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; + CXXStdlibType + GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void + AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + + std::string computeSysRoot() const override; + std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override; + + std::string + getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, + FileType Type = ToolChain::FT_Static) const override; + + const char *getDefaultLinker() const override { + return "ld.lld"; + } + + Tool *buildLinker() const override { + return new tools::gnutools::Linker(*this); + } + Tool *buildAssembler() const override { + return new tools::gnutools::Assembler(*this); + } + + path_list getRuntimePaths() const; + +protected: + std::string getMultiarchTriple(const llvm::Triple &T) const; + std::string getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) const override; + void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override; + SanitizerMask getSupportedSanitizers() const override; + void addProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + std::string getArchSpecificLibPath() const override; +private: + Multilib SelectedMultilib; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 20bfbf144a30aa559b8adf2d7ebaf18b8d637af7..34f8c91fb79d478db7657076f38dcbdad40253b3 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1185,6 +1185,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__SSP_STRONG__", "2"); else if (LangOpts.getStackProtector() == LangOptions::SSPReq) Builder.defineMacro("__SSP_ALL__", "3"); + else if (LangOpts.getStackProtector() == LangOptions::SSPRet) + Builder.defineMacro("__SSP_RET__", "4"); if (PPOpts.SetUpStaticAnalyzer) Builder.defineMacro("__clang_analyzer__"); diff --git a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 84886b93d2e4aa5a36fd2d5affb2743c5cc2d645..9a0c774b859a0f934265165b1c4609655a67f433 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/clang/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -135,6 +135,8 @@ add_clang_library(clangStaticAnalyzerCheckers WebKit/UncountedCallArgsChecker.cpp WebKit/UncountedLambdaCapturesChecker.cpp WebKit/UncountedLocalVarsChecker.cpp + OpenHarmony/UnixAPIArgsChecker.cpp + OpenHarmony/MemcpyChecker.cpp LINK_LIBS clangAST diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65f3259b6753732d1346e10c6f46b59290a83fe3 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp @@ -0,0 +1,113 @@ +//== MemcpyChecker.cpp ------------------------------*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines MemcpyChecker, which is a path-sensitive check +// looking for mismatch src and dest buffer length may cause buffer overflow. +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" + +using namespace clang; +using namespace ento; + +namespace { +class MemcpyChecker : public Checker { + CallDescription MemcpyS; + + std::unique_ptr OverflowBugType; +public: + MemcpyChecker(); + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; +}; + +MemcpyChecker::MemcpyChecker() + : MemcpyS("memcpy_s") { + OverflowBugType.reset( + new BugType(this, "Unsafe buffer operation", categories::UnixAPI)); + } + +void MemcpyChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { + if (!MemcpyS.matches(Call)) { + return; + } + + SValBuilder &SVB = C.getSValBuilder(); + ProgramStateRef state = C.getState(); + SVal dstAddrSVal = Call.getArgSVal(0); + SVal srcLengthSVal = Call.getArgSVal(3); + + const MemRegion *dstAddrMR = dstAddrSVal.getAsRegion(); + if (!dstAddrMR) { + return; + } + + const ElementRegion *dstAddrER = dyn_cast(dstAddrMR); + if (!dstAddrER) { + return; + } + + DefinedOrUnknownSVal Idx = dstAddrER->getIndex().castAs(); + Optional IdxSVal = Idx.getAs(); + if (!IdxSVal) { + return; + } + + DefinedOrUnknownSVal ElementCount = getDynamicElementCount( + state, dstAddrER->getSuperRegion(), C.getSValBuilder(), dstAddrER->getValueType()); + + Optional dstAddrLenSVal = ElementCount.getAs(); + if (!dstAddrLenSVal) { + return; + } + + Optional srcLengthDSVal = srcLengthSVal.getAs(); + if (!srcLengthDSVal) { + return; + } + + SVal srcLenDSval = SVB.evalBinOp(state, BO_Add, *srcLengthDSVal, *IdxSVal, SVB.getArrayIndexType()); + + SVal dstLessThanSrcLength = SVB.evalBinOp(state, BO_LT, *dstAddrLenSVal, srcLenDSval, SVB.getConditionType()); + + Optional dstLessThanSrcLengthDVal = dstLessThanSrcLength.getAs(); + if (!dstLessThanSrcLengthDVal) { + return; + } + + if (state->assume(*dstLessThanSrcLengthDVal, true)) { + // it is possible that dst less than src length + ExplodedNode *ErrNode = C.generateNonFatalErrorNode(); + // If we've already reached this node on another path, return. + if (!ErrNode) + return; + + // Generate the report. + auto R = std::make_unique( + *OverflowBugType, "memcpy_s(): src length may be larger than dst length", ErrNode); + R->addRange(Call.getSourceRange()); + C.emitReport(std::move(R)); + return; + } +} +} + +void ento::registerMemcpyChecker(CheckerManager &mgr) { + mgr.registerChecker(); +} + +// This checker should be enabled regardless of how language options are set. +bool ento::shouldRegisterMemcpyChecker(const CheckerManager &mgr) { + return true; +} diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/UnixAPIArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/UnixAPIArgsChecker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4747fcdfe336ff10741437bef7861d9036a2583 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/UnixAPIArgsChecker.cpp @@ -0,0 +1,239 @@ +//== UnixAPIArgsChecker.cpp ------------------------------*- C++ -*--==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This defines UnixAPIArgsChecker, which is a path-sensitive checker +// looking for open a file with open() with GROUP and OTHER having +// write or execute permission +// +//===----------------------------------------------------------------------===// + +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; +using namespace ento; + +enum class OpenVariant { + /// The standard open() call: + /// int open(const char *pathname, int flags, mode_t mode); + Open, + + /// The variant taking a directory file descriptor and a relative path: + /// int openat(int fd, const char *pathname, int flags, mode_t mode); + OpenAt +}; + +namespace { +class UnixAPIArgsChecker : public Checker< check::PreStmt > { + mutable std::unique_ptr BT_open; + // value of O_CREAT flag + const uint64_t Val_O_CREAT = 0100; + // value of mode being checked + const uint64_t Val_MODE = 0133; + +public: + void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + + void CheckOpen(CheckerContext &C, const CallExpr *CE) const; + void CheckOpenAt(CheckerContext &C, const CallExpr *CE) const; + + void CheckOpenVariant(CheckerContext &C, + const CallExpr *CE, OpenVariant Variant) const; + + void ReportOpenBug(CheckerContext &C, + ProgramStateRef State, + const char *Msg, + SourceRange SR) const; +}; +} //end anonymous namespace + +static void LazyInitialize(const CheckerBase *Checker, + std::unique_ptr &BT, + const char *name) { + if (BT) + return; + BT.reset(new BugType(Checker, name, categories::UnixAPI)); +} + +//===----------------------------------------------------------------------===// +// "open" (man 2 open) +//===----------------------------------------------------------------------===/ + +void UnixAPIArgsChecker::checkPreStmt(const CallExpr *CE, + CheckerContext &C) const { + const FunctionDecl *FD = C.getCalleeDecl(CE); + if (!FD || FD->getKind() != Decl::Function) + return; + + // Don't treat functions in namespaces with the same name a Unix function + // as a call to the Unix function. + const DeclContext *NamespaceCtx = FD->getEnclosingNamespaceContext(); + if (NamespaceCtx && isa(NamespaceCtx)) + return; + + StringRef FName = C.getCalleeName(FD); + if (FName.empty()) + return; + + if (FName == "open") + CheckOpen(C, CE); + + else if (FName == "openat") + CheckOpenAt(C, CE); +} +void UnixAPIArgsChecker::ReportOpenBug(CheckerContext &C, + ProgramStateRef State, + const char *Msg, + SourceRange SR) const { + ExplodedNode *N = C.generateErrorNode(State); + if (!N) + return; + + LazyInitialize(this, BT_open, "Improper use of 'open'"); + + auto Report = std::make_unique(*BT_open, Msg, N); + Report->addRange(SR); + C.emitReport(std::move(Report)); +} + +void UnixAPIArgsChecker::CheckOpen(CheckerContext &C, + const CallExpr *CE) const { + CheckOpenVariant(C, CE, OpenVariant::Open); +} + +void UnixAPIArgsChecker::CheckOpenAt(CheckerContext &C, + const CallExpr *CE) const { + CheckOpenVariant(C, CE, OpenVariant::OpenAt); +} + +void UnixAPIArgsChecker::CheckOpenVariant(CheckerContext &C, + const CallExpr *CE, + OpenVariant Variant) const { + // The index of the argument taking the flags open flags (O_RDONLY, + // O_WRONLY, O_CREAT, etc.), + unsigned int FlagsArgIndex; + switch (Variant) { + case OpenVariant::Open: + FlagsArgIndex = 1; + break; + case OpenVariant::OpenAt: + FlagsArgIndex = 2; + break; + }; + + // All calls should at least provide arguments up to the 'flags' parameter. + unsigned int MinArgCount = FlagsArgIndex + 1; + + // If the flags has O_CREAT set then open/openat() require an additional + // argument specifying the file mode (permission bits) for the created file. + unsigned int CreateModeArgIndex = FlagsArgIndex + 1; + + // The create mode argument should be the last argument. + unsigned int MaxArgCount = CreateModeArgIndex + 1; + + ProgramStateRef state = C.getState(); + + // Checked via UnixAPIChecker + if (CE->getNumArgs() < MinArgCount || CE->getNumArgs() > MaxArgCount) { + return; + } else if (CE->getNumArgs() == MaxArgCount) { + const Expr *Arg = CE->getArg(CreateModeArgIndex); + QualType QT = Arg->getType(); + if (!QT->isIntegerType()) { + return; + } + } + + // Now check if oflags has O_CREAT set. + const Expr *oflagsEx = CE->getArg(FlagsArgIndex); + const SVal V = C.getSVal(oflagsEx); + if (!V.getAs()) { + // The case where 'V' can be a location can only be due to a bad header, + // so in this case bail out. + return; + } + NonLoc oflags = V.castAs(); + NonLoc ocreateFlag = C.getSValBuilder() + .makeIntVal(Val_O_CREAT, oflagsEx->getType()).castAs(); + SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And, + oflags, ocreateFlag, + oflagsEx->getType()); + if (maskedFlagsUC.isUnknownOrUndef()) + return; + DefinedSVal maskedFlags = maskedFlagsUC.castAs(); + + // Check if maskedFlags is non-zero. + ProgramStateRef trueState, falseState; + std::tie(trueState, falseState) = state->assume(maskedFlags); + + // Only emit an error if the value of 'maskedFlags' is properly + // constrained; + if (!(trueState && !falseState)) + return; + + if (CE->getNumArgs() < MaxArgCount) { + return; + } + + // Now check mode when O_CREAT flag is set, GROUP and OTHER should not + // have write or execute permission + const Expr *createModeEx = CE->getArg(CreateModeArgIndex); + const SVal CM = C.getSVal(createModeEx); + if (!CM.getAs()) { + return; + } + NonLoc createMode = CM.castAs(); + NonLoc createModeCheck = C.getSValBuilder(). + makeIntVal(Val_MODE, createModeEx->getType()).castAs(); + + SVal maskedCreateMode = C.getSValBuilder().evalBinOpNN(state, BO_And, + createMode, createModeCheck, + createModeEx->getType()); + if (maskedCreateMode.isUnknownOrUndef()) + return; + DefinedSVal maskedCreateModeSVal = maskedCreateMode.castAs(); + + // Check if maskedFlags is non-zero. + ProgramStateRef t, f; + std::tie(t, f) = state->assume(maskedCreateModeSVal); + + // Only emit an error if the value of 'maskedFlags' is properly + // constrained; + if (t && !f) { + SmallString<256> SBuf; + llvm::raw_svector_ostream OS(SBuf); + OS << "Open() system call, GROUP/OTHER should not have write or execute permission"; + ReportOpenBug(C, t, + SBuf.c_str(), + createModeEx->getSourceRange()); + } +} + +//===----------------------------------------------------------------------===// +// Registration. +//===----------------------------------------------------------------------===// + +#define REGISTER_CHECKER(CHECKERNAME) \ + void ento::register##CHECKERNAME(CheckerManager &mgr) { \ + mgr.registerChecker(); \ + } \ + \ + bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \ + return true; \ + } + +REGISTER_CHECKER(UnixAPIArgsChecker) diff --git a/clang/test/Analysis/memcpy_s.c b/clang/test/Analysis/memcpy_s.c new file mode 100644 index 0000000000000000000000000000000000000000..d945a4b4a96939993e9e1ad62f32d365ec23425f --- /dev/null +++ b/clang/test/Analysis/memcpy_s.c @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// + +// RUN: %clang_analyze_cc1 -analyzer-checker=openharmony -verify %s + +int memcpy_s(char *dst, int dstLen, char *src, int srcLen) { + return dstLen; +} + +void check1(int dstLen, int srcLen) { + char dstStr[dstLen]; + char srcStr[srcLen]; + memcpy_s(dstStr, sizeof(dstStr), srcStr, srcLen); // expected-warning{{memcpy_s(): src length may be larger than dst length}} +} + +void check2() { + char dstStr[20]; + char srcStr[10]; + memcpy_s(dstStr, sizeof(dstStr), srcStr, 10); // no-warning +} + +void check3() { + char dstStr[10]; + char srcStr[20]; + memcpy_s(dstStr, sizeof(dstStr), srcStr, 20); // expected-warning{{memcpy_s(): src length may be larger than dst length}} +} + +void check4() { + char dstStr[20]; + char srcStr[10]; + memcpy_s(&dstStr[15], 10, srcStr, 10); // expected-warning{{memcpy_s(): src length may be larger than dst length}} + memcpy_s(&dstStr[5], 10, srcStr, 10); // no-warning +} diff --git a/clang/test/Analysis/unix-api.c b/clang/test/Analysis/unix-api.c index 64ff3c0fccf426799cb8e4fc37aea39f376600b9..4adca811bfee282f75ed7944feebaea0db450df4 100644 --- a/clang/test/Analysis/unix-api.c +++ b/clang/test/Analysis/unix-api.c @@ -1,9 +1,19 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API -verify %s +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +//===----------------------------------------------------------------------===// + +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.API,openharmony -verify %s #ifndef O_RDONLY #define O_RDONLY 0 #endif +#ifndef O_CREAT +#define O_CREAT 0100 +#endif + #ifndef NULL #define NULL ((void*) 0) #endif @@ -90,3 +100,19 @@ void open_8(const char *path) { if (fd > -1) close(fd); } + +void open_9(const char *path) { + int fd; + int mode = 0631; + fd = open(path, O_CREAT, mode); // expected-warning{{Open() system call, GROUP/OTHER should not have write or execute permission}} + if (fd > -1) + close(fd); +} + +void open_10(const char *path) { + int fd; + int mode = 0644; + fd = open(path, O_CREAT, mode); // no-warning + if (fd > -1) + close(fd); +} \ No newline at end of file diff --git a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c index 3ce5b9d122176e68c3b69a4b0d49919509fd248c..3d1a2c7aceb1f1ab633d3f59c9dd201565a0089b 100644 --- a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c +++ b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c @@ -7,6 +7,8 @@ // RUN: %clang -O3 -target aarch64-android-eabi %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s +// RUN: %clang -O3 -target aarch64-linux-ohos %s -S -o- \ +// RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s // RUN: %clang -O3 -target aarch64-android-eabi -mfix-cortex-a53-835769 %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s // RUN: %clang -O3 -target aarch64-android-eabi -mno-fix-cortex-a53-835769 %s -S -o- \ diff --git a/clang/test/CodeGen/arm64-abi-vector.c b/clang/test/CodeGen/arm64-abi-vector.c index 10f721ab1f2f928e972884a77980eca0359dcdfb..677639bb3c1da5041ddd95f136f1a4f19bba4f27 100644 --- a/clang/test/CodeGen/arm64-abi-vector.c +++ b/clang/test/CodeGen/arm64-abi-vector.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -no-opaque-pointers -triple arm64-apple-ios7 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-linux-android -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s +// RUN: %clang_cc1 -no-opaque-pointers -triple aarch64-linux-ohos -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s #include diff --git a/clang/test/CodeGen/merge-functions.c b/clang/test/CodeGen/merge-functions.c new file mode 100644 index 0000000000000000000000000000000000000000..7e382853cc7c35b62139ee0ba2adcae3284d2d11 --- /dev/null +++ b/clang/test/CodeGen/merge-functions.c @@ -0,0 +1,22 @@ +// Check that code gen really activates function merging. In this case +// just check a trivial functions merging case. + +// RUN: %clang_cc1 -emit-llvm %s -fmerge-functions -o - | FileCheck %s + +void foo1() {} +void foo2() {} + +int main() { + + // If merge functions pass is enabled, + // then second and first calls will refer to foo1 + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo1(); + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo2(); + + return 0; +} + diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/bin/.keep b/clang/test/Driver/Inputs/ohos_native_tree/llvm/bin/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/include/c++/v1/.keep b/clang/test/Driver/Inputs/ohos_native_tree/llvm/include/c++/v1/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/a7_soft/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/a7_soft/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/c++/a7_hard_neon-vfpv4/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/c++/a7_hard_neon-vfpv4/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/c++/a7_soft/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/c++/a7_soft/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/c++/a7_softfp_neon-vfpv4/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/c++/a7_softfp_neon-vfpv4/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/libc++.so b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/arm-liteos-ohos/libc++.so new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/.keep b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/.keep b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/clang_rt.crtbegin.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/clang_rt.crtend.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/clang_rt.crtend.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.builtins.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.builtins.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.profile.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.profile.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/.keep b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/clang_rt.crtbegin.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/clang_rt.crtend.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/clang_rt.crtend.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/libclang_rt.builtins.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/libclang_rt.builtins.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/libclang_rt.profile.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_soft/libclang_rt.profile.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/.keep b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/clang_rt.crtbegin.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/clang_rt.crtend.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/clang_rt.crtend.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.builtins.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.builtins.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.profile.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.profile.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/clang_rt.crtbegin.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/clang_rt.crtbegin.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/clang_rt.crtend.o b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/clang_rt.crtend.o new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/libclang_rt.builtins.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/libclang_rt.builtins.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/libclang_rt.profile.a b/clang/test/Driver/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z/lib/arm-liteos-ohos/libclang_rt.profile.a new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/include/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/include/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/include/arm-liteos-ohos/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/include/arm-liteos-ohos/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/a7_soft/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/a7_soft/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/.keep b/clang/test/Driver/Inputs/ohos_native_tree/sysroot/usr/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/.keep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/clang/test/Driver/as-fno-integrated-as.c b/clang/test/Driver/as-fno-integrated-as.c new file mode 100644 index 0000000000000000000000000000000000000000..866cc421e5221e4eef64e34021401e942201f6ad --- /dev/null +++ b/clang/test/Driver/as-fno-integrated-as.c @@ -0,0 +1,3 @@ +// Make sure that for BareMetal toolchain, we able to +// disable the use of integrated assembler. +// RUN: %clang -Werror --target="arm-none-eabi" -fno-integrated-as -c %s diff --git a/clang/test/Driver/fenable-merge-functions.cpp b/clang/test/Driver/fenable-merge-functions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f45cdd3b09e9bbb4eab2029344f6eec92d99261e --- /dev/null +++ b/clang/test/Driver/fenable-merge-functions.cpp @@ -0,0 +1,28 @@ +// First. Check that option is passed into clangcc1 +// RUN: %clang -fenable-merge-functions -### %s 2>&1 | FileCheck %s -check-prefix=CHECK_CC1 +// CHECK_CC1: "-cc1" {{.*}} "-fmerge-functions" + +// Second. Check that code gen really activates function merging. In this case +// just check a trivial functions merging case. +// One may say, that this is an superfluous check, +// for it is covered by clang/test/CodeGen/merge-functions.c +// But it is worth keeping, because it also checks whole driver + clang interaction chain. + +// RUN: %clang -emit-llvm %s -fenable-merge-functions -c -S -o - | FileCheck %s + +void foo1() {} +void foo2() {} + +int main() { + + // If merge functions pass is enabled, + // then second and first calls will refer to foo1 + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo1(); + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo2(); + + return 0; +} diff --git a/clang/test/Driver/ohos.c b/clang/test/Driver/ohos.c new file mode 100644 index 0000000000000000000000000000000000000000..480519c54112d5e012351ef19cd3e5616ac2ae01 --- /dev/null +++ b/clang/test/Driver/ohos.c @@ -0,0 +1,241 @@ +// RUN: %clang %s -### -no-canonical-prefixes --target=arm-liteos \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld -march=armv7-a 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHECK,CHECK-ARM %s +// RUN: %clang %s -### -no-canonical-prefixes --target=arm-liteos \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHECK,CHECK-ARM-A7-SOFT %s +// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK-NOT: "--mrelax-relocations" +// CHECK-NOT: "-munwind-tables" +// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include" +// CHECK-NOT: "-fsanitize=safe-stack" +// CHECK-NOT: "-stack-protector" "2" +// CHECK-NOT: "-fno-common" +// CHECK: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-NOT: "--sysroot=[[SYSROOT]]" +// CHECK: "-pie" +// CHECK-NOT: "--build-id" +// CHECK: "--hash-style=gnu" +// CHECK: "--hash-style=both" +// CHECK: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK: Scrt1.o +// CHECK: crti.o +// CHECK: clang_rt.crtbegin.o +// CHECK-ARM: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/" +// CHECK-ARM-A7-SOFT: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_soft" +// CHECK-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-ARM-A7-SOFT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos/a7_soft{{/|\\\\}}libclang_rt.builtins.a" +// CHECK: "-lc" +// CHECK: clang_rt.crtend.o +// CHECK: crtn.o + +// RUN: %clang %s -### --target=arm-liteos -rtlib=libgcc -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RTLIB +// CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc' + +// RUN: %clang %s -### --target=arm-liteos -static -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC +// CHECK-STATIC: "-static" +// CHECK-STATIC-NOT: "-Bdynamic" +// CHECK-STATIC: "-l:libunwind.a" +// CHECK-STATIC: "-lc" + +// RUN: %clang %s -### --target=arm-liteos -shared -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-SHARED +// CHECK-SHARED-NOT: "-pie" +// CHECK-SHARED: "-shared" +// CHECK-SHARED: "-lc" +// CHECK-SHARED: "-l:libunwind.a" + +// RUN: %clang %s -### --target=arm-linux-ohos -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RUNTIME +// RUN: %clang %s -### --target=aarch64-linux-ohos -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RUNTIME +// RUN: %clang %s -### --target=mipsel-linux-ohos -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RUNTIME +// RUN: %clang %s -### --target=x86_64-linux-ohos -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RUNTIME +// CHECK-RUNTIME: "{{.*}}/libclang_rt.builtins.a" +// CHECK-RUNTIME: "-l:libunwind.a" +// CHECK-LIBM: "-lm" + +// RUN: %clang %s -### --target=arm-liteos -r -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE +// CHECK-RELOCATABLE-NOT: "-pie" +// CHECK-RELOCATABLE-NOT: "--build-id" +// CHECK-RELOCATABLE: "-r" + +// RUN: %clang %s -### --target=arm-liteos -nodefaultlibs -fuse-ld=lld 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: | FileCheck %s -check-prefix=CHECK-NODEFAULTLIBS +// CHECK-NODEFAULTLIBS: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NODEFAULTLIBS-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-NODEFAULTLIBS-NOT: "-lc" + +// RUN: %clang %s -### --target=arm-liteos -nostdlib -fuse-ld=lld 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIB +// CHECK-NOSTDLIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NOSTDLIB-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-NOSTDLIB-NOT: "-lc" + +// RUN: %clang %s -### --target=arm-liteos -nolibc -fuse-ld=lld 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOLIBC +// CHECK-NOLIBC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NOLIBC: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-NOLIBC-NOT: "-lc" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=safe-stack 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-SAFESTACK +// CHECK-SAFESTACK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-SAFESTACK: "-fsanitize=safe-stack" +// CHECK-SAFESTACK: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.safestack.a" +// CHECK-SAFESTACK: "__safestack_init" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=address 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-ARM +// CHECK-ASAN-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-ASAN-ARM: "-fsanitize=address" +// CHECK-ASAN-ARM: "-fsanitize-address-use-after-scope" +// CHECK-ASAN-ARM: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK-ASAN-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan.a" +// CHECK-ASAN-ARM-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan-preinit.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=address -fPIC -shared 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -shared-libsan \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-SHARED +// CHECK-ASAN-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-ASAN-SHARED: "-fsanitize=address" +// CHECK-ASAN-SHARED: "-fsanitize-address-use-after-scope" +// CHECK-ASAN-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan.so" +// CHECK-ASAN-SHARED-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan-preinit.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=fuzzer 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-ARM +// CHECK-FUZZER-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-FUZZER-ARM: "-fsanitize=fuzzer,fuzzer-no-link" +// CHECK-FUZZER-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.fuzzer.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=scudo 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-ARM +// CHECK-SCUDO-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-SCUDO-ARM: "-fsanitize=scudo" +// CHECK-SCUDO-ARM: "-pie" +// CHECK-SCUDO-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.scudo.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=scudo -fPIC -shared 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -shared-libsan \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED +// CHECK-SCUDO-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-SCUDO-SHARED: "-fsanitize=scudo" +// CHECK-SCUDO-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.scudo.so" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fxray-instrument -fxray-modes=xray-basic \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-XRAY-ARM +// CHECK-XRAY-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-XRAY-ARM: "-fxray-instrument" +// CHECK-XRAY-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.xray.a" +// CHECK-XRAY-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.xray-basic.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-LTO +// CHECK-LTO: "-plugin-opt=mcpu=cortex-a53" +// CHECK-LTO: "-plugin-opt=O3" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -flto=thin -flto-jobs=8 -mcpu=cortex-a7 2>&1 \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO +// CHECK-THINLTO: "-plugin-opt=mcpu=cortex-a7" +// CHECK-THINLTO: "-plugin-opt=thinlto" +// CHECK-THINLTO: "-plugin-opt=jobs=8" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFT +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFTFP +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-HF,CHECK-MULTILIB-ARM-A7-HARD +// CHECK-MULTILIB: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MULTILIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-MULTILIB: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-MULTILIB: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-MULTILIB-SF: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK-MULTILIB-HF: "-dynamic-linker" "/lib/ld-musl-armhf.so.1" + +// CHECK-MULTILIB-ARM: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/" + +// CHECK-MULTILIB-ARM-A7-SOFT: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_soft" + +// CHECK-MULTILIB-ARM-A7-SOFTFP: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4" + +// CHECK-MULTILIB-ARM-A7-HARD: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_hard_neon-vfpv4" + +// CHECK-MULTILIB-ARM: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFT: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_soft/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFTFP: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-HARD: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.builtins.a" + +// RUN: %clang %s -### -no-canonical-prefixes --target=arm-linux-ohos -fprofile-instr-generate -v \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld -march=armv7-a 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHECK-PROFILE-RTLIB %s + +// CHECK-PROFILE-RTLIB: -u__llvm_profile_runtime +// CHECK-PROFILE-RTLIB: libclang_rt.profile + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=arm64-linux-ohos -pthread \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -shared \ +// RUN: | FileCheck --check-prefix=CHECK-OHOS-PTHREAD %s + +// CHECK-OHOS-PTHREAD-NOT: -lpthread + diff --git a/clang/test/Driver/ohos.cpp b/clang/test/Driver/ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b822350898c8be2eb5a41740b3e279d18a9ca2e --- /dev/null +++ b/clang/test/Driver/ohos.cpp @@ -0,0 +1,121 @@ +// RUN: %clangxx %s -### -no-canonical-prefixes --target=arm-liteos -march=armv7-a \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld 2>&1 | FileCheck %s +// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK: "-triple" "armv7-unknown-liteos-ohos" +// CHECK-NOT: "-fuse-init-array" +// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include" +// CHECK: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK: "-pie" +// CHECK-NOT: "--build-id" +// CHECK: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK: Scrt1.o +// CHECK: crti.o +// CHECK: clang_rt.crtbegin.o +// CHECK: "-L{{.*[/\\]}}lib/arm-liteos-ohos/" +// CHECK-NOT: "--push-state" +// CHECK-NOT: "--as-needed" +// CHECK: "-lc++" +// CHECK: "-lm" +// CHECK-NOT: "--pop-state" +// CHECK: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK: "-lc" +// CHECK: clang_rt.crtend.o +// CHECK: crtn.o + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -stdlib=libstdc++ \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STDLIB +// CHECK-STDLIB: error: invalid library name in argument '-stdlib=libstdc++' + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -static-libstdc++ \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC +// CHECK-STATIC-NOT: "--push-state" +// CHECK-STATIC-NOT: "--as-needed" +// CHECK-STATIC: "-Bstatic" +// CHECK-STATIC: "-lc++" +// CHECK-STATIC: "-Bdynamic" +// CHECK-STATIC: "-lm" +// CHECK-STATIC-NOT: "--pop-state" +// CHECK-STATIC: "-lc" + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -static \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC1 +// CHECK-STATIC1-NOT: "-fuse-init-array" +// CHECK-STATIC1: "-static" +// CHECK-STATIC1: "-lc++" +// CHECK-STATIC1: "-lc++abi" +// CHECK-STATIC1: "-lunwind" +// CHECK-STATIC1: "-lm" +// CHECK-STATIC1: "-lc" + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -march=armv7-a -mfloat-abi=soft -static -fPIE -fPIC -fpic -pie \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC2 +// CHECK-STATIC2: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-STATIC2: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-STATIC2: "-static" +// CHECK-STATIC2: "-lc++" +// CHECK-STATIC2: "-lc++abi" +// CHECK-STATIC2: "-lunwind" +// CHECK-STATIC2: "-lm" +// CHECK-STATIC2: "-lc" + +// RUN: %clangxx %s -### --target=arm-liteos -nostdlib++ -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIBXX +// CHECK-NOSTDLIBXX-NOT: "-lc++" +// CHECK-NOSTDLIBXX: "-lm" +// CHECK-NOSTDLIBXX: "-lc" + +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFT +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFTFP +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-HF,CHECK-MULTILIB-ARM-A7-HARD +// CHECK-MULTILIB: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MULTILIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-MULTILIB: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-MULTILIB: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-MULTILIB-SF: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK-MULTILIB-HF: "-dynamic-linker" "/lib/ld-musl-armhf.so.1" + +// CHECK-MULTILIB-ARM: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}" +// CHECK-MULTILIB-ARM: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/" + +// CHECK-MULTILIB-ARM-A7-SOFT: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}a7_soft" +// CHECK-MULTILIB-ARM-A7-SOFT: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_soft" + +// CHECK-MULTILIB-ARM-A7-SOFTFP: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}a7_softfp_neon-vfpv4" +// CHECK-MULTILIB-ARM-A7-SOFTFP: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4" + +// CHECK-MULTILIB-ARM-A7-HARD: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}a7_hard_neon-vfpv4" +// CHECK-MULTILIB-ARM-A7-HARD: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_hard_neon-vfpv4" + +// CHECK-MULTILIB-ARM: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFT: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_soft/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFTFP: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-HARD: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.builtins.a" diff --git a/clang/test/Preprocessor/ohos.c b/clang/test/Preprocessor/ohos.c new file mode 100644 index 0000000000000000000000000000000000000000..0c435c7ed5ab471e97d2358640d8ef838cd47955 --- /dev/null +++ b/clang/test/Preprocessor/ohos.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=ARM-OHOS-CXX +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=aarch64-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=ARM64-OHOS-CXX +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=riscv64-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=RISCV64-OHOS-CXX +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=mipsel-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=MIPSEL-OHOS-CXX +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=X86_64-OHOS-CXX +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-linux-ohos < /dev/null | FileCheck %s -check-prefix=OHOS-DEFS + +// ARM-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U +// ARM64-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// RISCV64-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// MIPSEL-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U +// X86_64-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// OHOS-DEFS: __OHOS_FAMILY__ +// OHOS-DEFS: __OHOS__ +// OHOS-DEFS-NOT: __OHOS__ diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt index 51fe5de9ce644838cc0c6beb2799df1250cb209c..37a2a167c38df4ae403e516000b5eb6cac579390 100644 --- a/clang/unittests/CMakeLists.txt +++ b/clang/unittests/CMakeLists.txt @@ -41,7 +41,9 @@ add_subdirectory(Interpreter) if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD) add_subdirectory(libclang) endif() -add_subdirectory(DirectoryWatcher) +if (NOT APPLE) + add_subdirectory(DirectoryWatcher) +endif() add_subdirectory(Rename) add_subdirectory(Index) add_subdirectory(Serialization) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 62737735695f2d268a56fce1a00e0a632b9a8e44..c72f90709cb5ad3b7694e56ad9502111775c3e8f 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -116,7 +116,14 @@ if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*") string(REGEX MATCH "-target(=| +)[^ ]+android[a-z]*([0-9]+)" ANDROID_API_LEVEL "${CMAKE_C_FLAGS}") set(ANDROID_API_LEVEL ${CMAKE_MATCH_2}) endif() + +# We define OHOS for ohos targets for now +if (OHOS) + set(OHOS_FAMILY 1) +endif() + pythonize_bool(ANDROID) +pythonize_bool(OHOS_FAMILY) set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) @@ -127,7 +134,7 @@ pythonize_bool(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) # and target a UNIX-like system or Windows. # We can run tests on Android even when we are cross-compiling. if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID - OR COMPILER_RT_EMULATOR) + OR COMPILER_RT_EMULATOR OR OHOS) option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON) else() option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF) @@ -258,7 +265,7 @@ cmake_dependent_option(COMPILER_RT_STATIC_CXX_LIBRARY "COMPILER_RT_CXX_LIBRARY" OFF) set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF) -if (FUCHSIA) +if (FUCHSIA OR OHOS) set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY ON) endif() @@ -477,7 +484,9 @@ append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS) # TODO: We should consider using the same model as libc++, that is use either # -nostdlib++ and --unwindlib=none if supported, or -nodefaultlibs otherwise. append_list_if(C_SUPPORTS_NODEFAULTLIBS_FLAG -nodefaultlibs SANITIZER_COMMON_LINK_FLAGS) -append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS) +if (NOT __MIPS) + append_list_if(COMPILER_RT_HAS_Z_TEXT -Wl,-z,text SANITIZER_COMMON_LINK_FLAGS) +endif() # Only necessary for 32-bit SPARC. Solaris 11.2+ ld uses -z ignore/-z record # natively, but supports --as-needed/--no-as-needed for GNU ld compatibility. @@ -510,24 +519,9 @@ if (SANITIZER_NO_UNDEFINED_SYMBOLS) list(APPEND SANITIZER_COMMON_LINK_FLAGS -Wl,-z,defs) endif() -# TODO: COMPILER_RT_COMMON_CFLAGS and COMPILER_RT_COMMON_LINK_FLAGS are -# intended for use in non-sanitizer runtimes such as libFuzzer, profile or XRay, -# move these higher to include common flags, then derive SANITIZER_COMMON_CFLAGS -# and SANITIZER_COMMON_LINK_FLAGS from those and append sanitizer-specific flags. -set(COMPILER_RT_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -set(COMPILER_RT_COMMON_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) - -# We don't use the C++ standard library, so avoid including it by mistake. -append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ SANITIZER_COMMON_CFLAGS) -append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ SANITIZER_COMMON_LINK_FLAGS) - -# Remove -stdlib= which is unused when passing -nostdinc++... -string(REGEX MATCHALL "-stdlib=[a-zA-Z+]*" stdlib_flag "${CMAKE_CXX_FLAGS}") -string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - -# ...we need it to build some runtimes and tests so readd it where appropriate. -list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag}) -list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag}) +if (OHOS) + list(APPEND SANITIZER_COMMON_LINK_LIBS unwind) +endif() # TODO: There's a lot of duplication across lib/*/tests/CMakeLists.txt files, # move some of the common flags to COMPILER_RT_UNITTEST_CFLAGS. diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index 00bb892be595a225e44677e31b3af04d34e8bd81..c0adcbc0a3586d4e804914b94972c0d572982791 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -282,9 +282,6 @@ function(add_compiler_rt_runtime name type) NOT name STREQUAL "clang_rt.builtins") get_compiler_rt_target(${arch} target) find_compiler_rt_library(builtins builtins_${libname} TARGET ${target}) - if(builtins_${libname} STREQUAL "NOTFOUND") - message(FATAL_ERROR "Cannot find builtins library for the target architecture") - endif() endif() set(sources_${libname} ${LIB_SOURCES}) format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS}) diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake index a1da35b0ac4b586efe84ad970ad7e231c3bf4b42..4612e4d8b9af7d41a9ab925f52224e4263e7f4a9 100644 --- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake +++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake @@ -41,7 +41,7 @@ if(OS_NAME MATCHES "Linux") set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${S390X}) elseif (OS_NAME MATCHES "Windows") set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64}) -elseif(OS_NAME MATCHES "Android") +elseif(OS_NAME MATCHES "Android|OHOS") set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) else() set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index e322af89a0427139837e07bbfe8d15ef5cfe79e2..8675f5689b99fb6f9c271b56b4aec3579385c053 100644 --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -182,7 +182,7 @@ macro(detect_target_arch) elseif(__MIPS64) # must be checked before __MIPS add_default_target_arch(mips64) elseif(__MIPS) - add_default_target_arch(mips) + add_default_target_arch(mipsel) elseif(__PPC64) # must be checked before __PPC add_default_target_arch(powerpc64) elseif(__PPC64LE) @@ -497,7 +497,11 @@ endfunction() function(get_compiler_rt_install_dir arch install_dir) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) get_compiler_rt_target(${arch} target) - set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR}/${target} PARENT_SCOPE) + if(OHOS) + set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR}/${target}/${LLVM_TARGET_MULTILIB_SUFFIX} PARENT_SCOPE) + else() + set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR}/${target} PARENT_SCOPE) + endif() else() set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR} PARENT_SCOPE) endif() @@ -506,7 +510,11 @@ endfunction() function(get_compiler_rt_output_dir arch output_dir) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) get_compiler_rt_target(${arch} target) - set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR}/${target} PARENT_SCOPE) + if(OHOS) + set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR}/${target}/${LLVM_TARGET_MULTILIB_SUFFIX} PARENT_SCOPE) + else() + set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR}/${target} PARENT_SCOPE) + endif() else() set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR} PARENT_SCOPE) endif() diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake index 8a6219568b3f454dc8756bf605414d9b15c09d22..f61b962bdb248d64ccddf5bce85a6e6e2748fb0d 100644 --- a/compiler-rt/cmake/base-config-ix.cmake +++ b/compiler-rt/cmake/base-config-ix.cmake @@ -191,6 +191,9 @@ macro(test_targets) # Examine compiler output to determine target architecture. detect_target_arch() set(COMPILER_RT_OS_SUFFIX "-android") + elseif(OHOS) + detect_target_arch() + set(COMPILER_RT_OS_SUFFIX "") elseif(NOT APPLE) # Supported archs for Apple platforms are generated later if(COMPILER_RT_DEFAULT_TARGET_ONLY) add_default_target_arch(${COMPILER_RT_DEFAULT_TARGET_ARCH}) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index cd45176cf2ba761667793903daccd5f02b0e690c..a631ae4e86c334d605340753a17b03fdad8eba8b 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -61,6 +61,8 @@ if (C_SUPPORTS_NODEFAULTLIBS_FLAG) shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt) list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES}) + elseif (OHOS) + list(APPEND CMAKE_REQUIRED_LIBRARIES unwind) endif() endif () @@ -148,9 +150,13 @@ check_include_files("sys/auxv.h" COMPILER_RT_HAS_AUXV) # Libraries. check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL) -check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT) +if (NOT OHOS) + check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT) +endif() check_library_exists(m pow "" COMPILER_RT_HAS_LIBM) -check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD) +if (NOT OHOS) + check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD) +endif() check_library_exists(execinfo backtrace "" COMPILER_RT_HAS_LIBEXECINFO) # Look for terminfo library, used in unittests that depend on LLVMSupport. @@ -692,7 +698,7 @@ set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}") if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND - (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS" OR + (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS|OHOS" OR (OS_NAME MATCHES "Windows" AND NOT CYGWIN AND (NOT MINGW OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")))) set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE) @@ -712,7 +718,7 @@ else() set(COMPILER_RT_HAS_ASAN FALSE) endif() -if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS") +if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS|OHOS") set(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME TRUE) else() set(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME FALSE) @@ -742,7 +748,7 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND HWASAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android|Fuchsia") + OS_NAME MATCHES "Linux|Android|Fuchsia|OHOS") set(COMPILER_RT_HAS_HWASAN TRUE) else() set(COMPILER_RT_HAS_HWASAN FALSE) @@ -756,14 +762,14 @@ else() endif() if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|OHOS") set(COMPILER_RT_HAS_PROFILE TRUE) else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH) - if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD") + if (OS_NAME MATCHES "Linux|Darwin|FreeBSD|NetBSD|OHOS") set(COMPILER_RT_HAS_TSAN TRUE) elseif (OS_NAME MATCHES "Android" AND ANDROID_PLATFORM_LEVEL GREATER 23) set(COMPILER_RT_HAS_TSAN TRUE) @@ -781,14 +787,14 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS|OHOS") set(COMPILER_RT_HAS_UBSAN TRUE) else() set(COMPILER_RT_HAS_UBSAN FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|FreeBSD|NetBSD|Android|Darwin") + OS_NAME MATCHES "Linux|FreeBSD|NetBSD|Android|Darwin|OHOS") set(COMPILER_RT_HAS_UBSAN_MINIMAL TRUE) else() set(COMPILER_RT_HAS_UBSAN_MINIMAL FALSE) @@ -816,7 +822,7 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Fuchsia") + OS_NAME MATCHES "Linux|Fuchsia|OHOS") set(COMPILER_RT_HAS_SCUDO TRUE) else() set(COMPILER_RT_HAS_SCUDO FALSE) @@ -836,14 +842,14 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND FUZZER_SUPPORTED_ARCH AND - OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|FreeBSD|Fuchsia|Windows") + OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|FreeBSD|Fuchsia|Windows|OHOS") set(COMPILER_RT_HAS_FUZZER TRUE) else() set(COMPILER_RT_HAS_FUZZER FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND SHADOWCALLSTACK_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android") + OS_NAME MATCHES "Linux|Android|OHOS") set(COMPILER_RT_HAS_SHADOWCALLSTACK TRUE) else() set(COMPILER_RT_HAS_SHADOWCALLSTACK FALSE) diff --git a/compiler-rt/cmake/crt-config-ix.cmake b/compiler-rt/cmake/crt-config-ix.cmake index 78d1a0de1c8a7caab9d30cc8f445d5d8c485dfc0..f737e4eba82248617a989a9b1aadc102ad2d062e 100644 --- a/compiler-rt/cmake/crt-config-ix.cmake +++ b/compiler-rt/cmake/crt-config-ix.cmake @@ -30,7 +30,7 @@ set(RISCV64 riscv64) set(VE ve) set(ALL_CRT_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} - ${PPC64} ${RISCV32} ${RISCV64} ${VE} ${HEXAGON}) + ${PPC64} ${MIPS32} ${RISCV32} ${RISCV64} ${VE} ${HEXAGON}) include(CompilerRTUtils) @@ -43,7 +43,7 @@ if(NOT APPLE) message(STATUS "Supported architectures for crt: ${CRT_SUPPORTED_ARCH}") endif() -if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND NOT LLVM_USE_SANITIZER) +if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux|OHOS" AND NOT LLVM_USE_SANITIZER) set(COMPILER_RT_HAS_CRT TRUE) else() set(COMPILER_RT_HAS_CRT FALSE) diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h index 27d826fb613ae9f686804b0f8bddf420f8aa80d7..893aa834bb8cd08e29b807b1e28aaedcea6adf0c 100644 --- a/compiler-rt/lib/asan/asan_allocator.h +++ b/compiler-rt/lib/asan/asan_allocator.h @@ -126,7 +126,7 @@ typedef DefaultSizeClassMap SizeClassMap; const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x20000000000ULL; // 2T. typedef DefaultSizeClassMap SizeClassMap; -# elif defined(__aarch64__) && SANITIZER_ANDROID +#elif defined(__aarch64__) && (SANITIZER_ANDROID || SANITIZER_OHOS) // Android needs to support 39, 42 and 48 bit VMA. const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x2000000000ULL; // 128G. diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h index c6ac88f6dc2ae4204b8fa4b6b409ffe452aa30bb..df9868c6a38237f55417a865ddfa617e90085592 100644 --- a/compiler-rt/lib/asan/asan_errors.h +++ b/compiler-rt/lib/asan/asan_errors.h @@ -339,10 +339,13 @@ struct ErrorODRViolation : ErrorBase { ErrorODRViolation(u32 tid, const __asan_global *g1, u32 stack_id1_, const __asan_global *g2, u32 stack_id2_) : ErrorBase(tid, 10, "odr-violation"), - global1(*g1), - global2(*g2), stack_id1(stack_id1_), - stack_id2(stack_id2_) {} + stack_id2(stack_id2_) { + // HUAWEI: We must avoid memcpy intrinsic, because memory for g2 + // is poisoned. + internal_memcpy(&global1, g1, sizeof(*g1)); + internal_memcpy(&global2, g2, sizeof(*g2)); + } void Print(); }; diff --git a/compiler-rt/lib/asan/asan_fake_stack.cpp b/compiler-rt/lib/asan/asan_fake_stack.cpp index 74a039b6579856974d2cc359d28977e136cad6d2..d924427c508c688c58eb9d49f522a7b45acf807d 100644 --- a/compiler-rt/lib/asan/asan_fake_stack.cpp +++ b/compiler-rt/lib/asan/asan_fake_stack.cpp @@ -169,7 +169,8 @@ void FakeStack::ForEachFakeFrame(RangeIteratorCallback callback, void *arg) { } } -#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA +#if (SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS) || \ + SANITIZER_FUCHSIA static THREADLOCAL FakeStack *fake_stack_tls; FakeStack *GetTLSFakeStack() { diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 9c46f225116ee557d924dcaabaa4293d3d9975c3..b5c56251d2d461169243723e1f8d808b84a6c968 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -35,7 +35,7 @@ // If set, values like allocator chunk size, as well as defaults for some flags // will be changed towards less memory overhead. #ifndef ASAN_LOW_MEMORY -# if SANITIZER_IOS || SANITIZER_ANDROID +# if SANITIZER_IOS || SANITIZER_ANDROID || SANITIZER_OHOS # define ASAN_LOW_MEMORY 1 # else # define ASAN_LOW_MEMORY 0 diff --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp index 89450fc120a0411e5e799de79ac7105ee71ef74a..35682cdb52fba2494657eaea4507d3e4ae63102a 100644 --- a/compiler-rt/lib/asan/asan_linux.cpp +++ b/compiler-rt/lib/asan/asan_linux.cpp @@ -45,7 +45,8 @@ #include #endif -#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS +#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS || \ + SANITIZER_OHOS #include extern "C" void* _DYNAMIC; #elif SANITIZER_NETBSD @@ -121,7 +122,7 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) { ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size)); } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS // FIXME: should we do anything for Android? void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} @@ -208,7 +209,7 @@ void AsanCheckIncompatibleRT() { } #endif // SANITIZER_ANDROID -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS void ReadContextStack(void *context, uptr *stack, uptr *ssize) { ucontext_t *ucp = (ucontext_t*)context; *stack = (uptr)ucp->uc_stack.ss_sp; diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index a0c6d2910d6f8c4766e2a28665d7e8c160d6f13d..7bbe9c2a36e816c2750034b8d0078decef01bcca 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -168,8 +168,13 @@ function(add_asan_tests arch test_runtime) # selection. Each configuration expects the test binaries in a corresponding # subdirectory. Generate subdirectory names based on the architecture name. string(TOUPPER ${arch} ARCH_UPPER_CASE) - set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) - set(CONFIG_NAME_DYNAMIC ${ARCH_UPPER_CASE}${OS_NAME}DynamicConfig) + if (OHOS) + set(CONFIG_NAME default) + set(CONFIG_NAME_DYNAMIC dynamic) + else() + set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + set(CONFIG_NAME_DYNAMIC ${ARCH_UPPER_CASE}${OS_NAME}DynamicConfig) + endif() # Closure to keep the values. function(generate_asan_tests test_objects test_suite testname) diff --git a/compiler-rt/lib/asan/tests/asan_test.cpp b/compiler-rt/lib/asan/tests/asan_test.cpp index eb61410d768fe50885e9c2a52d30ff4a5181008d..e392ea90dbc2aa0f2b0d7ea2b946f85f7f0ba143 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_test.cpp @@ -1322,7 +1322,9 @@ TEST(AddressSanitizer, LongDoubleNegativeTest) { memcpy(Ident(&c), Ident(&b), sizeof(long double)); } -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__OHOS__) +// On OHOS/Musl sched_param is not int. +// See __interceptor_pthread_getschedparam TEST(AddressSanitizer, pthread_getschedparam) { int policy; struct sched_param param; diff --git a/compiler-rt/lib/builtins/divtf3.c b/compiler-rt/lib/builtins/divtf3.c index 5bcc9a8e4aa1843a5542aaae5a31abe1609797eb..809c5a4f4adb1b534e0ebd485c5af0dd607d71ff 100644 --- a/compiler-rt/lib/builtins/divtf3.c +++ b/compiler-rt/lib/builtins/divtf3.c @@ -16,7 +16,7 @@ #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -#define NUMBER_OF_HALF_ITERATIONS 4 +#define NUMBER_OF_HALF_ITERATIONS 5 #define NUMBER_OF_FULL_ITERATIONS 1 #include "fp_div_impl.inc" diff --git a/compiler-rt/lib/builtins/emutls.c b/compiler-rt/lib/builtins/emutls.c index 390ffb25f6cf00e640a1d27da3bbc836fc0bb8aa..8ff6c86427f56b15d3acf0054ac0c45d9ccea145 100644 --- a/compiler-rt/lib/builtins/emutls.c +++ b/compiler-rt/lib/builtins/emutls.c @@ -12,7 +12,7 @@ #include "int_lib.h" -#ifdef __BIONIC__ +#if defined(__BIONIC__) || defined(__OHOS__) // There are 4 pthread key cleanup rounds on Bionic. Delay emutls deallocation // to round 2. We need to delay deallocation because: // - Android versions older than M lack __cxa_thread_atexit_impl, so apps @@ -397,7 +397,7 @@ void *__emutls_get_address(__emutls_control *control) { return array->data[index]; } -#ifdef __BIONIC__ +#if defined(__BIONIC__) || defined(__OHOS__) // Called by Bionic on dlclose to delete the emutls pthread key. __attribute__((visibility("hidden"))) void __emutls_unregister_key(void) { if (emutls_key_created) { diff --git a/compiler-rt/lib/builtins/fp_div_impl.inc b/compiler-rt/lib/builtins/fp_div_impl.inc index 29bcd1920edfb4c5ec59f2e4201548b0339f217e..b49a6fd2bd73721a906bf8cc66addee777a45e70 100644 --- a/compiler-rt/lib/builtins/fp_div_impl.inc +++ b/compiler-rt/lib/builtins/fp_div_impl.inc @@ -325,7 +325,7 @@ static __inline fp_t __divXf3__(fp_t a, fp_t b) { #define RECIPROCAL_PRECISION REP_C(10) #elif defined(DOUBLE_PRECISION) && NUMBER_OF_HALF_ITERATIONS == 3 && NUMBER_OF_FULL_ITERATIONS == 1 #define RECIPROCAL_PRECISION REP_C(220) -#elif defined(QUAD_PRECISION) && NUMBER_OF_HALF_ITERATIONS == 4 && NUMBER_OF_FULL_ITERATIONS == 1 +#elif defined(QUAD_PRECISION) && NUMBER_OF_HALF_ITERATIONS == 5 && NUMBER_OF_FULL_ITERATIONS == 1 #define RECIPROCAL_PRECISION REP_C(13922) #else #error Invalid number of iterations diff --git a/compiler-rt/lib/builtins/int_util.h b/compiler-rt/lib/builtins/int_util.h index c372c2edc637137d28926ad9af948f31766907ba..32b66732f8f7514391b6b7ce0dc6f6f4e78045da 100644 --- a/compiler-rt/lib/builtins/int_util.h +++ b/compiler-rt/lib/builtins/int_util.h @@ -40,6 +40,9 @@ NORETURN void __compilerrt_abort_impl(const char *file, int line, #define REPEAT_4_TIMES(code_to_repeat) \ REPEAT_3_TIMES(code_to_repeat) \ code_to_repeat +#define REPEAT_5_TIMES(code_to_repeat) \ + REPEAT_4_TIMES(code_to_repeat) \ + code_to_repeat #define REPEAT_N_TIMES_(N, code_to_repeat) REPEAT_##N##_TIMES(code_to_repeat) #define REPEAT_N_TIMES(N, code_to_repeat) REPEAT_N_TIMES_(N, code_to_repeat) diff --git a/compiler-rt/lib/cfi/CMakeLists.txt b/compiler-rt/lib/cfi/CMakeLists.txt index 2197fa4a5c758d8da9c856ba7a6bbfd83556a6d3..cf8479d39c25e09a0fbdac54ea9b029d28d717ae 100644 --- a/compiler-rt/lib/cfi/CMakeLists.txt +++ b/compiler-rt/lib/cfi/CMakeLists.txt @@ -1,6 +1,6 @@ add_compiler_rt_component(cfi) -if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetBSD") +if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetBSD" OR OS_NAME MATCHES "OHOS") set(CFI_SOURCES cfi.cpp ) diff --git a/compiler-rt/lib/fuzzer/CMakeLists.txt b/compiler-rt/lib/fuzzer/CMakeLists.txt index a9a10f724d1aa353ed52fdef17cc6c349429d712..a0532c838c27abf954e6123e6a960858bdbcd73b 100644 --- a/compiler-rt/lib/fuzzer/CMakeLists.txt +++ b/compiler-rt/lib/fuzzer/CMakeLists.txt @@ -147,7 +147,7 @@ if(OS_NAME MATCHES "Linux|Fuchsia" AND set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD - COMMAND ${CMAKE_CXX_COMPILER} ${target_cflags} -Wl,--whole-archive "$" -Wl,--no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o + COMMAND ${CMAKE_CXX_COMPILER} ${target_cflags} -Wl,--whole-archive "$" -Wl,--no-whole-archive ${dir}/lib/libc++.a -nodefaultlibs -r -o ${name}.o COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o COMMAND ${CMAKE_COMMAND} -E remove "$" COMMAND ${CMAKE_AR} qcs "$" ${name}.o diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp index b771025cb93d319183e26e619182c0aa5e44ca1e..235aa73740af811a8d25785f087179835fb08100 100644 --- a/compiler-rt/lib/hwasan/hwasan.cpp +++ b/compiler-rt/lib/hwasan/hwasan.cpp @@ -83,7 +83,7 @@ static void InitializeFlags() { cf.intercept_tls_get_addr = true; cf.exitcode = 99; // 8 shadow pages ~512kB, small enough to cover common stack sizes. - cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8); + cf.clear_shadow_mmap_threshold = 4096 * ((SANITIZER_ANDROID) ? 2 : 8); // Sigtrap is used in error reporting. cf.handle_sigtrap = kHandleSignalExclusive; diff --git a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp index 7642ba6c0bf08fddee2f820a2b4016b6deec0488..bf69694a5476277e0f1e02ecfa002c6f10451f56 100644 --- a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp +++ b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp @@ -26,7 +26,7 @@ // The code in this file needs to run in an unrelocated binary. It should not // access any external symbol, including its own non-hidden globals. -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS extern "C" { INTERFACE_ATTRIBUTE void __hwasan_shadow(); diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h index d97974ee9074e9eb16a9dc8ae6abce3e23d12614..1acfe19dc8b6b0c9dc3175b08794041807eab49d 100644 --- a/compiler-rt/lib/interception/interception.h +++ b/compiler-rt/lib/interception/interception.h @@ -18,7 +18,7 @@ #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \ !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \ - !SANITIZER_SOLARIS + !SANITIZER_SOLARIS && !SANITIZER_OHOS # error "Interception doesn't work on this operating system." #endif diff --git a/compiler-rt/lib/interception/interception_type_test.cpp b/compiler-rt/lib/interception/interception_type_test.cpp index 2a118fb214fffee8ef568f2034fc83d4ea46b8d7..0146b2b34f0a25c9b2fcdeda50424c9d1e7e0ace 100644 --- a/compiler-rt/lib/interception/interception_type_test.cpp +++ b/compiler-rt/lib/interception/interception_type_test.cpp @@ -31,8 +31,8 @@ COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t)); // The following are the cases when pread (and friends) is used instead of // pread64. In those cases we need OFF_T to match off_t. We don't care about the // rest (they depend on _FILE_OFFSET_BITS setting when building an application). -# if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \ - _FILE_OFFSET_BITS != 64 +#if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \ + _FILE_OFFSET_BITS != 64 || SANITIZER_OHOS COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t)); # endif diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index d7153751faee0fe33c519df24a4973d3056b825c..2fc038b8fd14a2aedd2adc9e1700eaaad12f0e47 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -32,7 +32,8 @@ // the new architecture inside the sanitizer library. // Exclude leak-detection on arm32 for Android because `__aeabi_read_tp` // is missing. This caused a link error. -#if SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__)) +#if SANITIZER_OHOS || \ + (SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__))) # define CAN_SANITIZE_LEAKS 0 #elif (SANITIZER_LINUX || SANITIZER_APPLE) && (SANITIZER_WORDSIZE == 64) && \ (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \ diff --git a/compiler-rt/lib/orc/endianness.h b/compiler-rt/lib/orc/endianness.h index 4ee5505ce6ddf167329d5dfb1f4b2c6ac3232e66..a8e55629a6be32a8d332eac056348adf52b33a25 100644 --- a/compiler-rt/lib/orc/endianness.h +++ b/compiler-rt/lib/orc/endianness.h @@ -22,7 +22,8 @@ #endif #if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \ - defined(__Fuchsia__) || defined(__EMSCRIPTEN__) + defined(__Fuchsia__) || defined(__EMSCRIPTEN__) || \ + defined(__OHOS_FAMILY__) #include #elif defined(_AIX) #include diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index b29665a633907de5f26591e18395c191f0ac6857..507c181f0526103dba0602fa289d917bc7d30125 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2276,11 +2276,13 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) { #if SANITIZER_GLIBC namespace __sanitizer { extern "C" { +#if !SANITIZER_OHOS int real_clock_gettime(u32 clk_id, void *tp) { if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) return internal_clock_gettime(clk_id, tp); return REAL(clock_gettime)(clk_id, tp); } +#endif } // extern "C" } // namespace __sanitizer #endif @@ -2666,7 +2668,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) { } return res; } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage); @@ -3973,7 +3975,7 @@ INTERCEPTOR(char *, strerror, int errnum) { // static storage. #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \ SANITIZER_APPLE || SANITIZER_ANDROID || SANITIZER_NETBSD || \ - SANITIZER_FREEBSD + SANITIZER_FREEBSD || SANITIZER_OHOS // POSIX version. Spec is not clear on whether buf is NULL-terminated. // At least on OSX, buf contents are valid even when the call fails. INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc index 49ec4097c900bd7fd23efaa7ac3bf32438d67ee8..17ac1af2431cb8a8999678b170835f32c21b1145 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc @@ -98,7 +98,7 @@ static void ioctl_table_fill() { _(SIOCSIFNETMASK, READ, struct_ifreq_sz); #endif -#if (SANITIZER_LINUX && !SANITIZER_ANDROID) +# if (SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS) _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz); _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index a38b134085aabde4e4d589bc98de222f0fc297e5..7e7628ea0c1cb970b3285a3a2d3538f6f89bd5b1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -2509,7 +2509,7 @@ PRE_SYSCALL(ni_syscall)() {} POST_SYSCALL(ni_syscall)(long res) {} PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { -# if !SANITIZER_ANDROID && \ +# if !SANITIZER_ANDROID && !SANITIZER_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ SANITIZER_RISCV64) @@ -2531,7 +2531,7 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { } POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) { -# if !SANITIZER_ANDROID && \ +# if !SANITIZER_ANDROID && !SANITIZER_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ SANITIZER_RISCV64) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index 6148ae56067cae03e7094070062f5ec083454565..509bcf6afd1af8dc6f0c5b0376aed036e2749c24 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -62,7 +62,7 @@ COMMON_FLAG( COMMON_FLAG(const char *, log_suffix, nullptr, "String to append to log file name, e.g. \".txt\".") COMMON_FLAG( - bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE, + bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_OHOS || (bool)SANITIZER_APPLE, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( @@ -242,13 +242,13 @@ COMMON_FLAG(bool, intercept_stat, true, COMMON_FLAG(bool, intercept_send, true, "If set, uses custom wrappers for send* functions " "to find more errors.") -COMMON_FLAG(bool, decorate_proc_maps, (bool)SANITIZER_ANDROID, +COMMON_FLAG(bool, decorate_proc_maps, (bool)SANITIZER_ANDROID || (bool)SANITIZER_OHOS, "If set, decorate sanitizer mappings in /proc/self/maps with " "user-readable names") COMMON_FLAG(int, exitcode, 1, "Override the program exit status if the tool " "found an error") COMMON_FLAG( - bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE, + bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_OHOS || (bool)SANITIZER_APPLE, "If set, the tool calls abort() instead of _exit() after printing the " "error report.") COMMON_FLAG(bool, suppress_equal_pcs, true, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index 15738ff1e1bcbda31cf87ec3357bf715fad52d2d..00c0a5b0bbc393a40715acdb18ec783bfa60339d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -104,7 +104,7 @@ // // FIXME: do we have anything like this on Mac? #ifndef SANITIZER_CAN_USE_PREINIT_ARRAY -#if (SANITIZER_LINUX || SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC) +#if ((SANITIZER_LINUX && !SANITIZER_OHOS) || SANITIZER_FUCHSIA || SANITIZER_NETBSD) && !defined(PIC) #define SANITIZER_CAN_USE_PREINIT_ARRAY 1 // Before Solaris 11.4, .preinit_array is fully supported only with GNU ld. // FIXME: Check for those conditions. @@ -177,7 +177,8 @@ typedef long pid_t; typedef int pid_t; #endif -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_APPLE || \ +#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_APPLE || \ + SANITIZER_OHOS || \ (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \ (SANITIZER_LINUX && !SANITIZER_GLIBC && !SANITIZER_ANDROID) || \ (SANITIZER_LINUX && (defined(__x86_64__) || defined(__hexagon__))) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index dc2ea933fadc710916d4bdcfd41a03bd6b3dec0f..f03ef2562033f78452f64eae697fa20cbe3a52d8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -34,7 +34,7 @@ // format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To // access stat from asm/stat.h, without conflicting with definition in // sys/stat.h, we use this trick. -#if SANITIZER_MIPS64 +#if SANITIZER_MIPS64 || SANITIZER_RISCV64 #include #include #define stat kernel_stat @@ -49,7 +49,6 @@ #include #undef stat #endif - #include #include #include @@ -74,7 +73,7 @@ #include #endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS #include #endif @@ -163,7 +162,7 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *old) { ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) { __sanitizer_sigset_t set; internal_sigfillset(&set); -# if SANITIZER_LINUX && !SANITIZER_ANDROID +# if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked // on any thread, setuid call hangs. // See test/sanitizer_common/TestCases/Linux/setuid.c. @@ -277,7 +276,9 @@ uptr internal_ftruncate(fd_t fd, uptr size) { return res; } -#if (!SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_SPARC) && SANITIZER_LINUX +# if (!SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_SPARC || \ + SANITIZER_OHOS) && \ + SANITIZER_LINUX static void stat64_to_stat(struct stat64 *in, struct stat *out) { internal_memset(out, 0, sizeof(*out)); out->st_dev = in->st_dev; @@ -378,18 +379,19 @@ uptr internal_stat(const char *path, void *buf) { AT_NO_AUTOMOUNT, STATX_BASIC_STATS, (uptr)&bufx); statx_to_stat(&bufx, (struct stat *)buf); return res; -# elif (SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \ - (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \ - !SANITIZER_SPARC +# elif ( \ + SANITIZER_WORDSIZE == 64 || SANITIZER_X32 || \ + (defined(__mips__) && _MIPS_SIM == _ABIN32 && !SANITIZER_OHOS)) && \ + !SANITIZER_SPARC return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); -# else +# else struct stat64 buf64; int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path, (uptr)&buf64, 0); stat64_to_stat(&buf64, (struct stat *)buf); return res; -# endif +# endif # else struct stat64 buf64; int res = internal_syscall(SYSCALL(stat64), path, &buf64); @@ -410,18 +412,19 @@ uptr internal_lstat(const char *path, void *buf) { STATX_BASIC_STATS, (uptr)&bufx); statx_to_stat(&bufx, (struct stat *)buf); return res; -# elif (defined(_LP64) || SANITIZER_X32 || \ - (defined(__mips__) && _MIPS_SIM == _ABIN32)) && \ - !SANITIZER_SPARC +# elif ( \ + defined(_LP64) || SANITIZER_X32 || \ + (defined(__mips__) && _MIPS_SIM == _ABIN32 && !SANITIZER_OHOS)) && \ + !SANITIZER_SPARC return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); -# else +# else struct stat64 buf64; int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path, (uptr)&buf64, AT_SYMLINK_NOFOLLOW); stat64_to_stat(&buf64, (struct stat *)buf); return res; -# endif +# endif # else struct stat64 buf64; int res = internal_syscall(SYSCALL(lstat64), path, &buf64); @@ -895,7 +898,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { // rt_sigaction, so we need to do the same (we'll need to reimplement the // restorers; for x86_64 the restorer address can be obtained from // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact). -#if !SANITIZER_ANDROID || !SANITIZER_MIPS32 +#if (!SANITIZER_ANDROID && !SANITIZER_OHOS) || !SANITIZER_MIPS32 k_act.sa_restorer = u_act->sa_restorer; #endif } @@ -911,7 +914,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask, sizeof(__sanitizer_kernel_sigset_t)); u_oldact->sa_flags = k_oldact.sa_flags; -#if !SANITIZER_ANDROID || !SANITIZER_MIPS32 +#if (!SANITIZER_ANDROID && !SANITIZER_OHOS) || !SANITIZER_MIPS32 u_oldact->sa_restorer = k_oldact.sa_restorer; #endif } @@ -1081,7 +1084,7 @@ static uptr GetKernelAreaSize() { if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0; } -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS // Even if nothing is mapped, top Gb may still be accessible // if we are running on 64-bit kernel. // Uname may report misleading results if personality type diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index 761c57d1b8eb8802c50da49a1bb3c7e9e7b03bac..1b1b98fe4989d23a3e890ed022b00a11917a7c4b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -134,7 +134,7 @@ inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { ReleaseMemoryPagesToOS(beg, end); } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS #if defined(__aarch64__) # define __get_tls() \ @@ -152,6 +152,9 @@ inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { "rdhwr %0,$29\n" \ ".set pop\n" : "=r"(__v)); \ __v; }) +#elif defined(__riscv) +# define __get_tls() \ + ({ void** __v; __asm__("mv %0, tp" : "=r"(__v)); __v; }) #elif defined(__i386__) # define __get_tls() \ ({ void** __v; __asm__("movl %%gs:0, %0" : "=r"(__v)); __v; }) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index d74851c43e14e2627d596ee59ce5062f0b348b29..9032962b7f9e93e33468c9c1cda41ba55e6be9cc 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -82,7 +82,7 @@ struct __sanitizer::linux_dirent { #endif #endif -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS #include #include #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 32005eef08cd5ed3e12d5199cd5383570862cccc..9469f0587f7f4de8ecc7629f2580b5d5b8a08fe9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -14,7 +14,7 @@ #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \ - !(defined(__sun__) && defined(__svr4__)) + !defined(__OHOS_FAMILY__) && !(defined(__sun__) && defined(__svr4__)) # error "This operating system is not supported" #endif @@ -123,6 +123,12 @@ # define SANITIZER_ANDROID 0 #endif +#if defined(__OHOS__) +#define SANITIZER_OHOS 1 +#else +#define SANITIZER_OHOS 0 +#endif + #if defined(__Fuchsia__) # define SANITIZER_FUCHSIA 1 #else @@ -284,7 +290,8 @@ // For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or // change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here. #ifndef SANITIZER_CAN_USE_ALLOCATOR64 -# if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA +# if ((SANITIZER_ANDROID || SANITIZER_OHOS) && defined(__aarch64__)) || \ + SANITIZER_FUCHSIA # define SANITIZER_CAN_USE_ALLOCATOR64 1 # elif defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \ defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__) @@ -435,7 +442,9 @@ # endif #endif -#if defined(__thumb__) && defined(__linux__) +// HUAWEI: musl seems to not respect static ctor order and we start +// background thread before parsing flags. FIXME +#if (defined(__thumb__) && defined(__linux__)) || SANITIZER_OHOS // Workaround for // https://lab.llvm.org/buildbot/#/builders/clang-thumbv7-full-2stage // or diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index ffa7e272b7e0195eb392fa3de5071b5e13686779..b78534e8fc4210c103cf6a8974df165abe7346aa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -58,6 +58,12 @@ #define SI_ANDROID 0 #endif +#if SANITIZER_OHOS +#define SI_OHOS 1 +#else +#define SI_OHOS 0 +#endif + #if SANITIZER_FREEBSD #define SI_FREEBSD 1 #else @@ -270,7 +276,7 @@ #define SANITIZER_INTERCEPT_SYSINFO SI_LINUX #define SANITIZER_INTERCEPT_READDIR SI_POSIX #define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 -#if SI_LINUX_NOT_ANDROID && \ +#if SI_LINUX_NOT_ANDROID && !SI_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ defined(__s390__) || SANITIZER_RISCV64) @@ -340,7 +346,7 @@ (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID) #define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID) #define SANITIZER_INTERCEPT_SHMCTL \ - (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \ + (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && !SI_OHOS && SANITIZER_WORDSIZE == 64) || \ SI_NETBSD || SI_SOLARIS) #define SANITIZER_INTERCEPT_RANDOM_R SI_GLIBC #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX @@ -405,7 +411,7 @@ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) #define SANITIZER_INTERCEPT_TLS_GET_ADDR \ - (SI_FREEBSD || SI_NETBSD || SI_LINUX_NOT_ANDROID || SI_SOLARIS) + (SI_FREEBSD || SI_NETBSD || (SI_LINUX_NOT_ANDROID && !SI_OHOS) || SI_SOLARIS) #define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX #define SANITIZER_INTERCEPT_GETXATTR SI_LINUX @@ -466,7 +472,7 @@ #define SI_STAT_LINUX (SI_LINUX && __GLIBC_PREREQ(2, 33)) #define SANITIZER_INTERCEPT_STAT \ (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || \ - SI_STAT_LINUX) + SI_STAT_LINUX || SI_OHOS) #define SANITIZER_INTERCEPT_STAT64 SI_STAT_LINUX && SANITIZER_HAS_STAT64 #define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD || SI_STAT_LINUX) #define SANITIZER_INTERCEPT___XSTAT \ @@ -497,7 +503,7 @@ #define SANITIZER_INTERCEPT_WCSCAT SI_POSIX #define SANITIZER_INTERCEPT_WCSDUP SI_POSIX #define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA) -#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID +#define SANITIZER_INTERCEPT_BSD_SIGNAL (SI_ANDROID || SI_OHOS) #define SANITIZER_INTERCEPT_ACCT (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_USER_FROM_UID SI_NETBSD @@ -509,7 +515,7 @@ #define SANITIZER_INTERCEPT_GETGROUPLIST \ (SI_NETBSD || SI_FREEBSD || SI_LINUX) #define SANITIZER_INTERCEPT_STRLCPY \ - (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID) + (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID || SI_OHOS) #define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX_NOT_ANDROID diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp index bf0f355847cb13332fac82fb756fe2afa068991a..6d608cbb63ed6ab9623e39f451f105e5d80f635e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp @@ -76,7 +76,7 @@ CHECK_SIZE_AND_OFFSET(io_event, obj); CHECK_SIZE_AND_OFFSET(io_event, res); CHECK_SIZE_AND_OFFSET(io_event, res2); -#if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID && !SANITIZER_OHOS COMPILER_CHECK(sizeof(struct __sanitizer_perf_event_attr) <= sizeof(struct perf_event_attr)); CHECK_SIZE_AND_OFFSET(perf_event_attr, type); @@ -85,7 +85,7 @@ CHECK_SIZE_AND_OFFSET(perf_event_attr, size); COMPILER_CHECK(iocb_cmd_pread == IOCB_CMD_PREAD); COMPILER_CHECK(iocb_cmd_pwrite == IOCB_CMD_PWRITE); -#if !SANITIZER_ANDROID +# if !SANITIZER_ANDROID && !SANITIZER_OHOS COMPILER_CHECK(iocb_cmd_preadv == IOCB_CMD_PREADV); COMPILER_CHECK(iocb_cmd_pwritev == IOCB_CMD_PWRITEV); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index c85cf1626a75b1b0d43fc6f3026e3b87fb6bcb15..839d31a8b75ca518fd09124bb8632af7f3eb07f6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -69,7 +69,9 @@ #include #include #include +#if !SANITIZER_OHOS #include +#endif #include #include #include @@ -93,6 +95,13 @@ #if SANITIZER_LINUX # include # include +# if SANITIZER_OHOS +// Do not include asm/sigcontext.h on behalf of asm/ptrace.h +// to avoid multiple definiton errors. +# define __ASM_SIGCONTEXT_H 1 +# include +# endif + # if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \ defined(__hexagon__) || SANITIZER_RISCV64 # include @@ -133,6 +142,13 @@ typedef struct user_fpregs elf_fpregset_t; #if SANITIZER_ANDROID #include +#elif SANITIZER_OHOS +#include +#include +#include +#include +#include +#include #else #include #include @@ -303,7 +319,6 @@ namespace __sanitizer { int e_tabsz = (int)E_TABSZ; #endif - #if SANITIZER_LINUX && !SANITIZER_ANDROID unsigned struct_shminfo_sz = sizeof(struct shminfo); unsigned struct_shm_info_sz = sizeof(struct shm_info); @@ -521,7 +536,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats); #endif // SANITIZER_GLIBC -#if !SANITIZER_ANDROID && !SANITIZER_APPLE +#if !SANITIZER_ANDROID && !SANITIZER_APPLE && !SANITIZER_OHOS unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req); unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req); #endif @@ -574,7 +589,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_TIOCSPGRP = TIOCSPGRP; unsigned IOCTL_TIOCSTI = TIOCSTI; unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT; unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT; #endif @@ -866,7 +881,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE; #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE; unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE; unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG; @@ -950,7 +965,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL; #endif // SANITIZER_LINUX && !SANITIZER_ANDROID -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP; unsigned IOCTL_KDDISABIO = KDDISABIO; unsigned IOCTL_KDENABIO = KDENABIO; @@ -1118,7 +1133,8 @@ CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask); // didn't exist. CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags); #endif -#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32) +#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32) && \ + !SANITIZER_OHOS CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer); #endif @@ -1212,7 +1228,7 @@ CHECK_TYPE_SIZE(clock_t); CHECK_TYPE_SIZE(clockid_t); #endif -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS CHECK_TYPE_SIZE(ifaddrs); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index bd5692ed511b2970bdac0efbb4954cdbdad3c164..a13117a330ec668c4965c2bf5504cbd27f152e8b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -98,6 +98,9 @@ const unsigned struct_kernel_stat64_sz = 104; const unsigned struct_kernel_stat_sz = 144; const unsigned struct_kernel_stat64_sz = 104; #elif defined(__mips__) +# if SANITIZER_OHOS +# define _ABIN32 1 +# endif const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID ? FIRST_32_SECOND_64(104, 128) @@ -212,13 +215,15 @@ struct __sanitizer_struct_mallinfo { #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID -struct __sanitizer_struct_mallinfo { - int v[10]; -}; - extern unsigned struct_ustat_sz; extern unsigned struct_rlimit64_sz; extern unsigned struct_statvfs64_sz; +#endif + +#if SANITIZER_LINUX && !SANITIZER_ANDROID +struct __sanitizer_struct_mallinfo { + int v[10]; +}; struct __sanitizer_ipc_perm { int __key; @@ -617,7 +622,7 @@ struct __sanitizer_sigaction { }; __sanitizer_sigset_t sa_mask; }; -#elif SANITIZER_ANDROID && (SANITIZER_WORDSIZE == 32) +# elif (SANITIZER_ANDROID || SANITIZER_OHOS) && (SANITIZER_WORDSIZE == 32) struct __sanitizer_sigaction { union { __sanitizer_sigactionhandler_ptr sigaction; @@ -627,59 +632,59 @@ struct __sanitizer_sigaction { uptr sa_flags; void (*sa_restorer)(); }; -#else // !SANITIZER_ANDROID +# else // !SANITIZER_ANDROID struct __sanitizer_sigaction { -#if defined(__mips__) && !SANITIZER_FREEBSD +# if defined(__mips__) && !SANITIZER_FREEBSD unsigned int sa_flags; -#endif +# endif union { __sanitizer_sigactionhandler_ptr sigaction; __sanitizer_sighandler_ptr handler; }; -#if SANITIZER_FREEBSD +# if SANITIZER_FREEBSD int sa_flags; __sanitizer_sigset_t sa_mask; -#else -#if defined(__s390x__) +# else +# if defined(__s390x__) int sa_resv; -#else +# else __sanitizer_sigset_t sa_mask; -#endif -#ifndef __mips__ -#if defined(__sparc__) -#if __GLIBC_PREREQ (2, 20) +# endif +# ifndef __mips__ +# if defined(__sparc__) +# if __GLIBC_PREREQ(2, 20) // On sparc glibc 2.19 and earlier sa_flags was unsigned long. -#if defined(__arch64__) +# if defined(__arch64__) // To maintain ABI compatibility on sparc64 when switching to an int, // __glibc_reserved0 was added. int __glibc_reserved0; -#endif +# endif int sa_flags; -#else +# else unsigned long sa_flags; -#endif -#else +# endif +# else int sa_flags; -#endif -#endif -#endif -#if SANITIZER_LINUX +# endif +# endif +# endif +# if SANITIZER_LINUX void (*sa_restorer)(); -#endif -#if defined(__mips__) && (SANITIZER_WORDSIZE == 32) +# endif +# if defined(__mips__) && (SANITIZER_WORDSIZE == 32) int sa_resv[1]; -#endif -#if defined(__s390x__) +# endif +# if defined(__s390x__) __sanitizer_sigset_t sa_mask; -#endif +# endif }; -#endif // !SANITIZER_ANDROID +# endif // !SANITIZER_ANDROID -#if defined(__mips__) -#define __SANITIZER_KERNEL_NSIG 128 -#else -#define __SANITIZER_KERNEL_NSIG 64 -#endif +# if defined(__mips__) +# define __SANITIZER_KERNEL_NSIG 128 +# else +# define __SANITIZER_KERNEL_NSIG 64 +# endif struct __sanitizer_kernel_sigset_t { uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)]; @@ -816,7 +821,7 @@ struct __sanitizer_wordexp_t { uptr we_offs; }; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS struct __sanitizer_FILE { int _flags; char *_IO_read_ptr; @@ -840,7 +845,7 @@ typedef void __sanitizer_FILE; # define SANITIZER_HAS_STRUCT_FILE 0 #endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID && \ +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ defined(__s390__) || SANITIZER_RISCV64) @@ -1018,7 +1023,7 @@ extern unsigned struct_synth_info_sz; extern unsigned struct_vt_mode_sz; #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS extern unsigned struct_ax25_parms_struct_sz; extern unsigned struct_input_keymap_entry_sz; extern unsigned struct_ipx_config_data_sz; @@ -1044,7 +1049,7 @@ extern unsigned struct_audio_buf_info_sz; extern unsigned struct_ppp_stats_sz; #endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID -#if !SANITIZER_ANDROID && !SANITIZER_APPLE +#if !SANITIZER_ANDROID && !SANITIZER_APPLE && !SANITIZER_OHOS extern unsigned struct_sioc_sg_req_sz; extern unsigned struct_sioc_vif_req_sz; #endif @@ -1099,7 +1104,7 @@ extern unsigned IOCTL_TIOCSETD; extern unsigned IOCTL_TIOCSPGRP; extern unsigned IOCTL_TIOCSTI; extern unsigned IOCTL_TIOCSWINSZ; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS extern unsigned IOCTL_SIOCGETSGCNT; extern unsigned IOCTL_SIOCGETVIFCNT; #endif @@ -1371,7 +1376,16 @@ extern unsigned IOCTL_VT_SETMODE; extern unsigned IOCTL_VT_WAITACTIVE; #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS +extern unsigned IOCTL_CYGETDEFTHRESH; +extern unsigned IOCTL_CYGETDEFTIMEOUT; +extern unsigned IOCTL_CYGETMON; +extern unsigned IOCTL_CYGETTHRESH; +extern unsigned IOCTL_CYGETTIMEOUT; +extern unsigned IOCTL_CYSETDEFTHRESH; +extern unsigned IOCTL_CYSETDEFTIMEOUT; +extern unsigned IOCTL_CYSETTHRESH; +extern unsigned IOCTL_CYSETTIMEOUT; extern unsigned IOCTL_EQL_EMANCIPATE; extern unsigned IOCTL_EQL_ENSLAVE; extern unsigned IOCTL_EQL_GETMASTRCFG; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp index b0e32b50c0764e53cb2cc9c3bc33aa34992081e7..87d2d717de3ab88b8a5a1aa57fb6d5a134f58ac8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp @@ -344,7 +344,7 @@ bool ShouldMockFailureToOpen(const char *path) { internal_strncmp(path, "/proc/", 6) == 0; } -#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO && !SANITIZER_OHOS int GetNamedMappingFd(const char *name, uptr size, int *flags) { if (!common_flags()->decorate_proc_maps || !name) return -1; @@ -376,7 +376,7 @@ int GetNamedMappingFd(const char *name, uptr size, int *flags) { } #endif -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS #define PR_SET_VMA 0x53564d41 #define PR_SET_VMA_ANON_NAME 0 void DecorateMapping(uptr addr, uptr size, const char *name) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp index 46e41c669738cd3833cac3605c7efb883a5c9d67..ec874e50adc446e41de36e7622677fdc011ac59f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -171,7 +171,8 @@ void SetAlternateSignalStack() { CHECK_EQ(0, sigaltstack(nullptr, &oldstack)); // If the alternate stack is already in place, do nothing. // Android always sets an alternate stack, but it's too small for us. - if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return; + if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) + return; // TODO(glider): the mapped stack should have the MAP_STACK flag in the // future. It is not required by man 2 sigaltstack now (they're using // malloc()). diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp index a746d4621936c62555caa89efcf533804f4716d7..590348fd67ad2e86a0a1eec636008d47389f75fe 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp @@ -27,7 +27,7 @@ struct StackDepotNode { u32 link; StackStore::Id store_id; - static const u32 kTabSizeLog = SANITIZER_ANDROID ? 16 : 20; + static const u32 kTabSizeLog = (SANITIZER_ANDROID || SANITIZER_OHOS) ? 16 : 20; typedef StackTrace args_type; bool eq(hash_type hash, const args_type &args) const { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h index cca6fd53468839c63d40e22e7b49ce182406c341..91b93a1b937ee53bf8171c59d42fe0e547cc8a25 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h @@ -31,7 +31,8 @@ struct StackDepotHandle { void inc_use_count_unsafe(); }; -const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20); +const int kStackDepotMaxUseCount = + 1U << ((SANITIZER_ANDROID || SANITIZER_OHOS) ? 16 : 20); StackDepotStats StackDepotGetStats(); u32 StackDepotPut(StackTrace stack); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp index d24fae98213aa4daa15868afe06d432dcda91417..937afb1645d0f8dd2067f46f735443bfdb623afe 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cpp @@ -149,6 +149,11 @@ void BufferedStackTrace::UnwindFast(uptr pc, uptr bp, uptr stack_top, #endif // !defined(__sparc__) void BufferedStackTrace::PopStackFrames(uptr count) { + // HUAWEI: Don't atempt to pop if stack unwinding failed + // this may happen at the aearly stage of ASAN initialization + // (e.g malloc called from __dl_vseterr) + if (count == 0) + return; CHECK_LT(count, size); size -= count; for (uptr i = 0; i < size; ++i) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp index 403bda1174cc46b7a9998e26be388c2173e93850..556fdfaaa89e9e9c609f8cc0cbf44ea23debceca 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp @@ -33,28 +33,33 @@ #include // for NT_PRSTATUS #if (defined(__aarch64__) || SANITIZER_RISCV64) && !SANITIZER_ANDROID // GLIBC 2.20+ sys/user does not include asm/ptrace.h +#if SANITIZER_OHOS +// Do not include asm/sigcontext.h on behalf of asm/ptrace.h +// to avoid multiple definiton errors. +#define __ASM_SIGCONTEXT_H 1 +#endif # include #endif #include // for user_regs_struct -#if SANITIZER_ANDROID && SANITIZER_MIPS -# include // for mips SP register in sys/user.h -#endif -#include // for signal-related stuff - -#ifdef sa_handler -# undef sa_handler -#endif - -#ifdef sa_sigaction -# undef sa_sigaction -#endif - -#include "sanitizer_common.h" -#include "sanitizer_flags.h" -#include "sanitizer_libc.h" -#include "sanitizer_linux.h" -#include "sanitizer_mutex.h" -#include "sanitizer_placement_new.h" +# if (SANITIZER_ANDROID || SANITIZER_OHOS) && SANITIZER_MIPS +# include // for mips SP register in sys/user.h +# endif +# include // for signal-related stuff + +# ifdef sa_handler +# undef sa_handler +# endif + +# ifdef sa_sigaction +# undef sa_sigaction +# endif + +# include "sanitizer_common.h" +# include "sanitizer_flags.h" +# include "sanitizer_libc.h" +# include "sanitizer_linux.h" +# include "sanitizer_mutex.h" +# include "sanitizer_placement_new.h" // Sufficiently old kernel headers don't provide this value, but we can still // call prctl with it. If the runtime kernel is new enough, the prctl call will @@ -504,9 +509,14 @@ typedef pt_regs regs_struct; typedef struct user regs_struct; # if SANITIZER_ANDROID # define REG_SP regs[EF_R29] -# else -# define REG_SP regs[EF_REG29] -# endif +// FIXME: For some reason, EF_R29 is not defined in asm/reg.h under +// #if _MIPS_SIM == _MIPS_SIM_ABI32 condition, so use MIPS32_EF_R29 as a +// temporary solution. +# elif SANITIZER_OHOS +# define REG_SP regs[MIPS32_EF_R29] +# else +# define REG_SP regs[EF_REG29] +# endif #elif defined(__aarch64__) typedef struct user_pt_regs regs_struct; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp index d5c028e3640d221bd87f7166a44e81bd6b8388b5..f4e138d5c990b0cb923463d4ad08c37f9896c150 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -89,7 +89,7 @@ void ReportErrorSummary(const char *error_type, const StackTrace *stack, } void ReportMmapWriteExec(int prot, int flags) { -#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID) +#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID) && !SANITIZER_OHOS int pflags = (PROT_WRITE | PROT_EXEC); if ((prot & pflags) != pflags) return; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp index 72f025a7d307adcd30fd000562c61bc923c5faf9..a793432c5276e1a57caca4eb9ce608933bdb1186 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp @@ -16,7 +16,7 @@ #include "sanitizer_common.h" #include "sanitizer_stacktrace.h" -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS #include // for dlopen() #endif diff --git a/compiler-rt/lib/scudo/scudo_flags.inc b/compiler-rt/lib/scudo/scudo_flags.inc index c124738c1f3a712f84f320242cb93a07d90b6f46..ce4d641b811ae481ec1235839a8346421034af0c 100644 --- a/compiler-rt/lib/scudo/scudo_flags.inc +++ b/compiler-rt/lib/scudo/scudo_flags.inc @@ -39,7 +39,7 @@ SCUDO_FLAG(int, QuarantineChunksUpToSize, -1, // Disable the deallocation type check by default on Android, it causes too many // issues with third party libraries. SCUDO_FLAG(bool, DeallocationTypeMismatch, !SANITIZER_ANDROID, - "Report errors on malloc/delete, new/free, new/delete[], etc.") + "Report errors on malloc/delete, new/free, new/delete[], etc.") SCUDO_FLAG(bool, DeleteSizeMismatch, true, "Report errors on mismatch between size of new and delete.") diff --git a/compiler-rt/lib/scudo/scudo_platform.h b/compiler-rt/lib/scudo/scudo_platform.h index 07d4b70fc8e9bc0a86d5f1098ee19db81272672b..c2414ec60237d4c038f3de953145a56cb82c9ceb 100644 --- a/compiler-rt/lib/scudo/scudo_platform.h +++ b/compiler-rt/lib/scudo/scudo_platform.h @@ -24,10 +24,10 @@ #ifndef SCUDO_TSD_EXCLUSIVE // SCUDO_TSD_EXCLUSIVE wasn't defined, use a default TSD model for the platform. -# if SANITIZER_ANDROID || SANITIZER_FUCHSIA +#if SANITIZER_ANDROID || SANITIZER_FUCHSIA // Android and Fuchsia use a pool of TSDs shared between threads. # define SCUDO_TSD_EXCLUSIVE 0 -# elif SANITIZER_LINUX && !SANITIZER_ANDROID +#elif SANITIZER_LINUX && !SANITIZER_ANDROID // Non-Android Linux use an exclusive TSD per thread. # define SCUDO_TSD_EXCLUSIVE 1 # else @@ -42,7 +42,7 @@ // Maximum number of TSDs that can be created for the Shared model. #ifndef SCUDO_SHARED_TSD_POOL_SIZE -# if SANITIZER_ANDROID +#if SANITIZER_ANDROID # define SCUDO_SHARED_TSD_POOL_SIZE 2U # else # define SCUDO_SHARED_TSD_POOL_SIZE 32U @@ -67,7 +67,7 @@ namespace __scudo { #if SANITIZER_CAN_USE_ALLOCATOR64 -# if defined(__aarch64__) && SANITIZER_ANDROID +#if defined(__aarch64__) && SANITIZER_ANDROID const uptr AllocatorSize = 0x4000000000ULL; // 256G. # elif defined(__aarch64__) const uptr AllocatorSize = 0x10000000000ULL; // 1T. diff --git a/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp b/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp index 2c91db8ca3974841a2314b86a97b6d259c9e0d9c..002e87038cfbe5e44cef3896d105bc10ba814dca 100644 --- a/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp +++ b/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp @@ -26,7 +26,7 @@ // debuggerd handler, but before the ART handler. // * Interceptors don't work at all when ubsan runtime is loaded late, ex. when // it is part of an APK that does not use wrap.sh method. -#if SANITIZER_FUCHSIA || SANITIZER_ANDROID +#if SANITIZER_FUCHSIA || SANITIZER_ANDROID || SANITIZER_OHOS namespace __ubsan { void InitializeDeadlySignals() {} diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt index d02ee4b5bd68098d74265d77b4153e4d3876d029..91f4bc675d79dcdad82ec53e0355edb80d5c0ba2 100644 --- a/compiler-rt/test/asan/CMakeLists.txt +++ b/compiler-rt/test/asan/CMakeLists.txt @@ -143,7 +143,7 @@ if(COMPILER_RT_INCLUDE_TESTS) ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME_DYNAMIC}/lit.site.cfg.py) endif() # FIXME: support unit test in the android test runner - if (NOT ANDROID) + if (NOT ANDROID AND NOT OHOS) list(APPEND ASAN_TEST_DEPS AsanUnitTests) list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit/${CONFIG_NAME}) if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME) diff --git a/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py index 57271b8078a49730b9ae06f901ec3faf907dcef5..c2352c676cc594c3ddab7ddc92b1ab0b7382f885 100644 --- a/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py @@ -5,5 +5,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ['Linux']: +if root.host_os not in ['Linux', 'OHOS']: config.unsupported = True diff --git a/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c b/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c index 9929b4a67af38fdfd71e44aea17c754691665c3d..f5f2340288675702333a19c6ebf62c852eb69ef8 100644 --- a/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c +++ b/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c @@ -17,7 +17,7 @@ __attribute__((aligned(8))) int x; __attribute__((aligned(1))) char y; // The gold linker puts ZZZ at the start of bss (where it is aligned) // unless we have a large alternative like Displace: -__attribute__((aligned(1))) char Displace[105]; +__attribute__((aligned(8))) char Displace[105]; __attribute__((aligned(1))) char ZZZ[100]; #elif defined(FILE2) int ZZZ = 1; diff --git a/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cpp b/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cpp index f7bccbfbe8db81476de5a6404399bec2d20ffea4..35530e61b3dd61017625a707a25ec933ea5815e7 100644 --- a/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/quarantine_size_mb.cpp @@ -4,7 +4,9 @@ // RUN: %env_asan_opts=quarantine_size_mb=10:verbosity=1:hard_rss_limit_mb=50 %run %t 2>&1 | FileCheck %s --check-prefix=Q10 // RUN: %env_asan_opts=quarantine_size_mb=10:quarantine_size=20:verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=BOTH // RUN: %env_asan_opts=quarantine_size_mb=1000:hard_rss_limit_mb=50 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT -// RUN: %env_asan_opts=hard_rss_limit_mb=20 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT + +// HUAWEI: Sometimes measured RSS on device is 19Mb and test fails with 20Mb limit +// RUN: %env_asan_opts=hard_rss_limit_mb=10 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT // https://github.com/google/sanitizers/issues/981 // UNSUPPORTED: android-26 diff --git a/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp b/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp index e1752bc894c063f3b998d81b90557fd5bd5ba4ed..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 @@ -22,6 +22,6 @@ int main() { struct shm_info shmInfo; res = shmctl(0, SHM_INFO, (struct shmid_ds *)&shmInfo); assert(res > -1); - + return 0; } diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py index b437a151e16a907178b79635a4973a8bbcda43e1..cbe84170c61e52b1c3440280d8408e5f6789e4f4 100644 --- a/compiler-rt/test/asan/lit.cfg.py +++ b/compiler-rt/test/asan/lit.cfg.py @@ -239,7 +239,7 @@ else: config.substitutions.append(('%pie', '-pie')) # Only run the tests on supported OSs. -if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'SunOS', 'Windows', 'NetBSD']: +if config.host_os not in ['OHOS', 'Linux', 'Darwin', 'FreeBSD', 'SunOS', 'Windows', 'NetBSD']: config.unsupported = True if not config.parallelism_group: diff --git a/compiler-rt/test/builtins/Unit/divtf3_test.c b/compiler-rt/test/builtins/Unit/divtf3_test.c index 927d0b826f8f57cf995c6542a230fdf3f7957c71..f8b1f20e59d266fae6de933de77bf929c803bf57 100644 --- a/compiler-rt/test/builtins/Unit/divtf3_test.c +++ b/compiler-rt/test/builtins/Unit/divtf3_test.c @@ -185,6 +185,11 @@ int main() UINT64_C(0))) return 1; + if (test__divtf3(-1L, + -0.999999999999999999999999999999999904L, + UINT64_C(0x1), + UINT64_C(0x3fff000000000000))) + return 1; #else printf("skipped\n"); diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index 3dd258283e5ce26cb043b6b73034ea6713f74fca..a49c3c0bbfdea651830b3caa45a39725fbaa292a 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -83,6 +83,9 @@ def find_compiler_libdir(): return None +def is_ohos_family_mobile(): + return config.ohos_family and config.target_arch != 'x86_64' + # Choose between lit's internal shell pipeline runner and a real shell. If # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") @@ -232,10 +235,10 @@ if config.host_os == 'NetBSD': config.netbsd_nomprotect_prefix = ('sh ' + os.path.join(nb_commands_dir, 'run_nomprotect.sh')) - config.substitutions.append( ('%run_nomprotect', - config.netbsd_nomprotect_prefix) ) + config.substitutions.append(('%run_nomprotect', + config.netbsd_nomprotect_prefix)) else: - config.substitutions.append( ('%run_nomprotect', '%run') ) + config.substitutions.append(('%run_nomprotect', '%run')) # Copied from libcxx's config.py def get_lit_conf(name, default=None): @@ -254,13 +257,26 @@ def get_ios_commands_dir(): # Allow tests to be executed on a simulator or remotely. if emulator: - config.substitutions.append( ('%run', emulator) ) - config.substitutions.append( ('%env ', "env ") ) + config.substitutions.append(('%run', emulator)) + config.substitutions.append(('%env ', "env ")) # TODO: Implement `%device_rm` to perform removal of files in the emulator. # For now just make it a no-op. lit_config.warning('%device_rm is not implemented') - config.substitutions.append( ('%device_rm', 'echo ') ) + config.substitutions.append(('%device_rm', 'echo ')) config.compile_wrapper = "" +elif is_ohos_family_mobile(): + config.available_features.add('ohos_family') + # FIXME: some tests for hos also need this now, + # probably this shouldn't be added for ohos + config.available_features.add('android') + compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "ohos_family_commands", "ohos_compile.py") + " " + config.compile_wrapper = compile_wrapper + config.substitutions.append( ('%run', "") ) + config.substitutions.append( ('%env ', "env ") ) + # TODO: Implement `%device_rm` to perform removal of files on a device. For + # now just make it a no-op. + lit_config.warning('%device_rm is not implemented') + config.substitutions.append( ('%device_rm', 'echo ') ) elif config.host_os == 'Darwin' and config.apple_platform != "osx": # Darwin tests can be targetting macOS, a device or a simulator. All devices # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly, @@ -321,20 +337,20 @@ elif config.android: config.available_features.add('android') compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "android_commands", "android_compile.py") + " " config.compile_wrapper = compile_wrapper - config.substitutions.append( ('%run', "") ) - config.substitutions.append( ('%env ', "env ") ) + config.substitutions.append(('%run', "")) + config.substitutions.append(('%env ', "env ")) else: - config.substitutions.append( ('%run', "") ) - config.substitutions.append( ('%env ', "env ") ) + config.substitutions.append(('%run', "")) + config.substitutions.append(('%env ', "env ")) # When running locally %device_rm is a no-op. - config.substitutions.append( ('%device_rm', 'echo ') ) + config.substitutions.append(('%device_rm', 'echo ')) config.compile_wrapper = "" # Define CHECK-%os to check for OS-dependent output. -config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os))) +config.substitutions.append(('CHECK-%os', ("CHECK-" + config.host_os))) # Define %arch to check for architecture-dependent output. -config.substitutions.append( ('%arch', (config.host_arch))) +config.substitutions.append(('%arch', (config.host_arch))) if config.host_os == 'Windows': # FIXME: This isn't quite right. Specifically, it will succeed if the program @@ -345,7 +361,7 @@ if config.host_os == 'Windows': else: config.expect_crash = "not --crash " -config.substitutions.append( ("%expect_crash ", config.expect_crash) ) +config.substitutions.append(("%expect_crash ", config.expect_crash)) target_arch = getattr(config, 'target_arch', None) if target_arch: @@ -475,26 +491,27 @@ if config.android: # These are needed for tests to upload/download temp files, such as # suppression-files, to device. config.substitutions.append( ('%device_rundir/', "/data/local/tmp/Output/") ) - config.substitutions.append( ('%push_to_device', "%s -s '%s' push " % (adb, env['ANDROID_SERIAL']) ) ) - config.substitutions.append( ('%adb_shell ', "%s -s '%s' shell " % (adb, env['ANDROID_SERIAL']) ) ) - config.substitutions.append( ('%device_rm', "%s -s '%s' shell 'rm ' " % (adb, env['ANDROID_SERIAL']) ) ) + if not config.host_os == 'OHOS': + config.substitutions.append( ('%push_to_device', "%s -s '%s' push " % (adb, env['ANDROID_SERIAL']) ) ) + config.substitutions.append( ('%adb_shell ', "%s -s '%s' shell " % (adb, env['ANDROID_SERIAL']) ) ) + config.substitutions.append( ('%device_rm', "%s -s '%s' shell 'rm ' " % (adb, env['ANDROID_SERIAL']) ) ) - try: - android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"], env=env).rstrip() - android_api_codename = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.codename"], env=env).rstrip().decode("utf-8") - except (subprocess.CalledProcessError, OSError): - lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb) - try: - android_api_level = int(android_api_level_str) - except ValueError: - lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str)) - android_api_level = min(android_api_level, int(config.android_api_level)) - for required in [26, 28, 29, 30]: - if android_api_level >= required: - config.available_features.add('android-%s' % required) - # FIXME: Replace with appropriate version when availible. - if android_api_level > 30 or (android_api_level == 30 and android_api_codename == 'S'): - config.available_features.add('android-thread-properties-api') + try: + android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"], env=env).rstrip() + android_api_codename = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.codename"], env=env).rstrip().decode("utf-8") + except (subprocess.CalledProcessError, OSError): + lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb) + try: + android_api_level = int(android_api_level_str) + except ValueError: + lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str)) + android_api_level = min(android_api_level, int(config.android_api_level)) + for required in [26, 28, 29, 30]: + if android_api_level >= required: + config.available_features.add('android-%s' % required) + # FIXME: Replace with appropriate version when availible. + if android_api_level > 30 or (android_api_level == 30 and android_api_codename == 'S'): + config.available_features.add('android-thread-properties-api') # Prepare the device. android_tmpdir = '/data/local/tmp/Output' @@ -636,7 +653,7 @@ for postfix in ["2", "1", ""]: elif config.host_os in ('FreeBSD', 'NetBSD', 'OpenBSD'): config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) - elif config.host_os == 'Linux': + elif config.host_os in ['Linux', 'OHOS']: config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) elif config.host_os == 'SunOS': @@ -675,7 +692,7 @@ if config.host_os == 'Darwin': lit_config.warning('log command found but cannot queried') else: lit_config.warning('log command not found. Some tests will be skipped.') -elif config.android: +elif config.android or is_ohos_family_mobile(): config.default_sanitizer_opts += ['abort_on_error=0'] # Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in index 5db6ef0121fbe631442c021cde37c2959c25532b..a06ede7e73313af10081e4eb3b53d2c1e6d5ea49 100644 --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -41,6 +41,7 @@ set_default("use_lld", @COMPILER_RT_TEST_USE_LLD_PYBOOL@) set_default("use_thinlto", False) set_default("use_lto", config.use_thinlto) set_default("android", @ANDROID_PYBOOL@) +set_default("ohos_family", @OHOS_FAMILY_PYBOOL@) set_default("android_api_level", "@ANDROID_API_LEVEL@") set_default("android_serial", "@ANDROID_SERIAL_FOR_TESTING@") set_default("android_files_to_push", []) 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 new file mode 100755 index 0000000000000000000000000000000000000000..da6e6b9d2fd43e020e8d3946a0a84f236090d0be --- /dev/null +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py @@ -0,0 +1,45 @@ +import os, subprocess, tempfile + +HOS_TMPDIR = '/data/local/tmp/Output' +ADB = os.environ.get('ADB', 'adb') + +verbose = False +if os.environ.get('HOS_RUN_VERBOSE') == '1': + verbose = True + +def host_to_device_path(path): + rel = os.path.relpath(path, "/") + dev = os.path.join(HOS_TMPDIR, rel) + return dev + +def adb(args, attempts = 1): + if verbose: + print args + tmpname = tempfile.mktemp() + out = open(tmpname, 'w') + ret = 255 + while attempts > 0 and ret != 0: + attempts -= 1 + ret = subprocess.call([ADB] + args, stdout=out, stderr=subprocess.STDOUT) + if attempts != 0: + ret = 5 + if ret != 0: + print "adb command failed", args + print tmpname + out.close() + out = open(tmpname, 'r') + print out.read() + out.close() + os.unlink(tmpname) + return ret + +def pull_from_device(path): + tmp = tempfile.mktemp() + adb(['pull', path, tmp], 5) + text = open(tmp, 'r').read() + os.unlink(tmp) + return text + +def push_to_device(path): + dst_path = host_to_device_path(path) + adb(['push', path, dst_path], 5) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py new file mode 100755 index 0000000000000000000000000000000000000000..3a4769a5196b7f61093a8d2f77e34d034b28597f --- /dev/null +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + +import os, sys, subprocess +from ohos_common import * + + +here = os.path.abspath(os.path.dirname(sys.argv[0])) +hos_run = os.path.join(here, 'ohos_run.py') + +output = None +output_type = 'executable' + +args = sys.argv[1:] +append_args = [] +check_trgt = False +while args: + arg = args.pop(0) + if arg == '-shared': + output_type = 'shared' + elif arg == '-c': + output_type = 'object' + elif arg == '-o': + output = args.pop(0) + elif arg == '-target': + check_trgt = True + elif check_trgt or arg.startswith('--target='): + check_trgt = False + if arg.endswith('-linux-ohos'): + arg = arg.split('=')[-1] + dyld = 'unknown_hos_dyld' + # FIXME: Handle -mfloat-abi=hard for arm + # TODO: Support x86_64 + if arg.startswith('arm'): + dyld = 'ld-musl-arm.so.1' + elif arg.startswith('aarch64'): + dyld = 'ld-musl-aarch64.so.1' + append_args += ['-Wl,--dynamic-linker=' + os.path.join(HOS_TMPDIR, dyld)] + +if output == None: + print "No output file name!" + sys.exit(1) + +ret = subprocess.call(sys.argv[1:] + append_args) +if ret != 0: + sys.exit(ret) + +if output_type in ['executable', 'shared']: + push_to_device(output) + +if output_type == 'executable': + os.rename(output, output + '.real') + os.symlink(hos_run, output) 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 new file mode 100755 index 0000000000000000000000000000000000000000..84a8d9fb709cac3831c0fd229db812107b82f173 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +import os, signal, sys, subprocess +import re +from ohos_common import * + +device_binary = host_to_device_path(sys.argv[0]) + +def build_env(): + args = [] + # HOS linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir. + args.append('LD_LIBRARY_PATH=%s' % (HOS_TMPDIR,)) + for (key, value) in os.environ.items(): + if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or key.endswith('SAN_OPTIONS'): + args.append('%s="%s"' % (key, value)) + return ' '.join(args) + +device_env = build_env() +device_args = ' '.join(sys.argv[1:]) # FIXME: escape? +device_stdout = device_binary + '.stdout' +device_stderr = device_binary + '.stderr' +device_exitcode = device_binary + '.exitcode' +device_linker = '' + +ret = adb(['shell', 'cd %s && %s %s %s %s >%s 2>%s ; echo $? >%s' % + (HOS_TMPDIR, device_env, device_linker, device_binary, device_args, + device_stdout, device_stderr, device_exitcode)]) +if ret != 0: + sys.exit(ret) + +sys.stdout.write(pull_from_device(device_stdout)) +sys.stderr.write(pull_from_device(device_stderr)) +retcode = int(pull_from_device(device_exitcode)) +# If the device process died with a signal, do abort(). +# Not exactly the same, but good enough to fool "not --crash". +if retcode > 128: + os.kill(os.getpid(), signal.SIGABRT) +sys.exit(retcode) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 74eff2002fc9938511d9c119242b676ed98100a6..945a59509075d457fc88c0e6cc8dada627c6cc70 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -416,13 +416,21 @@ set(LIBCXX_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH "Path where built libc++ runtime libraries should be installed.") if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1") set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1") - set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH - "Path where built libc++ libraries should be installed.") set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE PATH "Path where target-specific libc++ headers should be installed.") + if(OHOS) + set(LIBCXX_LIBRARY_DIR + ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX}) + set(LIBCXX_INSTALL_LIBRARY_DIR + lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX} CACHE PATH + "Path where built libc++ libraries should be installed.") + else() + set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + "Path where built libc++ libraries should be installed.") + endif() if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBCXX_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) string(APPEND LIBCXX_INSTALL_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake index 209e6214a47180a48b44d9efa4326a1f547528c5..9e79b7bbde3ff42d1136594bd3789128e8bba97b 100644 --- a/libcxx/cmake/config-ix.cmake +++ b/libcxx/cmake/config-ix.cmake @@ -114,6 +114,8 @@ elseif(APPLE) set(LIBCXX_HAS_M_LIB NO) set(LIBCXX_HAS_RT_LIB NO) set(LIBCXX_HAS_ATOMIC_LIB NO) +elseif(OHOS) + set(LIBCXX_HAS_ATOMIC_LIB NO) elseif(FUCHSIA) set(LIBCXX_HAS_M_LIB NO) set(LIBCXX_HAS_PTHREAD_LIB NO) diff --git a/libcxx/include/__config b/libcxx/include/__config index 810189c94a94c43d5857c6edebae4dab82cfe777..8bc9e49e9b350b375272249a338abc78de16b1be 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -912,7 +912,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD defined(__sun__) || \ defined(__MVS__) || \ defined(_AIX) || \ - defined(__EMSCRIPTEN__) + defined(__EMSCRIPTEN__) || \ + defined(__OHOS_FAMILY__) // clang-format on # define _LIBCPP_HAS_THREAD_API_PTHREAD # elif defined(__Fuchsia__) @@ -990,7 +991,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # endif # if defined(__BIONIC__) || defined(__NuttX__) || defined(__Fuchsia__) || defined(__wasi__) || \ - defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__) + defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__) || defined(__OHOS_FAMILY__) # define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE # endif diff --git a/libcxx/include/__locale b/libcxx/include/__locale index 40f9a3ff57c22635254be654227333b2a10eca6a..e1407a07f63229c77e381cff99c04fb2d1d45463 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -40,6 +40,9 @@ #elif defined(__wasi__) // WASI libc uses musl's locales support. # include <__support/musl/xlocale.h> +#elif defined(__LITEOS__) || defined(__OHOS__) +// LiteOS libc uses musl's locales support. +# include <__support/musl/xlocale.h> #elif defined(_LIBCPP_HAS_MUSL_LIBC) # include <__support/musl/xlocale.h> #endif diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 9abf548abbb9526c6ba2da307114b9d12d781556..02ee3e023a23efc5584c5236920f627409706c09 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -194,6 +194,9 @@ endfunction() split_list(LIBCXX_COMPILE_FLAGS) split_list(LIBCXX_LINK_FLAGS) +if (NOT DEFINED LIBCXX_OUTPUT_NAME) + set (LIBCXX_OUTPUT_NAME "c++") +endif() # Build the shared library. if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) @@ -204,7 +207,7 @@ if (LIBCXX_ENABLE_SHARED) PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" - OUTPUT_NAME "c++" + OUTPUT_NAME "${LIBCXX_OUTPUT_NAME}" VERSION "${LIBCXX_LIBRARY_VERSION}" SOVERSION "${LIBCXX_ABI_VERSION}" DEFINE_SYMBOL "" @@ -278,6 +281,9 @@ endif() set(CMAKE_STATIC_LIBRARY_PREFIX "lib") +if (NOT DEFINED LIBCXX_OUTPUT_STATIC_NAME) + set (LIBCXX_OUTPUT_STATIC_NAME "c++") +endif() # Build the static library. if (LIBCXX_ENABLE_STATIC) add_library(cxx_static STATIC ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) @@ -289,7 +295,7 @@ if (LIBCXX_ENABLE_STATIC) PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" - OUTPUT_NAME "c++" + OUTPUT_NAME "${LIBCXX_OUTPUT_STATIC_NAME}" ) cxx_add_common_build_flags(cxx_static) cxx_set_common_defines(cxx_static) diff --git a/libcxx/src/include/config_elast.h b/libcxx/src/include/config_elast.h index bef26ec5019eccab758733eb85a1f8a6fc404968..0e762d276330d618fe77b4e1fb261006b4ade687 100644 --- a/libcxx/src/include/config_elast.h +++ b/libcxx/src/include/config_elast.h @@ -29,6 +29,8 @@ // No _LIBCPP_ELAST needed on Fuchsia #elif defined(__wasi__) // No _LIBCPP_ELAST needed on WASI +#elif defined(__OHOS_FAMILY__) +// No _LIBCPP_ELAST needed on OHOS #elif defined(__EMSCRIPTEN__) // No _LIBCPP_ELAST needed on Emscripten #elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC) diff --git a/libcxx/test/libcxx/modules_include.sh.cpp b/libcxx/test/libcxx/modules_include.sh.cpp index b6d73e8ed446078e241b8f79db547f5d7762e344..ddd9caafcd81dd76bff5f581de5746c38918fee1 100644 --- a/libcxx/test/libcxx/modules_include.sh.cpp +++ b/libcxx/test/libcxx/modules_include.sh.cpp @@ -16,6 +16,9 @@ // GCC doesn't support -fcxx-modules // UNSUPPORTED: gcc +// FIXME: hangs on CI +// UNSUPPORTED: ohos-ci + // The Windows headers don't appear to be compatible with modules // UNSUPPORTED: windows diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index dea8b38e7cbe9926c57b721afb10b26b7f871378..8ec356c85b9dc4afa54c5438edf1ffc8822f171b 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -299,3 +299,7 @@ DEFAULT_FEATURES += [ actions=[AddSubstitution('%{gdb}', lambda cfg: shutil.which('gdb'))] ) ] + +DEFAULT_FEATURES += [ + Feature(name='ohos-ci', when=lambda cfg: os.path.exists('/.dockerenv')) +] diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index b8326d08d23a8f743870b47b3733f39568e8f800..f6f945a134f867b857f8957c5937809a9be9e7b9 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -186,9 +186,17 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR}) - set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH - "Path where built libc++abi libraries should be installed.") + if(OHOS) + set(LIBCXXABI_LIBRARY_DIR + ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX}) + set(LIBCXXABI_INSTALL_LIBRARY_DIR + lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX} CACHE PATH + "Path where built libc++abi libraries should be installed.") + else() + set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + "Path where built libc++abi libraries should be installed.") + endif() if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR}) string(APPEND LIBCXXABI_INSTALL_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR}) diff --git a/libcxxabi/src/abort_message.cpp b/libcxxabi/src/abort_message.cpp index 859a5031b93fecdd24c07ca4246d822b61ead541..2264168e1ef0ab7bb0af8d4f32ca5721e18883d3 100644 --- a/libcxxabi/src/abort_message.cpp +++ b/libcxxabi/src/abort_message.cpp @@ -11,7 +11,7 @@ #include #include "abort_message.h" -#ifdef __BIONIC__ +#if defined(__BIONIC__) && !defined(__OHOS__) # include # if __ANDROID_API__ >= 21 # include @@ -52,7 +52,7 @@ void abort_message(const char* format, ...) va_end(list); CRSetCrashLogMessage(buffer); -#elif defined(__BIONIC__) +#elif defined(__BIONIC__) && !defined(__OHOS__) char* buffer; va_list list; va_start(list, format); diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index 5a06805f05f182a34f8d5f7223fe00d45deaba62..a895e4787c8550e76a2e61dfa9fccf09d5144917 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -116,9 +116,17 @@ set(LIBUNWIND_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH "Path where built libunwind runtime libraries should be installed.") if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH - "Path where built libunwind libraries should be installed.") + if(OHOS) + set(LIBUNWIND_LIBRARY_DIR + ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR + lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX} CACHE PATH + "Path where built libunwind libraries should be installed.") + else() + set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH + "Path where built libunwind libraries should be installed.") + endif() if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) string(APPEND LIBUNWIND_INSTALL_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) @@ -313,7 +321,7 @@ if (C_SUPPORTS_COMMENT_LIB_PRAGMA) if (LIBUNWIND_HAS_DL_LIB) add_definitions(-D_LIBUNWIND_LINK_DL_LIB) endif() - if (LIBUNWIND_HAS_PTHREAD_LIB) + if (LIBUNWIND_HAS_PTHREAD_LIB AND NOT OHOS) add_definitions(-D_LIBUNWIND_LINK_PTHREAD_LIB) endif() endif() diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index f878b46f034848fb4b6c7d1751300047cb8229d8..7e4f266fab372aaa93d11f99ba1fdfbc110e0e9f 100644 --- a/libunwind/include/libunwind.h +++ b/libunwind/include/libunwind.h @@ -84,7 +84,19 @@ typedef uintptr_t unw_word_t; #if defined(__arm__) && !defined(__ARM_DWARF_EH__) && !defined(__SEH__) typedef uint64_t unw_fpreg_t; #else +# if defined(_LIBUNWIND_TARGET_MIPS_O32) && defined(__mips_hard_float) +# if __mips_fpr == 0 +typedef uint64_t unw_fpreg_t; +# elif __mips_fpr == 32 +typedef float unw_fpreg_t; +# elif __mips_fpr == 64 +typedef double unw_fpreg_t; +# else +# error "Unknown __mips_fpr value" +# endif +# else typedef double unw_fpreg_t; +# endif #endif struct unw_proc_info_t { diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 36c9f5a9e36f9f39eacfa5c51330a0cf5c432c5f..fcfaf34f1a772888429e6039b40221783afed10a 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -176,9 +176,13 @@ public: memcpy(&val, (void *)addr, sizeof(val)); return val; } - double getDouble(pint_t addr) { - double val; + unw_fpreg_t getDouble(pint_t addr) { + unw_fpreg_t val; +#if defined(_LIBUNWIND_TARGET_MIPS_O32) + memcpy(&val, (void *)addr, Registers_mips_o32::getFpuRegsSize()); +#else memcpy(&val, (void *)addr, sizeof(val)); +#endif return val; } v128 getVector(pint_t addr) { diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index cee4ea53dab7ac6bfe0a7bf24cd9faa7d08f3783..394448dc44677883dfa543bd4f8e2cef0a37af4c 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -56,7 +56,7 @@ private: pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); - static double getSavedFloatRegister(A &addressSpace, const R ®isters, + static unw_fpreg_t getSavedFloatRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); @@ -119,7 +119,7 @@ typename A::pint_t DwarfInstructions::getSavedRegister( } template -double DwarfInstructions::getSavedFloatRegister( +unw_fpreg_t DwarfInstructions::getSavedFloatRegister( A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg) { switch (savedReg.location) { diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index 98adb78940f2a081e7a028fd999e9cb3515097ee..9c1f4c93610289d7f3690a9ecb85a8a1d9a2543d 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -63,8 +63,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int) const { return false; } v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -242,11 +242,11 @@ inline const char *Registers_x86::getRegisterName(int regNum) { } } -inline double Registers_x86::getFloatRegister(int) const { +inline unw_fpreg_t Registers_x86::getFloatRegister(int) const { _LIBUNWIND_ABORT("no x86 float registers"); } -inline void Registers_x86::setFloatRegister(int, double) { +inline void Registers_x86::setFloatRegister(int, unw_fpreg_t) { _LIBUNWIND_ABORT("no x86 float registers"); } @@ -281,8 +281,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -545,11 +545,11 @@ inline const char *Registers_x86_64::getRegisterName(int regNum) { } } -inline double Registers_x86_64::getFloatRegister(int) const { +inline unw_fpreg_t Registers_x86_64::getFloatRegister(int) const { _LIBUNWIND_ABORT("no x86_64 float registers"); } -inline void Registers_x86_64::setFloatRegister(int, double) { +inline void Registers_x86_64::setFloatRegister(int, unw_fpreg_t) { _LIBUNWIND_ABORT("no x86_64 float registers"); } @@ -600,8 +600,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -986,12 +986,12 @@ inline bool Registers_ppc::validFloatRegister(int regNum) const { return true; } -inline double Registers_ppc::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_ppc::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; } -inline void Registers_ppc::setFloatRegister(int regNum, double value) { +inline void Registers_ppc::setFloatRegister(int regNum, unw_fpreg_t value) { assert(validFloatRegister(regNum)); _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; } @@ -1170,8 +1170,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -1536,12 +1536,12 @@ inline bool Registers_ppc64::validFloatRegister(int regNum) const { return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; } -inline double Registers_ppc64::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_ppc64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; } -inline void Registers_ppc64::setFloatRegister(int regNum, double value) { +inline void Registers_ppc64::setFloatRegister(int regNum, unw_fpreg_t value) { assert(validFloatRegister(regNum)); _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; } @@ -1819,8 +1819,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2070,12 +2070,12 @@ inline bool Registers_arm64::validFloatRegister(int regNum) const { return true; } -inline double Registers_arm64::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_arm64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _vectorHalfRegisters[regNum - UNW_AARCH64_V0]; } -inline void Registers_arm64::setFloatRegister(int regNum, double value) { +inline void Registers_arm64::setFloatRegister(int regNum, unw_fpreg_t value) { assert(validFloatRegister(regNum)); _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value; } @@ -2613,8 +2613,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2704,12 +2704,12 @@ inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { return false; } -inline double Registers_or1k::getFloatRegister(int /* regNum */) const { +inline unw_fpreg_t Registers_or1k::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("or1k float support not implemented"); } inline void Registers_or1k::setFloatRegister(int /* regNum */, - double /* value */) { + unw_fpreg_t /* value */) { _LIBUNWIND_ABORT("or1k float support not implemented"); } @@ -2801,19 +2801,32 @@ inline const char *Registers_or1k::getRegisterName(int regNum) { #endif // _LIBUNWIND_TARGET_OR1K #if defined(_LIBUNWIND_TARGET_MIPS_O32) + +// TODO: check the following for FPU with 32-bit registers: +// - fpxx code works properly +// - fp32 code remains working properly + /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS /// process. class _LIBUNWIND_HIDDEN Registers_mips_o32 { public: Registers_mips_o32(); Registers_mips_o32(const void *registers); +#ifdef __mips_hard_float + Registers_mips_o32(const Registers_mips_o32 &) = default; + Registers_mips_o32 &operator=(const Registers_mips_o32 &src) { + memcpy(&_registers, &src._registers, sizeof(_registers)); + memcpy(&_floatsBuffer, &src._floatsBuffer, sizeof(_floatsBuffer)); + return *this; + } +#endif bool validRegister(int num) const; uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2823,6 +2836,9 @@ public: return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } static int getArch() { return REGISTERS_MIPS_O32; } +#ifdef __mips_hard_float + static uint32_t getFpuRegsSize(); +#endif uint32_t getSP() const { return _registers.__r[29]; } void setSP(uint32_t value) { _registers.__r[29] = value; } @@ -2843,19 +2859,50 @@ private: /// space. However, using the same layout for 32-bit vs 64-bit /// floating point registers results in a single context size for /// O32 with hard float. - uint32_t _padding; - double _floats[32]; + const uint32_t _fpuRegsSize; + char _floatsBuffer[32 * 8] = {0}; + + char *getFpuRegLocation(int regNum); + const char *getFpuRegLocation(int regNum) const; #endif }; -inline Registers_mips_o32::Registers_mips_o32(const void *registers) { +inline Registers_mips_o32::Registers_mips_o32(const void *registers) +#ifdef __mips_hard_float + : _fpuRegsSize(getFpuRegsSize()) +#endif +{ static_assert((check_fit::does_fit), "mips_o32 registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } -inline Registers_mips_o32::Registers_mips_o32() { +#ifdef __mips_hard_float +inline uint32_t Registers_mips_o32::getFpuRegsSize() { +#if __mips_fpr == 32 + return 4; +#elif __mips_fpr == 64 + return 8; +#elif __mips_fpr == 0 + unsigned fpuID; + __asm__ __volatile__(" .set push \n" + " cfc1 %0,$0 \n" + " .set pop \n" + : "=r"(fpuID)); + constexpr unsigned MIPS_FPIR_F64 = (1 << 22); + return (fpuID & MIPS_FPIR_F64) ? 8 : 4; +#else +#error "Unknown __mips_fpr value" +#endif +} +#endif + +inline Registers_mips_o32::Registers_mips_o32() +#ifdef __mips_hard_float + : _fpuRegsSize(getFpuRegsSize()) +#endif +{ memset(&_registers, 0, sizeof(_registers)); } @@ -2873,10 +2920,6 @@ inline bool Registers_mips_o32::validRegister(int regNum) const { return true; if (regNum == UNW_MIPS_LO) return true; -#endif -#if defined(__mips_hard_float) && __mips_fpr == 32 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) - return true; #endif // FIXME: DSP accumulator registers, MSA registers return false; @@ -2885,17 +2928,6 @@ inline bool Registers_mips_o32::validRegister(int regNum) const { inline uint32_t Registers_mips_o32::getRegister(int regNum) const { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) return _registers.__r[regNum - UNW_MIPS_R0]; -#if defined(__mips_hard_float) && __mips_fpr == 32 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { - uint32_t *p; - - if (regNum % 2 == 0) - p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; - else - p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; - return *p; - } -#endif switch (regNum) { case UNW_REG_IP: @@ -2915,19 +2947,6 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { _registers.__r[regNum - UNW_MIPS_R0] = value; return; } -#if defined(__mips_hard_float) && __mips_fpr == 32 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { - uint32_t *p; - - if (regNum % 2 == 0) - p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; - else - p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; - *p = value; - return; - } -#endif - switch (regNum) { case UNW_REG_IP: _registers.__pc = value; @@ -2945,20 +2964,51 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { _LIBUNWIND_ABORT("unsupported mips_o32 register"); } +#ifdef __mips_hard_float +inline const char *Registers_mips_o32::getFpuRegLocation(int regNum) const { + const char *regLocation = _floatsBuffer; + int fpuRegNum = regNum - UNW_MIPS_F0; + if (_fpuRegsSize == 4 && fpuRegNum % 2 == 1) + regLocation += (fpuRegNum - 1) * 8 + 4; + else + regLocation += fpuRegNum * 8; + return regLocation; +} + +inline char *Registers_mips_o32::getFpuRegLocation(int regNum) { + char *regLocation = _floatsBuffer; + int fpuRegNum = regNum - UNW_MIPS_F0; + if (_fpuRegsSize == 4 && fpuRegNum % 2 == 1) + regLocation += (fpuRegNum - 1) * 8 + 4; + else + regLocation += fpuRegNum * 8; + return regLocation; +} +#endif + inline bool Registers_mips_o32::validFloatRegister(int regNum) const { -#if defined(__mips_hard_float) && __mips_fpr == 64 - if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) - return true; +#if defined(__mips_hard_float) + return (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31); #else (void)regNum; -#endif return false; +#endif } -inline double Registers_mips_o32::getFloatRegister(int regNum) const { -#if defined(__mips_hard_float) && __mips_fpr == 64 +inline unw_fpreg_t Registers_mips_o32::getFloatRegister(int regNum) const { +#if defined(__mips_hard_float) assert(validFloatRegister(regNum)); - return _floats[regNum - UNW_MIPS_F0]; +#if __mips_fpr == 0 + const char *regLocation = getFpuRegLocation(regNum); + unw_fpreg_t regValue = 0; + memcpy(reinterpret_cast(®Value), regLocation, _fpuRegsSize); + return regValue; +#elif __mips_fpr == 32 || __mips_fpr == 64 + const char *regLocation = getFpuRegLocation(regNum); + return *reinterpret_cast(regLocation); +#else +#error "Unknown __mips_fpr value" +#endif #else (void)regNum; _LIBUNWIND_ABORT("mips_o32 float support not implemented"); @@ -2966,10 +3016,18 @@ inline double Registers_mips_o32::getFloatRegister(int regNum) const { } inline void Registers_mips_o32::setFloatRegister(int regNum, - double value) { -#if defined(__mips_hard_float) && __mips_fpr == 64 + unw_fpreg_t value) { +#if defined(__mips_hard_float) assert(validFloatRegister(regNum)); - _floats[regNum - UNW_MIPS_F0] = value; +#if __mips_fpr == 0 + char *regLocation = getFpuRegLocation(regNum); + memcpy(regLocation, reinterpret_cast(&value), _fpuRegsSize); +#elif __mips_fpr == 32 || __mips_fpr == 64 + char *regLocation = getFpuRegLocation(regNum); + *reinterpret_cast(regLocation) = value; +#else +#error "Unknown __mips_fpr value" +#endif #else (void)regNum; (void)value; @@ -3141,8 +3199,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3252,7 +3310,7 @@ inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { return false; } -inline double Registers_mips_newabi::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_mips_newabi::getFloatRegister(int regNum) const { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); return _floats[regNum - UNW_MIPS_F0]; @@ -3263,7 +3321,7 @@ inline double Registers_mips_newabi::getFloatRegister(int regNum) const { } inline void Registers_mips_newabi::setFloatRegister(int regNum, - double value) { + unw_fpreg_t value) { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); _floats[regNum - UNW_MIPS_F0] = value; @@ -3438,8 +3496,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3519,11 +3577,11 @@ inline void Registers_sparc::setRegister(int regNum, uint32_t value) { inline bool Registers_sparc::validFloatRegister(int) const { return false; } -inline double Registers_sparc::getFloatRegister(int) const { +inline unw_fpreg_t Registers_sparc::getFloatRegister(int) const { _LIBUNWIND_ABORT("no Sparc float registers"); } -inline void Registers_sparc::setFloatRegister(int, double) { +inline void Registers_sparc::setFloatRegister(int, unw_fpreg_t) { _LIBUNWIND_ABORT("no Sparc float registers"); } @@ -3809,8 +3867,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3885,12 +3943,12 @@ inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const { return false; } -inline double Registers_hexagon::getFloatRegister(int /* regNum */) const { +inline unw_fpreg_t Registers_hexagon::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("hexagon float support not implemented"); } inline void Registers_hexagon::setFloatRegister(int /* regNum */, - double /* value */) { + unw_fpreg_t /* value */) { _LIBUNWIND_ABORT("hexagon float support not implemented"); } @@ -4267,7 +4325,7 @@ inline bool Registers_riscv::validFloatRegister(int regNum) const { # endif } -inline fp_t Registers_riscv::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_riscv::getFloatRegister(int regNum) const { # if defined(__riscv_flen) assert(validFloatRegister(regNum)); return _floats[regNum - UNW_RISCV_F0]; @@ -4277,7 +4335,7 @@ inline fp_t Registers_riscv::getFloatRegister(int regNum) const { # endif } -inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) { +inline void Registers_riscv::setFloatRegister(int regNum, unw_fpreg_t value) { # if defined(__riscv_flen) assert(validFloatRegister(regNum)); _floats[regNum - UNW_RISCV_F0] = value; @@ -4312,8 +4370,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -4418,12 +4476,12 @@ inline bool Registers_ve::validFloatRegister(int /* regNum */) const { return false; } -inline double Registers_ve::getFloatRegister(int /* regNum */) const { +inline unw_fpreg_t Registers_ve::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("VE doesn't have float registers"); } inline void Registers_ve::setFloatRegister(int /* regNum */, - double /* value */) { + unw_fpreg_t /* value */) { _LIBUNWIND_ABORT("VE doesn't have float registers"); } @@ -4755,8 +4813,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -4850,7 +4908,7 @@ inline bool Registers_s390x::validFloatRegister(int regNum) const { return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15; } -inline double Registers_s390x::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_s390x::getFloatRegister(int regNum) const { // NOTE: FPR DWARF register numbers are not consecutive. switch (regNum) { case UNW_S390X_F0: @@ -4889,7 +4947,7 @@ inline double Registers_s390x::getFloatRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported s390x register"); } -inline void Registers_s390x::setFloatRegister(int regNum, double value) { +inline void Registers_s390x::setFloatRegister(int regNum, unw_fpreg_t value) { // NOTE: FPR DWARF register numbers are not consecutive. switch (regNum) { case UNW_S390X_F0: diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index eeb64534966dfd70dcec24dd45c2b8b554ce4a09..894b5f60a1555c8e21c21bb126885117eccc7282 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -917,7 +917,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) .set noreorder .set nomacro #ifdef __mips_hard_float -#if __mips_fpr != 64 +#if __mips_fpr == 32 ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) ldc1 $f4, (4 * 36 + 8 * 4)($4) @@ -934,7 +934,46 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) ldc1 $f26, (4 * 36 + 8 * 26)($4) ldc1 $f28, (4 * 36 + 8 * 28)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) -#else +#elif __mips_fpr == 64 + ldc1 $f0, (4 * 36 + 8 * 0)($4) + ldc1 $f1, (4 * 36 + 8 * 1)($4) + ldc1 $f2, (4 * 36 + 8 * 2)($4) + ldc1 $f3, (4 * 36 + 8 * 3)($4) + ldc1 $f4, (4 * 36 + 8 * 4)($4) + ldc1 $f5, (4 * 36 + 8 * 5)($4) + ldc1 $f6, (4 * 36 + 8 * 6)($4) + ldc1 $f7, (4 * 36 + 8 * 7)($4) + ldc1 $f8, (4 * 36 + 8 * 8)($4) + ldc1 $f9, (4 * 36 + 8 * 9)($4) + ldc1 $f10, (4 * 36 + 8 * 10)($4) + ldc1 $f11, (4 * 36 + 8 * 11)($4) + ldc1 $f12, (4 * 36 + 8 * 12)($4) + ldc1 $f13, (4 * 36 + 8 * 13)($4) + ldc1 $f14, (4 * 36 + 8 * 14)($4) + ldc1 $f15, (4 * 36 + 8 * 15)($4) + ldc1 $f16, (4 * 36 + 8 * 16)($4) + ldc1 $f17, (4 * 36 + 8 * 17)($4) + ldc1 $f18, (4 * 36 + 8 * 18)($4) + ldc1 $f19, (4 * 36 + 8 * 19)($4) + ldc1 $f20, (4 * 36 + 8 * 20)($4) + ldc1 $f21, (4 * 36 + 8 * 21)($4) + ldc1 $f22, (4 * 36 + 8 * 22)($4) + ldc1 $f23, (4 * 36 + 8 * 23)($4) + ldc1 $f24, (4 * 36 + 8 * 24)($4) + ldc1 $f25, (4 * 36 + 8 * 25)($4) + ldc1 $f26, (4 * 36 + 8 * 26)($4) + ldc1 $f27, (4 * 36 + 8 * 27)($4) + ldc1 $f28, (4 * 36 + 8 * 28)($4) + ldc1 $f29, (4 * 36 + 8 * 29)($4) + ldc1 $f30, (4 * 36 + 8 * 30)($4) + ldc1 $f31, (4 * 36 + 8 * 31)($4) +#elif __mips_fpr == 0 + cfc1 $t0, $0 + li $t1, 1 + sll $t1, $t1, 22 + and $t0, $t0, $t1 + beq $t0, $0, _fp32 +_fp64: ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) @@ -967,8 +1006,29 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) ldc1 $f29, (4 * 36 + 8 * 29)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4) + j _after_float +_fp32: + ldc1 $f0, (4 * 36 + 8 * 0)($4) + ldc1 $f2, (4 * 36 + 8 * 2)($4) + ldc1 $f4, (4 * 36 + 8 * 4)($4) + ldc1 $f6, (4 * 36 + 8 * 6)($4) + ldc1 $f8, (4 * 36 + 8 * 8)($4) + ldc1 $f10, (4 * 36 + 8 * 10)($4) + ldc1 $f12, (4 * 36 + 8 * 12)($4) + ldc1 $f14, (4 * 36 + 8 * 14)($4) + ldc1 $f16, (4 * 36 + 8 * 16)($4) + ldc1 $f18, (4 * 36 + 8 * 18)($4) + ldc1 $f20, (4 * 36 + 8 * 20)($4) + ldc1 $f22, (4 * 36 + 8 * 22)($4) + ldc1 $f24, (4 * 36 + 8 * 24)($4) + ldc1 $f26, (4 * 36 + 8 * 26)($4) + ldc1 $f28, (4 * 36 + 8 * 28)($4) + ldc1 $f30, (4 * 36 + 8 * 30)($4) +#else +#error "Unknown __mips_fpr value" #endif #endif +_after_float: // restore hi and lo lw $8, (4 * 33)($4) mthi $8 diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index f57dd637dd9d8020f056dbb4eb0e317a9883fac6..2b79f448507f2e2fad979fdd35be581d2d3e80b9 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -135,46 +135,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .set noat .set noreorder .set nomacro - sw $1, (4 * 1)($4) - sw $2, (4 * 2)($4) - sw $3, (4 * 3)($4) - sw $4, (4 * 4)($4) - sw $5, (4 * 5)($4) - sw $6, (4 * 6)($4) - sw $7, (4 * 7)($4) - sw $8, (4 * 8)($4) - sw $9, (4 * 9)($4) - sw $10, (4 * 10)($4) - sw $11, (4 * 11)($4) - sw $12, (4 * 12)($4) - sw $13, (4 * 13)($4) - sw $14, (4 * 14)($4) - sw $15, (4 * 15)($4) - sw $16, (4 * 16)($4) - sw $17, (4 * 17)($4) - sw $18, (4 * 18)($4) - sw $19, (4 * 19)($4) - sw $20, (4 * 20)($4) - sw $21, (4 * 21)($4) - sw $22, (4 * 22)($4) - sw $23, (4 * 23)($4) - sw $24, (4 * 24)($4) - sw $25, (4 * 25)($4) - sw $26, (4 * 26)($4) - sw $27, (4 * 27)($4) - sw $28, (4 * 28)($4) - sw $29, (4 * 29)($4) - sw $30, (4 * 30)($4) - sw $31, (4 * 31)($4) - # Store return address to pc - sw $31, (4 * 32)($4) - # hi and lo - mfhi $8 - sw $8, (4 * 33)($4) - mflo $8 - sw $8, (4 * 34)($4) #ifdef __mips_hard_float -#if __mips_fpr != 64 +#if __mips_fpr == 32 sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) sdc1 $f4, (4 * 36 + 8 * 4)($4) @@ -191,7 +153,46 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) sdc1 $f26, (4 * 36 + 8 * 26)($4) sdc1 $f28, (4 * 36 + 8 * 28)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) -#else +#elif __mips_fpr == 64 + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f1, (4 * 36 + 8 * 1)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f3, (4 * 36 + 8 * 3)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f5, (4 * 36 + 8 * 5)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f7, (4 * 36 + 8 * 7)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f9, (4 * 36 + 8 * 9)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f11, (4 * 36 + 8 * 11)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f13, (4 * 36 + 8 * 13)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f15, (4 * 36 + 8 * 15)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f17, (4 * 36 + 8 * 17)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f19, (4 * 36 + 8 * 19)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f21, (4 * 36 + 8 * 21)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f23, (4 * 36 + 8 * 23)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f25, (4 * 36 + 8 * 25)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f27, (4 * 36 + 8 * 27)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f29, (4 * 36 + 8 * 29)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) + sdc1 $f31, (4 * 36 + 8 * 31)($4) +#elif __mips_fpr == 0 + cfc1 $t0, $0 + li $t1, 1 + sll $t1, $t1, 22 + and $t0, $t0, $t1 + beq $t0, $0, _fp32 +_fp64: sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) @@ -224,8 +225,67 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) sdc1 $f29, (4 * 36 + 8 * 29)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) sdc1 $f31, (4 * 36 + 8 * 31)($4) + j _after_float +_fp32: + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) +#else +#error "Unknown __mips_fpr value" #endif #endif +_after_float: + sw $1, (4 * 1)($4) + sw $2, (4 * 2)($4) + sw $3, (4 * 3)($4) + sw $4, (4 * 4)($4) + sw $5, (4 * 5)($4) + sw $6, (4 * 6)($4) + sw $7, (4 * 7)($4) + sw $8, (4 * 8)($4) + sw $9, (4 * 9)($4) + sw $10, (4 * 10)($4) + sw $11, (4 * 11)($4) + sw $12, (4 * 12)($4) + sw $13, (4 * 13)($4) + sw $14, (4 * 14)($4) + sw $15, (4 * 15)($4) + sw $16, (4 * 16)($4) + sw $17, (4 * 17)($4) + sw $18, (4 * 18)($4) + sw $19, (4 * 19)($4) + sw $20, (4 * 20)($4) + sw $21, (4 * 21)($4) + sw $22, (4 * 22)($4) + sw $23, (4 * 23)($4) + sw $24, (4 * 24)($4) + sw $25, (4 * 25)($4) + sw $26, (4 * 26)($4) + sw $27, (4 * 27)($4) + sw $28, (4 * 28)($4) + sw $29, (4 * 29)($4) + sw $30, (4 * 30)($4) + sw $31, (4 * 31)($4) + # Store return address to pc + sw $31, (4 * 32)($4) + # hi and lo + mfhi $8 + sw $8, (4 * 33)($4) + mflo $8 + sw $8, (4 * 34)($4) jr $31 # return UNW_ESUCCESS or $2, $0, $0 diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp index b8b41ff25e54f543b5014fce7bd56be4d736eb01..0f67d15dc935937a24be050b8f562ec6e11bb760 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -157,7 +157,7 @@ _LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg, unw_get_fpreg) /// Set value of specified float register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t value) { -#if defined(_LIBUNWIND_ARM_EHABI) +#if defined(_LIBUNWIND_ARM_EHABI) || (defined(__mips__) && __mips_fpr == 0) _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", static_cast(cursor), regNum, value); #else diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index af976e39147db43cab849b8a5189bb7920d09ac3..d6babe9f74c256bcf7f16f29389bf7b6712413c2 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -286,6 +286,8 @@ struct Configuration { uint64_t zStackSize; unsigned ltoPartitions; unsigned ltoo; + unsigned ltos; + bool mergeFunctions; unsigned optimize; StringRef thinLTOJobs; unsigned timeTraceGranularity; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 296fb4220012e06f8a6807a954db7424c3809c3c..abcc8a984a65905cc2b62a84903015a86b588c7b 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -63,6 +63,7 @@ #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include +#include #include using namespace llvm; @@ -1018,6 +1019,47 @@ static bool isValidReportString(StringRef arg) { return arg == "none" || arg == "warning" || arg == "error"; } +static std::pair +parseLTOOptArg(opt::InputArgList &args, unsigned key, StringRef defaultValue) { + auto *a = args.getLastArg(key); + llvm::StringRef value = a ? a->getValue() : defaultValue; + + unsigned optLevel = 0; + unsigned sizeLevel = 0; + + if (value.size() != 1) { + error("invalid optimization level for LTO: " + value); + return {optLevel, sizeLevel}; + } + + char c = value[0]; + + switch (c) { + + case '0': + case '1': + case '2': + case '3': + optLevel = c - '0'; + break; + + case 's': + optLevel = 2; + sizeLevel = 1; + break; + + case 'z': + optLevel = 2; + sizeLevel = 2; + break; + + default: + error("invalid optimization level for LTO: " + value); + } + + return {optLevel, sizeLevel}; +} + // Initializes Config members by the command line options. static void readConfigs(opt::InputArgList &args) { errorHandler().verbose = args.hasArg(OPT_verbose); @@ -1104,8 +1146,9 @@ static void readConfigs(opt::InputArgList &args) { config->ltoWholeProgramVisibility = args.hasFlag(OPT_lto_whole_program_visibility, OPT_no_lto_whole_program_visibility, false); - config->ltoo = args::getInteger(args, OPT_lto_O, 2); config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq); + std::tie(config->ltoo, config->ltos) = parseLTOOptArg(args, OPT_lto_O, "2"); + config->mergeFunctions = args.hasArg(OPT_lto_mf); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); config->ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile); config->ltoBasicBlockSections = diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index d9266e59588793faaa96ec811eb5b258796d83e4..4e6c20f5c7f6014f4f23ed17b0962212966989c6 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -557,6 +557,10 @@ def lto_newpm_passes: JJ<"lto-newpm-passes=">, HelpText<"Passes to run during LTO">; def lto_O: JJ<"lto-O">, MetaVarName<"">, HelpText<"Optimization level for LTO">; +def lto_S: J<"lto-S">, MetaVarName<"">, + HelpText<"Size Optimization level for LTO, works only with -lto-O2">; +def lto_mf: F<"lto-mf">, + HelpText<"Enable Merge Functions pass for link time optimizations.">; def lto_partitions: JJ<"lto-partitions=">, HelpText<"Number of LTO codegen partitions">; def lto_cs_profile_generate: FF<"lto-cs-profile-generate">, diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 7fc50b293b15add5355e3f227f7f97d570e477cd..0576c6e66f4d325fa0b6887b6a7a754c66edd6af 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -1578,6 +1578,7 @@ unsigned ScriptParser::readPhdrType() { .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE) .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) + .Case("PT_OHOS_RANDOMDATA", PT_OHOS_RANDOMDATA) .Default(-1); if (ret == (unsigned)-1) { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ad80d4344e3640e9a8dc0fda841f54bfacd9d699..bf213b199d4fed4da2c19d4c4ffebec134647659 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -832,7 +832,8 @@ static bool isRelroSection(const OutputSection *sec) { return s == ".data.rel.ro" || s == ".bss.rel.ro" || s == ".ctors" || s == ".dtors" || s == ".jcr" || s == ".eh_frame" || s == ".fini_array" || s == ".init_array" || - s == ".openbsd.randomdata" || s == ".preinit_array"; + s == ".openbsd.randomdata" || s == ".preinit_array" || + s == ".ohos.randomdata"; } // We compute a rank for each section. The rank indicates where the @@ -2427,6 +2428,9 @@ SmallVector Writer::createPhdrs(Partition &part) { if (OutputSection *cmd = findSection(".note.gnu.property", partNo)) addHdr(PT_GNU_PROPERTY, PF_R)->add(cmd); + if (OutputSection *cmd = findSection(".ohos.randomdata", partNo)) + addHdr(PT_OHOS_RANDOMDATA, cmd->getPhdrFlags())->add(cmd); + // Create one PT_NOTE per a group of contiguous SHT_NOTE sections with the // same alignment. PhdrEntry *note = nullptr; diff --git a/lld/test/ELF/lto/opt-level.ll b/lld/test/ELF/lto/opt-level.ll index 6e0cc9ac98c55c945e418a9154c5533f36c9cfc7..628e4ef7126c0504c86bb352fd73448df225f9df 100644 --- a/lld/test/ELF/lto/opt-level.ll +++ b/lld/test/ELF/lto/opt-level.ll @@ -19,14 +19,14 @@ ; RUN: FileCheck --check-prefix=INVALID1 %s ; RUN: not ld.lld -o /dev/null -e main --plugin-opt=Ofoo %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALID2 %s -; INVALID2: --plugin-opt=Ofoo: number expected, but got 'foo' +; INVALID2: invalid optimization level for LTO: foo ; RUN: not ld.lld -o /dev/null -e main --lto-O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE1 %s -; INVALIDNEGATIVE1: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE1: invalid optimization level for LTO: -1 ; RUN: not ld.lld -o /dev/null -e main --plugin-opt=O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE2 %s -; INVALIDNEGATIVE2: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE2: invalid optimization level for LTO: -1 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/lldb/cmake/modules/FindPythonAndSwig.cmake b/lldb/cmake/modules/FindPythonAndSwig.cmake index 3535b548c45f2de5dda4c1e5c9b7d5ead261c936..562d5307e8c8047d23dae32ae6e060951443b343 100644 --- a/lldb/cmake/modules/FindPythonAndSwig.cmake +++ b/lldb/cmake/modules/FindPythonAndSwig.cmake @@ -35,6 +35,17 @@ macro(FindPython3) endif() endmacro() +#OHOS specific: copy LLVM-10 definitions if new Python3_*** are not set +if(NOT Python3_EXECUTABLE AND PYTHON_EXECUTABLE) + set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE}) +endif() +if(NOT Python3_LIBRARIES AND PYTHON_LIBRARIES) + set(Python3_LIBRARIES ${PYTHON_LIBRARIES}) +endif() +if(NOT Python3_INCLUDE_DIRS AND PYTHON_INCLUDE_DIRS) + set(Python3_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) +endif() + if(Python3_LIBRARIES AND Python3_INCLUDE_DIRS AND Python3_EXECUTABLE AND SWIG_EXECUTABLE) set(PYTHONANDSWIG_FOUND TRUE) else() diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index 987353517d0d5947aa94cfaf07cfb85465e5e15a..55d1aa17b46b597240e2acc0a09ac3832a22ccb6 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -313,7 +313,7 @@ endif() # Figure out if lldb could use lldb-server. If so, then we'll # ensure we build lldb-server when an lldb target is being built. -if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows|OHOS") set(LLDB_CAN_USE_LLDB_SERVER ON) else() set(LLDB_CAN_USE_LLDB_SERVER OFF) diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h index b7010d69d88e7fc33e079cce514558ff6d49ff51..fbb5bbf1e442c77e73a926fb038441e5eb03aaa0 100644 --- a/lldb/include/lldb/Host/HostInfo.h +++ b/lldb/include/lldb/Host/HostInfo.h @@ -39,6 +39,9 @@ #if defined(__ANDROID__) #include "lldb/Host/android/HostInfoAndroid.h" #define HOST_INFO_TYPE HostInfoAndroid +#elif defined(__OHOS_FAMILY__) +#include "lldb/Host/ohos/HostInfoOHOS.h" +#define HOST_INFO_TYPE HostInfoOHOS #else #include "lldb/Host/linux/HostInfoLinux.h" #define HOST_INFO_TYPE HostInfoLinux diff --git a/lldb/include/lldb/Host/MainLoop.h b/lldb/include/lldb/Host/MainLoop.h index f04ac7359cc1851e91078f25d925c148f9e809a0..c89a28387b6a654af18a9f15a3c255c7cc13ef82 100644 --- a/lldb/include/lldb/Host/MainLoop.h +++ b/lldb/include/lldb/Host/MainLoop.h @@ -16,7 +16,8 @@ #include #include -#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__) +#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__) && \ + !defined(__OHOS_FAMILY__) #define SIGNAL_POLLING_UNSUPPORTED 1 #endif diff --git a/lldb/include/lldb/Host/ohos/HostInfoOHOS.h b/lldb/include/lldb/Host/ohos/HostInfoOHOS.h new file mode 100644 index 0000000000000000000000000000000000000000..e20582820145a886be2c46b40e81032075eebde1 --- /dev/null +++ b/lldb/include/lldb/Host/ohos/HostInfoOHOS.h @@ -0,0 +1,32 @@ +//===-- HostInfoOHOS.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_ohos_HostInfoOHOS_h_ +#define lldb_Host_ohos_HostInfoOHOS_h_ + +#include "lldb/Host/linux/HostInfoLinux.h" + +namespace lldb_private { + +class HostInfoOHOS : public HostInfoLinux { + friend class HostInfoBase; + +public: + static FileSpec GetDefaultShell(); + static FileSpec ResolveLibraryPath(const std::string &path, + const ArchSpec &arch); + +protected: + static void ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64); + static bool ComputeTempFileBaseDirectory(FileSpec &file_spec); +}; + +} // end of namespace lldb_private + +#endif // #ifndef lldb_Host_ohos_HostInfoOHOS_h_ diff --git a/lldb/include/lldb/Interpreter/OptionGroupPlatform.h b/lldb/include/lldb/Interpreter/OptionGroupPlatform.h index fed2791a6130925b7c9520090eb8f1dcf3984d50..3c24d77cdbe52fff69af9ba32de37d8defbc5111 100644 --- a/lldb/include/lldb/Interpreter/OptionGroupPlatform.h +++ b/lldb/include/lldb/Interpreter/OptionGroupPlatform.h @@ -57,12 +57,17 @@ public: void SetSDKBuild(ConstString sdk_build) { m_sdk_build = sdk_build; } + bool GetContainer() const { return m_container; } + + void SetContainer(bool b_container) { m_container = b_container; } + bool PlatformMatches(const lldb::PlatformSP &platform_sp) const; protected: std::string m_platform_name; ConstString m_sdk_sysroot; ConstString m_sdk_build; + bool m_container; llvm::VersionTuple m_os_version; bool m_include_platform_option; }; diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index aa09b345e4e1a5e3af0a799057d210ac294b849d..997472c591269ff0105a7c38bf3656d8f62b47dd 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -455,6 +455,10 @@ public: void SetSDKBuild(ConstString sdk_build) { m_sdk_build = sdk_build; } + void SetContainer(bool b_container) { m_container = b_container; } + + bool GetContainer() const { return m_container; } + // Override this to return true if your platform supports Clang modules. You // may also need to override AddClangModuleCompilationOptions to pass the // right Clang flags for your platform. @@ -544,6 +548,8 @@ public: virtual Status Unlink(const FileSpec &file_spec); + virtual ConstString GetMmapSymbolName(const ArchSpec &arch); + virtual MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, lldb::addr_t length, @@ -874,6 +880,7 @@ protected: ConstString m_sdk_sysroot; // the root location of where the SDK files are all located ConstString m_sdk_build; + bool m_container; FileSpec m_working_dir; // The working directory which is used when installing // modules that have no install path set std::string m_remote_url; diff --git a/lldb/include/lldb/Target/ThreadPlanStepRange.h b/lldb/include/lldb/Target/ThreadPlanStepRange.h index 2fe88527710006b00f395ebf98e713ca025ce28c..36288a0d10aefccae00690f0a2974e3944cb4791 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepRange.h @@ -44,6 +44,7 @@ protected: bool InRange(); lldb::FrameComparison CompareCurrentFrameToStartFrame(); bool InSymbol(); + bool MaybeAArch32Or64FunctionTail(); void DumpRanges(Stream *s); Disassembler *GetDisassembler(); diff --git a/lldb/packages/Python/lldbsuite/test/concurrent_base.py b/lldb/packages/Python/lldbsuite/test/concurrent_base.py index 6acd71ce9e46d8acc124301d0937218e659f3c90..bb33d05da2167a03f90d66aaf02da125a72e1177 100644 --- a/lldb/packages/Python/lldbsuite/test/concurrent_base.py +++ b/lldb/packages/Python/lldbsuite/test/concurrent_base.py @@ -76,7 +76,7 @@ class ConcurrentEventsBase(TestBase): bp = self.inferior_target.FindBreakpointByID(bpno) descriptions.append( ": file = 'main.cpp', line = %d" % - self.finish_breakpoint_line) + line) return bp def inferior_done(self): diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index 191a1e0ad7cccf78bd20f3a1cbd75a6909e62654..dc553938e1cceabfb4b31bb993cc0ae25fc4edc0 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -663,6 +663,9 @@ def skipIfPlatform(oslist): return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist, "skip on %s" % (", ".join(oslist))) +def skipOnOpenHarmonyCI(func): + return unittest2.skipIf(lldbplatformutil.isOpenHarmonyCI(), "skip on OpenHarmony CI")(func) + def skipUnlessPlatform(oslist): """Decorate the item to skip tests unless running on one of the listed platforms.""" diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 719131c9248e816c5c4ae9ef88f7a68c7bdd405b..317f19bd712f69042c3fde8e956f3c8e91764a06 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -149,6 +149,8 @@ def platformIsDarwin(): """Returns true if the OS triple for the selected platform is any valid apple OS""" return getPlatform() in getDarwinOSTriples() +def isOpenHarmonyCI(): + return getPlatform() == 'linux' and os.path.exists('/.dockerenv') def findMainThreadCheckerDylib(): if not platformIsDarwin(): diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index d46e54f30bd5555c88d7484ea21d2a9837ebb7e7..2889030cc21f555635d8b2fcef978e18be88db22 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -739,11 +739,6 @@ class Base(unittest2.TestCase): for setting, value in configuration.settings: commands.append('setting set %s %s'%(setting, value)) - # Make sure that a sanitizer LLDB's environment doesn't get passed on. - if cls.platformContext and cls.platformContext.shlib_environment_var in os.environ: - commands.append('settings set target.env-vars {}='.format( - cls.platformContext.shlib_environment_var)) - # Set environment variables for the inferior. if lldbtest_config.inferior_env: commands.append('settings set target.env-vars {}'.format( @@ -897,6 +892,56 @@ class Base(unittest2.TestCase): self.subprocesses.append(proc) return proc + def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): + """ + Ask the command interpreter to handle the command and then check its + return status. + """ + # Fail fast if 'cmd' is not meaningful. + if cmd is None: + raise Exception("Bad 'cmd' parameter encountered") + + trace = (True if traceAlways else trace) + + if cmd.startswith("target create "): + cmd = cmd.replace("target create ", "file ") + + running = (cmd.startswith("run") or cmd.startswith("process launch")) + + for i in range(self.maxLaunchCount if running else 1): + self.ci.HandleCommand(cmd, self.res, inHistory) + + with recording(self, trace) as sbuf: + print("runCmd:", cmd, file=sbuf) + if not check: + print("check of return status not required", file=sbuf) + if self.res.Succeeded(): + print("output:", self.res.GetOutput(), file=sbuf) + else: + print("runCmd failed!", file=sbuf) + print(self.res.GetError(), file=sbuf) + + if self.res.Succeeded(): + break + elif running: + # For process launch, wait some time before possible next try. + time.sleep(self.timeWaitNextLaunch) + with recording(self, trace) as sbuf: + print("Command '" + cmd + "' failed!", file=sbuf) + + if check: + output = "" + if self.res.GetOutput(): + output += "\nCommand output:\n" + self.res.GetOutput() + if self.res.GetError(): + output += "\nError output:\n" + self.res.GetError() + if msg: + msg += output + if cmd: + cmd += output + self.assertTrue(self.res.Succeeded(), + msg if (msg) else CMD_MSG(cmd)) + def HideStdout(self): """Hide output to stdout from the user. @@ -1947,56 +1992,6 @@ class TestBase(Base): if matched: self.runCmd('thread select %s' % matched.group(1)) - def runCmd(self, cmd, msg=None, check=True, trace=False, inHistory=False): - """ - Ask the command interpreter to handle the command and then check its - return status. - """ - # Fail fast if 'cmd' is not meaningful. - if cmd is None: - raise Exception("Bad 'cmd' parameter encountered") - - trace = (True if traceAlways else trace) - - if cmd.startswith("target create "): - cmd = cmd.replace("target create ", "file ") - - running = (cmd.startswith("run") or cmd.startswith("process launch")) - - for i in range(self.maxLaunchCount if running else 1): - self.ci.HandleCommand(cmd, self.res, inHistory) - - with recording(self, trace) as sbuf: - print("runCmd:", cmd, file=sbuf) - if not check: - print("check of return status not required", file=sbuf) - if self.res.Succeeded(): - print("output:", self.res.GetOutput(), file=sbuf) - else: - print("runCmd failed!", file=sbuf) - print(self.res.GetError(), file=sbuf) - - if self.res.Succeeded(): - break - elif running: - # For process launch, wait some time before possible next try. - time.sleep(self.timeWaitNextLaunch) - with recording(self, trace) as sbuf: - print("Command '" + cmd + "' failed!", file=sbuf) - - if check: - output = "" - if self.res.GetOutput(): - output += "\nCommand output:\n" + self.res.GetOutput() - if self.res.GetError(): - output += "\nError output:\n" + self.res.GetError() - if msg: - msg += output - if cmd: - cmd += output - self.assertTrue(self.res.Succeeded(), - msg if (msg) else CMD_MSG(cmd)) - def match( self, str, diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py index df1fd2cb71b6f2c96f2d7915a51ebd024e857f3b..794f4170832c45961437bf1778b90dcfabd9de44 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -139,7 +139,9 @@ class GdbRemoteTestCaseBase(Base): if configuration.lldb_platform_url.startswith('unix-'): url_pattern = '(.+)://\[?(.+?)\]?/.*' else: - url_pattern = '(.+)://(.+):\d+' + # use (.*) for host instead of (.+) because + # 'connect://:port' - is a valid way to connect to lldb-server + url_pattern = '(.+)://(.*):\d+' scheme, host = re.match( url_pattern, configuration.lldb_platform_url).groups() if configuration.lldb_platform_name == 'remote-android' and host != 'localhost': @@ -274,8 +276,8 @@ class GdbRemoteTestCaseBase(Base): logger = self.logger - triple = self.dbg.GetSelectedPlatform().GetTriple() - if re.match(".*-.*-.*-android", triple): + # TODO: forward port always when use adb connection + if configuration.lldb_platform_name == 'remote-android': self.forward_adb_port( self.port, self.port, diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 98c6a3b2dd301d7ea7f41f575b9ddf198a0aa4ef..87f5af22d80285c850f9f2004c3df9ed1a137c37 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -166,11 +166,16 @@ public: protected: bool DoExecute(Args &args, CommandReturnObject &result) override { - if (args.GetArgumentCount() == 1) { + if (args.GetArgumentCount() >= 1) { const char *platform_name = args.GetArgumentAtIndex(0); if (platform_name && platform_name[0]) { const bool select = true; m_platform_options.SetPlatformName(platform_name); + if (args.GetArgumentCount() == 2) { + std::string inner(args.GetArgumentAtIndex(1)); + if (inner == "inner") + m_platform_options.SetContainer(true); + } Status error; ArchSpec platform_arch; PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions( diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index a6efeb3f960f7fc20264287b50cbc2f408974b69..2a080fbcfd221baa216f1fb04b8b88199b4e98bb 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -167,6 +167,18 @@ public: const Constant *constant = dyn_cast(value); if (constant) { + if (constant->getValueID() == Value::ConstantFPVal) { + if (auto *cfp = dyn_cast(constant)) { + if (cfp->getType()->isDoubleTy()) + scalar = cfp->getValueAPF().convertToDouble(); + else if (cfp->getType()->isFloatTy()) + scalar = cfp->getValueAPF().convertToFloat(); + else + return false; + return true; + } + return false; + } APInt value_apint; if (!ResolveConstantValue(value_apint, constant)) @@ -189,9 +201,18 @@ public: lldb::offset_t offset = 0; if (value_size <= 8) { - uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); - return AssignToMatchType(scalar, llvm::APInt(64, u64value), - value->getType()); + Type *ty = value->getType(); + if (ty->isDoubleTy()) { + scalar = value_extractor.GetDouble(&offset); + return true; + } else if (ty->isFloatTy()) { + scalar = value_extractor.GetFloat(&offset); + return true; + } else { + uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); + return AssignToMatchType(scalar, llvm::APInt(64, u64value), + value->getType()); + } } return false; @@ -205,11 +226,15 @@ public: return false; lldb_private::Scalar cast_scalar; - - scalar.MakeUnsigned(); - if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), - value->getType())) - return false; + Type *vty = value->getType(); + if (vty->isFloatTy() || vty->isDoubleTy()) { + cast_scalar = scalar; + } else { + scalar.MakeUnsigned(); + if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), + value->getType())) + return false; + } size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); @@ -543,16 +568,17 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, } break; case Instruction::GetElementPtr: break; + case Instruction::FCmp: case Instruction::ICmp: { - ICmpInst *icmp_inst = dyn_cast(&ii); + CmpInst *cmp_inst = dyn_cast(&ii); - if (!icmp_inst) { + if (!cmp_inst) { error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; } - switch (icmp_inst->getPredicate()) { + switch (cmp_inst->getPredicate()) { default: { LLDB_LOGF(log, "Unsupported ICmp predicate: %s", PrintValue(&ii).c_str()); @@ -561,11 +587,17 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, error.SetErrorString(unsupported_opcode_error); return false; } + case CmpInst::FCMP_OEQ: case CmpInst::ICMP_EQ: + case CmpInst::FCMP_UNE: case CmpInst::ICMP_NE: + case CmpInst::FCMP_OGT: case CmpInst::ICMP_UGT: + case CmpInst::FCMP_OGE: case CmpInst::ICMP_UGE: + case CmpInst::FCMP_OLT: case CmpInst::ICMP_ULT: + case CmpInst::FCMP_OLE: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: @@ -595,6 +627,11 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, case Instruction::Xor: case Instruction::ZExt: break; + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + break; } for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) { @@ -709,7 +746,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, case Instruction::AShr: case Instruction::And: case Instruction::Or: - case Instruction::Xor: { + case Instruction::Xor: + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: { const BinaryOperator *bin_op = dyn_cast(inst); if (!bin_op) { @@ -748,12 +789,15 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, default: break; case Instruction::Add: + case Instruction::FAdd: result = L + R; break; case Instruction::Mul: + case Instruction::FMul: result = L * R; break; case Instruction::Sub: + case Instruction::FSub: result = L - R; break; case Instruction::SDiv: @@ -766,6 +810,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, R.MakeUnsigned(); result = L / R; break; + case Instruction::FDiv: + result = L / R; + break; case Instruction::SRem: L.MakeSigned(); R.MakeSigned(); @@ -1028,10 +1075,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str()); } } break; + case Instruction::FCmp: case Instruction::ICmp: { - const ICmpInst *icmp_inst = cast(inst); + const CmpInst *cmp_inst = cast(inst); - CmpInst::Predicate predicate = icmp_inst->getPredicate(); + CmpInst::Predicate predicate = cmp_inst->getPredicate(); Value *lhs = inst->getOperand(0); Value *rhs = inst->getOperand(1); @@ -1059,9 +1107,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, default: return false; case CmpInst::ICMP_EQ: + case CmpInst::FCMP_OEQ: result = (L == R); break; case CmpInst::ICMP_NE: + case CmpInst::FCMP_UNE: result = (L != R); break; case CmpInst::ICMP_UGT: @@ -1074,16 +1124,28 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, R.MakeUnsigned(); result = (L >= R); break; + case CmpInst::FCMP_OGE: + result = (L >= R); + break; + case CmpInst::FCMP_OGT: + result = (L > R); + break; case CmpInst::ICMP_ULT: L.MakeUnsigned(); R.MakeUnsigned(); result = (L < R); break; + case CmpInst::FCMP_OLT: + result = (L < R); + break; case CmpInst::ICMP_ULE: L.MakeUnsigned(); R.MakeUnsigned(); result = (L <= R); break; + case CmpInst::FCMP_OLE: + result = (L <= R); + break; case CmpInst::ICMP_SGT: L.MakeSigned(); R.MakeSigned(); diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 64d9bb00ffab3622e19368f2f29653dea345ec56..ea368a6d4d71c45fe6a2d94e7016fbe27c0f2d02 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -96,7 +96,7 @@ else() endif() - elseif (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + elseif (CMAKE_SYSTEM_NAME MATCHES "Linux|Android|OHOS") add_host_subdirectory(linux linux/AbstractSocket.cpp linux/Host.cpp @@ -110,6 +110,11 @@ else() android/LibcGlue.cpp ) endif() + if (CMAKE_SYSTEM_NAME MATCHES "OHOS") + add_host_subdirectory(ohos + ohos/HostInfoOHOS.cpp + ) + endif() elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") add_host_subdirectory(freebsd freebsd/Host.cpp diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp index 8e384c9266b6b12a21500dbcd060aa2f81eea389..bfc1fb16ea0e15ab7b53e80c73faecd6263cf322 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/common/MainLoop.cpp @@ -86,7 +86,7 @@ private: int num_events = -1; #else -#ifdef __ANDROID__ +#if defined(__ANDROID__) fd_set read_fd_set; #else std::vector read_fds; @@ -140,7 +140,7 @@ void MainLoop::RunImpl::ProcessEvents() { } #else MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { -#ifndef __ANDROID__ +#if !defined(__ANDROID__) read_fds.reserve(loop.m_read_fds.size()); #endif } @@ -162,7 +162,7 @@ sigset_t MainLoop::RunImpl::get_sigmask() { return sigmask; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) Status MainLoop::RunImpl::Poll() { // ppoll(2) is not supported on older all android versions. Also, older // versions android (API <= 19) implemented pselect in a non-atomic way, as a @@ -218,7 +218,7 @@ Status MainLoop::RunImpl::Poll() { #endif void MainLoop::RunImpl::ProcessEvents() { -#ifdef __ANDROID__ +#if defined(__ANDROID__) // Collect first all readable file descriptors into a separate vector and // then iterate over it to invoke callbacks. Iterating directly over // loop.m_read_fds is not possible because the callbacks can modify the diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index c2fb5509034e5c20879d3df81e2f177c0ef8895b..db954a6d9efa32ad1fa4f48cc3fc3f489f3f6c8b 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -38,7 +38,7 @@ #include "lldb/Host/linux/AbstractSocket.h" #endif -#ifdef __ANDROID__ +#if defined(__ANDROID__) #include #include #include diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp index eabc9fef8a661c867978f7313f1005ef741feb84..c1d7308025eb22defb4dee6dd83f171c211952a6 100644 --- a/lldb/source/Host/common/TCPSocket.cpp +++ b/lldb/source/Host/common/TCPSocket.cpp @@ -160,6 +160,8 @@ Status TCPSocket::Connect(llvm::StringRef name) { std::vector addresses = SocketAddress::GetAddressInfo(host_port->hostname.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + llvm::partition(addresses, + [](auto &sa) { return sa.GetFamily() == AF_INET; }); for (SocketAddress &address : addresses) { error = CreateSocket(address.GetFamily()); if (error.Fail()) diff --git a/lldb/source/Host/ohos/HostInfoOHOS.cpp b/lldb/source/Host/ohos/HostInfoOHOS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e47d26e3e93868d2fc1fbe6dbd241ed83264576b --- /dev/null +++ b/lldb/source/Host/ohos/HostInfoOHOS.cpp @@ -0,0 +1,94 @@ +//===-- HostInfoOHOS.cpp -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ohos/HostInfoOHOS.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/linux/HostInfoLinux.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +using namespace lldb_private; +using namespace llvm; + +void HostInfoOHOS::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64); + + if (arch_32.IsValid()) { + arch_32.GetTriple().setEnvironment(llvm::Triple::UnknownEnvironment); + } + if (arch_64.IsValid()) { + arch_64.GetTriple().setEnvironment(llvm::Triple::UnknownEnvironment); + } +} + +FileSpec HostInfoOHOS::GetDefaultShell() { + return FileSpec("/system/bin/sh"); +} + +FileSpec HostInfoOHOS::ResolveLibraryPath(const std::string &module_path, + const ArchSpec &arch) { + static const char *const ld_library_path_separator = ":"; + static const char *const default_lib32_path[] = {"/vendor/lib", "/system/lib", + nullptr}; + static const char *const default_lib64_path[] = {"/vendor/lib64", + "/system/lib64", nullptr}; + + if (module_path.empty() || module_path[0] == '/') { + FileSpec file_spec(module_path.c_str()); + FileSystem::Instance().Resolve(file_spec); + return file_spec; + } + + SmallVector ld_paths; + + if (const char *ld_library_path = ::getenv("LD_LIBRARY_PATH")) + StringRef(ld_library_path) + .split(ld_paths, StringRef(ld_library_path_separator), -1, false); + + const char *const *default_lib_path = nullptr; + switch (arch.GetAddressByteSize()) { + case 4: + default_lib_path = default_lib32_path; + break; + case 8: + default_lib_path = default_lib64_path; + break; + default: + assert(false && "Unknown address byte size"); + return FileSpec(); + } + + for (const char *const *it = default_lib_path; *it; ++it) + ld_paths.push_back(StringRef(*it)); + + for (const StringRef &path : ld_paths) { + FileSpec file_candidate(path.str().c_str()); + FileSystem::Instance().Resolve(file_candidate); + file_candidate.AppendPathComponent(module_path.c_str()); + + if (FileSystem::Instance().Exists(file_candidate)) + return file_candidate; + } + + return FileSpec(); +} + +bool HostInfoOHOS::ComputeTempFileBaseDirectory(FileSpec &file_spec) { + bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); + + // On OHOS, there is no path which is guaranteed to be writable. If the + // user has not provided a path via an environment variable, the generic + // algorithm will deduce /tmp, which is plain wrong. In that case we have an + // invalid directory, we substitute the path with /data/local/tmp, which is + // correct at least in some cases (i.e., when running as shell user). + if (!success || !FileSystem::Instance().Exists(file_spec)) + file_spec = FileSpec("/data/local/tmp"); + + return FileSystem::Instance().Exists(file_spec); +} diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index ddbd983abb81dd155d20888caa1093d4b33b8beb..bd2809817de8b5e2f3ec6df001c604974e115001 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -18,7 +18,7 @@ using namespace lldb; using namespace lldb_private; -#ifdef __ANDROID__ +#if defined(__ANDROID__) // Android does not have SUN_LEN #ifndef SUN_LEN #define SUN_LEN(ptr) \ diff --git a/lldb/source/Host/posix/HostInfoPosix.cpp b/lldb/source/Host/posix/HostInfoPosix.cpp index 63553590dff51119534aefefaad4c8bf8232733f..0c8e05aecdf319e17bee59b71eadf5752e60c029 100644 --- a/lldb/source/Host/posix/HostInfoPosix.cpp +++ b/lldb/source/Host/posix/HostInfoPosix.cpp @@ -95,7 +95,7 @@ llvm::Optional PosixUserIDResolver::DoGetUserName(id_t uid) { } llvm::Optional PosixUserIDResolver::DoGetGroupName(id_t gid) { -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__OHOS_FAMILY__) char group_buffer[PATH_MAX]; size_t group_buffer_size = sizeof(group_buffer); struct group group_info; diff --git a/lldb/source/Interpreter/OptionGroupPlatform.cpp b/lldb/source/Interpreter/OptionGroupPlatform.cpp index acdf3f293496f6222b080d2b68eab3870d852079..45694fe112dfd0e18abded738861b7adbd34d23b 100644 --- a/lldb/source/Interpreter/OptionGroupPlatform.cpp +++ b/lldb/source/Interpreter/OptionGroupPlatform.cpp @@ -21,7 +21,10 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions( PlatformList &platforms = interpreter.GetDebugger().GetPlatformList(); PlatformSP platform_sp; - + Log *log = GetLog(LLDBLog::Commands); + if (log) + log->Printf("Hsu file(%s):%d OptionGroupPlatform::%s call make_selected:%d", + __FILE__, __LINE__, __FUNCTION__, make_selected); if (!m_platform_name.empty()) { platform_sp = platforms.Create(m_platform_name); if (!platform_sp) { @@ -30,6 +33,11 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions( m_platform_name); } if (platform_sp) { + if (GetContainer()) { + if (log) + log->Printf("Platform is created inside container."); + platform_sp->SetContainer(true); + } if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture( arch, {}, false, &platform_arch)) { error.SetErrorStringWithFormatv("platform '{0}' doesn't support '{1}'", @@ -65,6 +73,7 @@ void OptionGroupPlatform::OptionParsingStarting( m_sdk_sysroot.Clear(); m_sdk_build.Clear(); m_os_version = llvm::VersionTuple(); + m_container = false; } static constexpr OptionDefinition g_option_table[] = { @@ -99,7 +108,6 @@ OptionGroupPlatform::SetOptionValue(uint32_t option_idx, ++option_idx; const int short_option = g_option_table[option_idx].short_option; - switch (short_option) { case 'p': m_platform_name.assign(std::string(option_arg)); @@ -141,6 +149,10 @@ bool OptionGroupPlatform::PlatformMatches( if (!m_os_version.empty() && m_os_version != platform_sp->GetOSVersion()) return false; + + if (m_container != platform_sp->GetContainer()) + return false; + return true; } return false; diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt index 6869587f917ebab915a5ecfa9ca290da9e8884cd..c2c5c9f73be5f27e5f3ac32a9a5e17713ceecf0e 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -8,3 +8,5 @@ add_subdirectory(OpenBSD) add_subdirectory(POSIX) add_subdirectory(QemuUser) add_subdirectory(Windows) +add_subdirectory(HOS) +add_subdirectory(OHOS) diff --git a/lldb/source/Plugins/Platform/HOS/CMakeLists.txt b/lldb/source/Plugins/Platform/HOS/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ec9e85def9f55c498fd48d6d61191a39646e86c4 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/CMakeLists.txt @@ -0,0 +1,4 @@ +add_lldb_library(lldbPluginPlatformHOS PLUGIN HdcClient.cpp PlatformHOS.cpp + PlatformHOSRemoteGDBServer.cpp LINK_LIBS lldbCore + lldbHost lldbPluginPlatformLinux lldbPluginPlatformGDB + LINK_COMPONENTS Support) diff --git a/lldb/source/Plugins/Platform/HOS/HdcClient.cpp b/lldb/source/Plugins/Platform/HOS/HdcClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ee3d17b73dc60cd40399ada49f3c373dcbf4200 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/HdcClient.cpp @@ -0,0 +1,790 @@ +//===-- HdcClient.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HdcClient.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileUtilities.h" + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/PosixApi.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timeout.h" + +#include + +#include +#include +#include +#include + +// On Windows, transitive dependencies pull in , which defines a +// macro that clashes with a method name. +#ifdef SendMessage +#undef SendMessage +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_hos; +using namespace std::chrono; + +namespace { + +const seconds kReadTimeout(20); +const char *kOKAY = "OKAY"; +const char *kFAIL = "FAIL"; +const char *kDATA = "DATA"; +const char *kDONE = "DONE"; + +const char *kSEND = "SEND"; +const char *kRECV = "RECV"; +const char *kSTAT = "STAT"; + +const size_t kSyncPacketLen = 8; +// Maximum size of a filesync DATA packet. +const size_t kMaxPushData = 2 * 1024; +// Default mode for pushed files. +const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG + +const char *kSocketNamespaceAbstract = "localabstract"; +const char *kSocketNamespaceFileSystem = "localfilesystem"; + +Status ReadAllBytes(Connection &conn, void *buffer, size_t size) { + + Status error; + ConnectionStatus status; + char *read_buffer = static_cast(buffer); + + auto now = steady_clock::now(); + const auto deadline = now + kReadTimeout; + size_t total_read_bytes = 0; + while (total_read_bytes < size && now < deadline) { + auto read_bytes = + conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, + duration_cast(deadline - now), status, &error); + if (error.Fail()) + return error; + total_read_bytes += read_bytes; + if (status != eConnectionStatusSuccess) + break; + now = steady_clock::now(); + } + if (total_read_bytes < size) + error = Status( + "Unable to read requested number of bytes. Connection status: %d.", + status); + return error; +} + +} // namespace + +Status HdcClient::CreateByDeviceID(const std::string &device_id, + HdcClient &hdc) { + DeviceIDList connect_devices; + auto error = hdc.GetDevices(connect_devices); + if (error.Fail()) + return error; + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s device_id(%s)", __FILE__, + __LINE__, __FUNCTION__, device_id.c_str()); + std::string android_serial; + if (!device_id.empty()) + android_serial = device_id; + else if (const char *env_serial = std::getenv("ANDROID_SERIAL")) + android_serial = env_serial; + + if (android_serial.empty()) { + if (connect_devices.size() != 1) + return Status("Expected a single connected device, got instead %zu - try " + "setting 'ANDROID_SERIAL'", + connect_devices.size()); + hdc.SetDeviceID(connect_devices.front()); + } else { + auto find_it = std::find(connect_devices.begin(), connect_devices.end(), + android_serial); + if (find_it == connect_devices.end()) + return Status("Device \"%s\" not found", android_serial.c_str()); + + hdc.SetDeviceID(*find_it); + } + return error; +} + +HdcClient::HdcClient() {} + +HdcClient::HdcClient(const std::string &device_id) : m_device_id(device_id) {} + +HdcClient::~HdcClient() {} + +void HdcClient::SetDeviceID(const std::string &device_id) { + m_device_id = device_id; + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s m_device_id(%s)", __FILE__, + __LINE__, __FUNCTION__, m_device_id.c_str()); +} + +const std::string &HdcClient::GetDeviceID() const { return m_device_id; } + +Status HdcClient::Connect() { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s new ConnectionFileDescriptor", + __FILE__, __LINE__, __FUNCTION__); + Status error; + m_conn.reset(new ConnectionFileDescriptor); + std::string port = "5037"; + + const char *env_port = std::getenv("HDC_SERVER_PORT"); + if ((env_port != NULL) && (atoi(env_port) > 0)) { + port = env_port; + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s env_port(%s) port(%s)", + __FILE__, __LINE__, __FUNCTION__, env_port, port.c_str()); + } + + std::string uri = "connect://127.0.0.1:" + port; + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s uri(%s)", __FILE__, __LINE__, + __FUNCTION__, uri.c_str()); + m_conn->Connect(uri.c_str(), &error); + + return error; +} + +Status HdcClient::GetDevices(DeviceIDList &device_list) { + device_list.clear(); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s call", __FILE__, __LINE__, + __FUNCTION__); + auto error = SendMessage("host:devices"); + if (error.Fail()) + return error; + + error = ReadResponseStatus(); + if (error.Fail()) + return error; + + std::vector in_buffer; + error = ReadMessage(in_buffer); + + llvm::StringRef response(&in_buffer[0], in_buffer.size()); + llvm::SmallVector devices; + response.split(devices, "\n", -1, false); + + for (const auto &device : devices) + device_list.push_back(device.split('\t').first.str()); + + // Force disconnect since hdc closes connection after host:devices response + // is sent. + m_conn.reset(); + return error; +} + +Status HdcClient::SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s local_port(%d) remote_port(%d)", + __FILE__, __LINE__, __FUNCTION__, local_port, remote_port); + char message[48]; + snprintf(message, sizeof(message), "forward:tcp:%d;tcp:%d", local_port, + remote_port); + + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s message(%s)", __FILE__, __LINE__, + __FUNCTION__, message); + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status +HdcClient::SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s local_port(%d)", __FILE__, + __LINE__, __FUNCTION__, local_port); + char message[PATH_MAX]; + const char *sock_namespace_str = + (socket_namespace == UnixSocketNamespaceAbstract) + ? kSocketNamespaceAbstract + : kSocketNamespaceFileSystem; + snprintf(message, sizeof(message), "forward:tcp:%d;%s:%s", local_port, + sock_namespace_str, remote_socket_name.str().c_str()); + + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s message(%s)", __FILE__, __LINE__, + __FUNCTION__, message); + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status HdcClient::DeletePortForwarding(const uint16_t local_port) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s local_port(%d)", __FILE__, + __LINE__, __FUNCTION__, local_port); + char message[32]; + snprintf(message, sizeof(message), "killforward:tcp:%d", local_port); + + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s message(%s)", __FILE__, __LINE__, + __FUNCTION__, message); + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status HdcClient::SendMessage(const std::string &packet, const bool reconnect) { + Status error; + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s packet(%s) reconnect(%d)", + __FILE__, __LINE__, __FUNCTION__, packet.c_str(), reconnect); + if (!m_conn || reconnect) { + error = Connect(); + if (error.Fail()) + return error; + } + + char length_buffer[5]; + snprintf(length_buffer, sizeof(length_buffer), "%04x", + static_cast(packet.size())); + + ConnectionStatus status; + + m_conn->Write(length_buffer, 4, status, &error); + if (error.Fail()) + return error; + + m_conn->Write(packet.c_str(), packet.size(), status, &error); + return error; +} + +Status HdcClient::SendDeviceMessage(const std::string &packet) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s packet(%s) ", __FILE__, __LINE__, + __FUNCTION__, packet.c_str()); + + std::ostringstream msg; + msg << "host-serial:" << m_device_id << ":" << packet; + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s msg(%s) ", __FILE__, __LINE__, + __FUNCTION__, msg.str().c_str()); + + return SendMessage(msg.str()); +} + +Status HdcClient::ReadMessage(std::vector &message) { + message.clear(); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s call ", __FILE__, __LINE__, + __FUNCTION__); + char buffer[5]; + buffer[4] = 0; + + auto error = ReadAllBytes(buffer, 4); + if (error.Fail()) + return error; + + unsigned int packet_len = 0; + sscanf(buffer, "%x", &packet_len); + + message.resize(packet_len, 0); + error = ReadAllBytes(&message[0], packet_len); + if (error.Fail()) + message.clear(); + + return error; +} + +Status HdcClient::ReadMessageStream(std::vector &message, + milliseconds timeout) { + auto start = steady_clock::now(); + message.clear(); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s call ", __FILE__, __LINE__, + __FUNCTION__); + + Status error; + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char buffer[1024]; + while (error.Success() && status == lldb::eConnectionStatusSuccess) { + auto end = steady_clock::now(); + auto elapsed = end - start; + if (elapsed >= timeout) + return Status("Timed out"); + + size_t n = m_conn->Read(buffer, sizeof(buffer), + duration_cast(timeout - elapsed), + status, &error); + if (n > 0) + message.insert(message.end(), &buffer[0], &buffer[n]); + } + return error; +} + +Status HdcClient::ReadResponseStatus() { + char response_id[5]; + static const size_t packet_len = 4; + response_id[packet_len] = 0; + + auto error = ReadAllBytes(response_id, packet_len); + if (error.Fail()) + return error; + + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s response_id(%s) ", __FILE__, + __LINE__, __FUNCTION__, response_id); + + if (strncmp(response_id, kOKAY, packet_len) != 0) + return GetResponseError(response_id); + + return error; +} + +Status HdcClient::GetResponseError(const char *response_id) { + if (strcmp(response_id, kFAIL) != 0) + return Status("Got unexpected response id from hdc: \"%s\"", response_id); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s response_id(%s) ", __FILE__, + __LINE__, __FUNCTION__, response_id); + + std::vector error_message; + auto error = ReadMessage(error_message); + if (error.Success()) + error.SetErrorString( + std::string(&error_message[0], error_message.size()).c_str()); + + return error; +} + +Status HdcClient::SwitchDeviceTransport() { + std::ostringstream msg; + msg << "host:transport:" << m_device_id; + + auto error = SendMessage(msg.str()); + if (error.Fail()) + return error; + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s m_device_id(%s) msg(%s)", + __FILE__, __LINE__, __FUNCTION__, m_device_id.c_str(), + msg.str().c_str()); + + return ReadResponseStatus(); +} + +Status HdcClient::StartSync() { + auto error = SwitchDeviceTransport(); + if (error.Fail()) + return Status("Failed to switch to device transport: %s", + error.AsCString()); + + error = Sync(); + if (error.Fail()) + return Status("Sync failed: %s", error.AsCString()); + + return error; +} + +Status HdcClient::Sync() { + auto error = SendMessage("sync:", false); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status HdcClient::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size); +} + +Status HdcClient::internalShell(const char *command, milliseconds timeout, + std::vector &output_buf) { + output_buf.clear(); + + auto error = SwitchDeviceTransport(); + if (error.Fail()) + return Status("Failed to switch to device transport: %s", + error.AsCString()); + + StreamString hdc_command; + hdc_command.Printf("shell:%s", command); + error = SendMessage(hdc_command.GetString().str(), false); + if (error.Fail()) + return error; + + error = ReadResponseStatus(); + if (error.Fail()) + return error; + + error = ReadMessageStream(output_buf, timeout); + if (error.Fail()) + return error; + + // HDC doesn't propagate return code of shell execution - if + // output starts with /system/bin/sh: most likely command failed. + static const char *kShellPrefix = "/system/bin/sh:"; + if (output_buf.size() > strlen(kShellPrefix)) { + if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix))) + return Status("Shell command %s failed: %s", command, + std::string(output_buf.begin(), output_buf.end()).c_str()); + } + + return Status(); +} + +Status HdcClient::Shell(const char *command, milliseconds timeout, + std::string *output) { + std::vector output_buffer; + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s command(%s)", __FILE__, __LINE__, + __FUNCTION__, command); + + auto error = internalShell(command, timeout, output_buffer); + if (error.Fail()) + return error; + + if (output) + output->assign(output_buffer.begin(), output_buffer.end()); + return error; +} + +Status HdcClient::ShellToFile(const char *command, milliseconds timeout, + const FileSpec &output_file_spec) { + std::vector output_buffer; + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s command(%s)", __FILE__, __LINE__, + __FUNCTION__, command); + + auto error = internalShell(command, timeout, output_buffer); + if (error.Fail()) + return error; + + const auto output_filename = output_file_spec.GetPath(); + std::error_code EC; + llvm::raw_fd_ostream dst(output_filename, EC, llvm::sys::fs::OF_None); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s output_filename(%s)", __FILE__, + __LINE__, __FUNCTION__, output_filename.c_str()); + if (EC) + return Status("Unable to open local file %s", output_filename.c_str()); + + dst.write(&output_buffer[0], output_buffer.size()); + dst.close(); + if (dst.has_error()) + return Status("Failed to write file %s", output_filename.c_str()); + return Status(); +} + +std::unique_ptr +HdcClient::GetSyncService(Status &error) { + std::unique_ptr sync_service; + error = StartSync(); + if (error.Success()) + sync_service.reset(new SyncService(std::move(m_conn))); + + return sync_service; +} + +Status HdcClient::SyncService::internalPullFile(const FileSpec &remote_file, + const FileSpec &local_file) { + const auto local_file_path = local_file.GetPath(); + llvm::FileRemover local_file_remover(local_file_path); + + std::error_code EC; + llvm::raw_fd_ostream dst(local_file_path, EC, llvm::sys::fs::OF_None); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s local_file_path(%s)", __FILE__, + __LINE__, __FUNCTION__, local_file_path.c_str()); + + if (EC) + return Status("Unable to open local file %s", local_file_path.c_str()); + + const auto remote_file_path = remote_file.GetPath(false); + auto error = SendSyncRequest(kRECV, remote_file_path.length(), + remote_file_path.c_str()); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s remote_file_path(%s)", __FILE__, + __LINE__, __FUNCTION__, remote_file_path.c_str()); + + if (error.Fail()) + return error; + + std::vector chunk; + bool eof = false; + while (!eof) { + error = PullFileChunk(chunk, eof); + if (error.Fail()) + return error; + if (!eof) + dst.write(&chunk[0], chunk.size()); + } + dst.close(); + if (dst.has_error()) + return Status("Failed to write file %s", local_file_path.c_str()); + + local_file_remover.releaseFile(); + return error; +} + +Status HdcClient::SyncService::internalPushFile(const FileSpec &local_file, + const FileSpec &remote_file) { + const auto local_file_path(local_file.GetPath()); + std::ifstream src(local_file_path.c_str(), std::ios::in | std::ios::binary); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s local_file_path(%s)", __FILE__, + __LINE__, __FUNCTION__, local_file_path.c_str()); + + if (!src.is_open()) + return Status("Unable to open local file %s", local_file_path.c_str()); + + std::stringstream file_description; + file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode; + std::string file_description_str = file_description.str(); + auto error = SendSyncRequest(kSEND, file_description_str.length(), + file_description_str.c_str()); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s file_description_str(%s)", + __FILE__, __LINE__, __FUNCTION__, file_description_str.c_str()); + + if (error.Fail()) + return error; + + char chunk[kMaxPushData]; + while (!src.eof() && !src.read(chunk, kMaxPushData).bad()) { + size_t chunk_size = src.gcount(); + error = SendSyncRequest(kDATA, chunk_size, chunk); + if (error.Fail()) + return Status("Failed to send file chunk: %s", error.AsCString()); + } + error = SendSyncRequest( + kDONE, + llvm::sys::toTimeT( + FileSystem::Instance().GetModificationTime(local_file)), + nullptr); + if (error.Fail()) + return error; + + std::string response_id; + uint32_t data_len; + error = ReadSyncHeader(response_id, data_len); + if (error.Fail()) + return Status("Failed to read DONE response: %s", error.AsCString()); + if (response_id == kFAIL) { + std::string error_message(data_len, 0); + error = ReadAllBytes(&error_message[0], data_len); + if (error.Fail()) + return Status("Failed to read DONE error message: %s", error.AsCString()); + return Status("Failed to push file: %s", error_message.c_str()); + } else if (response_id != kOKAY) + return Status("Got unexpected DONE response: %s", response_id.c_str()); + + // If there was an error reading the source file, finish the hdc file + // transfer first so that hdc isn't expecting any more data. + if (src.bad()) + return Status("Failed read on %s", local_file_path.c_str()); + return error; +} + +Status HdcClient::SyncService::internalStat(const FileSpec &remote_file, + uint32_t &mode, uint32_t &size, + uint32_t &mtime) { + const std::string remote_file_path(remote_file.GetPath(false)); + auto error = SendSyncRequest(kSTAT, remote_file_path.length(), + remote_file_path.c_str()); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s remote_file_path(%s)", __FILE__, + __LINE__, __FUNCTION__, remote_file_path.c_str()); + + if (error.Fail()) + return Status("Failed to send request: %s", error.AsCString()); + + static const size_t stat_len = strlen(kSTAT); + static const size_t response_len = stat_len + (sizeof(uint32_t) * 3); + + std::vector buffer(response_len); + error = ReadAllBytes(&buffer[0], buffer.size()); + if (error.Fail()) + return Status("Failed to read response: %s", error.AsCString()); + + DataExtractor extractor(&buffer[0], buffer.size(), eByteOrderLittle, + sizeof(void *)); + offset_t offset = 0; + + const void *command = extractor.GetData(&offset, stat_len); + if (!command) + return Status("Failed to get response command"); + const char *command_str = static_cast(command); + if (strncmp(command_str, kSTAT, stat_len)) + return Status("Got invalid stat command: %s", command_str); + + mode = extractor.GetU32(&offset); + size = extractor.GetU32(&offset); + mtime = extractor.GetU32(&offset); + return Status(); +} + +Status HdcClient::SyncService::PullFile(const FileSpec &remote_file, + const FileSpec &local_file) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s remote_file(%s) local_file(%s)", + __FILE__, __LINE__, __FUNCTION__, remote_file.GetPath().c_str(), + local_file.GetPath().c_str()); + + return executeCommand([this, &remote_file, &local_file]() { + return internalPullFile(remote_file, local_file); + }); +} + +Status HdcClient::SyncService::PushFile(const FileSpec &local_file, + const FileSpec &remote_file) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s remote_file(%s) local_file(%s)", + __FILE__, __LINE__, __FUNCTION__, remote_file.GetPath().c_str(), + local_file.GetPath().c_str()); + return executeCommand([this, &local_file, &remote_file]() { + return internalPushFile(local_file, remote_file); + }); +} + +Status HdcClient::SyncService::Stat(const FileSpec &remote_file, uint32_t &mode, + uint32_t &size, uint32_t &mtime) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d HdcClient::%s remote_file(%s) mode(%d)", + __FILE__, __LINE__, __FUNCTION__, remote_file.GetPath().c_str(), + mode); + return executeCommand([this, &remote_file, &mode, &size, &mtime]() { + return internalStat(remote_file, mode, size, mtime); + }); +} + +bool HdcClient::SyncService::IsConnected() const { + return m_conn && m_conn->IsConnected(); +} + +HdcClient::SyncService::SyncService(std::unique_ptr &&conn) + : m_conn(std::move(conn)) {} + +Status +HdcClient::SyncService::executeCommand(const std::function &cmd) { + if (!m_conn) + return Status("SyncService is disconnected"); + + const auto error = cmd(); + if (error.Fail()) + m_conn.reset(); + + return error; +} + +HdcClient::SyncService::~SyncService() {} + +Status HdcClient::SyncService::SendSyncRequest(const char *request_id, + const uint32_t data_len, + const void *data) { + const DataBufferSP data_sp(new DataBufferHeap(kSyncPacketLen, 0)); + DataEncoder encoder(data_sp->GetBytes(), data_sp->GetByteSize(), + eByteOrderLittle, sizeof(void *)); + auto offset = encoder.PutData(0, request_id, strlen(request_id)); + encoder.PutUnsigned(offset, 4, data_len); + + Status error; + ConnectionStatus status; + m_conn->Write(data_sp->GetBytes(), kSyncPacketLen, status, &error); + if (error.Fail()) + return error; + + if (data) + m_conn->Write(data, data_len, status, &error); + return error; +} + +Status HdcClient::SyncService::ReadSyncHeader(std::string &response_id, + uint32_t &data_len) { + char buffer[kSyncPacketLen]; + + auto error = ReadAllBytes(buffer, kSyncPacketLen); + if (error.Success()) { + response_id.assign(&buffer[0], 4); + DataExtractor extractor(&buffer[4], 4, eByteOrderLittle, sizeof(void *)); + offset_t offset = 0; + data_len = extractor.GetU32(&offset); + } + + return error; +} + +Status HdcClient::SyncService::PullFileChunk(std::vector &buffer, + bool &eof) { + buffer.clear(); + + std::string response_id; + uint32_t data_len; + auto error = ReadSyncHeader(response_id, data_len); + if (error.Fail()) + return error; + + if (response_id == kDATA) { + buffer.resize(data_len, 0); + error = ReadAllBytes(&buffer[0], data_len); + if (error.Fail()) + buffer.clear(); + } else if (response_id == kDONE) { + eof = true; + } else if (response_id == kFAIL) { + std::string error_message(data_len, 0); + error = ReadAllBytes(&error_message[0], data_len); + if (error.Fail()) + return Status("Failed to read pull error message: %s", error.AsCString()); + return Status("Failed to pull file: %s", error_message.c_str()); + } else + return Status("Pull failed with unknown response: %s", response_id.c_str()); + + return Status(); +} + +Status HdcClient::SyncService::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size); +} diff --git a/lldb/source/Plugins/Platform/HOS/HdcClient.h b/lldb/source/Plugins/Platform/HOS/HdcClient.h new file mode 100644 index 0000000000000000000000000000000000000000..33d4370c9d020ef969c09475ab5fcb32a1d81914 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/HdcClient.h @@ -0,0 +1,138 @@ +//===-- HdcClient.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_HdcClient_h_ +#define liblldb_HdcClient_h_ + +#include "lldb/Utility/Status.h" +#include +#include +#include +#include +#include +#include + +namespace lldb_private { + +class FileSpec; + +namespace platform_hos { + +class HdcClient { +public: + enum UnixSocketNamespace { + UnixSocketNamespaceAbstract, + UnixSocketNamespaceFileSystem, + }; + + using DeviceIDList = std::list; + + class SyncService { + friend class HdcClient; + + public: + ~SyncService(); + + Status PullFile(const FileSpec &remote_file, const FileSpec &local_file); + + Status PushFile(const FileSpec &local_file, const FileSpec &remote_file); + + Status Stat(const FileSpec &remote_file, uint32_t &mode, uint32_t &size, + uint32_t &mtime); + + bool IsConnected() const; + + private: + explicit SyncService(std::unique_ptr &&conn); + + Status SendSyncRequest(const char *request_id, const uint32_t data_len, + const void *data); + + Status ReadSyncHeader(std::string &response_id, uint32_t &data_len); + + Status PullFileChunk(std::vector &buffer, bool &eof); + + Status ReadAllBytes(void *buffer, size_t size); + + Status internalPullFile(const FileSpec &remote_file, + const FileSpec &local_file); + + Status internalPushFile(const FileSpec &local_file, + const FileSpec &remote_file); + + Status internalStat(const FileSpec &remote_file, uint32_t &mode, + uint32_t &size, uint32_t &mtime); + + Status executeCommand(const std::function &cmd); + + std::unique_ptr m_conn; + }; + + static Status CreateByDeviceID(const std::string &device_id, HdcClient &hdc); + HdcClient(); + explicit HdcClient(const std::string &device_id); + + ~HdcClient(); + const std::string &GetDeviceID() const; + + Status GetDevices(DeviceIDList &device_list); + + Status SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port); + + Status SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace); + + Status DeletePortForwarding(const uint16_t local_port); + + Status Shell(const char *command, std::chrono::milliseconds timeout, + std::string *output); + + Status ShellToFile(const char *command, std::chrono::milliseconds timeout, + const FileSpec &output_file_spec); + + std::unique_ptr GetSyncService(Status &error); + + Status SwitchDeviceTransport(); + +private: + Status Connect(); + + void SetDeviceID(const std::string &device_id); + + Status SendMessage(const std::string &packet, const bool reconnect = true); + + Status SendDeviceMessage(const std::string &packet); + + Status ReadMessage(std::vector &message); + + Status ReadMessageStream(std::vector &message, + std::chrono::milliseconds timeout); + + Status GetResponseError(const char *response_id); + + Status ReadResponseStatus(); + + Status Sync(); + + Status StartSync(); + + Status internalShell(const char *command, std::chrono::milliseconds timeout, + std::vector &output_buf); + + Status ReadAllBytes(void *buffer, size_t size); + + std::string m_device_id; + std::unique_ptr m_conn; +}; + +} // namespace platform_hos +} // namespace lldb_private + +#endif // liblldb_HdcClient_h_ diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..808d2af4a0b7d0356bfc077e3a6277096fef2147 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp @@ -0,0 +1,450 @@ +//===-- PlatformHOS.cpp -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Scalar.h" +#include "lldb/Utility/UriParser.h" +#include "llvm/Config/config.h" + +#include "HdcClient.h" +#include "PlatformHOS.h" +#include "PlatformHOSRemoteGDBServer.h" +#if defined __MINGW32__ +// SetEnvironmentVariableA +#include +#endif + +using namespace lldb; +using namespace lldb_private; +// using namespace lldb_private::platform_android; +using namespace lldb_private::platform_hos; +using namespace std::chrono; +static uint32_t g_initialize_count = 0; +static const unsigned int g_hos_default_cache_size = 2048; +LLDB_PLUGIN_DEFINE(PlatformHOS) + +static void platform_setenv(const char *env, const char *val) { +#if HAVE_SETENV || _MSC_VER + setenv(env, val, true); +#elif defined(__MINGW32__) + SetEnvironmentVariableA(env, val); +#else +#error "setenv not found" +#endif +} + +void PlatformHOS::Initialize() { + PlatformLinux::Initialize(); + Log *log = GetLog(LLDBLog::Platform); + if (g_initialize_count++ == 0) { +#if defined(__HOS__) + PlatformSP default_platform_sp(new PlatformHOS(true)); + default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); + Platform::SetHostPlatform(default_platform_sp); + if (log) + log->Printf("Hsu file(%s)%d PlatformHOS::%s new PlatformHOS(true)", + __FILE__, __LINE__, __FUNCTION__); +#endif + PluginManager::RegisterPlugin( + PlatformHOS::GetPluginNameStatic(false), + PlatformHOS::GetPluginDescriptionStatic(false), + PlatformHOS::CreateInstance); + } +} + +void PlatformHOS::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformHOS::CreateInstance); + } + } + PlatformLinux::Terminate(); +} + +PlatformSP PlatformHOS::CreateInstance(bool force, const ArchSpec *arch) { + Log *log = GetLog(LLDBLog::Platform); + if (log) { + const char *triple_cstr = + arch ? arch->GetTriple().getTriple().c_str() : ""; + + log->Printf("PlatformHOS::%s(force=%s, triple=%s)", __FUNCTION__, + force ? "true" : "false", triple_cstr); + } + + bool create = force; + if (!create && arch && arch->IsValid()) { + const llvm::Triple &triple = arch->GetTriple(); + + switch (triple.getVendor()) { + case llvm::Triple::PC: + create = true; + break; + + default: + create = triple.isOpenHOS(); + break; + } + } + + if (create) { + if (const char *env = std::getenv("HDC_UTID")) + platform_setenv("ANDROID_SERIAL", env); + + log->Printf("PlatformHOS::%s() creating remote-hos platform", __FUNCTION__); + return PlatformSP(new PlatformHOS(false)); + } + + log->Printf("PlatformHOS::%s() aborting creation of remote-hos platform", + __FUNCTION__); + + return PlatformSP(); +} + +PlatformHOS::PlatformHOS(bool is_host) + : PlatformLinux(is_host), m_sdk_version(0) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d PlatformHOS::%s is_host(%d)", __FILE__, + __LINE__, __FUNCTION__, is_host); +} + +PlatformHOS::~PlatformHOS() {} + +llvm::StringRef PlatformHOS::GetPluginNameStatic(bool is_host) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu %s:%d PlatformHOS::GetPluginNameStatic is_host(%d)", + __FILE__, __LINE__, is_host); + if (is_host) { + if (log) + log->Printf("Hsu %s:%d PlatformHOS::GetPluginNameStatic g_host_name", + __FILE__, __LINE__); + return Platform::GetHostPlatformName(); + } else { + if (log) + log->Printf("Hsu %s:%d PlatformHOS::GetPluginNameStatic g_remote_name", + __FILE__, __LINE__); + return "remote-hos"; + } +} + +const char *PlatformHOS::GetPluginDescriptionStatic(bool is_host) { + if (is_host) + return "Local HarmonyOS user platform plug-in."; + else + return "Remote HarmonyOS user platform plug-in."; +} + +Status PlatformHOS::ConnectRemote(Args &args) { + m_device_id.clear(); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu %s:%d PlatformHOS::ConnectRemote call", __FILE__, + __LINE__); + + if (IsHost()) { + return Status("can't connect to the host platform '%s', always connected", + GetPluginName().str().c_str()); + } + + if (!m_remote_platform_sp) { + if (log) + log->Printf("Hsu %s:%d PlatformHOS::ConnectRemote new " + "PlatformHOSRemoteGDBServer()", + __FILE__, __LINE__); + m_remote_platform_sp = PlatformSP(new PlatformHOSRemoteGDBServer()); + } + + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + llvm::Optional uri = URI::Parse(url); + if (!uri) + return Status("Invalid URL: %s", url); + if (uri->hostname != "localhost") + m_device_id = static_cast(uri->hostname); + + auto error = PlatformLinux::ConnectRemote(args); + if (error.Success()) { + HdcClient hdc; + if (log) + log->Printf("Hsu file(%s):%d PlatformHOS::ConnectRemote m_device_id(%s)", + __FILE__, __LINE__, m_device_id.c_str()); + error = HdcClient::CreateByDeviceID(m_device_id, hdc); + if (error.Fail()) + return error; + + m_device_id = hdc.GetDeviceID(); + if (log) + log->Printf("Hsu file(%s):%d PlatformHOS::ConnectRemote m_device_id(%s)", + __FILE__, __LINE__, m_device_id.c_str()); + } + return error; +} + +Status PlatformHOS::GetFile(const FileSpec &source, + const FileSpec &destination) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::GetFile(source, destination); + + FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix); + if (source_spec.IsRelative()) + source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + source_spec.GetCString(false)); + + Status error; + auto sync_service = GetSyncService(error); + if (error.Fail()) + return error; + + uint32_t mode = 0, size = 0, mtime = 0; + error = sync_service->Stat(source_spec, mode, size, mtime); + if (error.Fail()) + return error; + + if (mode != 0) + return sync_service->PullFile(source_spec, destination); + + auto source_file = source_spec.GetCString(false); + + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", + source_file); + + if (strchr(source_file, '\'') != nullptr) + return Status("Doesn't support single-quotes in filenames"); + + // mode == 0 can signify that adbd cannot access the file due security + // constraints - try "cat ..." as a fallback. + if (log) + log->Printf("Hsu file(%s):%d PlatformHOS::%s source_file(%s)", __FILE__, + __LINE__, __FUNCTION__, source_file); + HdcClient hdc(m_device_id); + + char cmd[PATH_MAX]; + int len = strlen(source_file); + std::string tempFile(source_file); + if (m_container) { + /* + /data /data/ohos_data + /vendor /sytem/ohos/vendor + /system /system/ohos/system + */ + const std::string str_data = "/data"; + const std::string str_vendor = "/vendor"; + const std::string str_system = "/system"; + const std::string str_data_append = "/data/ohos_data"; + const std::string str_vendor_append = "/vendor/ohos/vendor"; + const std::string str_system_append = "/system/ohos/system"; + if (!strncmp(source_file, str_data.c_str(), strlen(str_data.c_str()))) { + tempFile = str_data_append + tempFile.substr(strlen(str_data.c_str())); + snprintf(cmd, sizeof(cmd), "cat '%s'", tempFile.c_str()); + return hdc.ShellToFile(cmd, minutes(1), destination); + } + if (!strncmp(source_file, str_vendor.c_str(), strlen(str_vendor.c_str()))) { + tempFile = + str_vendor_append + tempFile.substr(strlen(str_vendor.c_str())); + snprintf(cmd, sizeof(cmd), "cat '%s'", tempFile.c_str()); + return hdc.ShellToFile(cmd, minutes(1), destination); + } + + if (!strncmp(source_file, str_system.c_str(), strlen(str_system.c_str()))) { + tempFile = + str_system_append + tempFile.substr(strlen(str_system.c_str())); + snprintf(cmd, sizeof(cmd), "cat '%s'", tempFile.c_str()); + return hdc.ShellToFile(cmd, minutes(1), destination); + } + return error; + } else { + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + } + + if (log) + log->Printf("Hsu file(%s):%d PlatformHOS::%s source_file(%s)", __FILE__, + __LINE__, __FUNCTION__, source_file); + + return hdc.ShellToFile(cmd, minutes(1), destination); +} + +Status PlatformHOS::PutFile(const FileSpec &source, const FileSpec &destination, + uint32_t uid, uint32_t gid) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::PutFile(source, destination, uid, gid); + + FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix); + if (destination_spec.IsRelative()) + destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + destination_spec.GetCString(false)); + + // TODO: Set correct uid and gid on remote file. + Status error; + auto sync_service = GetSyncService(error); + if (error.Fail()) + return error; + return sync_service->PushFile(source, destination_spec); +} + +const char *PlatformHOS::GetCacheHostname() { return m_device_id.c_str(); } + +Status PlatformHOS::DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec &dst_file_spec) { + if (src_offset != 0) + return Status("Invalid offset - %" PRIu64, src_offset); + + return GetFile(src_file_spec, dst_file_spec); +} + +Status PlatformHOS::DisconnectRemote() { + Status error = PlatformLinux::DisconnectRemote(); + if (error.Success()) { + m_device_id.clear(); + m_sdk_version = 0; + } + return error; +} + +uint32_t PlatformHOS::GetDefaultMemoryCacheLineSize() { + return g_hos_default_cache_size; +} + +uint32_t PlatformHOS::GetSdkVersion() { + if (!IsConnected()) + return 0; + + if (m_sdk_version != 0) + return m_sdk_version; + + std::string version_string; + HdcClient hdc(m_device_id); + Status error = + hdc.Shell("getprop ro.build.version.sdk", seconds(5), &version_string); + version_string = llvm::StringRef(version_string).trim().str(); + + if (error.Fail() || version_string.empty()) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Get SDK version failed. (error: %s, output: %s)", + error.AsCString(), version_string.c_str()); + return 0; + } + + llvm::to_integer(version_string.c_str(), m_sdk_version); + return m_sdk_version; +} + +Status PlatformHOS::DownloadSymbolFile(const lldb::ModuleSP &module_sp, + const FileSpec &dst_file_spec) { + // For oat file we can try to fetch additional debug info from the device + ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); + if (extension != ".oat" && extension != ".odex") + return Status( + "Symbol file downloading only supported for oat and odex files"); + + // If we have no information about the platform file we can't execute oatdump + if (!module_sp->GetPlatformFileSpec()) + return Status("No platform file specified"); + + // Symbolizer isn't available before SDK version 23 + if (GetSdkVersion() < 23) + return Status("Symbol file generation only supported on SDK 23+"); + + // If we already have symtab then we don't have to try and generate one + if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != + nullptr) + return Status("Symtab already available in the module"); + + HdcClient hdc(m_device_id); + std::string tmpdir; + Status error; + if (m_container) { + error = hdc.Shell("mktemp --directory --tmpdir /data/ohos_data/local/tmp", + seconds(5), &tmpdir); + } else { + error = hdc.Shell("mktemp --directory --tmpdir /data/local/tmp", seconds(5), + &tmpdir); + } + if (error.Fail() || tmpdir.empty()) + return Status("Failed to generate temporary directory on the device (%s)", + error.AsCString()); + tmpdir = llvm::StringRef(tmpdir).trim().str(); + + // Create file remover for the temporary directory created on the device + std::unique_ptr> + tmpdir_remover(&tmpdir, [&hdc](std::string *s) { + StreamString command; + command.Printf("rm -rf %s", s->c_str()); + Status error = hdc.Shell(command.GetData(), seconds(5), nullptr); + + Log *log = GetLog(LLDBLog::Platform); + if (log && error.Fail()) + log->Printf("Failed to remove temp directory: %s", error.AsCString()); + }); + + FileSpec symfile_platform_filespec(tmpdir); + symfile_platform_filespec.AppendPathComponent("symbolized.oat"); + + // Execute oatdump on the remote device to generate a file with symtab + StreamString command; + command.Printf("oatdump --symbolize=%s --output=%s", + module_sp->GetPlatformFileSpec().GetCString(false), + symfile_platform_filespec.GetCString(false)); + error = hdc.Shell(command.GetData(), minutes(1), nullptr); + if (error.Fail()) + return Status("Oatdump failed: %s", error.AsCString()); + + // Download the symbolfile from the remote device + return GetFile(symfile_platform_filespec, dst_file_spec); +} + +bool PlatformHOS::GetRemoteOSVersion() { + m_os_version = llvm::VersionTuple(GetSdkVersion()); + return !m_os_version.empty(); +} + +llvm::StringRef +PlatformHOS::GetLibdlFunctionDeclarations(lldb_private::Process *process) { + SymbolContextList matching_symbols; + std::vector dl_open_names = {"__dl_dlopen", "dlopen"}; + const char *dl_open_name = nullptr; + Target &target = process->GetTarget(); + for (auto name : dl_open_names) { + target.GetImages().FindFunctionSymbols( + ConstString(name), eFunctionNameTypeFull, matching_symbols); + if (matching_symbols.GetSize()) { + dl_open_name = name; + break; + } + } + // Older platform versions have the dl function symbols mangled + if (dl_open_name == dl_open_names[0]) + return R"( + extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); + extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); + extern "C" int dlclose(void*) asm("__dl_dlclose"); + extern "C" char* dlerror(void) asm("__dl_dlerror"); + )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(process); +} + +HdcClient::SyncService *PlatformHOS::GetSyncService(Status &error) { + if (m_adb_sync_svc && m_adb_sync_svc->IsConnected()) + return m_adb_sync_svc.get(); + + HdcClient hdc(m_device_id); + m_adb_sync_svc = hdc.GetSyncService(error); + return (error.Success()) ? m_adb_sync_svc.get() : nullptr; +} diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.h b/lldb/source/Plugins/Platform/HOS/PlatformHOS.h new file mode 100644 index 0000000000000000000000000000000000000000..d725972243ca8ef444b9771387cfc1c96e5c5b81 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.h @@ -0,0 +1,82 @@ +//===-- PlatformHOS.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformHOS_h_ +#define liblldb_PlatformHOS_h_ + +#include +#include + +//#include "Plugins/Platform/Android/PlatformAndroid.h" +#include "HdcClient.h" +#include "Plugins/Platform/Linux/PlatformLinux.h" + +namespace lldb_private { +namespace platform_hos { + +// class PlatformHOS : public platform_android::PlatformAndroid { +class PlatformHOS : public platform_linux::PlatformLinux { +public: + // PlatformHOS(bool is_host) : PlatformAndroid(is_host) {} + PlatformHOS(bool is_host); + // lldb_private::PluginInterface functions + ~PlatformHOS() override; + static void Initialize(); + + static void Terminate(); + + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + + static llvm::StringRef GetPluginNameStatic(bool is_host); + + static const char *GetPluginDescriptionStatic(bool is_host); + + llvm::StringRef GetPluginName() override { + return GetPluginNameStatic(IsHost()); + } + + Status ConnectRemote(Args &args) override; + + Status GetFile(const FileSpec &source, const FileSpec &destination) override; + + Status PutFile(const FileSpec &source, const FileSpec &destination, + uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; + + uint32_t GetSdkVersion(); + + bool GetRemoteOSVersion() override; + + Status DisconnectRemote() override; + + uint32_t GetDefaultMemoryCacheLineSize() override; + +protected: + const char *GetCacheHostname() override; + + Status DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, const uint64_t src_size, + const FileSpec &dst_file_spec) override; + + Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, + const FileSpec &dst_file_spec) override; + + llvm::StringRef + GetLibdlFunctionDeclarations(lldb_private::Process *process) override; + +private: + HdcClient::SyncService *GetSyncService(Status &error); + + std::unique_ptr m_adb_sync_svc; + std::string m_device_id; + uint32_t m_sdk_version; +}; + +} // namespace platform_hos +} // namespace lldb_private + +#endif // liblldb_PlatformHOS_h_ diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..344300ea0086fa9a05d12a39df77d8a30f077b5f --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp @@ -0,0 +1,235 @@ +//===-- PlatformHOSRemoteGDBServer.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UriParser.h" + +#include "PlatformHOSRemoteGDBServer.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_hos; + +static const lldb::pid_t g_remote_platform_pid = + 0; // Alias for the process id of lldb-platform + +static Status ForwardPortWithHdc( + const uint16_t local_port, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + const llvm::Optional &socket_namespace, + std::string &device_id) { + Log *log = GetLog(LLDBLog::Platform); + + HdcClient hdc; + auto error = HdcClient::CreateByDeviceID(device_id, hdc); + if (error.Fail()) + return error; + + device_id = hdc.GetDeviceID(); + log->Printf("Hsu file(%s):%d function(ForwardPortWithHdc) Connected to Hos " + "device \"%s\"", + __FILE__, __LINE__, device_id.c_str()); + + if (remote_port != 0) { + log->Printf( + "Hsu file(%s):%d function(ForwardPortWithHdc) Forwarding remote " + "TCP port %d to local TCP port %d", + __FILE__, __LINE__, remote_port, local_port); + return hdc.SetPortForwarding(local_port, remote_port); + } + + log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name.str().c_str(), local_port); + + if (!socket_namespace) + return Status("Invalid socket namespace"); + + return hdc.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); +} + +static Status DeleteForwardPortWithHdc(uint16_t local_port, + const std::string &device_id) { + HdcClient hdc(device_id); + return hdc.DeletePortForwarding(local_port); +} + +static Status FindUnusedPort(uint16_t &port) { + Status error; + std::unique_ptr tcp_socket(new TCPSocket(true, false)); + if (error.Fail()) + return error; + + error = tcp_socket->Listen("127.0.0.1:0", 1); + if (error.Success()) + port = tcp_socket->GetLocalPortNumber(); + + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d FindUnusedPort port(%d)", __FILE__, __LINE__, + port); + return error; +} + +PlatformHOSRemoteGDBServer::PlatformHOSRemoteGDBServer() {} + +PlatformHOSRemoteGDBServer::~PlatformHOSRemoteGDBServer() { + for (const auto &it : m_port_forwards) + DeleteForwardPortWithHdc(it.second, m_device_id); +} + +bool PlatformHOSRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, + std::string &connect_url) { + uint16_t remote_port = 0; + std::string socket_name; + if (!m_gdb_client_up->LaunchGDBServer("127.0.0.1", pid, remote_port, + socket_name)) + return false; + + Log *log = GetLog(LLDBLog::Platform); + auto error = + MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url); + if (error.Success() && log) + log->Printf("gdbserver connect URL: %s", connect_url.c_str()); + + return error.Success(); +} + +bool PlatformHOSRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { + DeleteForwardPort(pid); + return m_gdb_client_up->KillSpawnedProcess(pid); +} + +Status PlatformHOSRemoteGDBServer::ConnectRemote(Args &args) { + m_device_id.clear(); + if (args.GetArgumentCount() != 1) + return Status( + "\"platform connect\" takes a single argument: "); + + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + + llvm::Optional uri; + uri = URI::Parse(url); + if (!uri) + return Status("Invalid URL: %s", url); + + if (uri->hostname != "localhost") + m_device_id = static_cast(uri->hostname); + + m_socket_namespace.reset(); + if (uri->scheme == "unix-connect") + m_socket_namespace = HdcClient::UnixSocketNamespaceFileSystem; + else if (uri->scheme == "unix-abstract-connect") + m_socket_namespace = HdcClient::UnixSocketNamespaceAbstract; + + std::string connect_url; + unsigned remote_port = uri->port ? (*uri->port) : 0; + auto error = MakeConnectURL(g_remote_platform_pid, remote_port, uri->path, + connect_url); + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Hsu file(%s):%d g_remote_platform_pid(%lu) remote_port(%d) " + "connect_url(%s)", + __FILE__, __LINE__, g_remote_platform_pid, remote_port, + connect_url.c_str()); + if (error.Fail()) + return error; + + args.ReplaceArgumentAtIndex(0, connect_url); + + log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); + + error = PlatformRemoteGDBServer::ConnectRemote(args); + if (error.Fail()) + DeleteForwardPort(g_remote_platform_pid); + + return error; +} + +Status PlatformHOSRemoteGDBServer::DisconnectRemote() { + DeleteForwardPort(g_remote_platform_pid); + return PlatformRemoteGDBServer::DisconnectRemote(); +} + +void PlatformHOSRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) { + Log *log = GetLog(LLDBLog::Platform); + auto it = m_port_forwards.find(pid); + if (it == m_port_forwards.end()) + return; + + const auto port = it->second; + const auto error = DeleteForwardPortWithHdc(port, m_device_id); + if (error.Fail()) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", port=%d, device=%s): %s", + pid, port, m_device_id.c_str(), error.AsCString()); + m_port_forwards.erase(it); +} + +Status PlatformHOSRemoteGDBServer::MakeConnectURL( + const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, std::string &connect_url) { + static const int kAttempsNum = 5; + + Status error; + // There is a race possibility that somebody will occupy a port while we're + // in between FindUnusedPort and ForwardPortWithHdc - adding the loop to + // mitigate such problem. + for (auto i = 0; i < kAttempsNum; ++i) { + uint16_t local_port = 0; + error = FindUnusedPort(local_port); + if (error.Fail()) + return error; + + error = ForwardPortWithHdc(local_port, remote_port, remote_socket_name, + m_socket_namespace, m_device_id); + if (error.Success()) { + m_port_forwards[pid] = local_port; + std::ostringstream url_str; + url_str << "connect://127.0.0.1:" << local_port; + connect_url = url_str.str(); + break; + } + } + + return error; +} + +lldb::ProcessSP PlatformHOSRemoteGDBServer::ConnectProcess( + llvm::StringRef connect_url, llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, lldb_private::Target *target, + lldb_private::Status &error) { + // We don't have the pid of the remote gdbserver when it isn't started by us + // but we still want to store the list of port forwards we set up in our port + // forward map. Generate a fake pid for these cases what won't collide with + // any other valid pid on android. + static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; + + llvm::Optional uri = URI::Parse(connect_url); + if (!uri) { + error.SetErrorStringWithFormat("Invalid URL: %s", + connect_url.str().c_str()); + return nullptr; + } + std::string new_connect_url; + error = MakeConnectURL(s_remote_gdbserver_fake_pid--, + (*uri->port) ? (*uri->port) : 0, uri->path, + new_connect_url); + if (error.Fail()) + return nullptr; + + return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name, + debugger, target, error); +} diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h new file mode 100644 index 0000000000000000000000000000000000000000..c30b15dd9a803d841c6006b9f8d9f29c93cf1ee9 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h @@ -0,0 +1,65 @@ +//===-- PlatformHOSRemoteGDBServer.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PLATFORM_HOS_PLATFORMHOSREMOTEGDBSERVER_H +#define LLDB_SOURCE_PLUGINS_PLATFORM_HOS_PLATFORMHOSREMOTEGDBSERVER_H + +#include +#include + +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" + +#include "llvm/ADT/Optional.h" + +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_hos { + +class PlatformHOSRemoteGDBServer + : public platform_gdb_server::PlatformRemoteGDBServer { +public: + PlatformHOSRemoteGDBServer(); + + ~PlatformHOSRemoteGDBServer() override; + + Status ConnectRemote(Args &args) override; + + Status DisconnectRemote() override; + + lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, + llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Status &error) override; + +protected: + std::string m_device_id; + std::map m_port_forwards; + llvm::Optional m_socket_namespace; + + bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; + + bool KillSpawnedProcess(lldb::pid_t pid) override; + + void DeleteForwardPort(lldb::pid_t pid); + + Status MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + std::string &connect_url); + +private: + PlatformHOSRemoteGDBServer(const PlatformHOSRemoteGDBServer &) = delete; + const PlatformHOSRemoteGDBServer & + operator=(const PlatformHOSRemoteGDBServer &) = delete; +}; + +} // namespace platform_hos +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PLATFORM_HOS_PLATFORMANDROIDREMOTEGDBSERVER_H diff --git a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp index 9fdfe4c0dc14096e58f000198077cfcd9f347e1a..1fe7f35d0d7541b827f04c723d0bf4bb216b8da8 100644 --- a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -85,7 +85,7 @@ void PlatformLinux::Initialize() { PlatformPOSIX::Initialize(); if (g_initialize_count++ == 0) { -#if defined(__linux__) && !defined(__ANDROID__) +#if defined(__linux__) && !defined(__ANDROID__) && !defined(__OHOS_FAMILY__) PlatformSP default_platform_sp(new PlatformLinux(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); Platform::SetHostPlatform(default_platform_sp); diff --git a/lldb/source/Plugins/Platform/OHOS/CMakeLists.txt b/lldb/source/Plugins/Platform/OHOS/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..cc71762efe2ea58aafadcf05184ebe6fc3bd4078 --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/CMakeLists.txt @@ -0,0 +1,13 @@ +add_lldb_library(lldbPluginPlatformOHOS PLUGIN + HdcClient.cpp + PlatformOHOS.cpp + PlatformOHOSRemoteGDBServer.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbPluginPlatformLinux + lldbPluginPlatformGDB + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6807d24cf317f4dc4a38769f57f1ea648b702110 --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp @@ -0,0 +1,399 @@ +//===-- HdcClient.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HdcClient.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileUtilities.h" + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/PosixApi.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timeout.h" + +#if defined(_WIN32) +#include +#else +#include +#endif + +#include + +#include +#include +#include +#include + +// On Windows, transitive dependencies pull in , which defines a +// macro that clashes with a method name. +#ifdef SendMessage +#undef SendMessage +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_ohos; +using namespace std::chrono; + +namespace { + +const seconds kReadTimeout(20); +const char *kSocketNamespaceAbstract = "localabstract"; +const char *kSocketNamespaceFileSystem = "localfilesystem"; + +Status ReadAllBytes(Connection &conn, void *buffer, size_t size, + size_t *read_ptr, ConnectionStatus *status_ptr) { + + Status error; + ConnectionStatus status; + char *read_buffer = static_cast(buffer); + + auto now = steady_clock::now(); + const auto deadline = now + kReadTimeout; + size_t total_read_bytes = 0; + while (total_read_bytes < size && now < deadline) { + auto read_bytes = + conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, + duration_cast(deadline - now), status, &error); + if (status_ptr) + *status_ptr = status; + if (error.Fail()) + return error; + total_read_bytes += read_bytes; + if (read_ptr) + *read_ptr = total_read_bytes; + if (status != eConnectionStatusSuccess) + break; + now = steady_clock::now(); + } + if (total_read_bytes < size) + error = Status( + "Unable to read requested number of bytes. Connection status: %d.", + status); + return error; +} + +} // namespace + +Status HdcClient::CreateByDeviceID(const std::string &device_id, + HdcClient &hdc) { + DeviceIDList connect_devices; + auto error = hdc.GetDevices(connect_devices); + if (error.Fail()) + return error; + + std::string hdc_utid; + if (!device_id.empty()) + hdc_utid = device_id; + else if (const char *env_hdc_utid = std::getenv("HDC_UTID")) + hdc_utid = env_hdc_utid; + + if (hdc_utid.empty()) { + if (connect_devices.size() != 1) + return Status("Expected a single connected device, got instead %zu - try " + "setting 'HDC_UTID'", + connect_devices.size()); + hdc.SetDeviceID(connect_devices.front()); + } else { + auto find_it = std::find(connect_devices.begin(), connect_devices.end(), + hdc_utid); + if (find_it == connect_devices.end()) + return Status( + "Device \"%s\" not found, check HDC_UTID environment variable", + hdc_utid.c_str()); + + hdc.SetDeviceID(*find_it); + } + return error; +} + +HdcClient::HdcClient() {} + +HdcClient::HdcClient(const std::string &device_id) : m_device_id(device_id) {} + +HdcClient::~HdcClient() {} + +void HdcClient::SetDeviceID(const std::string &device_id) { + m_device_id = device_id; +} + +const std::string &HdcClient::GetDeviceID() const { return m_device_id; } + +namespace { +typedef unsigned msg_len_t; +struct ChannelHandShake { + msg_len_t size; + char banner[12]; // must first index + union { + uint32_t channelId; + char connectKey[32]; + }; +} __attribute__((packed)); +} // namespace + +Status HdcClient::Connect() { + Status error; + ChannelHandShake handshake = {}; + if (m_device_id.size() > sizeof(handshake.connectKey)) + return Status("Device id is too long: %s", m_device_id.c_str()); + m_conn.reset(new ConnectionFileDescriptor); + std::string port = "8710"; + + const char *env_port = std::getenv("OHOS_HDC_SERVER_PORT"); + if ((env_port != NULL) && (atoi(env_port) > 0)) { + port = env_port; + } + + std::string uri = "connect://localhost:" + port; + m_conn->Connect(uri.c_str(), &error); + ConnectionStatus status = eConnectionStatusError; + if (error.Success()) { + error = ReadAllBytes(&handshake, sizeof(handshake)); + if (error.Success()) { + memset(handshake.connectKey, 0, sizeof(handshake.connectKey)); + memcpy(handshake.connectKey, m_device_id.c_str(), m_device_id.size()); + m_conn->Write(&handshake, sizeof(handshake), status, &error); + } + } + return error; +} + +Status HdcClient::GetDevices(DeviceIDList &device_list) { + device_list.clear(); + + auto error = SendMessage("list targets"); + if (error.Fail()) + return error; + + std::vector in_buffer; + error = ReadMessage(in_buffer); + + llvm::StringRef response(&in_buffer[0], in_buffer.size()); + llvm::SmallVector devices; + response.split(devices, "\n", -1, false); + + for (const auto device : devices) + device_list.push_back(static_cast(device.split('\t').first)); + + // Force disconnect since ADB closes connection after host:devices response + // is sent. + m_conn.reset(); + return error; +} + +Status HdcClient::SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port) { + char message[48]; + snprintf(message, sizeof(message), "fport tcp:%d tcp:%d", local_port, + remote_port); + + const auto error = SendMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus("Forwardport result:OK"); +} + +Status +HdcClient::SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace) { + char message[PATH_MAX]; + const char *sock_namespace_str = + (socket_namespace == UnixSocketNamespaceAbstract) + ? kSocketNamespaceAbstract + : kSocketNamespaceFileSystem; + snprintf(message, sizeof(message), "fport tcp:%d %s:%s", local_port, + sock_namespace_str, remote_socket_name.str().c_str()); + + const auto error = SendMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus("Forwardport result:OK"); +} + +Status HdcClient::DeletePortForwarding(std::pair fwd) { + char message[32]; + snprintf(message, sizeof(message), "fport rm tcp:%d tcp:%d", fwd.first, + fwd.second); + + const auto error = SendMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus("Remove forward ruler success"); +} + +Status HdcClient::DeletePortForwarding(const uint16_t local_port, + const std::string remote_socket_name, + const UnixSocketNamespace socket_namespace) { + const char *sock_namespace_str = + (socket_namespace == UnixSocketNamespaceAbstract) + ? kSocketNamespaceAbstract + : kSocketNamespaceFileSystem; + char message[PATH_MAX] = ""; + + snprintf(message, sizeof(message), "fport rm tcp:%d %s:%s", local_port, + sock_namespace_str, remote_socket_name.c_str()); + + const auto error = SendMessage(message); + if (error.Fail()){ + return error; + } + + return ReadResponseStatus("Remove forward ruler success"); +} + +Status HdcClient::TransferFile(const char *direction, const FileSpec &src, + const FileSpec &dst) { + llvm::SmallVector cwd; + std::error_code ec = llvm::sys::fs::current_path(cwd); + if (ec) + return Status(ec); + + std::stringstream cmd; + cmd << "file " << direction << " -cwd "; + cmd.write(cwd.data(), cwd.size()); + cmd << " " << src.GetPath() << " " << dst.GetPath(); + Status error = SendMessage(cmd.str()); + if (error.Fail()) + return error; + + return ReadResponseStatus("FileTransfer finish"); +} + +Status HdcClient::RecvFile(const FileSpec &src, const FileSpec &dst) { + return TransferFile("recv", src, dst); +} + +Status HdcClient::SendFile(const FileSpec &src, const FileSpec &dst) { + return TransferFile("send", src, dst); +} + +Status HdcClient::SendMessage(llvm::StringRef packet, const bool reconnect) { + Status error; + if (!m_conn || reconnect) { + error = Connect(); + if (error.Fail()) + return error; + } + + unsigned msg_len = packet.size() + 1; + llvm::SmallVector message(msg_len + sizeof(msg_len_t), 0); + msg_len_t len = htonl(msg_len); + memcpy(message.data(), &len, sizeof(len)); + memcpy(message.data() + sizeof(len), packet.data(), packet.size()); + + ConnectionStatus status; + m_conn->Write(message.data(), message.size(), status, &error); + if (error.Fail()) + return error; + + return error; +} + +Status HdcClient::ReadMessage(std::vector &message) { + message.clear(); + + msg_len_t packet_len; + auto error = ReadAllBytes(&packet_len, sizeof(packet_len)); + if (error.Fail()) + return error; + + packet_len = htonl(packet_len); + message.resize(packet_len, 0); + error = ReadAllBytes(&message[0], packet_len); + if (error.Fail()) + message.clear(); + + return error; +} + +Status HdcClient::ReadMessageStream(std::vector &message, + milliseconds timeout) { + auto start = steady_clock::now(); + message.clear(); + + Status error; + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char buffer[1024]; + while (error.Success() && status == lldb::eConnectionStatusSuccess) { + auto end = steady_clock::now(); + auto elapsed = end - start; + if (elapsed >= timeout) + return Status("Timed out"); + + size_t n = m_conn->Read(buffer, sizeof(buffer), + duration_cast(timeout - elapsed), + status, &error); + if (n > 0) + message.insert(message.end(), &buffer[0], &buffer[n]); + } + return error; +} + +Status HdcClient::ReadResponseStatus(const char *expected) { + msg_len_t len; + ConnectionStatus conn_status; + size_t read; + + auto error = ::ReadAllBytes(*m_conn, &len, sizeof(len), &read, &conn_status); + // Special case: we expect server to close connection + if (expected == nullptr) { + if (read == 0 && conn_status == eConnectionStatusEndOfFile) + return Status(); + else if (error.Fail()) + return error; + // Something went wrong - response is not empty + // Read it and wrap to error object + } + + len = htonl(len); + llvm::SmallVector message(len + 1); + error = ReadAllBytes(message.data(), len); + if (error.Fail()) + return error; + + message[len] = 0; + if (expected == nullptr || + strncmp(message.data(), expected, strlen(expected))) + return Status("%s", message.data()); + + return error; +} + +Status HdcClient::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size, nullptr, nullptr); +} + +Status HdcClient::Shell(const char *command, milliseconds timeout, + std::string *output) { + assert(command && command[0]); + std::string cmd = "shell "; + cmd += command; + Status error = SendMessage(cmd); + if (error.Fail()) + return error; + + std::vector message; + error = ReadMessageStream(message, timeout); + if (error.Fail()) + return error; + + (*output) = std::string(message.data(), message.size()); + return error; +} diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.h b/lldb/source/Plugins/Platform/OHOS/HdcClient.h new file mode 100644 index 0000000000000000000000000000000000000000..39b6569b447a38007e48a2fee784855f82ff6603 --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.h @@ -0,0 +1,93 @@ +//===-- HdcClient.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_HdcClient_h_ +#define liblldb_HdcClient_h_ + +#include "lldb/Utility/Status.h" +#include +#include +#include +#include +#include +#include + +namespace lldb_private { + +class FileSpec; + +namespace platform_ohos { + +class HdcClient { +public: + enum UnixSocketNamespace { + UnixSocketNamespaceAbstract, + UnixSocketNamespaceFileSystem, + }; + + using DeviceIDList = std::list; + + static Status CreateByDeviceID(const std::string &device_id, HdcClient &hdc); + + HdcClient(); + explicit HdcClient(const std::string &device_id); + + ~HdcClient(); + + const std::string &GetDeviceID() const; + + Status GetDevices(DeviceIDList &device_list); + + Status SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port); + + Status SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace); + + Status DeletePortForwarding(std::pair fwd); + + Status DeletePortForwarding(const uint16_t local_port, const std::string remote_socket_name, + const UnixSocketNamespace socket_namespace); + + Status RecvFile(const FileSpec &src, const FileSpec &dst); + + Status SendFile(const FileSpec &src, const FileSpec &dst); + + Status Shell(const char *command, std::chrono::milliseconds timeout, + std::string *output); + +private: + Status Connect(); + + Status TransferFile(const char *direction, const FileSpec &src, + const FileSpec &dst); + + void SetDeviceID(const std::string &device_id); + + Status SendMessage(llvm::StringRef packet, const bool reconnect = true); + + Status SendDeviceMessage(const std::string &packet); + + Status ReadMessage(std::vector &message); + + Status ReadMessageStream(std::vector &message, + std::chrono::milliseconds timeout); + + Status ReadResponseStatus(const char *expected); + + Status ReadAllBytes(void *buffer, size_t size); + + std::string m_device_id; + std::unique_ptr m_conn; +}; + +} // namespace platform_ohos +} // namespace lldb_private + +#endif // liblldb_HdcClient_h_ diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb0cfd9c7fffab0edf196887efffc14a6c76c0ec --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp @@ -0,0 +1,291 @@ +//===-- PlatformOHOS.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Scalar.h" +#include "lldb/Utility/UriParser.h" +#include "llvm/Config/config.h" + +#include "HdcClient.h" +#include "PlatformOHOS.h" +#include "PlatformOHOSRemoteGDBServer.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_ohos; +using namespace std::chrono; + +static uint32_t g_initialize_count = 0; +static const unsigned int g_ohos_default_cache_size = + 2048; // Fits inside 4k adb packet. +static constexpr uint32_t INVALID_SDK_VERSION = 0xFFFFFFFF; + +LLDB_PLUGIN_DEFINE(PlatformOHOS) + +void PlatformOHOS::Initialize() { + PlatformLinux::Initialize(); + + if (g_initialize_count++ == 0) { +#if defined(__OHOS__) + PlatformSP default_platform_sp(new PlatformOHOS(true)); + default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); + Platform::SetHostPlatform(default_platform_sp); +#endif + PluginManager::RegisterPlugin( + PlatformOHOS::GetPluginNameStatic(false), + PlatformOHOS::GetPluginDescriptionStatic(false), + PlatformOHOS::CreateInstance); + } +} + +void PlatformOHOS::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformOHOS::CreateInstance); + } + } + + PlatformLinux::Terminate(); +} + +PlatformSP PlatformOHOS::CreateInstance(bool force, const ArchSpec *arch) { + Log *log = GetLog(LLDBLog::Platform); + if (log) { + const char *arch_name; + if (arch && arch->GetArchitectureName()) + arch_name = arch->GetArchitectureName(); + else + arch_name = ""; + + const char *triple_cstr = + arch ? arch->GetTriple().getTriple().c_str() : ""; + + log->Printf("PlatformOHOS::%s(force=%s, arch={%s,%s})", __FUNCTION__, + force ? "true" : "false", arch_name, triple_cstr); + } + + bool create = force; + if (!create && arch && arch->IsValid()) { + const llvm::Triple &triple = arch->GetTriple(); + switch (triple.getVendor()) { + case llvm::Triple::PC: + create = true; + break; + default: + break; + } + + if (create) { + switch (triple.getEnvironment()) { + case llvm::Triple::OpenHOS: + break; + default: + create = false; + break; + } + } + } + + if (create) { + if (log) + log->Printf("PlatformOHOS::%s() creating remote-ohos platform", + __FUNCTION__); + + return PlatformSP(new PlatformOHOS(false)); + } + + if (log) + log->Printf( + "PlatformOHOS::%s() aborting creation of remote-ohos platform", + __FUNCTION__); + + return PlatformSP(); +} + +PlatformOHOS::PlatformOHOS(bool is_host) + : PlatformLinux(is_host), m_sdk_version(0) {} + +PlatformOHOS::~PlatformOHOS() {} + +llvm::StringRef PlatformOHOS::GetPluginNameStatic(bool is_host) { + return is_host ? Platform::GetHostPlatformName() : "remote-ohos"; +} + +const char *PlatformOHOS::GetPluginDescriptionStatic(bool is_host) { + return is_host ? "Local Open HarmonyOS user platform plug-in." + : "Remote Open HarmonyOS user platform plug-in."; +} + +llvm::StringRef PlatformOHOS::GetPluginName() { + return GetPluginNameStatic(IsHost()); +} + +Status PlatformOHOS::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (IsHost()) { + return Status("can't connect to the host platform '%s', always connected", + GetPluginName().str().c_str()); + } + + if (!m_remote_platform_sp) + m_remote_platform_sp = PlatformSP(new PlatformOHOSRemoteGDBServer()); + + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + llvm::Optional uri = URI::Parse(url); + if (!uri) + return Status("Invalid URL: %s", url); + if (uri->hostname != "localhost") + m_device_id = static_cast(uri->hostname); + + auto error = PlatformLinux::ConnectRemote(args); + if (error.Success()) { + HdcClient adb; + error = HdcClient::CreateByDeviceID(m_device_id, adb); + if (error.Fail()) + return error; + + m_device_id = adb.GetDeviceID(); + } + return error; +} + +Status PlatformOHOS::GetFile(const FileSpec &source, + const FileSpec &destination) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::GetFile(source, destination); + + FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix); + if (source_spec.IsRelative()) + source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + source_spec.GetCString(false)); + + HdcClient hdc(m_device_id); + Status error = hdc.RecvFile(source, destination); + return error; +} + +Status PlatformOHOS::PutFile(const FileSpec &source, + const FileSpec &destination, uint32_t uid, + uint32_t gid) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::PutFile(source, destination, uid, gid); + + FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix); + if (destination_spec.IsRelative()) + destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + destination_spec.GetCString(false)); + + // TODO: Set correct uid and gid on remote file. + HdcClient hdc(m_device_id); + Status error = hdc.SendFile(source, destination_spec); + return error; +} + +const char *PlatformOHOS::GetCacheHostname() { return m_device_id.c_str(); } + +Status PlatformOHOS::DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec &dst_file_spec) { + if (src_offset != 0) + return Status("Invalid offset - %" PRIu64, src_offset); + + return GetFile(src_file_spec, dst_file_spec); +} + +Status PlatformOHOS::DisconnectRemote() { + Status error = PlatformLinux::DisconnectRemote(); + if (error.Success()) { + m_device_id.clear(); + m_sdk_version = 0; + m_remote_platform_sp.reset(); + } + return error; +} + +uint32_t PlatformOHOS::GetDefaultMemoryCacheLineSize() { + return g_ohos_default_cache_size; +} + +uint32_t PlatformOHOS::GetSdkVersion() { + if (!IsConnected()) + return 0; + + if (m_sdk_version != 0) + return m_sdk_version; + + std::string version_string; + HdcClient hdc(m_device_id); + Status error = + hdc.Shell("param get const.ohos.apiversion", seconds(5), &version_string); + version_string = llvm::StringRef(version_string).trim().str(); + + if (error.Fail() || version_string.empty()) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Get SDK version failed. (error: %s, output: %s)", + error.AsCString(), version_string.c_str()); + m_sdk_version = INVALID_SDK_VERSION; + return 0; + } + + m_sdk_version = INVALID_SDK_VERSION; + llvm::to_integer(version_string, m_sdk_version); + if (m_sdk_version == INVALID_SDK_VERSION) { + return 0; + } + + return m_sdk_version; +} + +bool PlatformOHOS::GetRemoteOSVersion() { + m_os_version = llvm::VersionTuple(GetSdkVersion()); + return !m_os_version.empty(); +} + +llvm::StringRef +PlatformOHOS::GetLibdlFunctionDeclarations(lldb_private::Process *process) { + SymbolContextList matching_symbols; + std::vector dl_open_names = { "__dl_dlopen", "dlopen" }; + const char *dl_open_name = nullptr; + Target &target = process->GetTarget(); + for (auto name: dl_open_names) { + target.GetImages().FindFunctionSymbols(ConstString(name), + eFunctionNameTypeFull, + matching_symbols); + if (matching_symbols.GetSize()) { + dl_open_name = name; + break; + } + } + // Older platform versions have the dl function symbols mangled + if (dl_open_name == dl_open_names[0]) + return R"( + extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); + extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); + extern "C" int dlclose(void*) asm("__dl_dlclose"); + extern "C" char* dlerror(void) asm("__dl_dlerror"); + )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(process); +} + +ConstString PlatformOHOS::GetMmapSymbolName(const ArchSpec &arch) { + return arch.GetTriple().isArch32Bit() + ? ConstString("__lldb_mmap") + : PlatformLinux::GetMmapSymbolName(arch); +} diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h new file mode 100644 index 0000000000000000000000000000000000000000..83645ff209a5e29124838f9e7e2089ce3f90c6d2 --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h @@ -0,0 +1,80 @@ +//===-- PlatformOHOS.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformOHOS_h_ +#define liblldb_PlatformOHOS_h_ + +#include +#include + +#include "Plugins/Platform/Linux/PlatformLinux.h" + +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_ohos { + +class PlatformOHOS : public platform_linux::PlatformLinux { +public: + PlatformOHOS(bool is_host); + + ~PlatformOHOS() override; + + static void Initialize(); + + static void Terminate(); + + // lldb_private::PluginInterface functions + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + + static llvm::StringRef GetPluginNameStatic(bool is_host); + + static const char *GetPluginDescriptionStatic(bool is_host); + + llvm::StringRef GetPluginName() override; + + // lldb_private::Platform functions + Status ConnectRemote(Args &args) override; + + Status GetFile(const FileSpec &source, const FileSpec &destination) override; + + Status PutFile(const FileSpec &source, const FileSpec &destination, + uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; + + uint32_t GetSdkVersion(); + + bool GetRemoteOSVersion() override; + + Status DisconnectRemote() override; + + uint32_t GetDefaultMemoryCacheLineSize() override; + + ConstString GetMmapSymbolName(const ArchSpec &arch) override; + +protected: + const char *GetCacheHostname() override; + + Status DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, const uint64_t src_size, + const FileSpec &dst_file_spec) override; + + llvm::StringRef + GetLibdlFunctionDeclarations(lldb_private::Process *process) override; + +private: + std::string m_device_id; + uint32_t m_sdk_version; + + PlatformOHOS(const PlatformOHOS &other) = delete; + PlatformOHOS& operator=(const PlatformOHOS &other) = delete; +}; + +} // namespace platform_ohos +} // namespace lldb_private + +#endif // liblldb_PlatformOHOS_h_ diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..348572ec05534d949fc8f9005cc888dedd9ddef2 --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp @@ -0,0 +1,283 @@ +//===-- PlatformOHOSRemoteGDBServer.cpp ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UriParser.h" + +#include "PlatformOHOSRemoteGDBServer.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace platform_ohos; + +static const lldb::pid_t g_remote_platform_pid = + 0; // Alias for the process id of lldb-platform + +static uint16_t g_hdc_forward_port_offset = 0; + +static Status ForwardPortWithHdc( + const uint16_t local_port, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + const llvm::Optional &socket_namespace, + std::string &device_id) { + Log *log = GetLog(LLDBLog::Platform); + + HdcClient hdc; + auto error = HdcClient::CreateByDeviceID(device_id, hdc); + if (error.Fail()) + return error; + + device_id = hdc.GetDeviceID(); + if (log) + log->Printf("Connected to OHOS device \"%s\"", device_id.c_str()); + + if (remote_port != 0) { + if (log) + log->Printf("Forwarding remote TCP port %d to local TCP port %d", + remote_port, local_port); + return hdc.SetPortForwarding(local_port, remote_port); + } + + if (log) + log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name.str().c_str(), local_port); + + if (!socket_namespace) + return Status("Invalid socket namespace"); + + return hdc.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); +} + +static Status DeleteForwardPortWithHdc(std::pair ports, + const std::string &device_id) { + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Delete port forwarding %d -> %d, device=%s", ports.first, + ports.second, device_id.c_str()); + + HdcClient hdc(device_id); + return hdc.DeletePortForwarding(ports); +} + +static Status DeleteForwardPortWithHdc(std::pair remote_socket, + const llvm::Optional &socket_namespace, + const std::string &device_id) { + + Log *log = GetLog(LLDBLog::Platform); + uint16_t local_port = remote_socket.first; + std::string remote_socket_name = remote_socket.second; + if (log) + log->Printf("Delete port forwarding %d -> %s, device=%s", local_port, + remote_socket_name.c_str(), device_id.c_str()); + if (!socket_namespace) + return Status("Invalid socket namespace"); + + HdcClient hdc(device_id); + return hdc.DeletePortForwarding(local_port, remote_socket_name, *socket_namespace); +} + +static Status FindUnusedPort(uint16_t &port) { + Status error; + + if (const char *env_port = std::getenv("HDC_FORWARD_PORT_BASE_FOR_LLDB")) { + port = std::atoi(env_port) + g_hdc_forward_port_offset; + g_hdc_forward_port_offset++; + return error; + } + + std::unique_ptr tcp_socket(new TCPSocket(true, false)); + if (error.Fail()) + return error; + + error = tcp_socket->Listen("127.0.0.1:0", 1); + if (error.Success()) + port = tcp_socket->GetLocalPortNumber(); + + return error; +} + +PlatformOHOSRemoteGDBServer::PlatformOHOSRemoteGDBServer() {} + +PlatformOHOSRemoteGDBServer::~PlatformOHOSRemoteGDBServer() { + for (const auto &it : m_port_forwards) { + DeleteForwardPortWithHdc(it.second, m_device_id); + } + for (const auto &it_socket : m_remote_socket_name) { + DeleteForwardPortWithHdc(it_socket.second, m_socket_namespace, m_device_id); + } +} + +bool PlatformOHOSRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, + std::string &connect_url) { + uint16_t remote_port = 0; + std::string socket_name; + if (!m_gdb_client_up->LaunchGDBServer("127.0.0.1", pid, remote_port, socket_name)) + return false; + + Log *log = GetLog(LLDBLog::Platform); + + auto error = + MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url); + if (error.Success() && log) + log->Printf("gdbserver connect URL: %s", connect_url.c_str()); + + return error.Success(); +} + +bool PlatformOHOSRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { + DeleteForwardPort(pid); + return m_gdb_client_up->KillSpawnedProcess(pid); +} + +Status PlatformOHOSRemoteGDBServer::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (args.GetArgumentCount() != 1) + return Status( + "\"platform connect\" takes a single argument: "); + + llvm::Optional uri; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + uri = URI::Parse(url); + if (!uri) + return Status("Invalid URL: %s", url); + if (uri->hostname != "localhost") + m_device_id = static_cast(uri->hostname); + + m_socket_namespace.reset(); + if (uri->scheme == "unix-connect") + m_socket_namespace = HdcClient::UnixSocketNamespaceFileSystem; + else if (uri->scheme == "unix-abstract-connect") + m_socket_namespace = HdcClient::UnixSocketNamespaceAbstract; + + std::string connect_url; + auto error = + MakeConnectURL(g_remote_platform_pid, uri->port ? (*uri->port) : 0, + uri->path, connect_url); + + if (error.Fail()) + return error; + + args.ReplaceArgumentAtIndex(0, connect_url); + + Log *log = GetLog(LLDBLog::Platform); + if (log) + log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); + + error = PlatformRemoteGDBServer::ConnectRemote(args); + if (error.Fail()) + DeleteForwardPort(g_remote_platform_pid); + + return error; +} + +Status PlatformOHOSRemoteGDBServer::DisconnectRemote() { + DeleteForwardPort(g_remote_platform_pid); + g_hdc_forward_port_offset = 0; + return PlatformRemoteGDBServer::DisconnectRemote(); +} + +void PlatformOHOSRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) { + Log *log = GetLog(LLDBLog::Platform); + + auto it = m_port_forwards.find(pid); + auto it_socket = m_remote_socket_name.find(pid); + if (it != m_port_forwards.end() && it->second.second != 0) { + const auto error = DeleteForwardPortWithHdc(it->second, m_device_id); + if (error.Fail()) { + if (log) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", fwd=(%d -> %d), device=%s): %s", + pid, it->second.first, it->second.second, m_device_id.c_str(), + error.AsCString()); + } + m_port_forwards.erase(it); + } + + if(it_socket != m_remote_socket_name.end()) { + const auto error_Socket = DeleteForwardPortWithHdc(it_socket->second, m_socket_namespace, m_device_id); + if (error_Socket.Fail()) { + if (log) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", fwd=(%d->%s)device=%s): %s", pid, it_socket->second.first, it_socket->second.second.c_str(), m_device_id.c_str(),error_Socket.AsCString()); + } + m_remote_socket_name.erase(it_socket); + } + + return; +} + +Status PlatformOHOSRemoteGDBServer::MakeConnectURL( + const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, std::string &connect_url) { + static const int kAttempsNum = 5; + + Status error; + // There is a race possibility that somebody will occupy a port while we're + // in between FindUnusedPort and ForwardPortWithHdc - adding the loop to + // mitigate such problem. + for (auto i = 0; i < kAttempsNum; ++i) { + uint16_t local_port = 0; + error = FindUnusedPort(local_port); + if (error.Fail()) + return error; + + error = ForwardPortWithHdc(local_port, remote_port, remote_socket_name, + m_socket_namespace, m_device_id); + if (error.Success()) { + if (remote_port != 0){ + m_port_forwards[pid] = {local_port, remote_port}; + } + else{ + m_remote_socket_name[pid] ={local_port, remote_socket_name.str()}; + } + std::ostringstream url_str; + url_str << "connect://localhost:" << local_port; + connect_url = url_str.str(); + break; + } + } + + return error; +} + +lldb::ProcessSP PlatformOHOSRemoteGDBServer::ConnectProcess( + llvm::StringRef connect_url, llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, lldb_private::Target *target, + lldb_private::Status &error) { + // We don't have the pid of the remote gdbserver when it isn't started by us + // but we still want to store the list of port forwards we set up in our port + // forward map. Generate a fake pid for these cases what won't collide with + // any other valid pid on ohos. + static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; + + llvm::Optional uri = URI::Parse(connect_url); + if (!uri) { + error.SetErrorStringWithFormat("Invalid URL: %s", + connect_url.str().c_str()); + return nullptr; + } + + std::string new_connect_url; + error = MakeConnectURL(s_remote_gdbserver_fake_pid--, + (*uri->port) ? (*uri->port) : 0, uri->path, + new_connect_url); + if (error.Fail()) + return nullptr; + + return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name, + debugger, target, error); +} diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h new file mode 100644 index 0000000000000000000000000000000000000000..680ddc1e733c182c1cdbb64e45b802c8e6580103 --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h @@ -0,0 +1,65 @@ +//===-- PlatformOHOSRemoteGDBServer.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformOHOSRemoteGDBServer_h_ +#define liblldb_PlatformOHOSRemoteGDBServer_h_ + +#include +#include + +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" + +#include "llvm/ADT/Optional.h" + +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_ohos { + +class PlatformOHOSRemoteGDBServer + : public platform_gdb_server::PlatformRemoteGDBServer { +public: + PlatformOHOSRemoteGDBServer(); + + ~PlatformOHOSRemoteGDBServer() override; + + Status ConnectRemote(Args &args) override; + + Status DisconnectRemote() override; + + lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, + llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Status &error) override; + +protected: + std::string m_device_id; + std::map> m_port_forwards; + std::map> m_remote_socket_name; + llvm::Optional m_socket_namespace; + + bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; + + bool KillSpawnedProcess(lldb::pid_t pid) override; + + void DeleteForwardPort(lldb::pid_t pid); + + Status MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + std::string &connect_url); + +private: + PlatformOHOSRemoteGDBServer(const PlatformOHOSRemoteGDBServer &other) = delete; + PlatformOHOSRemoteGDBServer& operator=(const PlatformOHOSRemoteGDBServer &other) = delete; +}; + +} // namespace platform_ohos +} // namespace lldb_private + +#endif // liblldb_PlatformOHOSRemoteGDBServer_h_ diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index a51d0f7afd1759121b89a1bb0dfe3a254c15b6b0..d30d90ca4dfd72f977b2f07f767aebab712d79a7 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -1,4 +1,4 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") +if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android|OHOS") add_subdirectory(Linux) add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 14f669a3ce98f04ba0d77040dec96c9066c595f1..9fee81e1b65955bec3f83bb7d7d3ac8834c4e60c 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -16,6 +16,11 @@ #include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#if __OHOS__ +// Do not include to avoid conflicting definitions for +// aarch64-linux-ohos target +#define __ASM_SIGCONTEXT_H 1 +#endif #include namespace lldb_private { diff --git a/lldb/source/Plugins/Process/Linux/Procfs.h b/lldb/source/Plugins/Process/Linux/Procfs.h index 3a068432074b7d330488fa0a756ba1fc8a657334..79bc35d8105daa4eab4996e495126f6cd578f3ed 100644 --- a/lldb/source/Plugins/Process/Linux/Procfs.h +++ b/lldb/source/Plugins/Process/Linux/Procfs.h @@ -17,7 +17,7 @@ #include -#ifdef __ANDROID__ +#if defined(__ANDROID__) #if defined(__arm64__) || defined(__aarch64__) typedef unsigned long elf_greg_t; typedef elf_greg_t diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 5091f68a9acfedb3f993c7d19c6e57ae4786dd22..fb0ab2523190986ee1474233e0f5b156a7e71ad9 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -46,9 +46,11 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, function_options.include_symbols = true; function_options.include_inlines = false; + const ArchSpec arch = process->GetTarget().GetArchitecture(); + auto mmap_name = process->GetTarget().GetPlatform()->GetMmapSymbolName(arch); SymbolContextList sc_list; process->GetTarget().GetImages().FindFunctions( - ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list); + mmap_name, eFunctionNameTypeFull, function_options, sc_list); const uint32_t count = sc_list.GetSize(); if (count > 0) { SymbolContext sc; @@ -91,7 +93,6 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, CompilerType void_ptr_type = type_system_or_err->GetBasicTypeFromAST(eBasicTypeVoid) .GetPointerType(); - const ArchSpec arch = process->GetTarget().GetArchitecture(); MmapArgList args = process->GetTarget().GetPlatform()->GetMmapArgumentList( arch, addr, length, prot_arg, flags, fd, offset); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 2a58f2028386892fd198674c5081ca62307aeca1..39fb9a8a8fde31169f67df833d270611ffb49465 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -45,12 +45,15 @@ #include "lldb/Host/android/HostInfoAndroid.h" #endif +#if defined(__OHOS_FAMILY__) +#include "lldb/Host/ohos/HostInfoOHOS.h" +#endif using namespace lldb; using namespace lldb_private::process_gdb_remote; using namespace lldb_private; -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__OHOS_FAMILY__) const static uint32_t g_default_packet_timeout_sec = 20; // seconds #else const static uint32_t g_default_packet_timeout_sec = 0; // not specified @@ -181,7 +184,6 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( StreamString response; // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 - ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); @@ -1309,6 +1311,8 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( const std::string &module_path, const ArchSpec &arch) { #ifdef __ANDROID__ return HostInfoAndroid::ResolveLibraryPath(module_path, arch); +#elif defined(__OHOS_FAMILY__) + return HostInfoOHOS::ResolveLibraryPath(module_path, arch); #else FileSpec file_spec(module_path); FileSystem::Instance().Resolve(file_spec); @@ -1320,7 +1324,6 @@ ModuleSpec GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple) { ArchSpec arch(triple); - FileSpec req_module_path_spec(module_path); FileSystem::Instance().Resolve(req_module_path_spec); @@ -1336,7 +1339,6 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, ModuleSpec matched_module_spec; if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) return ModuleSpec(); - return matched_module_spec; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp index 37e28a09f3c45a1ab27a5892ed319c76bbec68e2..c357033aa91d7aa42e2d3341845a069f10f58f41 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -92,8 +92,8 @@ const DWARFDataExtractor &DWARFContext::getOrLoadLocListsData() { } const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() { - return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None, - m_data_debug_macro); + return LoadOrGetSection(eSectionTypeDWARFDebugMacro, + eSectionTypeDWARFDebugMacro, m_data_debug_macro); } const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp index 19c6448c4e74a063dadc2b4d36edec7c6ca1b785..e84a76451727a6a99e8f82db9b4b01a844f39497 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -16,6 +16,13 @@ using namespace lldb_private; using namespace lldb_private::dwarf; +uint64_t DWARFStrOffsetsInfo::GetOffset(uint64_t index) const { + assert(IsValid()); + // LLDB doesn't support DWARF64, so we always have item size of 4. + uint64_t offset = cu_offset + 4 * index; + return data->GetU32(&offset); +} + DWARFDebugMacroHeader DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) { @@ -59,7 +66,8 @@ void DWARFDebugMacroHeader::SkipOperandTable( void DWARFDebugMacroEntry::ReadMacroEntries( const DWARFDataExtractor &debug_macro_data, - const DWARFDataExtractor &debug_str_data, const bool offset_is_64_bit, + const DWARFDataExtractor &debug_str_data, + const DWARFStrOffsetsInfo &str_offsets_info, const bool offset_is_64_bit, lldb::offset_t *offset, SymbolFileDWARF *sym_file_dwarf, DebugMacrosSP &debug_macros_sp) { llvm::dwarf::MacroEntryType type = @@ -97,6 +105,22 @@ void DWARFDebugMacroEntry::ReadMacroEntries( debug_macros_sp->AddMacroEntry( DebugMacroEntry::CreateUndefEntry(line, macro_str)); break; + case DW_MACRO_define_strx: + case DW_MACRO_undef_strx: + line = debug_macro_data.GetULEB128(offset); + str_offset = debug_macro_data.GetULEB128(offset); + if (!str_offsets_info.IsValid()) + // Can't do much in this case, skip all such entries + continue; + str_offset = str_offsets_info.GetOffset(str_offset); + macro_str = debug_str_data.GetCStr(&str_offset); + if (type == DW_MACRO_define_strx) + debug_macros_sp->AddMacroEntry( + DebugMacroEntry::CreateDefineEntry(line, macro_str)); + else + debug_macros_sp->AddMacroEntry( + DebugMacroEntry::CreateUndefEntry(line, macro_str)); + break; case DW_MACRO_start_file: line = debug_macro_data.GetULEB128(offset); debug_line_file_idx = debug_macro_data.GetULEB128(offset); @@ -113,7 +137,7 @@ void DWARFDebugMacroEntry::ReadMacroEntries( else new_offset = debug_macro_data.GetU32(offset); debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateIndirectEntry( - sym_file_dwarf->ParseDebugMacros(&new_offset))); + sym_file_dwarf->ParseDebugMacros(&new_offset, str_offsets_info))); break; default: // TODO: Add support for other standard operations. diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h index cbf762458331bcd1f127d4372e87469efcdbc7f9..b598d680d5fb74f627f62bd697d34e6e8a73577c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -24,6 +24,14 @@ class DWARFDataExtractor; class SymbolFileDWARF; +struct DWARFStrOffsetsInfo { + lldb::offset_t cu_offset; + const lldb_private::DWARFDataExtractor *data; + + bool IsValid() const { return cu_offset && cu_offset != DW_INVALID_OFFSET; } + uint64_t GetOffset(uint64_t index) const; +}; + class DWARFDebugMacroHeader { public: enum HeaderFlagMask { @@ -53,6 +61,7 @@ public: static void ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data, const lldb_private::DWARFDataExtractor &debug_str_data, + const DWARFStrOffsetsInfo &str_offsets_info, const bool offset_is_64_bit, lldb::offset_t *sect_offset, SymbolFileDWARF *sym_file_dwarf, lldb_private::DebugMacrosSP &debug_macros_sp); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 8ee709db9cdb59f523f34ecadd689775c0c4673e..1049012cef0d887e68832471ac6e27d0a921220b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1174,7 +1174,8 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { } lldb_private::DebugMacrosSP -SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { +SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset, + const DWARFStrOffsetsInfo &str_offsets_info) { auto iter = m_debug_macros_map.find(*offset); if (iter != m_debug_macros_map.end()) return iter->second; @@ -1190,8 +1191,8 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset); DWARFDebugMacroEntry::ReadMacroEntries( - debug_macro_data, m_context.getOrLoadStrData(), header.OffsetIs64Bit(), - offset, this, debug_macros_sp); + debug_macro_data, m_context.getOrLoadStrData(), str_offsets_info, + header.OffsetIs64Bit(), offset, this, debug_macros_sp); return debug_macros_sp; } @@ -1199,7 +1200,7 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { std::lock_guard guard(GetModuleMutex()); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); + DWARFUnit *dwarf_cu = &GetDWARFCompileUnit(&comp_unit)->GetNonSkeletonUnit(); if (dwarf_cu == nullptr) return false; @@ -1215,8 +1216,16 @@ bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { if (sect_offset == DW_INVALID_OFFSET) return false; - comp_unit.SetDebugMacros(ParseDebugMacros(§_offset)); + DWARFStrOffsetsInfo str_offsets_info = {}; + str_offsets_info.cu_offset = dwarf_cu->GetStrOffsetsBase(); + SymbolFileDWARF &symfile = dwarf_cu->GetSymbolFileDWARF(); + + if (str_offsets_info.IsValid()) + str_offsets_info.data = + &symfile.GetDWARFContext().getOrLoadStrOffsetsData(); + comp_unit.SetDebugMacros( + symfile.ParseDebugMacros(§_offset, str_offsets_info)); return true; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index cfd18f02053b40af7dfe29e221be6e2f43580b48..ccf955ee4b90f31b15274de7b1b1f4db0f1ec500 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -55,6 +55,8 @@ class SymbolFileDWARFDebugMap; class SymbolFileDWARFDwo; class SymbolFileDWARFDwp; +struct DWARFStrOffsetsInfo; + #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1) class SymbolFileDWARF : public lldb_private::SymbolFileCommon, @@ -244,7 +246,9 @@ public: bool Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu); - lldb_private::DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset); + lldb_private::DebugMacrosSP + ParseDebugMacros(lldb::offset_t *offset, + const DWARFStrOffsetsInfo &str_offsets_info); static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die); diff --git a/lldb/source/Target/ModuleCache.cpp b/lldb/source/Target/ModuleCache.cpp index 29bd2b2394b58983574b034dc35f6d7cedc5a54b..5d8b30946456489f8e2d3ef24b24f985d6be8ecc 100644 --- a/lldb/source/Target/ModuleCache.cpp +++ b/lldb/source/Target/ModuleCache.cpp @@ -129,9 +129,26 @@ Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec, const FileSpec &platform_module_spec, const FileSpec &local_module_spec, bool delete_existing) { + Log *log = GetLog(LLDBLog::Modules); const auto sysroot_module_path_spec = JoinPath(JoinPath(root_dir_spec, hostname), platform_module_spec.GetPath().c_str()); + UUID module_uuid; + { + auto module_sp = + std::make_shared(ModuleSpec(sysroot_module_path_spec)); + module_uuid = module_sp->GetUUID(); + } + + if (!module_uuid.IsValid()) { + LLDB_LOGF(log, "Try CreateHostSysRootModuleLink but uuid is invalid %s", + module_uuid.GetAsString().c_str()); + return Status(); + } + + LLDB_LOGF(log, "CreateHostSysRootModuleLink with uuid %s", + module_uuid.GetAsString().c_str()); + if (FileSystem::Instance().Exists(sysroot_module_path_spec)) { if (!delete_existing) return Status(); diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp index 4ebb175fcd85ac4c877a2c69b00ac430c50f2aa4..45c166e7e5cf8c49d527e87ff658908d1f40ac80 100644 --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -131,7 +131,7 @@ void PathMappingList::Dump(Stream *s, int pair_index) { } } -void PathMappingList::Clear(bool notify) { +void PathMappingList::Clear (bool notify) { if (!m_pairs.empty()) ++m_mod_id; m_pairs.clear(); @@ -197,7 +197,7 @@ PathMappingList::RemapPath(llvm::StringRef mapping_path, return {}; } -bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const { +bool PathMappingList::ReverseRemapPath (const FileSpec &file, FileSpec &fixed) const { std::string path = file.GetPath(); llvm::StringRef path_ref(path); for (const auto &it : m_pairs) { diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 559f7664c72ef40923af9625585b90fb66f69a3a..088d6f1331178212d8378b608d13595fa0635a61 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -274,7 +274,7 @@ Platform::Platform(bool is_host) m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(), m_ignores_remote_hostname(false), m_trap_handlers(), - m_calculated_trap_handlers(false), + m_container(false), m_calculated_trap_handlers(false), m_module_cache(std::make_unique()) { Log *log = GetLog(LLDBLog::Object); LLDB_LOGF(log, "%p Platform::Platform()", static_cast(this)); @@ -308,9 +308,19 @@ void Platform::GetStatus(Stream &strm) { strm.Printf(" Hostname: %s\n", GetHostname()); } else { const bool is_connected = IsConnected(); + const bool is_container = GetContainer(); + + if (Log *log = GetLog(LLDBLog::Platform)) { + LLDB_LOGF(log, + "%p file(%s):%d Platform::GetStatus() is_container(%d) " + "is_connected(%d)", + static_cast(this), __FILE__, __LINE__, is_container, + is_connected); + } if (is_connected) strm.Printf(" Hostname: %s\n", GetHostname()); strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); + strm.Printf(" Container: %s\n", is_container ? "yes" : "no"); } if (GetSDKRootDirectory()) { @@ -1262,6 +1272,10 @@ Status Platform::Unlink(const FileSpec &path) { return Status("unimplemented"); } +ConstString Platform::GetMmapSymbolName(const ArchSpec &) { + return ConstString("mmap"); +} + MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr, addr_t length, unsigned prot, unsigned flags, addr_t fd, diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 0d5144d7a46b5f33f17f89709fc7e0bcefa7291a..d08805460ee1f851eecd6bfb580f11513655f5e3 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -206,6 +206,13 @@ bool ThreadPlanStepRange::InSymbol() { return false; } +// TODO: Limit this function scope to OHOS targets +bool ThreadPlanStepRange::MaybeAArch32Or64FunctionTail() { + const llvm::Triple &triple = GetTarget().GetArchitecture().GetTriple(); + const bool isArm32or64 = triple.isAArch64() || triple.isARM(); + return isArm32or64 && InSymbol() && InRange(); +} + // FIXME: This should also handle inlining if we aren't going to do inlining in // the // main stack. diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index a99aed82bc886852782ff7f859aab684504bf5bc..79c5cd3f18fc0a4a93a072219e26a1faffb87e49 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -936,7 +936,7 @@ bool ArchSpec::IsCompatibleMatch(const ArchSpec &rhs) const { return IsEqualTo(rhs, false); } -static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, +static bool IsCompatibleEnvironment (llvm::Triple::EnvironmentType lhs, llvm::Triple::EnvironmentType rhs) { if (lhs == rhs) return true; @@ -958,6 +958,8 @@ static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, // that they are using the Android ABI. if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) || (rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) || + (lhs == llvm::Triple::OpenHOS && rhs == llvm::Triple::EABI) || + (rhs == llvm::Triple::OpenHOS && lhs == llvm::Triple::EABI) || (lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) || (rhs == llvm::Triple::GNUEABI && lhs == llvm::Triple::EABI) || (lhs == llvm::Triple::GNUEABIHF && rhs == llvm::Triple::EABIHF) || diff --git a/lldb/source/Utility/TildeExpressionResolver.cpp b/lldb/source/Utility/TildeExpressionResolver.cpp index 6311ae062f1f5399102ce180d4c649c68ee0193c..d4c464ddfe01446cf44aa1dea82d99245b982e4f 100644 --- a/lldb/source/Utility/TildeExpressionResolver.cpp +++ b/lldb/source/Utility/TildeExpressionResolver.cpp @@ -47,7 +47,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, assert(Expr.empty() || Expr[0] == '~'); Output.clear(); -#if defined(_WIN32) || defined(__ANDROID__) +#if defined(_WIN32) || defined(__ANDROID__) || defined(__OHOS_FAMILY__) return false; #else if (Expr.empty()) diff --git a/lldb/test/API/api/command-return-object/Makefile b/lldb/test/API/api/command-return-object/Makefile index 99998b20bcb0502181cbf488a2034823e5f66d22..680e1abfbef58d92108cf5a6b041381abe69af7e 100644 --- a/lldb/test/API/api/command-return-object/Makefile +++ b/lldb/test/API/api/command-return-object/Makefile @@ -1,3 +1,4 @@ CXX_SOURCES := main.cpp +USE_LIBCPP := 1 include Makefile.rules diff --git a/lldb/test/API/functionalities/plugins/command_plugin/Makefile b/lldb/test/API/functionalities/plugins/command_plugin/Makefile index 3119c3707841d4a0565af78008b4e120e2f834aa..b792c8d50d989c9cd8a90a613daed540edbb63c2 100644 --- a/lldb/test/API/functionalities/plugins/command_plugin/Makefile +++ b/lldb/test/API/functionalities/plugins/command_plugin/Makefile @@ -2,5 +2,6 @@ DYLIB_CXX_SOURCES := plugin.cpp DYLIB_NAME := plugin DYLIB_ONLY := YES MAKE_DSYM := NO +USE_LIBCPP := 1 include Makefile.rules diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py index 820bdab6e85036a7088cfcdb27bb1e332691fe20..64c2b62c3fefea8f9300410df9a91fc0bdc32e5e 100644 --- a/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py @@ -1,4 +1,5 @@ import tempfile +import os import gdbremote_testcase from lldbsuite.test.lldbtest import * from lldbsuite.test.decorators import * @@ -10,7 +11,10 @@ class GdbRemoteCompletionTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): self.debug_monitor_exe = get_lldb_server_exe() if not self.debug_monitor_exe: self.skipTest("lldb-server exe not found") - port_file = tempfile.NamedTemporaryFile().name + port_file = os.path.join( + lldb.remote_platform.GetWorkingDirectory(), + 'connect.sock' + ) if lldb.remote_platform else tempfile.NamedTemporaryFile().name commandline_args = [ "platform", "--listen", diff --git a/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py b/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py index 2ab6820c09203d5b7e3c5fe697810cd834d8a954..53805f5d535fdd34887a59fda9a23335e76f603e 100644 --- a/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py +++ b/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py @@ -72,6 +72,7 @@ class TestGdbRemoteMemoryAllocation(gdbremote_testcase.GdbRemoteTestCaseBase): True) self.expect_gdbremote_sequence() + @skipOnOpenHarmonyCI # investigate CI test failures def test_bad_packet(self): """Make sure we get a proper error for malformed packets.""" diff --git a/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py b/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py index 7acb0188dcff72112de93f0354e8e3181925f726..ca84825af0e68d1e0a701f5ed90726f4316a1e3a 100644 --- a/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py +++ b/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py @@ -59,6 +59,7 @@ class TestGdbRemote_QPassSignals(gdbremote_testcase.GdbRemoteTestCaseBase): self.expect_exit_code(len(signals_to_ignore)) @skipUnlessPlatform(["linux", "android"]) + @skipOnOpenHarmonyCI #investigate CI timeouts def test_change_signals_at_runtime(self): self.build() self.set_inferior_startup_launch() diff --git a/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py b/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py index af563af158ce2a5c1a01580913aad5fc0b7547aa..52d81871c46dfa609e8a4b1a4f22e2f6f558da57 100644 --- a/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py +++ b/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py @@ -25,6 +25,7 @@ class TestGdbRemoteThreadName(gdbremote_testcase.GdbRemoteTestCaseBase): self.assertEqual(expected_name, kv_dict.get("name")) @skipIfWindows # the test is not updated for Windows. + @skipOnOpenHarmonyCI # investigate CI timeouts def test(self): """ Make sure lldb-server can retrieve inferior thread name""" self.build() diff --git a/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py b/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py index cda935ff70c3f29db325f58f0415628255e7f17b..9c956ab5c11c6a9833e9e61e1ac44a428db963ea 100644 --- a/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py +++ b/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py @@ -42,6 +42,7 @@ class TestVSCode_attach(lldbvscode_testcase.VSCodeTestCaseBase): self.continue_to_exit() @skipIfWindows + @skipIfLinux @skipIfNetBSD # Hangs on NetBSD as well @skipIfRemote def test_by_pid(self): diff --git a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py index 4731d13821a5c70f7f7aaca74a973babcab816e5..61d1dba1f46c4339ed6690f59675e6d1194ce0e0 100644 --- a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py +++ b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py @@ -46,6 +46,7 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): return False @skipIfWindows + @skipIfLinux @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_runInTerminal(self): diff --git a/lldb/tools/lldb-server/CMakeLists.txt b/lldb/tools/lldb-server/CMakeLists.txt index 3fb22b0a61098d5dfdf198b9ebb188d233bd9247..b7026ef121654f9d9c5791555e1df8b042777104 100644 --- a/lldb/tools/lldb-server/CMakeLists.txt +++ b/lldb/tools/lldb-server/CMakeLists.txt @@ -5,7 +5,7 @@ set_target_properties(LLGSOptionsTableGen PROPERTIES FOLDER "lldb misc") set(LLDB_PLUGINS) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android|OHOS") list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) endif() diff --git a/llvm-build/Makefile b/llvm-build/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2e3562419e15fb56ea8718c797611a4bfde944b0 --- /dev/null +++ b/llvm-build/Makefile @@ -0,0 +1,230 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ARCH = arm +ifneq ($(GCC),) +TARGET = +CROSS_COMPILE = $(GCC:%gcc=%) +CC = $(GCC) $(ARCH_CFLAGS) +MULTILIB = $(patsubst %.,%,$(shell $(CC) -print-multi-directory)) +else +TARGET = $(ARCH)-liteos-ohos +CLANG ?= clang +CROSS_COMPILE = $(CLANG:%clang=%llvm-) +CC = $(CLANG) --target=$(TARGET) $(ARCH_CFLAGS) +BUILD=x86_64-linux-gnu +MULTILIB = $(patsubst $(dir $(shell $(filter-out $(ARCH_CFLAGS),$(CC)) -print-libgcc-file-name))%,/%,$(dir $(shell $(CC) -print-libgcc-file-name))) +endif +MUSLBUILDDIR = build_$(or $(TARGET),$(ARCH))$(subst /,_,$(MULTILIB:%/=%)) +HIDE = @ +BUILD_DEBUG = false +SED_ARGS = -e '/install-libs:/s/if/and/g' + +TOPDIR = $(shell pwd)/../../../.. +MUSLDIR = $(TOPDIR)/third_party/musl +LINUXKERNELDIR = $(TOPDIR)/third_party/Linux_Kernel +OPTRTDIR = $(TOPDIR)/third_party/optimized-routines +NUTTXDIR = $(TOPDIR)/third_party/NuttX +SYSROOTDIR = $(TOPDIR)/prebuilts/lite/sysroot +LITEOSADIR = $(TOPDIR)/kernel/liteos_a +LINUXDIR = $(TOPDIR)/kernel/linux/linux-5.10 + +TARGETS = $(if $(wildcard $(LITEOSADIR)),liteos_a_user,) +TARGETS += $(if $(wildcard $(LINUXDIR)),linux_user,) + +define LINUX_TYPES_H +#ifndef _LINUX_TYPES_H +#define _LINUX_TYPES_H +#include +typedef uint32_t __u32, __le32; +#endif +endef +export LINUX_TYPES_H + +ifeq ($(ARCH),arm) +ARCH_CFLAGS = -mfloat-abi=softfp -mcpu=cortex-a7 -mfpu=neon-vfpv4 +else +ifeq ($(ARCH),aarch64) +ARCH_CFLAGS = +else +ifeq ($(ARCH),riscv64) +ARCH_CFLAGS = +else +ifeq ($(ARCH),mips) +ARCH_CFLAGS = +else +ifeq ($(ARCH),x86_64) +ARCH_CFLAGS = +else +$(warning *** warning: ARCH $(ARCH) has not been tested yet, use with cautions!) +ARCH_CFLAGS = +endif +endif +endif +endif +endif + +ifeq ($(ARCH),aarch64) +CFLAGS = -march=armv8 -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +else +ifeq ($(ARCH),riscv64) +CFLAGS = -march=rv64gc -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +else +ifeq ($(ARCH),mips) +CFLAGS = -march=mips32r2 -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +else +ifeq ($(ARCH),x86_64) +CFLAGS = -march=x86-64 -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +else +CFLAGS = -march=armv7-a -O2 -Wall -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack +endif +endif +endif +endif + +CFLAGS += -Wno-int-conversion + +.PHONY: $(TARGETS:%=musl_copy_for_%) +.PHONY: $(TARGETS:%=musl_patch_for_%) +.PHONY: $(TARGETS:%=musl_install_for_%) +.PHONY: $(TARGETS:%=musl_header_install_for_%) +.PHONY: $(TARGETS:%=linux_header_install_for_%) +.PHONY: $(TARGETS:%=nuttx_header_install_for_%) +.PHONY: $(TARGETS:%=optimized_routines_install_for_%) +.PHONY: all clean distclean + +all: $(TARGETS:%=musl_install_for_%) + +$(TARGETS:%=musl_copy_for_%): + $(HIDE) mkdir -p $@ + $(HIDE) cp -rfu $(MUSLDIR)/[^p]* $@ + +optimized_routines_install_for_liteos_a_user: musl_copy_for_liteos_a_user +ifneq ($(ARCH),) + $(HIDE) cp -rfp $(OPTRTDIR)/string/$(ARCH)/* $> $ $ $/dev/null && \ + make -sj install-headers + +musl_install_for_liteos_a_user: musl_patch_for_liteos_a_user + $(HIDE) cd musl_copy_for_liteos_a_user && mkdir -p $(MUSLBUILDDIR) && cd $(MUSLBUILDDIR) && \ + ../configure --prefix=$(SYSROOTDIR)/$(TARGET)/usr --target=$(TARGET) \ + --includedir=$(SYSROOTDIR)/$(TARGET)/usr/include \ + --libdir=$(SYSROOTDIR)/$(TARGET)/usr/lib/$(MULTILIB) \ + --syslibdir=$(SYSROOTDIR)/$(TARGET)/usr/lib/$(MULTILIB) \ + --build=$(BUILD) \ + $(if $(LDFLAGS),LDFLAGS="$(LDFLAGS)",) \ + CC="$(CC)" CROSS_COMPILE="$(CROSS_COMPILE)" CFLAGS="$(CFLAGS)" >/dev/null && \ + make -sj install + +musl_patch_for_linux_user: musl_copy_for_linux_user + $(HIDE) cp -rfp $(MUSLDIR)/porting/linux/user/* $/dev/null && \ + make -sj install-headers + +musl_install_for_linux_user: musl_patch_for_linux_user + $(HIDE) cd musl_copy_for_linux_user && mkdir -p $(MUSLBUILDDIR) && cd $(MUSLBUILDDIR) && \ + ../configure --prefix=$(SYSROOTDIR)/$(TARGET)/usr --target=$(TARGET) \ + --includedir=$(SYSROOTDIR)/$(TARGET)/usr/include \ + --libdir=$(SYSROOTDIR)/$(TARGET)/usr/lib/$(MULTILIB) \ + --syslibdir=$(SYSROOTDIR)/$(TARGET)/usr/lib/$(MULTILIB) \ + --build=$(BUILD) \ + CC="$(CC)" CROSS_COMPILE="$(CROSS_COMPILE)" CFLAGS="$(CFLAGS)" >/dev/null && \ + make -sj install + +clean: + $(HIDE) rm -rf musl_copy_for_* linux_header_install_for_* + +distclean: clean + $(HIDE) rm -rf $(SYSROOTDIR)/lib $(SYSROOTDIR)/usr diff --git a/llvm-build/OHOS.cmake b/llvm-build/OHOS.cmake new file mode 100644 index 0000000000000000000000000000000000000000..df2c08ce41ba84d48fd24b5c2d2b7a7ff7a566ac --- /dev/null +++ b/llvm-build/OHOS.cmake @@ -0,0 +1,22 @@ +# Copyright (C) 2021 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. + +include(Platform/Linux) + +# OHOS has soname, but binary names must end in ".so" so we cannot append +# a version number. Also we cannot portably represent symlinks on the host. +set(CMAKE_PLATFORM_NO_VERSIONED_SONAME 1) + +# OHOS reportedly ignores RPATH, and we cannot predict the install +# location anyway. +set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "") diff --git a/llvm-build/README.md b/llvm-build/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e12de6c793fa98dd4ffffc1737c0acb374bc0913 --- /dev/null +++ b/llvm-build/README.md @@ -0,0 +1,126 @@ +## Overview + +This readme briefly describes the functionality of our LLVM toolchain and how to build it + +1. [Build WIKI](#build_wiki) +2. [Function Introduction](#function_introduction) + + +## Build WIKI +
+ +### System Requirements for Toolchain BUild + +Ubuntu >= 16.04 +MacOS X >= 10.15.4 + +
+ +### Get Code +``` +repo init -u https://gitee.com/OpenHarmony/manifest.git -b add_llvm_toolchain-dev (not ready yet) +repo sync -c +repo forall -c 'git lfs pull' +cp -r toolchain/llvm-project/llvm-build toolchain +``` +
+ +### Toolchain build process + +Here is an example of starting build process on Linux or MacOS: +``` +# update prebuilts, no need to run each time +./toolchain/llvm-project/llvm-build/env_prepare.sh +# build +python3 ./toolchain/llvm-build/build.py +``` + +1. env_prepare (one time only) +![输入图片说明](../data/one_time_setup.png) + +2. build +![输入图片说明](../data/llvm_build.png) + +
+ +### Options + +build.py options: + +``` +--skip-build # skip compile and goto package step +--skip-package # do compile without package step +--enable-assertions # enable assertion when compiling +--build-name # specify release package name +--debug # build debug version llvm toolchain +--no-build-arm # skip triplet arm +--no-build-aarch64 # skip triplet arm64 +--no-build-x86_64 # skip triplet x86_64 +--no-lto # disable LTO optimization when build toolchain +--build-instrumented # enable instrument pgo when build toolchain +--xunit-xml-output # specify LLVM unit test XML report path +--no-build # optional, skip some targets + windows + libs + lldb-mi + lldb-server + linux + check-api +``` +
+ +### Output Layout + +When build successfully completed. following artifacts will be available in `out` directory + +`sysroot` -> sysroots for OHOS targets +`install` -> toolchain build +`*.tar.bz2` -> archived versions of toolchain and sysroots +
+ +### OHOS Archive + +1. llvm +``` +contains: +1. toolchain which provides clang compiler, lldb(-mi), clang-tidy etc. tools +2. libc++/clang_rt/asan/fuzzer libs for target device + +OHOS sync from: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ +Which is the same as: out/clang-dev-${platform}-${arch}.tar.bz2 +OHOS archive to: prebuilts/clang/ohos//${platform}/llvm + +License: Apache License v2.0 with LLVM Exceptions +``` + +2. libcxx-ndk +``` +contains: provide libc++ for ndk in target device + +OHOS fetch prebuilts from: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ and archive it to prebuilts/clang/ohos//${platform}/libcxx-ndk. This tar is + +License: Apache License v2.0 with LLVM Exceptions +``` + + +## Function Introduction +
+ +### Functionality + +The LLVM toolchain is built based on LLVM 12.0.1. It is used to provide capability of building ohos image. For detailed information about LLVM 12.0.1, please refer to [LLVM 12.0.1](https://lists.llvm.org/pipermail/llvm-announce/2021-July/000093.html). +
+ +### Specifically Included Triplets + +Despite all the components provided by LLVM community, we included several triplets for different types of ohos devices to our LLVM toochain, listed as below. For specification, liteos is a newly included OS name which indicate the simplified linux kernel. + +| Triplet Name | Architecture | System Kernel | System | +| ---------------------- | ------------ | ------------- | --------------- | +| arm-liteos-ohos | ARM 32bits | LiteOS | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Standard system | +| aarch64-linux-ohos | ARM 64bits | Linux | Standard system | + +For detailed definition of Small System and Standard System, please refer to [System Types](https://gitee.com/openharmony/docs/blob/master/en/device-dev/Readme-EN.md). + diff --git a/llvm-build/build.py b/llvm-build/build.py new file mode 100755 index 0000000000000000000000000000000000000000..e5a74de8ed96eb81c709cb62f17c36b8fa050082 --- /dev/null +++ b/llvm-build/build.py @@ -0,0 +1,1796 @@ +#!/usr/bin/env python +# Copyright (C) 2021 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. +# 2021.3.15 build for OHOS LLVM. +# Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + +import os +import platform +import re +import datetime +import logging +import glob +import subprocess +import shutil +import argparse +import mingw +import stat + + +class BuildConfig(): + # Defines public methods and functions and obtains script parameters. + + def __init__(self): + args = self.parse_args() + self.do_build = not args.skip_build + self.do_package = not args.skip_package + self.build_name = args.build_name + self.debug = args.debug + self.no_lto = args.no_lto + self.build_instrumented = args.build_instrumented + self.xunit_xml_output = args.xunit_xml_output + self.enable_assertions = args.enable_assertions + self.need_libs = self.do_build and 'libs' not in args.no_build + self.need_lldb_mi = self.do_build and 'lldb-mi' not in args.no_build + self.need_lldb_server = self.do_build and 'lldb-server' not in args.no_build + + 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 + self.no_build_mipsel = args.skip_build or args.no_build_mipsel + self.no_build_x86_64 = args.skip_build or args.no_build_x86_64 + + self.CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) + self.REPOROOT_DIR = os.path.abspath(os.path.join(self.CURRENT_DIR, '../../')) + self.LLVM_PROJECT_DIR = os.path.abspath(os.path.join(self.REPOROOT_DIR, 'toolchain', 'llvm-project')) + self.OUT_PATH = os.path.join(self.REPOROOT_DIR, 'out') + self.TARGETS = 'AArch64;ARM;BPF;Mips;RISCV;X86' + self.ORIG_ENV = dict(os.environ) + self.VERSION = None # autodetected + + self.OPENHOS_SFX = '-linux-ohos' + self.LITEOS_SFX = '-liteos-ohos' + self.LLDB_PY_VERSION = '3.10' + self.CLANG_VERSION = '10.0.1' + self.MINGW_TRIPLE = 'x86_64-windows-gnu' + logging.basicConfig(level=logging.INFO) + + @staticmethod + def parse_add_argument(parser): + + parser.add_argument( + '--enable-assertions', + action='store_true', + default=False, + help='Apply assertions, some parameters are affected.') + + parser.add_argument( + '--build-name', + default='dev', + help='Release name for the package.') + + parser.add_argument( + '--debug', + action='store_true', + default=False, + help='Building Clang and LLVM Tools for Debugging (only affects stage2)') + + parser.add_argument( + '--no-build-arm', + action='store_true', + default=False, + help='Omit build os target: arm.') + + parser.add_argument( + '--no-build-aarch64', + action='store_true', + default=False, + help='Omit build os target: aarch64.') + + parser.add_argument( + '--no-build-riscv64', + action='store_true', + default=False, + help='Omit build os target: 64-bit RISC-V.') + + parser.add_argument( + '--no-build-mipsel', + action='store_true', + default=False, + help='Omit build os target: mipsel.') + + parser.add_argument( + '--no-build-x86_64', + action='store_true', + default=False, + help='Omit build os target: x86_64.') + + parser.add_argument( + '--no-lto', + action='store_true', + default=False, + help='Accelerate builds by disabling LTO (only affects llvm product)') + + parser.add_argument( + '--build-instrumented', + action='store_true', + default=False, + help='Using the PGO instrumentation to build LLVM tool') + + parser.add_argument( + '--xunit-xml-output', + default=None, + help='Output path for LLVM unit tests XML report') + + def parse_args(self): + + parser = argparse.ArgumentParser(description='Process some integers.') + + # Options to skip build or packaging, can't skip two + build_package_group = parser.add_mutually_exclusive_group() + build_package_group.add_argument( + '--skip-build', + '-sb', + action='store_true', + default=False, + help='Omit the build, perform the packaging step directly.') + + build_package_group.add_argument( + '--skip-package', + '-sp', + action='store_true', + default=False, + help='Omit the packaging, perform the packaging step directly.') + + self.parse_add_argument(parser) + + known_platforms = ('windows', 'libs', 'lldb-mi', 'lldb-server', 'linux', 'check-api') + known_platforms_str = ', '.join(known_platforms) + + class SeparatedListByCommaAction(argparse.Action): + def __call__(self, parser, namespace, vals, option_string): + for val in vals.split(','): + if val in known_platforms: + continue + else: + error = '\'{}\' invalid. Choose from {}'.format(val, known_platforms) + raise argparse.ArgumentError(self, error) + setattr(namespace, self.dest, vals.split(',')) + + parser.add_argument( + '--no-build', + action=SeparatedListByCommaAction, + default=list(), + help='Don\'t build toolchain for specified platforms. Choices: ' + known_platforms_str) + + return parser.parse_args() + + +class ClangVersion(object): + """Parse and save clang version from version file.""" + + def __init__(self, version_file): + self._parse_version_file(version_file) + + @staticmethod + def _parse(text, key): + return re.findall(r'%s\s+(\d+)' % key, text)[0] + + def _parse_version_file(self, version_file): + with open(version_file, 'r') as fp: + text = fp.read() + self.major = self._parse(text, 'CLANG_VERSION_MAJOR') + self.minor = self._parse(text, 'CLANG_VERSION_MINOR') + self.patch = self._parse(text, 'CLANG_VERSION_PATCHLEVEL') + + def long_version(self): + return '.'.join([self.major, self.minor, self.patch]) + + def short_version(self): + return '.'.join([self.major, self.minor]) + + def major_version(self): + return self.major + + +class BuildUtils(object): + + def __init__(self, build_config): + self.build_config = build_config + + self.CMAKE_BIN_DIR = os.path.abspath( + os.path.join(self.build_config.REPOROOT_DIR, 'prebuilts/cmake', self.platform_prefix(), 'bin')) + + def open_ohos_triple(self, arch): + return arch + self.build_config.OPENHOS_SFX + + def liteos_triple(self, arch): + return arch + self.build_config.LITEOS_SFX + + def set_clang_version(self, install_dir): + self.build_config.VERSION = self.get_clang_version(install_dir).long_version() + + def invoke_ninja(self, + out_path, + env, + target=None, + install=True, + build_threads=False): + + ninja_bin_path = os.path.join(self.CMAKE_BIN_DIR, 'ninja') + + ninja_list = ['-l{}'.format(build_threads)] if build_threads else [] + + ninja_target = [target] if target else [] + + self.check_call([ninja_bin_path] + ninja_list + ninja_target, cwd=out_path, env=env) + if install: + self.check_call([ninja_bin_path, 'install'], cwd=out_path, env=env) + + def invoke_cmake(self, + cmake_path, + out_path, + invoke_defines, + env): + + cmake_bin_path = os.path.join(self.CMAKE_BIN_DIR, 'cmake') + flags = ['-G', 'Ninja'] + flags += ['-DCMAKE_PREFIX_PATH=%s' % self.CMAKE_BIN_DIR] + + for key in invoke_defines: + newdef = ''.join(['-D', key, '=', invoke_defines[key]]) + flags += [newdef] + + flags += [cmake_path] + self.check_create_dir(out_path) + + self.check_call([cmake_bin_path] + flags, cwd=out_path, env=env) + + @staticmethod + def logger(): + """Returns the module level logger.""" + return logging.getLogger(__name__) + + @staticmethod + def get_clang_version(llvm_install): + version_file = os.path.join(llvm_install, 'include', 'clang', 'Basic', + 'Version.inc') + return ClangVersion(version_file) + + def check_create_dir(self, path): + if not os.path.exists(path): + """Proxy for os.makedirs with logging and dry-run support.""" + self.logger().info('makedirs %s', path) + os.makedirs(path) + + def check_rm_tree(self, tree_dir): + """Removes directory tree.""" + def chmod_and_retry(func, path, _): + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWUSR) + return func(path) + raise IOError("rmtree on %s failed" % path) + + if os.path.exists(tree_dir): + self.logger().info('shutil rmtree %s', tree_dir) + shutil.rmtree(tree_dir, onerror=chmod_and_retry) + + def check_copy_tree(self, src_dir, dst_dir): + self.check_rm_tree(dst_dir) + """Proxy for shutil.copytree with logging and dry-run support.""" + self.logger().info('copytree %s %s', src_dir, dst_dir) + shutil.copytree(src_dir, dst_dir, symlinks=True) + + def check_copy_file(self, src_file, dst_file): + if os.path.exists(src_file): + """Proxy for shutil.copy2 with logging and dry-run support.""" + self.logger().info('copy %s %s', src_file, dst_file) + shutil.copy2(src_file, dst_file) + + def check_call(self, cmd, *args, **kwargs): + """subprocess.check_call with logging.""" + self.logger().info('check_call:%s %s', + datetime.datetime.now().strftime("%H:%M:%S"), subprocess.list2cmdline(cmd)) + + subprocess.check_call(cmd, *args, **kwargs) + + def merge_out_path(self, *args): + return os.path.abspath(os.path.join(self.build_config.OUT_PATH, *args)) + + @staticmethod + def use_platform(): + sysstr = platform.system().lower() + arch = platform.machine() + return "%s-%s" % (sysstr, arch) + + def platform_prefix(self): + prefix = self.use_platform() + if (prefix.endswith('x86_64')): + return prefix[:-3] + return prefix + + def host_is_linux(self): + return self.use_platform().startswith('linux-') + + def host_is_darwin(self): + return self.use_platform().startswith('darwin-') + + def rm_cmake_cache(self, cache_dir): + for dirpath, dirs, files in os.walk(cache_dir): + if 'CMakeCache.txt' in files: + self.logger().info('rm CMakeCache.txt on %s', cache_dir) + os.remove(os.path.join(dirpath, 'CMakeCache.txt')) + if 'CMakeFiles' in dirs: + self.logger().info('rm CMakeFiles on %s', cache_dir) + self.check_rm_tree(os.path.join(dirpath, 'CMakeFiles')) + + @staticmethod + def find_program(name): + # FIXME: Do we need Windows support here? + return os.popen('which ' + name).read().strip() + + # Base cmake options such as build type that are common across all invocations + def base_cmake_defines(self): + mac_min_version = '10.9' + defines = {} + + defines['CMAKE_BUILD_TYPE'] = 'Release' + defines['LLVM_ENABLE_ASSERTIONS'] = 'OFF' + defines['LLVM_ENABLE_TERMINFO'] = 'OFF' + defines['LLVM_ENABLE_THREADS'] = 'ON' + defines['LLVM_USE_NEWPM'] = 'ON' + defines['LLVM_ENABLE_BINDINGS'] = 'OFF' + defines['CLANG_REPOSITORY_STRING'] = 'llvm-project' + + if self.host_is_darwin(): + defines['CMAKE_OSX_DEPLOYMENT_TARGET'] = mac_min_version + defines['LLDB_INCLUDE_TESTS'] = 'OFF' + defines['LIBCXX_INCLUDE_TESTS'] = 'OFF' + + defines['COMPILER_RT_BUILD_XRAY'] = 'OFF' + return defines + + +class LlvmCore(BuildUtils): + + def __init__(self, build_config): + super(LlvmCore, self).__init__(build_config) + + def build_llvm(self, + targets, + build_dir, + install_dir, + build_name, + extra_defines=None, + extra_env=None): + + common_defines = self.base_cmake_defines() + common_defines['CMAKE_INSTALL_PREFIX'] = install_dir + common_defines['LLVM_INSTALL_UTILS'] = 'ON' + common_defines['LLVM_TARGETS_TO_BUILD'] = targets + common_defines['LLVM_BUILD_LLVM_DYLIB'] = 'ON' + + build_number = '' + if re.match(r'\d+-.\D*$', build_name): + build_number, build_name = build_name.split('-', 1) + elif re.match(r'^\d+$', build_name): + build_number = build_name + build_name = '' + elif re.match(r'^\D+$', build_name): + build_name = build_name + else: + raise Exception('Warning! Build name is invalid, because it must not contain digits. ' + 'If you want to pass digit version, please, use follow template: {NUMBER}-{SUFFIX} ' + 'or just pass number. Otherwise unit tests will fail with assertions') + + common_defines['CLANG_VENDOR'] = 'OHOS (%s) ' % build_name + common_defines['CLANG_VENDOR_BUILD_VERSION'] = build_number + common_defines.update(extra_defines) + + env = dict(self.build_config.ORIG_ENV) + if extra_env is not None: + env.update(extra_env) + + llvm_project_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm')) + + self.invoke_cmake(llvm_project_path, + build_dir, + common_defines, + env=env) + + self.invoke_ninja(out_path=build_dir, + env=env, + target=None, + install=True) + + + def llvm_compile_darwin_defines(self, llvm_defines): + if self.host_is_darwin(): + llvm_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF' + llvm_defines['LLDB_NO_DEBUGSERVER'] = 'ON' + llvm_defines['LLDB_ENABLE_PYTHON'] = 'ON' + llvm_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'OFF' + llvm_defines['LLVM_BUILD_EXTERNAL_COMPILER_RT'] = 'ON' + + def llvm_compile_linux_defines(self, + llvm_defines, + debug_build=False, + no_lto=False, + build_instrumented=False): + if self.host_is_linux(): + llvm_defines['LLVM_ENABLE_LLD'] = 'ON' + llvm_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'ON' + llvm_defines['LIBCXX_ENABLE_STATIC_ABI_LIBRARY'] = 'ON' + llvm_defines['LIBCXX_ENABLE_ABI_LINKER_SCRIPT'] = 'OFF' + llvm_defines['LIBCXX_USE_COMPILER_RT'] = 'ON' + llvm_defines['LIBCXXABI_USE_LLVM_UNWINDER'] = 'ON' + llvm_defines['LIBCXXABI_ENABLE_STATIC_UNWINDER'] = 'ON' + llvm_defines['LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY'] = 'YES' + llvm_defines['LIBCXXABI_USE_COMPILER_RT'] = 'ON' + llvm_defines['COMPILER_RT_USE_LLVM_UNWINDER'] = 'ON' + llvm_defines['COMPILER_RT_ENABLE_STATIC_UNWINDER'] = 'ON' + llvm_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON' + llvm_defines['COMPILER_RT_BUILD_ORC'] = 'OFF' + llvm_defines['LIBUNWIND_USE_COMPILER_RT'] = 'ON' + llvm_defines['LLVM_BINUTILS_INCDIR'] = '/usr/include' + + + if not build_instrumented and not no_lto and not debug_build: + llvm_defines['LLVM_ENABLE_LTO'] = 'Thin' + + @staticmethod + def llvm_compile_llvm_defines(llvm_defines, llvm_cc, llvm_cxx, cflags, ldflags): + llvm_defines['LLVM_ENABLE_PROJECTS'] = 'clang;lld;clang-tools-extra;openmp;lldb' + llvm_defines['LLVM_ENABLE_RUNTIMES'] = 'libunwind;libcxxabi;libcxx;compiler-rt' + llvm_defines['LLVM_ENABLE_BINDINGS'] = 'OFF' + llvm_defines['CMAKE_C_COMPILER'] = llvm_cc + llvm_defines['CMAKE_CXX_COMPILER'] = llvm_cxx + llvm_defines['LLVM_ENABLE_LIBCXX'] = 'ON' + llvm_defines['SANITIZER_ALLOW_CXXABI'] = 'OFF' + llvm_defines['LIBOMP_ENABLE_SHARED'] = 'FALSE' + llvm_defines['OPENMP_TEST_FLAGS'] = '-Wl,-ldl' + llvm_defines['CLANG_BUILD_EXAMPLES'] = 'OFF' + llvm_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF' + llvm_defines['LLDB_ENABLE_PYTHON'] = 'ON' + llvm_defines['COMPILER_RT_BUILD_SANITIZERS'] = 'OFF' + llvm_defines['COMPILER_RT_BUILD_MEMPROF'] = 'OFF' + llvm_defines['CMAKE_ASM_FLAGS'] = cflags + llvm_defines['CMAKE_C_FLAGS'] = cflags + llvm_defines['CMAKE_CXX_FLAGS'] = '%s -stdlib=libc++' % cflags + llvm_defines['CMAKE_EXE_LINKER_FLAGS'] = ldflags + llvm_defines['CMAKE_SHARED_LINKER_FLAGS'] = ldflags + llvm_defines['CMAKE_MODULE_LINKER_FLAGS'] = ldflags + + def llvm_compile(self, + build_name, + out_dir, + debug_build=False, + no_lto=False, + build_instrumented=False, + xunit_xml_output=None): + + llvm_clang_install = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, + 'prebuilts/clang/ohos', self.use_platform(), + 'clang-%s' % self.build_config.CLANG_VERSION)) + llvm_path = self.merge_out_path('llvm_make') + llvm_cc = os.path.join(llvm_clang_install, 'bin', 'clang') + llvm_cxx = os.path.join(llvm_clang_install, 'bin', 'clang++') + llvm_profdata = os.path.join(llvm_clang_install, 'bin', 'llvm-profdata') + + if self.host_is_darwin(): + ldflags = '' + else: + ldflags = '-fuse-ld=lld' + ldflags = '%s -L%s' % (ldflags, os.path.join(llvm_clang_install, 'lib')) + + llvm_extra_env = {} + llvm_extra_env['LD_LIBRARY_PATH'] = os.path.join(llvm_clang_install, 'lib') + + llvm_defines = {} + + self.llvm_compile_darwin_defines(llvm_defines) + self.llvm_compile_linux_defines(llvm_defines, debug_build, no_lto, build_instrumented) + + if self.host_is_linux(): + ldflags += ' -l:libunwind.a -l:libc++abi.a --rtlib=compiler-rt -stdlib=libc++ -static-libstdc++' + + if xunit_xml_output: + llvm_defines['LLVM_LIT_ARGS'] = "--xunit-xml-output={} -sv".format(xunit_xml_output) + + if self.build_config.enable_assertions: + llvm_defines['LLVM_ENABLE_ASSERTIONS'] = 'ON' + + if debug_build: + llvm_defines['CMAKE_BUILD_TYPE'] = 'Debug' + + if build_instrumented: + llvm_defines['LLVM_BUILD_INSTRUMENTED'] = 'ON' + llvm_defines['LLVM_PROFDATA'] = llvm_profdata + + resource_dir = "lib/clang/10.0.1/lib/linux/libclang_rt.profile-x86_64.a" + ldflags += ' %s' % os.path.join(llvm_clang_install, resource_dir) + + cflags = '-fstack-protector-strong -fPIE' + if not self.host_is_darwin(): + ldflags += ' -Wl,-z,relro,-z,now -pie -s' + + self.llvm_compile_llvm_defines(llvm_defines, llvm_cc, llvm_cxx, cflags, ldflags) + + linker_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'prebuilts', 'clang', + 'ohos', 'linux-x86_64', 'llvm', 'bin', 'ld.lld')) + llvm_defines['CMAKE_LINKER'] = linker_path + + self.build_llvm(targets=self.build_config.TARGETS, + build_dir=llvm_path, + install_dir=out_dir, + build_name=build_name, + extra_defines=llvm_defines, + extra_env=llvm_extra_env) + + def llvm_compile_windows_defines(self, + windows_defines, + cc, + cxx, + windows_sysroot): + + if self.build_config.enable_assertions: + + windows_defines['LLVM_ENABLE_ASSERTIONS'] = 'ON' + + windows_defines['LLDB_RELOCATABLE_PYTHON'] = 'OFF' + win_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE) + windows_defines['LLDB_ENABLE_PYTHON'] = 'ON' + windows_defines['LLDB_PYTHON_HOME'] = 'python' + windows_defines['LLDB_PYTHON_RELATIVE_PATH'] = \ + 'bin/python/lib/python%s' % (self.build_config.LLDB_PY_VERSION) + windows_defines['LLDB_PYTHON_EXE_RELATIVE_PATH'] = 'bin/python' + windows_defines['LLDB_PYTHON_EXT_SUFFIX'] = '.pys' + windows_defines['PYTHON_INCLUDE_DIRS'] = os.path.join(win_sysroot, + 'include', 'python%s' % self.build_config.LLDB_PY_VERSION) + windows_defines['PYTHON_LIBRARIES'] = os.path.join(win_sysroot, 'lib', 'libpython%s.dll.a' + % self.build_config.LLDB_PY_VERSION) + windows_defines['SWIG_EXECUTABLE'] = self.find_program('swig') + windows_defines['PYTHON_EXECUTABLE'] = self.find_program('python3') + + windows_defines['CMAKE_C_COMPILER'] = cc + windows_defines['CMAKE_CXX_COMPILER'] = cxx + windows_defines['CMAKE_SYSTEM_NAME'] = 'Windows' + windows_defines['CMAKE_BUILD_TYPE'] = 'Release' + windows_defines['LLVM_BUILD_RUNTIME'] = 'OFF' + windows_defines['LLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD'] = 'ON' + windows_defines['LLVM_TOOL_OPENMP_BUILD'] = 'OFF' + windows_defines['LLVM_INCLUDE_TESTS'] = 'OFF' + windows_defines['LLVM_ENABLE_LIBCXX'] = 'ON' + windows_defines['LLVM_ENABLE_PROJECTS'] = 'clang;clang-tools-extra;lld;lldb' + windows_defines['LLVM_BUILD_LLVM_DYLIB'] = 'OFF' + windows_defines['CLANG_BUILD_EXAMPLES'] = 'OFF' + windows_defines['CMAKE_SYSROOT'] = windows_sysroot + windows_defines['CMAKE_FIND_ROOT_PATH_MODE_INCLUDE'] = 'ONLY' + windows_defines['CMAKE_FIND_ROOT_PATH_MODE_LIBRARY'] = 'ONLY' + windows_defines['CMAKE_FIND_ROOT_PATH_MODE_PACKAGE'] = 'ONLY' + windows_defines['CMAKE_FIND_ROOT_PATH_MODE_PROGRAM'] = 'NEVER' + windows_defines['LLDB_ENABLE_LIBEDIT'] = 'OFF' + windows_defines['LLDB_RELOCATABLE_PYTHON'] = 'OFF' + + def llvm_compile_windows_flags(self, + windows_defines, + windowstool_path, + windows64_install, + ldflags, + cflags): + + windows_defines['CROSS_TOOLCHAIN_FLAGS_NATIVE'] = ';'.join([ + '-DCMAKE_PREFIX_PATH=%s' % self.CMAKE_BIN_DIR, + '-DCOMPILER_RT_BUILD_LIBFUZZER=OFF', + '-DLLVM_ENABLE_LIBCXX=ON', + '-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE', + '-DCMAKE_INSTALL_RPATH=%s' % os.path.join(windowstool_path, 'lib')] + ) + + ldflag = ['-fuse-ld=lld', + '-stdlib=libc++', + '--rtlib=compiler-rt', + '-lunwind', '-Wl,--dynamicbase', + '-Wl,--nxcompat', + '-lucrt', + '-lucrtbase', + '-L', + os.path.join(windows64_install, 'lib'), + '-Wl,--high-entropy-va'] + ldflags.extend(ldflag) + + cflag = ['-stdlib=libc++', + '--target=x86_64-pc-windows-gnu', + '-D_LARGEFILE_SOURCE', + '-D_FILE_OFFSET_BITS=64', + '-D_WIN32_WINNT=0x0600', + '-DWINVER=0x0600', + '-D__MSVCRT_VERSION__=0x1400', + '-DMS_WIN64'] + cflags.extend(cflag) + + def llvm_compile_windows_cmake(self, + cflags, + cxxflags, + ldflags, + windows_defines): + + + zlib_path = self.merge_out_path('../', 'prebuilts', 'clang', 'host', 'windows-x86', 'toolchain-prebuilts', + 'zlib') + zlib_inc = os.path.join(zlib_path, 'include') + zlib_lib = os.path.join(zlib_path, 'lib') + + cflags.extend(['-I', zlib_inc]) + cxxflags.extend(['-I', zlib_inc]) + ldflags.extend(['-L', zlib_lib]) + + windows_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags) + windows_defines['CMAKE_C_FLAGS'] = ' '.join(cflags) + windows_defines['CMAKE_CXX_FLAGS'] = ' '.join(cxxflags) + windows_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags) + windows_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + windows_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags) + + + def llvm_compile_for_windows(self, + targets, + enable_assertions, + build_name): + + self.logger().info('Building llvm for windows.') + + build_dir = self.merge_out_path("windows-x86_64") + windowstool_path = self.merge_out_path('llvm-install') + windows64_install = self.merge_out_path('windows-x86_64-install') + windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE) + + self.check_create_dir(build_dir) + + # Write a NATIVE.cmake in windows_path that contains the compilers used + # to build native tools such as llvm-tblgen and llvm-config. This is + # used below via the CMake variable CROSS_TOOLCHAIN_FLAGS_NATIVE. + cc = os.path.join(windowstool_path, 'bin', 'clang') + cxx = os.path.join(windowstool_path, 'bin', 'clang++') + + # Extra cmake defines to use while building for Windows + windows_defines = {} + self.llvm_compile_windows_defines(windows_defines, cc, cxx, windows_sysroot) + + # Set CMake path, toolchain file for native compilation (to build tablegen + # etc). Also disable libfuzzer build during native compilation. + + ldflags = [] + cflags = [] + + self.llvm_compile_windows_flags(windows_defines, + windowstool_path, windows64_install, ldflags, cflags) + + cxxflags = list(cflags) + + windows_extra_env = dict() + + cxxflags.append('-fuse-cxa-atexit') + cxxflags.extend(('-I', os.path.join(windows64_install, 'include', 'c++', 'v1'))) + + self.llvm_compile_windows_cmake(cflags, cxxflags, ldflags, windows_defines) + + self.build_llvm(self.build_config.TARGETS, + build_dir, + windows64_install, + build_name, + extra_defines=windows_defines, + extra_env=windows_extra_env) + + +class SysrootComposer(BuildUtils): + + def __init__(self, build_config): + super(SysrootComposer, self).__init__(build_config) + + def setup_cmake_platform(self, llvm_install): + + # OHOS.cmake already exsit on cmake prebuilts, + # but it didn't contain these two lines, so we still need OHOS.cmake. + ohos_cmake = 'OHOS.cmake' + dst_dir = self.merge_out_path( + '../prebuilts/cmake/%s/share/cmake-3.16/Modules/Platform' % self.platform_prefix()) + src_file = '%s/%s' % (self.build_config.CURRENT_DIR, ohos_cmake) + if os.path.exists(os.path.join(dst_dir, ohos_cmake)): + os.remove(os.path.join(dst_dir, ohos_cmake)) + shutil.copy2(src_file, dst_dir) + + + def build_musl(self, llvm_install, target, *extra_args): + cur_dir = os.getcwd() + os.chdir(self.build_config.CURRENT_DIR) + self.logger().info('build musl %s', self.merge_out_path('install')) + args = ['./build_musl.sh', '-t', target, '-c', + self.merge_out_path(llvm_install, 'bin'), '-o', self.merge_out_path()] + list(extra_args) + self.check_call(args) + os.chdir(cur_dir) + + def install_linux_headers(self, arch, target): + dir_suffix = arch + if arch == 'x86_64': + dir_suffix = 'x86' + elif arch == 'mipsel': + dir_suffix = 'mips' + linux_kernel_dir = os.path.join('kernel_linux_patches', 'linux-5.10') + linux_kernel_path = os.path.join(self.build_config.OUT_PATH, '..', linux_kernel_dir) + ohosmusl_sysroot_dst = self.merge_out_path('sysroot', target, 'usr') + headers_tmp_dir = os.path.join(linux_kernel_path, 'prebuilts', 'usr', 'include') + self.check_copy_tree(os.path.join(headers_tmp_dir, 'linux'), + os.path.join(ohosmusl_sysroot_dst, 'include/linux')) + self.check_copy_tree(os.path.join(headers_tmp_dir, 'asm-%s' % dir_suffix,'asm'), + os.path.join(ohosmusl_sysroot_dst, 'include', 'asm')) + self.check_copy_tree(os.path.join(headers_tmp_dir, 'asm-generic'), + os.path.join(ohosmusl_sysroot_dst, 'include/asm-generic')) + + def copy_libz_to_sysroot(self, libz_path, llvm_triple): + # Install to sysroot + dest_usr = self.merge_out_path('sysroot', llvm_triple, 'usr') + dest_usr_include = os.path.join(dest_usr, 'include') + + # Copy over usr/include. + zlib_h = self.merge_out_path('../third_party/zlib', 'zlib.h') + self.check_copy_file(zlib_h, dest_usr_include) + + zconf_h = os.path.join(libz_path, 'zconf.h') + self.check_copy_file(zconf_h, dest_usr_include) + + # Copy over usr/lib. + dest_usr_lib = os.path.join(dest_usr, 'lib') + static_zlib = os.path.join(libz_path, 'libz.a') + self.check_copy_file(static_zlib, dest_usr_lib) + + +class LlvmLibs(BuildUtils): + + def __init__(self, build_config, sysroot_composer, llvm_package): + super(LlvmLibs, self).__init__(build_config) + self.sysroot_composer = sysroot_composer + self.llvm_package = llvm_package + + def build_crt_libs(self, configs, llvm_install, need_lldb_server): + for (arch, target) in configs: + self.sysroot_composer.build_musl(llvm_install, target) + if target.endswith(self.build_config.OPENHOS_SFX): + self.sysroot_composer.install_linux_headers(arch, target) + self.build_libs(need_lldb_server, + llvm_install, + target, + precompilation=True) + self.sysroot_composer.build_musl(llvm_install, target, '-l') + + def build_libs_defines(self, + llvm_triple, + defines, + cc, + cxx, + ar, + llvm_config, + ldflags, + cflags, + extra_flags): + + sysroot = self.merge_out_path('sysroot') + + defines['CMAKE_C_COMPILER'] = cc + defines['CMAKE_CXX_COMPILER'] = cxx + defines['CMAKE_AR'] = ar + defines['LLVM_CONFIG_PATH'] = llvm_config + defines['CMAKE_SYSROOT'] = sysroot + defines['CMAKE_FIND_ROOT_PATH_MODE_INCLUDE'] = 'ONLY' + defines['CMAKE_FIND_ROOT_PATH_MODE_LIBRARY'] = 'ONLY' + defines['CMAKE_FIND_ROOT_PATH_MODE_PACKAGE'] = 'ONLY' + defines['CMAKE_FIND_ROOT_PATH_MODE_PROGRAM'] = 'NEVER' + + ldflag = [ + '-fuse-ld=lld', + '-Wl,--gc-sections', + '-Wl,--build-id=sha1', + '--rtlib=compiler-rt', + '-stdlib=libc++', ] + + if not self.host_is_darwin(): + ldflag.append('-Wl,-z,relro,-z,now -s -pie') + + ldflags.extend(ldflag) + + cflag = [ + '-fstack-protector-strong', + '-fPIE', + '--target=%s' % llvm_triple, + '-ffunction-sections', + '-fdata-sections', + extra_flags, ] + + cflags.extend(cflag) + + def build_libs(self, need_lldb_server, llvm_install, llvm_build, precompilation=False): + configs_list = [ + ('arm', self.liteos_triple('arm'), '-march=armv7-a -mfloat-abi=soft', ''), + ('arm', self.liteos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft', 'a7_soft'), + ('arm', self.liteos_triple('arm'), + '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4', 'a7_softfp_neon-vfpv4'), + ('arm', self.liteos_triple('arm'), + '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4', 'a7_hard_neon-vfpv4'), + + ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mfloat-abi=soft', ''), + ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft', 'a7_soft'), + ('arm', self.open_ohos_triple('arm'), + '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4', 'a7_softfp_neon-vfpv4'), + ('arm', self.open_ohos_triple('arm'), + '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4', 'a7_hard_neon-vfpv4'), + ('aarch64', self.open_ohos_triple('aarch64'), '', ''), + ('riscv64', self.open_ohos_triple('riscv64'), '', ''), + ('mipsel', self.open_ohos_triple('mipsel'), '-march=mips32r2', ''), + ('x86_64', self.open_ohos_triple('x86_64'), '', ''),] + + cc = os.path.join(llvm_install, 'bin', 'clang') + cxx = os.path.join(llvm_install, 'bin', 'clang++') + ar = os.path.join(llvm_install, 'bin', 'llvm-ar') + llvm_config = os.path.join(llvm_install, 'bin', 'llvm-config') + seen_arch_list = [self.liteos_triple('arm')] + + self.set_clang_version(llvm_install) + for (arch, llvm_triple, extra_flags, multilib_suffix) in configs_list: + if llvm_build != llvm_triple: + continue + + has_lldb_server = arch not in ['riscv64', 'mipsel'] + + defines = {} + ldflags = [] + cflags = [] + self.logger().info('Build libs for %s', llvm_triple) + self.build_libs_defines(llvm_triple, defines, cc, cxx, ar, llvm_config, ldflags, cflags, extra_flags) + if arch == 'mipsel': + ldflags.append('-Wl,-z,notext') + ldflags.append('-Wl,--no-check-dynamic-relocations') + + llvm_path = self.merge_out_path('llvm_make') + arch_list = [self.liteos_triple('arm'), self.open_ohos_triple('arm'), + self.open_ohos_triple('aarch64'), self.open_ohos_triple('riscv64'), + self.open_ohos_triple('mipsel'), self.open_ohos_triple('x86_64')] + if precompilation: + self.build_crts(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines) + continue + # libunwind is added to linker command line by OHOS toolchain, so we have to use two step build + self.build_runtimes(llvm_install, "libunwind", ldflags, cflags, llvm_triple, arch, multilib_suffix, defines) + self.build_runtimes(llvm_install, "libunwind;libcxxabi;libcxx", ldflags, cflags, llvm_triple, arch, multilib_suffix, defines) + self.build_crts(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines, + first_time=False) + + if llvm_triple in arch_list: + if need_lldb_server and has_lldb_server and llvm_triple not in seen_arch_list: + self.build_lldb_server(llvm_install, llvm_path, arch, llvm_triple, cflags, ldflags, + defines) + seen_arch_list.append(llvm_triple) + continue + + self.build_libomp(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines) + self.build_libz(arch, llvm_triple, cflags, ldflags, defines) + if need_lldb_server and has_lldb_server and llvm_triple not in seen_arch_list: + self.build_lldb_server(llvm_install, llvm_path, arch, llvm_triple, cflags, ldflags, defines) + seen_arch_list.append(llvm_triple) + + def build_runtimes(self, + llvm_install, + rt_list, + ldflags, + cflags, + llvm_triple, + arch, + multilib_suffix, + defines): + + self.logger().info('Building runtimes(%s) for %s', (rt_list, arch)) + + out_path = self.merge_out_path('lib', rt_list.replace(';', '-') + '-' + str(llvm_triple)) + + rt_cflags = list(cflags) + rt_cflags.append('-fstack-protector-strong') + + rt_defines = defines.copy() + rt_defines['OHOS'] = '1' + rt_defines['LLVM_ENABLE_PER_TARGET_RUNTIME_DIR'] = 'ON' + rt_defines['LLVM_TARGET_MULTILIB_SUFFIX'] = multilib_suffix + rt_defines['LLVM_DEFAULT_TARGET_TRIPLE'] = llvm_triple + rt_defines['LLVM_ENABLE_RUNTIMES'] = rt_list + rt_defines['LIBUNWIND_USE_COMPILER_RT'] = 'ON' + rt_defines['LIBUNWIND_ENABLE_SHARED'] = 'OFF' + rt_defines['LIBCXXABI_USE_COMPILER_RT'] = 'ON' + rt_defines['LIBCXXABI_USE_LLVM_UNWINDER'] = 'ON' + rt_defines['LIBCXXABI_ENABLE_STATIC_UNWINDER'] = 'ON' + rt_defines['LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL'] = 'OFF' + rt_defines['LIBCXXABI_ENABLE_SHARED'] = 'OFF' + rt_defines['LIBCXXABI_LIBCXX_INCLUDES'] = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'libcxx', 'include')) + rt_defines['LIBCXX_USE_COMPILER_RT'] = 'ON' + rt_defines['LIBCXX_ABI_NAMESPACE'] = '__h' + rt_defines['LIBCXX_ENABLE_ABI_LINKER_SCRIPT'] = 'OFF' + rt_defines['LIBCXX_ENABLE_STATIC_ABI_LIBRARY'] = 'ON' + rt_defines['CMAKE_ASM_FLAGS'] = ' '.join(rt_cflags) + rt_defines['CMAKE_C_FLAGS'] = ' '.join(rt_cflags) + rt_defines['CMAKE_CXX_FLAGS'] = ' '.join(rt_cflags) + rt_defines['CMAKE_INSTALL_PREFIX'] = llvm_install + rt_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + rt_defines['CMAKE_SYSTEM_NAME'] = 'OHOS' + rt_defines['CMAKE_CROSSCOMPILING'] = 'True' + rt_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY' + + 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, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=out_path, + env=dict(self.build_config.ORIG_ENV), + target=None, + install=True) + + def build_crts(self, + llvm_install, + arch, + llvm_triple, + cflags, + ldflags, + multilib_suffix, + defines, + first_time=True): + + self.logger().info('Building compiler-rt for %s', arch) + + suffix = '-' + multilib_suffix if multilib_suffix else '' + crt_path = self.merge_out_path('lib', 'clangrt-%s%s' % (llvm_triple, suffix)) + crt_install = os.path.join(llvm_install, 'lib', 'clang', self.build_config.VERSION) + + crt_extra_flags = [] + if not self.build_config.debug: + # Remove absolute paths from compiler-rt debug info emitted with -gline-tables-only + crt_extra_flags = ['-ffile-prefix-map=%s=.' % self.build_config.REPOROOT_DIR] + + crt_defines = defines.copy() + crt_defines.update(self.base_cmake_defines()) + crt_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags) + crt_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + crt_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags) + crt_defines['CMAKE_C_FLAGS'] = ' '.join(cflags + crt_extra_flags) + crt_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags + crt_extra_flags) + crt_defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags + crt_extra_flags) + crt_defines['COMPILER_RT_TEST_COMPILER_CFLAGS'] = ' '.join(cflags) + crt_defines['OHOS'] = '1' + crt_defines['COMPILER_RT_TEST_TARGET_TRIPLE'] = llvm_triple + crt_defines['COMPILER_RT_INCLUDE_TESTS'] = 'ON' + crt_defines['CMAKE_INSTALL_PREFIX'] = crt_install + crt_defines['LLVM_TARGET_MULTILIB_SUFFIX'] = multilib_suffix + if first_time or llvm_triple == self.liteos_triple('arm'): + crt_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'OFF' + else: + crt_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'ON' + crt_defines['COMPILER_RT_BUILD_ORC'] = 'OFF' + crt_defines['LLVM_ENABLE_PER_TARGET_RUNTIME_DIR'] = 'ON' + crt_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON' + crt_defines['CMAKE_SYSTEM_NAME'] = 'OHOS' + crt_defines['CMAKE_CROSSCOMPILING'] = 'True' + crt_defines['SANITIZER_CXX_ABI'] = 'libcxxabi' + crt_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY' + crt_defines['COMPILER_RT_HWASAN_WITH_INTERCEPTORS'] = 'OFF' + crt_defines['COMPILER_RT_BUILD_SANITIZERS'] = \ + 'OFF' if llvm_triple == self.liteos_triple('arm') or first_time else 'ON' + crt_defines['COMPILER_RT_DEFAULT_TARGET_TRIPLE'] = llvm_triple + crt_cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'compiler-rt')) + self.rm_cmake_cache(crt_path) + + self.invoke_cmake(crt_cmake_path, + crt_path, + crt_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=crt_path, + env=dict(self.build_config.ORIG_ENV), + target=None, + install=True) + + def build_libomp(self, + llvm_install, + arch, + llvm_triple, + cflags, + ldflags, + multilib_suffix, + defines): + + self.logger().info('Building libomp for %s', arch) + + libomp_path = self.merge_out_path('lib', 'libomp-%s' % llvm_triple) + out_dir = os.path.join(libomp_path, 'lib') + + libomp_cflags = list(cflags) + libomp_cflags.append('-fPIC') + + libomp_defines = defines.copy() + libomp_defines.update(self.base_cmake_defines()) + libomp_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags) + libomp_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + libomp_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags) + + libomp_defines['OHOS'] = '1' + libomp_defines['CMAKE_ASM_FLAGS'] = ' '.join(libomp_cflags) + libomp_defines['CMAKE_C_FLAGS'] = ' '.join(libomp_cflags) + libomp_defines['CMAKE_CXX_FLAGS'] = ' '.join(libomp_cflags) + libomp_defines['OPENMP_ENABLE_LIBOMPTARGET'] = 'FALSE' + + libomp_defines['OPENMP_LIBDIR_SUFFIX'] = os.path.join(os.sep, llvm_triple, multilib_suffix) + libomp_defines['LIBOMP_ENABLE_SHARED'] = 'FALSE' + libomp_defines['CMAKE_POLICY_DEFAULT_CMP0056'] = 'NEW' + libomp_defines['CMAKE_INSTALL_PREFIX'] = llvm_install + libomp_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON' + libomp_defines['CMAKE_SYSTEM_NAME'] = 'OHOS' + libomp_defines['CMAKE_CROSSCOMPILING'] = 'True' + libomp_defines['LLVM_ENABLE_LIBCXX'] = 'ON' + libomp_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY' + + libomp_cmake_path = os.path.join(self.build_config.LLVM_PROJECT_DIR, 'openmp') + self.rm_cmake_cache(libomp_path) + + self.invoke_cmake(libomp_cmake_path, + libomp_path, + libomp_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=libomp_path, + env=dict(self.build_config.ORIG_ENV), + target=None, + install=True) + + def build_libz(self, + arch, + llvm_triple, + cflags, + ldflags, + defines): + + self.logger().info('Building libz for %s ', arch) + + libz_path = self.merge_out_path('lib', 'libz-%s' % llvm_triple) + if llvm_triple == self.hos_triple('arm'): + ldflags.append('-lunwind') + + libz_cflags = list(cflags) + libz_cflags.append('-fPIC') + + libz_defines = defines.copy() + libz_defines.update(self.base_cmake_defines()) + libz_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags) + libz_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + libz_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags) + libz_defines['OHOS'] = '1' + libz_defines['CMAKE_ASM_FLAGS'] = ' '.join(libz_cflags) + libz_defines['CMAKE_C_FLAGS'] = ' '.join(libz_cflags) + libz_defines['CMAKE_CXX_FLAGS'] = ' '.join(libz_cflags) + libz_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY' + + libz_cmake_path = os.path.join(self.build_config.REPOROOT_DIR, 'third_party/zlib') + self.rm_cmake_cache(libz_path) + + self.invoke_cmake(libz_cmake_path, + libz_path, + libz_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=libz_path, + env=dict(self.build_config.ORIG_ENV), + target=None, + install=False) + + self.sysroot_composer.copy_libz_to_sysroot(libz_path, llvm_triple) + + def build_lldb_server(self, + llvm_install, + llvm_path, + arch, + llvm_triple, + cflags, + ldflags, + defines): + + self.logger().info('Building lldb for %s', arch) + + lldb_path = self.merge_out_path('lib', 'lldb-server-%s' % llvm_triple) + crt_install = os.path.join(llvm_install, 'lib', 'clang', self.build_config.VERSION) + out_dir = os.path.join(lldb_path, 'bin') + + lldb_ldflags = list(ldflags) + lldb_cflags = list(cflags) + + lldb_ldflags.append('-lunwind') + lldb_ldflags.append('-static') + + lldb_defines = defines.copy() + lldb_defines.update(self.base_cmake_defines()) + + lldb_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(lldb_ldflags) + lldb_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(lldb_ldflags) + lldb_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(lldb_ldflags) + + lldb_defines['OHOS'] = '1' + lldb_defines['CMAKE_C_FLAGS'] = ' '.join(lldb_cflags) + lldb_defines['CMAKE_ASM_FLAGS'] = ' '.join(lldb_cflags) + lldb_defines['CMAKE_CXX_FLAGS'] = ' '.join(lldb_cflags) + lldb_defines['CMAKE_INSTALL_PREFIX'] = crt_install + lldb_defines['LLVM_ENABLE_PER_TARGET_RUNTIME_DIR'] = 'ON' + lldb_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'ON' + lldb_defines['CMAKE_SYSTEM_NAME'] = 'OHOS' + lldb_defines['CMAKE_CROSSCOMPILING'] = 'True' + lldb_defines['LLVM_DEFAULT_TARGET_TRIPLE'] = llvm_triple + lldb_defines['LLVM_ENABLE_LIBCXX'] = 'ON' + lldb_defines['LLVM_ENABLE_PROJECTS'] = 'clang;lldb' + lldb_defines['LLVM_TABLEGEN'] = os.path.join(llvm_install, 'bin', 'llvm-tblgen') + lldb_defines['CLANG_TABLEGEN'] = os.path.join(llvm_install, '..', llvm_path, 'bin', 'clang-tblgen') + lldb_defines['LLDB_TABLEGEN'] = os.path.join(llvm_install, '..', llvm_path, 'bin', 'lldb-tblgen') + lldb_defines['LLVM_HOST_TRIPLE'] = llvm_triple + lldb_defines['LLVM_TARGET_ARCH'] = arch + lldb_defines['LLVM_TARGETS_TO_BUILD'] = self.build_config.TARGETS + + lldb_cmake_path = os.path.join(self.build_config.LLVM_PROJECT_DIR, 'llvm') + + self.invoke_cmake(lldb_cmake_path, + lldb_path, + lldb_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path=lldb_path, + env=dict(self.build_config.ORIG_ENV), + target='lldb-server', + install=False) + + self.llvm_package.copy_lldb_server_to_llvm_install(lldb_path, crt_install, llvm_triple) + + + def build_runtimes_for_windows(self, enable_assertions): + + self.logger().info('Building libs for windows.') + toolchain_dir = self.merge_out_path('llvm-install') + install_dir = self.merge_out_path('windows-x86_64-install') + windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE) + + cflags = ['-stdlib=libc++', '--target=x86_64-pc-windows-gnu', '-D_LARGEFILE_SOURCE', + '-D_FILE_OFFSET_BITS=64', '-D_WIN32_WINNT=0x0600', '-DWINVER=0x0600', '-D__MSVCRT_VERSION__=0x1400'] + + cmake_defines = {} + cmake_defines['CMAKE_C_COMPILER'] = os.path.join(toolchain_dir, 'bin', 'clang') + cmake_defines['CMAKE_CXX_COMPILER'] = os.path.join(toolchain_dir, 'bin', 'clang++') + cmake_defines['CMAKE_CROSSCOMPILING'] = 'True' + cmake_defines['CMAKE_SYSTEM_NAME'] = 'Windows' + cmake_defines['CMAKE_SYSROOT'] = windows_sysroot + cmake_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags) + cmake_defines['CMAKE_C_FLAGS'] = ' '.join(cflags) + cmake_defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags) + 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') + cmake_defines['LIBCXX_ENABLE_SHARED'] = 'OFF' + cmake_defines['LIBCXX_ENABLE_STATIC_ABI_LIBRARY'] = 'ON' + cmake_defines['LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS'] = 'ON' + cmake_defines['LIBCXXABI_ENABLE_SHARED'] = 'OFF' + cmake_defines['LIBUNWIND_ENABLE_SHARED'] = 'OFF' + cmake_defines['LIBCXXABI_USE_LLVM_UNWINDER'] = 'ON' + cmake_defines['LLVM_ENABLE_RUNTIMES'] = 'libunwind;libcxxabi;libcxx' + cmake_defines['LLVM_ENABLE_ASSERTIONS'] = 'ON' if enable_assertions else 'OFF' + + out_path = self.merge_out_path('lib', 'windows-runtimes') + cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, 'runtimes')) + + self.invoke_cmake(cmake_path, + out_path, + cmake_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(out_path, + env=dict(self.build_config.ORIG_ENV), + install=True) + + + +class LldbMi(BuildUtils): + + def __init__(self, build_config, llvm_package): + super(LldbMi, self).__init__(build_config) + self.llvm_package = llvm_package + + def build_lldb_mi(self, llvm_install): + self.logger().info('Building lldb-mi for linux.') + + llvm_path = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, + 'prebuilts/clang/ohos', self.use_platform(), 'clang-%s' % self.build_config.CLANG_VERSION)) + lldb_mi_cmake_path = os.path.join(self.build_config.LLVM_PROJECT_DIR, '../lldb-mi') + lldb_mi_path = self.merge_out_path('lldb_mi_build') + + self.check_rm_tree(lldb_mi_path) + self.rm_cmake_cache(lldb_mi_path) + + if self.host_is_darwin(): + cflags = [] + cxxflags =[] + ldflags = ['-Wl,-rpath,%s' % '@loader_path/../lib'] + else: + cflags = [] + cxxflags =[] + ldflags = ['-fuse-ld=lld', '-Wl,-rpath,%s' % '\$ORIGIN/../lib'] + ldflags.append('-Wl,-z,relro,-z,now -pie -s') + + ldflags.append('-L%s' % os.path.join(llvm_path, 'lib')) + cxxflags.append('-std=c++14') + cxxflags.append('-fstack-protector-strong -fPIE') + cflags.append('-fstack-protector-strong -fPIE') + + lldb_mi_defines = {} + lldb_mi_defines['CMAKE_C_COMPILER'] = os.path.join(llvm_path, 'bin', 'clang') + lldb_mi_defines['CMAKE_CXX_COMPILER'] = os.path.join(llvm_path, 'bin', 'clang++') + lldb_mi_defines['CMAKE_C_FLAGS'] = ' '.join(cflags) + lldb_mi_defines['CMAKE_CXX_FLAGS'] = ' '.join(cxxflags) + lldb_mi_defines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags) + lldb_mi_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + lldb_mi_defines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags) + lldb_mi_defines['LLVM_DIR'] = os.path.join(llvm_install, 'lib/cmake/llvm/') + lldb_mi_defines['LLVM_ENABLE_LIBCXX'] = 'ON' + lldb_mi_defines['CMAKE_INSTALL_PREFIX'] = llvm_install + + self.invoke_cmake(lldb_mi_cmake_path, + lldb_mi_path, + lldb_mi_defines, + env=dict(self.build_config.ORIG_ENV)) + + self.invoke_ninja(lldb_mi_path, + env=dict(self.build_config.ORIG_ENV), + install=False) + + self.llvm_package.copy_lldb_mi_to_llvm_install(lldb_mi_path, llvm_install) + + @staticmethod + def ldflags_lists_define(): + ldflags_lists = ['-Wl,--dynamicbase', + '-Wl,--nxcompat', + '-lucrt', + '-lucrtbase', + '-L', ] + return ldflags_lists + + @staticmethod + def cflags_lists_define(): + cflags_lists = ['-D_LARGEFILE_SOURCE', + '-D_FILE_OFFSET_BITS=64', + '-D_WIN32_WINNT=0x0600', + '-DWINVER=0x0600', + '-D__MSVCRT_VERSION__=0x1400', + '-DMS_WIN64', ] + return cflags_lists + + # Extra cmake defines to use while building for Windows + def lldb_mi_windefines_dictionary(self, cc, cxx, windows_sysroot, cflags, cxxflags, ldflags): + lldb_mi_windefines = {} + lldb_mi_windefines['CMAKE_C_COMPILER'] = cc + lldb_mi_windefines['CMAKE_CXX_COMPILER'] = cxx + lldb_mi_windefines['CMAKE_C_COMPILER_WORKS'] = '1' + lldb_mi_windefines['CMAKE_CXX_COMPILER_WORKS'] = '1' + lldb_mi_windefines['CMAKE_SYSTEM_NAME'] = 'Windows' + lldb_mi_windefines['CMAKE_SYSTEM_PROCESSOR'] = 'x86_64' + lldb_mi_windefines['LLVM_ENABLE_LIBCXX'] = 'ON' + lldb_mi_windefines['CMAKE_SYSROOT'] = windows_sysroot + lldb_mi_windefines['LLVM_INSTALL_PREFIX'] = self.merge_out_path('windows-x86_64-install') + lldb_mi_windefines['LLVM_DIR'] = self.merge_out_path('windows-x86_64-install/lib/cmake/llvm/') + lldb_mi_windefines['CMAKE_C_FLAGS'] = ' '.join(cflags) + lldb_mi_windefines['CMAKE_CXX_FLAGS'] = ' '.join(cxxflags) + lldb_mi_windefines['CMAKE_EXE_LINKER_FLAGS'] = ' '.join(ldflags) + lldb_mi_windefines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + lldb_mi_windefines['CMAKE_MODULE_LINKER_FLAGS'] = ' '.join(ldflags) + + if self.build_config.enable_assertions: + lldb_mi_windefines['LLVM_ENABLE_ASSERTIONS'] = 'ON' + + return lldb_mi_windefines + + + def build_lldb_mi_for_windows(self): + self.logger().info('Building lldb-mi for windows.') + + build_dir = self.merge_out_path('llvm-install') + lldb_mi_windows64_path = self.merge_out_path('windows-x86_64-lldb-mi') + lldb_mi_cmake_path = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, '../lldb-mi')) + windows64_install = self.merge_out_path('windows-x86_64-install') + cc = os.path.join(build_dir, 'bin', 'clang') + cxx = os.path.join(build_dir, 'bin', 'clang++') + + windows_sysroot = self.merge_out_path('mingw', self.build_config.MINGW_TRIPLE) + self.check_create_dir(lldb_mi_windows64_path) + + ldflags = ['-fuse-ld=lld', + '--rtlib=compiler-rt', + '-lunwind', + '-L%s' % os.path.join(windows64_install, 'lib'), + ] + ldflags.extend(self.ldflags_lists_define()) + ldflags.append(os.path.join(windows64_install, 'lib')) + ldflags.append('-Wl,--high-entropy-va') + + + cflags = ['-stdlib=libc++', + '--target=x86_64-pc-windows-gnu', + ] + cflags.extend(self.cflags_lists_define()) + cflags.append('-fno-exceptions') + cflags.append('-fno-rtti') + + cxxflags = list(cflags) + cxxflags.extend(('-I', os.path.join(windows64_install, 'include', 'c++', 'v1'))) + + zlib_path = os.path.abspath( + os.path.join('../../', 'prebuilts', 'clang', 'host', 'windows-x86', 'toolchain-prebuilts', 'zlib')) + zlib_inc = os.path.join(zlib_path, 'include') + zlib_lib = os.path.join(zlib_path, 'lib') + + cflags.extend(['-I', zlib_inc]) + cxxflags.extend(['-I', zlib_inc]) + ldflags.extend(['-L', zlib_lib]) + + + lldb_mi_env = dict(self.build_config.ORIG_ENV) + lldb_mi_env['LD_LIBRARY_PATH'] = os.path.join(build_dir, 'lib') + self.rm_cmake_cache(lldb_mi_windows64_path) + + self.invoke_cmake(lldb_mi_cmake_path, + lldb_mi_windows64_path, + self.lldb_mi_windefines_dictionary(cc, cxx, windows_sysroot, cflags, cxxflags, ldflags), + env=lldb_mi_env) + + self.invoke_ninja(lldb_mi_windows64_path, + env=lldb_mi_env, + install=False) + + self.llvm_package.copy_lldb_mi_to_windows(windows64_install, lldb_mi_windows64_path) + + +class LlvmPackage(BuildUtils): + + def __init__(self, build_config): + super(LlvmPackage, self).__init__(build_config) + + def copy_lldb_server_to_llvm_install(self, lldb_path, crt_install, llvm_triple): + # Copy lldb-server + libname = 'lldb-server' + src_lib = os.path.join(lldb_path, 'bin', libname) + dst_dir = os.path.join(crt_install, 'bin', llvm_triple) + self.check_create_dir(dst_dir) + self.check_copy_file(src_lib, os.path.join(dst_dir, libname)) + + def copy_lldb_mi_to_llvm_install(self, lldb_mi_path, llvm_install): + # Copy lldb-mi + lldb_mi_dst = os.path.join(llvm_install, 'bin', 'lldb-mi') + lldb_mi_src = os.path.join(lldb_mi_path, 'src', 'lldb-mi') + + if os.path.exists(lldb_mi_dst): + os.remove(lldb_mi_dst) + self.check_copy_file(lldb_mi_src, lldb_mi_dst) + + def copy_lldb_mi_to_windows(self, windows64_install, lldb_mi_windows64_path): + # Copy lldb-mi for windows + lldb_mi_dst = os.path.join(windows64_install, 'bin', 'lldb-mi.exe') + lldb_mi_src = os.path.join(lldb_mi_windows64_path, 'src', 'lldb-mi.exe') + if os.path.exists(lldb_mi_dst): + os.remove(lldb_mi_dst) + self.check_copy_file(lldb_mi_src, lldb_mi_dst) + + def package_libcxx(self): + libcxx_ndk_install=self.merge_out_path('libcxx-ndk') + libcxx_ndk_install_include=self.merge_out_path(libcxx_ndk_install, 'include', 'libcxx-ohos', 'include', 'c++', 'v1') + hosts_list=['linux-x86_64', 'darwin-x86_64', 'windows-x86_64', 'darwin-arm64'] + + if os.path.exists(libcxx_ndk_install): + for headerfile in os.listdir(libcxx_ndk_install_include): + if not headerfile =='__config': + if os.path.isdir(os.path.join(libcxx_ndk_install_include, headerfile)): + shutil.rmtree(os.path.join(libcxx_ndk_install_include, headerfile)) + else: + os.remove(os.path.join(libcxx_ndk_install_include, headerfile)) + + #Package libcxx-ndk + for host in hosts_list: + tarball_name = 'libcxx-ndk-%s-%s' % (self.build_config.build_name, host) + package_path = '%s%s' % (self.merge_out_path(tarball_name), '.tar.bz2') + self.logger().info('Packaging %s', package_path) + args = ['tar', '-chjC', self.build_config.OUT_PATH, '-f', package_path, 'libcxx-ndk'] + self.check_call(args) + self.check_rm_tree(libcxx_ndk_install) + + @staticmethod + def merge_tree(src_dir, dst_dir): + for item in os.listdir(src_dir): + src_path = os.path.join(src_dir, item) + dst_path = os.path.join(dst_dir, item) + if os.path.isfile(src_path): + shutil.copyfile(src_path, dst_path) + else: + shutil.copytree(src_path, dst_path) + + + def install_mingw_python(self, install_dir): + py_root = self.merge_out_path('../third_party', 'mingw-w64', 'mingw-w64-python', + self.build_config.LLDB_PY_VERSION) + bin_root = os.path.join(install_dir, 'bin') + py_dll = 'libpython' + self.build_config.LLDB_PY_VERSION + '.dll' + shutil.copyfile(os.path.join(py_root, py_dll), os.path.join(bin_root, py_dll)) + self.merge_tree(os.path.join(py_root, 'lib'), + os.path.join(bin_root, 'python', 'lib', 'python%s' % self.build_config.LLDB_PY_VERSION)) + + + + + + def windows_lib_files_operation(self, lib_files, lib_dir, install_dir): + + # Remove unnecessary Windows lib files. + windows_necessary_lib_files = ['libc++.a', 'libc++abi.a'] + + for lib_file in lib_files: + if lib_file.endswith('.a') and lib_file not in windows_necessary_lib_files: + static_library = os.path.join(lib_dir, lib_file) + os.remove(static_library) + + for necessary_lib_file in windows_necessary_lib_files: + if not os.path.isfile(os.path.join(lib_dir, necessary_lib_file)): + raise RuntimeError('Did not find %s under %s' % (necessary_lib_file, lib_dir)) + self.install_mingw_python(install_dir) + + + def darwin_stripped_xargs(self, bin_dir, necessary_bin_files, script_bins, need_x_bins_darwin): + for bin_filename in os.listdir(bin_dir): + binary = os.path.join(bin_dir, bin_filename) + if not os.path.isfile(binary): + continue + if bin_filename not in necessary_bin_files: + os.remove(binary) + elif bin_filename not in script_bins: + if bin_filename not in need_x_bins_darwin and self.host_is_darwin(): + self.check_call(['strip', '-x', binary]) + else: + self.check_call(['strip', binary]) + + + def strip_lldb_server(self, host, install_dir): + clang_version_bin_dir = os.path.join(install_dir, 'lib', 'clang', self.build_config.CLANG_VERSION, 'bin') + + if not host.startswith('linux') or not os.path.exists(clang_version_bin_dir): + return + llvm_strip = os.path.join(install_dir, 'bin', 'llvm-strip') + for llvm_triple_dir in os.listdir(clang_version_bin_dir): + llvm_triple_bin_dir = os.path.join(clang_version_bin_dir, llvm_triple_dir) + + if not os.path.isdir(llvm_triple_bin_dir): + continue + + for bin_filename in os.listdir(llvm_triple_bin_dir): + binary = os.path.join(llvm_triple_bin_dir, bin_filename) + if os.path.isfile(binary): + self.check_call([llvm_strip, binary]) + + + def notice_prebuilts_file(self, host, projects, install_dir): + + # Fetch all the LICENSE.* files under our projects and append them into a + # Single NOTICE file for the resulting prebuilts. + notices = [] + for project in projects: + license_pattern = os.path.abspath(os.path.join(self.build_config.LLVM_PROJECT_DIR, project, 'LICENSE.*')) + for license_file in glob.glob(license_pattern): + with open(license_file) as notice_file: + notices.append(notice_file.read()) + + zlib_license_file = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, 'third_party/zlib/LICENSE')) + with open(zlib_license_file) as notice_file: + notices.append(notice_file.read()) + + if host.startswith('windows'): + mingw_license_file = os.path.abspath(os.path.join(self.build_config.REPOROOT_DIR, + 'third_party/mingw-w64/COPYING')) + with open(mingw_license_file) as notice_file: + notices.append(notice_file.read()) + + with open(os.path.join(install_dir, 'NOTICE'), 'w') as notice_file: + notice_file.write('\n'.join(notices)) + + + def package_clang_bin_file(self, necessary_bin_files, ext): + necessary_bin_file = [ + 'clang%s' % ext, + 'clang++%s' % ext, + 'clang-cpp%s' % ext, + 'clang-%s%s' % (self.build_config.VERSION.split('.')[0], ext), + 'clang-check%s' % ext, + 'clang-cl%s' % ext, + 'clang-format%s' % ext, + 'clang-tidy%s' % ext, + 'clangd%s' % ext, + 'count%s' % ext, + ] + necessary_bin_files.extend(necessary_bin_file) + + @staticmethod + def package_lldb_bin_file(necessary_bin_files, ext): + necessary_bin_file = [ + 'dsymutil%s' % ext, + 'FileCheck%s' % ext, + 'git-clang-format', + 'ld.lld%s' % ext, + 'ld64.lld%s' % ext, + 'lld%s' % ext, + 'lld-link%s' % ext, + 'lldb%s' % ext, + 'lldb-argdumper%s' % ext, + 'lldb-server%s' % ext, + 'lldb-vscode%s' % ext, + ] + necessary_bin_files.extend(necessary_bin_file) + + @staticmethod + def package_llvm_bin_file(necessary_bin_files, ext): + necessary_bin_file = [ + 'llvm-addr2line%s' % ext, + 'llvm-ar%s' % ext, + 'llvm-as%s' % ext, + 'llvm-cfi-verify%s' % ext, + 'llvm-config%s' % ext, + 'llvm-cov%s' % ext, + 'llvm-cxxfilt%s' % ext, + 'llvm-dis%s' % ext, + 'llvm-lib%s' % ext, + 'llvm-link%s' % ext, + 'llvm-modextract%s' % ext, + 'llvm-nm%s' % ext, + 'llvm-objcopy%s' % ext, + 'llvm-objdump%s' % ext, + 'llvm-profdata%s' % ext, + 'llvm-ranlib%s' % ext, + 'llvm-readelf%s' % ext, + 'llvm-readobj%s' % ext, + 'llvm-rc%s' % ext, + 'llvm-size%s' % ext, + 'llvm-strings%s' % ext, + 'llvm-strip%s' % ext, + 'llvm-symbolizer%s' % ext, + ] + necessary_bin_files.extend(necessary_bin_file) + + @staticmethod + def package_scan_bin_file(necessary_bin_files, ext): + necessary_bin_file = [ + 'not%s' % ext, + 'sancov%s' % ext, + 'sanstats%s' % ext, + 'scan-build%s' % ext, + 'scan-view%s' % ext, + 'yaml2obj%s' % ext, + ] + necessary_bin_files.extend(necessary_bin_file) + + @staticmethod + def package_license_project_tuple(): + # Install license files as NOTICE in the toolchain install dir. + projects = ( + 'llvm', + 'compiler-rt', + 'libcxx', + 'libcxxabi', + 'openmp', + 'clang', + 'clang-tools-extra', + 'lld', + 'lldb', + 'libunwind', + ) + return projects + + def remove_unnecessary_bin(self, necessary_bin_files, host, lib_dir, install_dir, ext, shlib_ext): + + lib_files = [] + if os.path.isdir(lib_dir): + lib_files = os.listdir(lib_dir) + if host.startswith('windows'): + vers_major = int(self.build_config.VERSION.split('.')[0]) + # Redefining necessary bin files for Windows. + windows_forbidden_list_bin_files = ['clang-%s%s' % (vers_major, ext), 'scan-build%s' % ext, + 'scan-view%s' % ext] + windows_additional_bin_files = ['liblldb%s' % shlib_ext, 'libpython3.10%s' % shlib_ext] + + new_necessary_bin_files = list(set(necessary_bin_files) - set(windows_forbidden_list_bin_files)) + new_necessary_bin_files.extend(windows_additional_bin_files) + del necessary_bin_files[:] + necessary_bin_files.extend(new_necessary_bin_files) + + self.windows_lib_files_operation(lib_files, lib_dir, install_dir) + else: + # Remove unnecessary static libraries. + for lib_file in lib_files: + if lib_file.endswith('.a'): + static_library = os.path.join(lib_dir, lib_file) + os.remove(static_library) + + def package_up_resulting(self, package_name, host, install_host_dir): + # Package up the resulting trimmed install/ directory. + tarball_name = '%s-%s' % (package_name, host) + package_path = '%s%s' % (self.merge_out_path(tarball_name), '.tar.bz2') + self.logger().info('Packaging %s', package_path) + args = ['tar', '-cjC', install_host_dir, '-f', package_path, package_name] + if host.startswith('windows'): + # windows do not support symlinks, + # replace them with file copies + args.insert(1, '--dereference') + + self.check_call(args) + + # Package ohos NDK + if os.path.exists(self.merge_out_path('sysroot')): + tarball_ndk_name = 'ohos-sysroot-%s' % self.build_config.build_name + package_ndk_path = '%s%s' % (self.merge_out_path(tarball_ndk_name), '.tar.bz2') + self.logger().info('Packaging %s', package_ndk_path) + args = ['tar', '-chjC', self.build_config.OUT_PATH, '-f', package_ndk_path, 'sysroot'] + self.check_call(args) + + # Packing Operation. + + def package_operation(self, build_dir, host): + + self.logger().info('Packaging for other environments.') + package_name = 'clang-%s' % self.build_config.build_name + self.set_clang_version(build_dir) + + if host.startswith('windows'): + ext = '.exe' + shlib_ext = '.dll' + elif host.startswith('linux'): + ext = '' + shlib_ext = '.so' + else: + ext = '' + shlib_ext = '.dylib' + + install_dir = self.merge_out_path('install', host, package_name) + bin_dir = os.path.join(install_dir, 'bin') + lib_dir = os.path.join(install_dir, 'lib') + install_host_dir = os.path.abspath(os.path.join(install_dir, '../')) + self.check_rm_tree(install_host_dir) + self.check_copy_tree(build_dir, install_dir) + # copy readme file to install_dir + shutil.copyfile(os.path.join(self.build_config.CURRENT_DIR, "toolchain_readme.md"), + os.path.join(install_dir, "README.md")) + + # Remove unnecessary binaries. + necessary_bin_files = [] + self.package_clang_bin_file(necessary_bin_files, ext) + self.package_lldb_bin_file(necessary_bin_files, ext) + self.package_llvm_bin_file(necessary_bin_files, ext) + self.package_scan_bin_file(necessary_bin_files, ext) + + if self.build_config.need_lldb_mi: + necessary_bin_files.append('lldb-mi%s' % ext) + self.remove_unnecessary_bin(necessary_bin_files, host, lib_dir, install_dir, ext, shlib_ext) + + # Scripts that should not be stripped + script_bins = ['git-clang-format', 'scan-build', 'scan-view'] + need_x_bins_darwin = ['clang', 'clang++', 'clang-9', 'clang-cl', 'clang-cpp'] + + # Bin file in the list should be stripped with -x args when host=darwin + self.darwin_stripped_xargs(bin_dir, necessary_bin_files, script_bins, need_x_bins_darwin) + + # Strip lldb-server + self.strip_lldb_server(host, install_dir) + + for necessary_bin_file in necessary_bin_files: + if not os.path.isfile(os.path.join(bin_dir, necessary_bin_file)): + print('Did not find %s in %s' % (necessary_bin_file, bin_dir)) + raise RuntimeError('Did not find %s in %s' % (necessary_bin_file, bin_dir)) + + cmake_dir = os.path.join(lib_dir, 'cmake') + self.check_rm_tree(cmake_dir) + + self.notice_prebuilts_file(host, self.package_license_project_tuple(), install_dir) + + create_tar = True + if create_tar: + self.package_up_resulting(package_name, host, install_host_dir) + + return + + + +def main(): + build_config = BuildConfig() + build_utils = BuildUtils(build_config) + sysroot_composer = SysrootComposer(build_config) + llvm_core = LlvmCore(build_config) + llvm_package = LlvmPackage(build_config) + lldb_mi = LldbMi(build_config, llvm_package) + llvm_libs = LlvmLibs(build_config, sysroot_composer, llvm_package) + + 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 \ + ('windows' not in args.no_build) + + llvm_install = build_utils.merge_out_path('llvm-install') + windows64_install = build_utils.merge_out_path('windows-x86_64-install') + + configs = [] + if not build_config.no_build_arm: + configs.append(('arm', build_utils.liteos_triple('arm'))) + configs.append(('arm', build_utils.open_ohos_triple('arm'))) + + if not build_config.no_build_aarch64: + configs.append(('arm64', build_utils.open_ohos_triple('aarch64'))) + + if not build_config.no_build_riscv64: + configs.append(('riscv', build_utils.open_ohos_triple('riscv64'))) + + if not build_config.no_build_mipsel: + configs.append(('mipsel', build_utils.open_ohos_triple('mipsel'))) + + if not build_config.no_build_x86_64: + configs.append(('x86_64', build_utils.open_ohos_triple('x86_64'))) + + + if build_config.do_build and need_host: + llvm_core.llvm_compile( + build_config.build_name, + llvm_install, + build_config.debug, + build_config.no_lto, + build_config.build_instrumented, + build_config.xunit_xml_output) + + llvm_core.set_clang_version(llvm_install) + + if build_config.do_build and build_utils.host_is_linux(): + sysroot_composer.setup_cmake_platform(llvm_install) + llvm_libs.build_crt_libs(configs, llvm_install, build_config.need_lldb_server) + + if build_config.need_libs: + for (arch, target) in configs: + llvm_libs.build_libs(build_config.need_lldb_server, llvm_install, target) + + if build_config.do_build and need_windows: + mingw.main(build_config.VERSION) + llvm_libs.build_runtimes_for_windows(build_config.enable_assertions) + llvm_core.llvm_compile_for_windows(build_config.TARGETS, + build_config.enable_assertions, + build_config.build_name) + + if build_config.need_lldb_mi: + lldb_mi.build_lldb_mi_for_windows() + + if build_config.do_build and build_config.need_lldb_mi and need_host: + lldb_mi.build_lldb_mi(llvm_install) + + if build_config.do_package: + if build_utils.host_is_linux(): + llvm_package.package_libcxx() + llvm_package.package_operation(llvm_install, build_utils.use_platform()) + if build_config.do_package and need_windows: + llvm_package.package_operation(windows64_install, 'windows-x86_64') + +if __name__ == '__main__': + main() diff --git a/llvm-build/build_cpython-mingw.sh b/llvm-build/build_cpython-mingw.sh new file mode 100755 index 0000000000000000000000000000000000000000..7419458cc7d956f3362f51213503ca4baca1666b --- /dev/null +++ b/llvm-build/build_cpython-mingw.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +PROJECT_ROOT=$(pwd) +CPYTHON_MINGW_SRC=${PROJECT_ROOT}/third_party/python +MINGW_W64_SRC=${PROJECT_ROOT}/third_party/mingw-w64 + +# prepare SYSROOT for cpython-mingw build +CLANG_MINGW_BUILD=${PROJECT_ROOT}/out/clang_mingw +python3 ${PROJECT_ROOT}/toolchain/llvm-build/mingw.py + +# refreash cpython-mingw config +cd ${CPYTHON_MINGW_SRC} +cat ./patchs/cpython_mingw_v3.10.2.patch | patch -d ./ -p1 -E +rm -rf ${CPYTHON_MINGW_SRC}/configure +autoconf ${CPYTHON_MINGW_SRC}/configure.ac > ${CPYTHON_MINGW_SRC}/configure +chmod 777 ${CPYTHON_MINGW_SRC}/configure +./configure + +# # prepare build config and build libpython for cpython-mingw +CPYTHON_MINGW_BUILD=${PROJECT_ROOT}/out/cpython-mingw-build +mkdir -p ${CPYTHON_MINGW_BUILD} +cd ${CPYTHON_MINGW_BUILD} +MINGW_PREFIX=${CPYTHON_MINGW_BUILD}/mingw64 +MINGW_CHOST=x86_64-w64-mingw32 +MINGW_BUILD=x86_64-unknown-linux-gnu +CLANG_VERSION=clang-10.0.1 +TOOLCHAIN_ROOT=${CLANG_MINGW_BUILD}/${CLANG_VERSION}/bin +SYSROOT=${CLANG_MINGW_BUILD}/${CLANG_VERSION}/x86_64-w64-mingw32 +mkdir $MINGW_BUILD + +export CC=$TOOLCHAIN_ROOT/clang +export CXX=$TOOLCHAIN_ROOT/clang++ +export CFLAGS="-target ${MINGW_CHOST} --sysroot=$SYSROOT" +export LDFLAGS="--sysroot=$SYSROOT -rtlib=compiler-rt -target ${MINGW_CHOST} -lucrt -lucrtbase -fuse-ld=lld" + +${CPYTHON_MINGW_SRC}/configure \ + --prefix=${MINGW_PREFIX} \ + --host=${MINGW_CHOST} \ + --build=${MINGW_BUILD} \ + --enable-shared \ + --enable-static \ + --without-ensurepip \ + --without-c-locale-coercion \ + --enable-loadable-sqlite-extensions + +make -j4 + +# copy build result to mingw-w64 +cp ${CPYTHON_MINGW_BUILD}/libpython3.10.dll.a ${MINGW_W64_SRC}/mingw-w64-crt/lib64 +cp ${CPYTHON_MINGW_BUILD}/libpython3.10.dll ${MINGW_W64_SRC}/mingw-w64-python/3.10 +cd ../.. + +# example steps to install autoconf 2.71 +# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz +# export PATH=/mnt/disk2/liwentao/workspace/tools/autoconf/autoconf-2.71/bin:$PATH +# sudo cp -r /mnt/disk2/liwentao/workspace/tools/autoconf/autoconf-2.71/lib /usr/local/share/autoconf + +# refreash configure and Makefile for mingw-w64 +# you need autoconf (2.69 for Ubuntu 20.04 LTS apt install, to support mingw-w64 9.x and later version, please install autoconf 2.71 http://ftp.gnu.org/gnu/autoconf/) +# and automake (1.16.1 for Ubuntu 20.04 LTS apt install) +cd ${MINGW_W64_SRC}/mingw-w64-crt +rm -rf configure +autoconf configure.ac > configure +chmod 777 configure + +aclocal +automake + +cd ${MINGW_W64_SRC}/mingw-w64-headers +rm -rf configure +autoconf configure.ac > configure +chmod 777 configure + +aclocal +automake + +# move cpython-mingw build result and python header file to mingw-w64 +cp -r ${CPYTHON_MINGW_SRC}/Include ${MINGW_W64_SRC}/mingw-w64-headers/include/python3.10 +cp ${CPYTHON_MINGW_SRC}/pyconfig.h ${MINGW_W64_SRC}/mingw-w64-headers/include/python3.10 +mkdir -p ${MINGW_W64_SRC}/mingw-w64-python/3.10 +cp -r ${CPYTHON_MINGW_SRC}/Lib ${MINGW_W64_SRC}/mingw-w64-python/3.10/lib \ No newline at end of file diff --git a/llvm-build/build_musl.sh b/llvm-build/build_musl.sh new file mode 100755 index 0000000000000000000000000000000000000000..9fb8737c032a015587d0a42f46add2c31c7ff372 --- /dev/null +++ b/llvm-build/build_musl.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# Copyright (C) 2021 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. +set -e + +# This script is used to create musl's libc.so. + +#default variables +CLANG_BIN_ROOT="${PWD}/../../out/install/linux-x86_64/clang-dev/bin/" +TARGET_TRIPLE="" +OUT="${PWD}/../../out" +make_libs=0 + +#argument parser +while getopts "c:t:o:lh" arg +do + case "${arg}" in + "c") + CLANG_BIN_ROOT=${OPTARG} + ;; + "t") + TARGET_TRIPLE=${OPTARG} + ;; + "o") + OUT=${OPTARG} + ;; + "l") + make_libs=1 + ;; + "h") + echo "Usage: ./build_musl.sh [OPTION]" + echo " Build C/C++ dynamic libs and runtime object" + echo " Options are:" + echo " -c Specify clang bin path" + echo " -t Specify target tripple" + echo " -o Specify the build output directory" + echo " -l Install libs" + exit 0 + ;; + ?) + echo "unkown argument" + exit 1 + ;; + esac +done + +if [ -z "${TARGET_TRIPLE}" ] +then + echo "[ERROR] Empty target triple in build_musl.sh" + exit 1 +fi + +# Canonicalize paths +CLANG_BIN_ROOT=$(readlink -f ${CLANG_BIN_ROOT}) + +CFLAGS_FOR_TARGET=("-mfloat-abi=soft" "-mfloat-abi=soft -mcpu=cortex-a7" +"-mfloat-abi=softfp -mfpu=neon-vfpv4 -mcpu=cortex-a7" "-mfloat-abi=hard -mfpu=neon-vfpv4 -mcpu=cortex-a7") + +if [ $TARGET_TRIPLE == "arm-liteos-ohos" ]; then + TARGET_USER="liteos_a_user" + TARGETS_PREFIX="arm" +elif [ $TARGET_TRIPLE == "arm-linux-ohos" ]; then + TARGET_USER="linux_user" + TARGETS_PREFIX="arm" +elif [ $TARGET_TRIPLE == "mipsel-linux-ohos" ]; then + TARGET_USER="linux_user" + TARGETS_PREFIX="mips" + CFLAGS_FOR_TARGET=("-march=mips32r2") +elif [ $TARGET_TRIPLE == "riscv64-linux-ohos" ]; then + TARGET_USER="linux_user" + TARGETS_PREFIX="riscv64" +elif [ $TARGET_TRIPLE == "x86_64-linux-ohos" ]; then + TARGET_USER="linux_user" + TARGETS_PREFIX="x86_64" +else + TARGET_USER="linux_user" + TARGETS_PREFIX="aarch64" +fi + +echo "CLANG_BIN_ROOT=${CLANG_BIN_ROOT}" +echo "ARCH=${TARGETS_PREFIX}" +echo "TARGET=${TARGET_TRIPLE}" +echo "TOPDIR=${PWD}/../.." +echo "TARGETS=${TARGET_USER}" +echo "OUT=${OUT}" +echo "SYSROOTDIR=${OUT}/sysroot" + +# build musl_headers +make musl_header_install_for_${TARGET_USER} CLANG="${CLANG_BIN_ROOT}/clang" TOPDIR=${PWD}/../../\ + SYSROOTDIR=${OUT}/sysroot TARGETS=${TARGET_USER} TARGET=${TARGET_TRIPLE} ARCH=${TARGETS_PREFIX} -f Makefile + +# build musl_libs +if ((make_libs == 1)); then + if [ $TARGET_TRIPLE == "aarch64-linux-ohos" ] || [ $TARGET_TRIPLE == "riscv64-linux-ohos" ] || \ + [ $TARGET_TRIPLE == "mipsel-linux-ohos" ] || [ $TARGET_TRIPLE == "x86_64-linux-ohos" ]; then + make CLANG="${CLANG_BIN_ROOT}/clang" TOPDIR=${PWD}/../../ SYSROOTDIR=${OUT}/sysroot TARGETS=${TARGET_USER}\ + TARGET=${TARGET_TRIPLE} ARCH=${TARGETS_PREFIX} -f Makefile + else + for ARCH_CFLAG in "${CFLAGS_FOR_TARGET[@]}" + do + make CLANG="${CLANG_BIN_ROOT}/clang" TOPDIR=${PWD}/../../ SYSROOTDIR=${OUT}/sysroot TARGETS=${TARGET_USER}\ + TARGET=${TARGET_TRIPLE} ARCH=${TARGETS_PREFIX} ARCH_CFLAGS="${ARCH_CFLAG}" -f Makefile + done + fi +fi +make distclean -f Makefile diff --git a/llvm-build/env_prepare.sh b/llvm-build/env_prepare.sh new file mode 100755 index 0000000000000000000000000000000000000000..552fbdba47722853296a9102ac013d6c9d6b0d29 --- /dev/null +++ b/llvm-build/env_prepare.sh @@ -0,0 +1,113 @@ +case $(uname -s) in + Linux) + + host_platform=linux + ;; + Darwin) + host_platform=darwin + ;; + *) + echo "Unsupported host platform: $(uname -s)" + exit 1 +esac + +case $(uname -m) in + arm64) + + host_cpu=arm64 + ;; + *) + host_cpu=x86_64 +esac + +# sync code directory +code_dir=$(pwd) + +# downloaded files will be automatically unzipped under this path +bin_dir=${code_dir}/download_packages + +# download and initialize prebuild files +if [ ! -d "${bin_dir}" ];then + mkdir -p "${bin_dir}" +fi + + +function download_and_archive() { + archive_dir=$1 + download_source_url=$2 + bin_file=$(basename ${download_source_url}) + wget -t3 -T10 -O "${bin_dir}/${bin_file}" "${download_source_url}" + if [ ! -d "${code_dir}/${archive_dir}" ];then + mkdir -p "${code_dir}/${archive_dir}" + fi + if [ "X${bin_file:0-3}" = "Xzip" ];then + unzip -o "${bin_dir}/${bin_file}" -d "${code_dir}/${archive_dir}/" + elif [ "X${bin_file:0-6}" = "Xtar.gz" ];then + tar -xvzf "${bin_dir}/${bin_file}" -C "${code_dir}/${archive_dir}" + else + tar -xvf "${bin_dir}/${bin_file}" -C "${code_dir}/${archive_dir}" + fi +} + + +copy_config=""" +""" + +copy_config_linux_x86_64=""" +prebuilts/cmake,https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/${host_platform}/cmake-${host_platform}-x86-3.16.5.tar.gz +prebuilts/clang/ohos/${host_platform}-${host_cpu},https://mirrors.huaweicloud.com/openharmony/compiler/clang/10.0.1-62608/${host_platform}/llvm.tar.gz +prebuilts/clang/ohos/${host_platform}-${host_cpu},https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz +""" + + +copy_config_darwin_x86_64=""" +prebuilts/cmake,https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/${host_platform}/cmake-${host_platform}-x86-3.16.5.tar.gz +prebuilts/clang/ohos/${host_platform}-${host_cpu},https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/clang+llvm-12.0.0-x86_64-apple-darwin.tar.xz +""" + + +if [[ "${host_platform}" == "linux" ]]; then + if [[ "${host_cpu}" == "x86_64" ]]; then + copy_config+=${copy_config_linux_x86_64} + echo "add ubuntu here" + else + echo "unknwon host_cpu - ${host_cpu} for linux" + fi +elif [[ "${host_platform}" == "darwin" ]]; then + if [[ "${host_cpu}" == "x86_64" ]]; then + copy_config+=${copy_config_darwin_x86_64} + echo "add x86-64 mac here" + elif [[ "${host_cpu}" == "arm64" ]]; then + echo "add m1 config here" + else + echo "unknwon host_cpu - ${host_cpu} for darwin" + fi +else + echo "unknown ${host_platform}" +fi + + +for i in $(echo ${copy_config}) +do + unzip_dir=$(echo $i|awk -F ',' '{print $1}') + remote_url=$(echo $i|awk -F ',' '{print $2}') + download_and_archive "${unzip_dir}" "${remote_url}" +done + + +if [ -d "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-62608" ];then + rm -rf "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm" + mv "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-62608" "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm" + ln -snf 10.0.1 "${code_dir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/clang/current" +fi + + +if [ -d "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04" ];then + rm -rf "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-10.0.1" + mv "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04" "${code_dir}/prebuilts/clang/ohos/linux-x86_64/clang-10.0.1" +fi + +if [ -d "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang+llvm-12.0.0-x86_64-apple-darwin" ];then + rm -rf "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang-10.0.1" + mv "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang+llvm-12.0.0-x86_64-apple-darwin" "${code_dir}/prebuilts/clang/ohos/darwin-x86_64/clang-10.0.1" +fi diff --git a/llvm-build/mingw.py b/llvm-build/mingw.py new file mode 100755 index 0000000000000000000000000000000000000000..78e1f5e5b217de4b0171e6920741d536b44b3f1e --- /dev/null +++ b/llvm-build/mingw.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2021 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. + +"""donwload and build mingw64-7.0.0 sysroot""" + +import logging +import os +import shutil +import subprocess +import sys + + +class BuildConfig(): + + def __init__(self, clang_version): + self.THIS_DIR = os.path.realpath(os.path.dirname(__file__)) + self.OUT_DIR = os.environ.get('OUT_DIR', self.repo_root('out')) + self.CLANG_VERSION = clang_version + self.LLVM_TRIPLE = 'x86_64-windows-gnu' + + def repo_root(self, *args): + return os.path.realpath(os.path.join(self.THIS_DIR, '../../', *args)) + + def out_root(self, *args): + return os.path.realpath(os.path.join(self.OUT_DIR, *args)) + + def mingw64_dir(self): + return self.out_root('mingw', self.LLVM_TRIPLE) + + def llvm_path(self, *args): + return os.path.realpath(os.path.join(self.THIS_DIR, '../llvm-project', *args)) + + +class LlvmMingw(): + + def __init__(self, build_config): + self.build_config = build_config + + self.CMAKE_BIN_PATH = os.path.join(self.cmake_prebuilt_bin_dir(), 'cmake') + self.NINJA_BIN_PATH = os.path.join(self.cmake_prebuilt_bin_dir(), 'ninja') + + self.LLVM_ROOT = self.build_config.out_root('llvm-install') + self.LLVM_CONFIG = os.path.join(self.LLVM_ROOT, 'bin', 'llvm-config') + self.SYSROOT = self.build_config.mingw64_dir() + self.CRT_PATH = self.build_config.out_root('lib', 'mingw-clangrt-%s' % self.build_config.LLVM_TRIPLE) + self.CRT_INSTALL = self.build_config.out_root('llvm-install', 'lib', 'clang', self.build_config.CLANG_VERSION) + # prefix & env + self.prefix = build_config.mingw64_dir() + common_flags = "-target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libc++ \ + -fuse-ld=lld -Qunused-arguments -g -O2 --sysroot=" + self.build_config.mingw64_dir() + self.env = { + "CC": "%s/bin/clang" % self.LLVM_ROOT, + "CXX": "%s/bin/clang++" % self.LLVM_ROOT, + "AR": "%s/bin/llvm-ar" % self.LLVM_ROOT, + "DLLTOOL": "%s/bin/llvm-dlltool" % self.LLVM_ROOT, + "LD": "%s/bin/ld.lld" % self.LLVM_ROOT, + "RANLIB": "%s/bin/llvm-ranlib" % self.LLVM_ROOT, + "STRIP": "%s/bin/llvm-strip" % self.LLVM_ROOT, + "LDFLAGS": common_flags, + "CFLAGS": common_flags, + "CXXFLAGS": common_flags, + } + + def cmake_prebuilt_bin_dir(self): + return self.build_config.repo_root('prebuilts/cmake', 'linux-x86', 'bin') + + def base_cmake_defines(self): + self.cmake_defines = {} + self.cmake_defines['CMAKE_BUILD_TYPE'] = 'Release' + self.cmake_defines['LLVM_ENABLE_ASSERTIONS'] = 'OFF' + self.cmake_defines['LLVM_ENABLE_TERMINFO'] = 'OFF' + self.cmake_defines['LLVM_ENABLE_THREADS'] = 'ON' + self.cmake_defines['LLVM_USE_NEWPM'] = 'ON' + self.cmake_defines['COMPILER_RT_BUILD_XRAY'] = 'OFF' + return self.cmake_defines + + @staticmethod + def check_create_path(path): + if not os.path.exists(path): + os.makedirs(path) + + @staticmethod + def check_call(cmd, *args, **kwargs): + subprocess.check_call(cmd, *args, **kwargs) + + @staticmethod + def update_cmake_sysroot_flags(defines, sysroot): + defines['CMAKE_SYSROOT'] = sysroot + defines['CMAKE_FIND_ROOT_PATH_MODE_INCLUDE'] = 'ONLY' + defines['CMAKE_FIND_ROOT_PATH_MODE_LIBRARY'] = 'ONLY' + defines['CMAKE_FIND_ROOT_PATH_MODE_PACKAGE'] = 'ONLY' + defines['CMAKE_FIND_ROOT_PATH_MODE_PROGRAM'] = 'NEVER' + + def compiler_rt_defines(self): + arch = 'x86_64' + cc = os.path.join(self.LLVM_ROOT, 'bin', 'clang') + cxx = os.path.join(self.LLVM_ROOT, 'bin', 'clang++') + self.crt_defines = {} + self.crt_defines['CMAKE_C_COMPILER'] = cc + self.crt_defines['CMAKE_CXX_COMPILER'] = cxx + self.crt_defines['LLVM_CONFIG_PATH'] = self.LLVM_CONFIG + clang_libcxx_lib = self.build_config.out_root('clang_mingw', 'clang-%s' % self.build_config.CLANG_VERSION, 'lib') + ldflags = [ + '-L%s' % clang_libcxx_lib, + '-fuse-ld=lld', + '-Wl,--gc-sections', + '-pie', + '--rtlib=compiler-rt', + '-stdlib=libc++', + '-v', + ] + self.crt_defines['CMAKE_SHARED_LINKER_FLAGS'] = ' '.join(ldflags) + self.update_cmake_sysroot_flags(self.crt_defines, self.SYSROOT) + cflags = [ + '--target=%s' % self.build_config.LLVM_TRIPLE, + '-ffunction-sections', + '-fdata-sections', + ] + cflags.append('-funwind-tables') + cflags.append('-v') + self.crt_defines['CMAKE_C_FLAGS'] = ' '.join(cflags) + self.crt_defines['CMAKE_ASM_FLAGS'] = ' '.join(cflags) + self.crt_defines['CMAKE_CXX_FLAGS'] = ' '.join(cflags) + self.crt_defines['COMPILER_RT_TEST_COMPILER_CFLAGS'] = ' '.join(cflags) + self.crt_defines['COMPILER_RT_TEST_TARGET_TRIPLE'] = self.build_config.LLVM_TRIPLE + self.crt_defines['COMPILER_RT_DEFAULT_TARGET_TRIPLE'] = self.build_config.LLVM_TRIPLE + self.crt_defines['COMPILER_RT_INCLUDE_TESTS'] = 'OFF' + self.crt_defines['CMAKE_INSTALL_PREFIX'] = self.CRT_INSTALL + self.crt_defines['COMPILER_RT_BUILD_LIBFUZZER'] = 'OFF' + self.crt_defines['COMPILER_RT_USE_BUILTINS_LIBRARY'] = 'TRUE' + self.crt_defines['CMAKE_SYSTEM_NAME'] = 'Windows' + self.crt_defines['CMAKE_CROSSCOMPILING'] = 'True' + self.crt_defines['CMAKE_C_COMPILER_WORKS'] = '1' + self.crt_defines['CMAKE_CXX_COMPILER_WORKS'] = '1' + self.crt_defines['SANITIZER_CXX_ABI'] = 'libcxxabi' + self.crt_defines['CMAKE_TRY_COMPILE_TARGET_TYPE'] = 'STATIC_LIBRARY' + self.crt_defines['COMPILER_RT_BUILD_SANITIZERS'] = 'OFF' + self.crt_defines['COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN'] = 'OFF' + #cmake config + self.crt_defines.update(self.base_cmake_defines()) + return self.crt_defines + + def build_compiler_rt(self): + crt_defines = self.compiler_rt_defines() + #environ + crt_env = dict(dict(os.environ)) + #compiler-rt path + crt_cmake_path = self.build_config.llvm_path('compiler-rt') + #cmake + self.invoke_cmake( + out_path=self.CRT_PATH, + defines=crt_defines, + env=crt_env, + cmake_path=crt_cmake_path) + + def invoke_cmake(self, out_path, defines, env, cmake_path, target=None, install=True): + flags = ['-G', 'Ninja'] + flags += ['-DCMAKE_PREFIX_PATH=%s' % self.cmake_prebuilt_bin_dir()] + + for key in defines: + newdef = ''.join(['-D', key, '=', defines[key]]) + flags += [newdef] + flags += [cmake_path] + + self.check_create_path(out_path) + + if target: + ninja_target = [target] + else: + ninja_target = [] + + self.check_call([self.CMAKE_BIN_PATH] + flags, cwd=out_path, env=env) + self.check_call([self.NINJA_BIN_PATH] + ninja_target, cwd=out_path, env=env) + if install: + self.check_call([self.NINJA_BIN_PATH, 'install'], cwd=out_path, env=env) + + def build_mingw64_headers(self): + headers_dir = self.build_config.repo_root('third_party', 'mingw-w64', 'mingw-w64-headers', 'build') + if os.path.isdir(headers_dir): + shutil.rmtree(headers_dir) + os.makedirs(headers_dir) + os.chdir(headers_dir) + cmd = ['../configure', '--prefix=%s' % self.prefix, + '--enable-idl', '--with-default-win32-winnt=0x600', + '--with-default-msvcrt=ucrt'] + self.env['INSTALL'] = "install -C" + self.check_call(cmd, env=self.env) + self.check_call(['make', 'install'], env=self.env) + + def build_mingw64_crtlibs(self): + crtlibs_dir = self.build_config.repo_root('third_party', 'mingw-w64', 'mingw-w64-crt', 'build') + if os.path.isdir(crtlibs_dir): + shutil.rmtree(crtlibs_dir) + os.makedirs(crtlibs_dir) + os.chdir(crtlibs_dir) + cmd = ['../configure', '--prefix=%s' % self.prefix, + '--host=x86_64-w64-mingw32', '--disable-lib32', + '--enable-lib64', '--with-default-msvcrt=ucrt'] + self.check_call(cmd, env=self.env) + self.check_call(['make', '-j4'], env=self.env) + self.check_call(['make', 'install'], env=self.env) + + +def main(clang_version): + build_config = BuildConfig(clang_version) + llvm_mingw = LlvmMingw(build_config) + + llvm_mingw.build_mingw64_headers() + llvm_mingw.build_mingw64_crtlibs() + llvm_mingw.build_compiler_rt() + return 0 + +if __name__ == '__main__': + main() diff --git a/llvm-build/toolchain_readme.md b/llvm-build/toolchain_readme.md new file mode 100644 index 0000000000000000000000000000000000000000..eb042745aa1111f0037f519bc1f0403d8148a68f --- /dev/null +++ b/llvm-build/toolchain_readme.md @@ -0,0 +1,26 @@ +## Overview + +This readme briefly describes the functionality of our LLVM toolchain and what we have included specially to the LLVM toolchain. + +## Functionality + +The LLVM toolchain is built based on LLVM 12.0.1. It is used to provide capability of building ohos image. For detailed information about LLVM 12.0.1, please refer to [LLVM 12.0.1](https://lists.llvm.org/pipermail/llvm-announce/2021-July/000093.html). +
+ + +## Specifically Included Triplets + +Despite all the components provided by LLVM community, we included several triplets for different types of ohos devices to our LLVM toochain, listed as below. For specification, liteos is a newly included OS name which indicate the simplified linux kernel. + +| Triplet Name | Architecture | System Kernel | System | +| ---------------------- | ------------ | ------------- | --------------- | +| arm-liteos-ohos | ARM 32bits | LiteOS | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Standard system | +| aarch64-linux-ohos | ARM 64bits | Linux | Standard system | + +For detailed definition of Small System and Standard System, please refer to [System Types](https://gitee.com/openharmony/docs/blob/master/en/device-dev/Readme-EN.md). + +### Specify the triplet + +To build images for different types of platform, you can configure the triplet in the build scripts by setting "--target=xxx" using cflags, xxx should be replaced with a specific triplet name. diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index ba4584dc60faf1b9a170493bbe3075c08d5ff2a8..72657016efcfa3f527be4f6ce206935f1631ea9e 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -190,7 +190,7 @@ public: IOS, KFreeBSD, Linux, - Lv2, // PS3 + Lv2, // PS3 MacOSX, NetBSD, OpenBSD, @@ -219,6 +219,7 @@ public: WASI, // Experimental WebAssembly OS Emscripten, ShaderModel, // DirectX ShaderModel + LiteOS, LastOSType = ShaderModel }; enum EnvironmentType { @@ -263,8 +264,8 @@ public: Callable, Mesh, Amplification, - - LastEnvironmentType = Amplification + OpenHOS, + LastEnvironmentType = OpenHOS }; enum ObjectFormatType { UnknownObjectFormat, @@ -717,9 +718,19 @@ public: return getEnvironment() == Triple::Musl || getEnvironment() == Triple::MuslEABI || getEnvironment() == Triple::MuslEABIHF || - getEnvironment() == Triple::MuslX32; + getEnvironment() == Triple::MuslX32 || + getEnvironment() == Triple::OpenHOS || + isOSLiteOS(); } + /// Tests whether the target is OHOS + /// LiteOS default enviroment is also OHOS, but omited on triple. + bool isOHOSFamily() const { return isOpenHOS() || isOSLiteOS(); } + + bool isOpenHOS() const { return getEnvironment() == Triple::OpenHOS; } + + bool isOSLiteOS() const { return getOS() == Triple::LiteOS; } + /// Tests whether the target is DXIL. bool isDXIL() const { return getArch() == Triple::dxil; @@ -766,6 +777,7 @@ public: getEnvironment() == Triple::MuslEABI || getEnvironment() == Triple::EABIHF || getEnvironment() == Triple::GNUEABIHF || + getEnvironment() == Triple::OpenHOS || getEnvironment() == Triple::MuslEABIHF || isAndroid()) && isOSBinFormatELF(); } @@ -919,7 +931,8 @@ public: /// Tests whether the target uses emulated TLS as default. bool hasDefaultEmulatedTLS() const { - return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); + return isOpenHOS() || isAndroid() || isOSOpenBSD() || + isWindowsCygwinEnvironment(); } /// Tests whether the target uses -data-sections as default. diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 99e7a9868c296bd8782b1f6438aee14f5f7212d6..9d4b9e9878dec18a0a4a9afb551052540c6a4e6b 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1381,6 +1381,8 @@ enum { PT_OPENBSD_WXNEEDED = 0x65a3dbe7, // Program does W^X violations. PT_OPENBSD_BOOTDATA = 0x65a41be6, // Section for boot arguments. + PT_OHOS_RANDOMDATA = 0x6788FC60, // Fill with random data. + // ARM program header types. PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info // These all contain stack unwind tables. diff --git a/llvm/include/llvm/BinaryFormat/MinidumpConstants.def b/llvm/include/llvm/BinaryFormat/MinidumpConstants.def index 543305feea77383cd7bc0a59fe835a631dc13062..c03a4f8fd9eaf83546e78996d9461d389988d321 100644 --- a/llvm/include/llvm/BinaryFormat/MinidumpConstants.def +++ b/llvm/include/llvm/BinaryFormat/MinidumpConstants.def @@ -115,6 +115,7 @@ HANDLE_MDMP_PLATFORM(0x8202, Solaris) // Solaris HANDLE_MDMP_PLATFORM(0x8203, Android) // Android HANDLE_MDMP_PLATFORM(0x8204, PS3) // PS3 HANDLE_MDMP_PLATFORM(0x8205, NaCl) // Native Client (NaCl) +HANDLE_MDMP_PLATFORM(0x8207, OpenHOS) HANDLE_MDMP_PROTECT(0x01, NoAccess, PAGE_NO_ACCESS) HANDLE_MDMP_PROTECT(0x02, ReadOnly, PAGE_READ_ONLY) diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index eee4c50cc13bc967e8a15072fa4d990c5457bf10..104068e0c2a0cca799d58c92e4e414294092c9dd 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -689,6 +689,7 @@ enum AttributeKindCodes { ATTR_KIND_ALLOC_KIND = 82, ATTR_KIND_PRESPLIT_COROUTINE = 83, ATTR_KIND_FNRETTHUNK_EXTERN = 84, + ATTR_KIND_STACK_PROTECT_RET = 85, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 7ea731b466559b16c1cadffb6928738efb3b8181..1c603e2ccdb209b96bae3f5690723dfabe77cb83 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -272,6 +272,13 @@ private: /// The frame index for the stack protector. int StackProtectorIdx = -1; + struct StackProtectorRet { + /// The register to use for stack protector & backwrad cfi calculations + unsigned Register = 0; + /// Set to true if this function needs stack-protector-ret + bool Needed = false; + } SPR; + /// The frame index for the function context. Used for SjLj exceptions. int FunctionContextIdx = -1; @@ -358,6 +365,14 @@ public: void setStackProtectorIndex(int I) { StackProtectorIdx = I; } bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; } + /// Get / Set stack protector ret calculation register + unsigned getStackProtectorRetRegister() const { return SPR.Register; } + void setStackProtectorRetRegister(unsigned I) { SPR.Register = I; } + bool hasStackProtectorRetRegister() const { return SPR.Register != 0; } + /// Get / Set if this frame needs backward cfi protect. + void setStackProtectorRetNeeded(bool I) { SPR.Needed = I; } + bool getStackProtectorRetNeeded() const { return SPR.Needed; } + /// Return the index for the function context object. /// This object is used for SjLj exceptions. int getFunctionContextIndex() const { return FunctionContextIdx; } diff --git a/llvm/include/llvm/CodeGen/StackProtector.h b/llvm/include/llvm/CodeGen/StackProtector.h index b96c0c74fabc0fd7a5b38af47cf25b7cc8961ddb..aac31eafc65dc6733f11647c1fa19801f45cccbe 100644 --- a/llvm/include/llvm/CodeGen/StackProtector.h +++ b/llvm/include/llvm/CodeGen/StackProtector.h @@ -100,6 +100,8 @@ private: /// stack protector based upon the stack protector level. bool RequiresStackProtector(); + bool CreateSSPRetCookie(); + public: static char ID; // Pass identification, replacement for typeid. diff --git a/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h b/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h new file mode 100644 index 0000000000000000000000000000000000000000..667d0f04ceea3f9b121095ca35e3eec3418afc42 --- /dev/null +++ b/llvm/include/llvm/CodeGen/StackProtectorRetLowering.h @@ -0,0 +1,57 @@ +//===-- StackProtectorRetLowering.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STACKPROTECTORRETLOWERING_H +#define LLVM_CODEGEN_STACKPROTECTORRETLOWERING_H + +#include +#include + +namespace llvm { +class CalleeSavedInfo; +class GlobalVariable; +class MachineBasicBlock; +class MachineFunction; +class MachineInstr; + +class StackProtectorRetLowering { +public: + virtual ~StackProtectorRetLowering() {} + + /// insert stack-protector-ret instrumentation in prologue or epilogue. + virtual void insertStackProtectorRetPrologue(MachineFunction &MF, + MachineBasicBlock &MBB, + GlobalVariable *cookie) const {} + virtual void insertStackProtectorRetEpilogue(MachineFunction &MF, + MachineInstr &MI, + GlobalVariable *cookie) const {} + + /// Check if it is a return instruction. + /// Need to overide the implementation for different architectures. + virtual bool instrIsRet(unsigned opcode) const { return false; } + + /// Get a caller saved temporary register for the target architecture. + /// Need to overide the implementation for different architectures. + virtual unsigned getTargetReg(void) const { return 0; } + + /// Check if backward CFI protection is required. + virtual void setupStackProtectorRet(MachineFunction &MF) const; + + /// Set SSPRetReg as a callee saved register to push the computed stack guard value onto the stack. + virtual void saveStackProtectorRetRegister(MachineFunction &MF, std::vector &CSI) const; + + /// Determine an available SSPRet register and feedback the determination result. + virtual bool determineStackProtectorRetRegister(MachineFunction &MF) const; + + /// insertStackProtectorRets - insert stack-protector-ret instrumentation. + virtual void insertStackProtectorRets(MachineFunction &MF) const; +}; + +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h index fbce5d7a9102a6eba3a91035a6b3bb1a01c3d553..9a8bc4bd517ab8a8cd294a507bc8c321786321b1 100644 --- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -14,6 +14,7 @@ #define LLVM_CODEGEN_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/StackProtectorRetLowering.h" #include "llvm/Support/TypeSize.h" #include @@ -217,6 +218,10 @@ public: virtual void emitZeroCallUsedRegs(BitVector RegsToZero, MachineBasicBlock &MBB) const {} + virtual const StackProtectorRetLowering *getStackProtectorRet() const { + return nullptr; + } + /// With basic block sections, emit callee saved frame moves for basic blocks /// that are in a different section. virtual void diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index ea4bf80205f86397a7b6019f99333fcf736381da..ce99b289bdbd7ba5f9e46a2f50c90e2eb0b294dd 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -244,6 +244,9 @@ def Speculatable : EnumAttr<"speculatable", [FnAttr]>; /// Stack protection. def StackProtect : EnumAttr<"ssp", [FnAttr]>; +/// Stack protection for return address. +def StackProtectRet : EnumAttr<"sspret", [FnAttr]>; + /// Stack protection required. def StackProtectReq : EnumAttr<"sspreq", [FnAttr]>; diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 7945c64c86103f39dff8356a2636ff845a17cd01..e661a11a7b7558964d70d75eb6a8c5d9fe06fed7 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -418,7 +418,8 @@ public: return AttributeSets.getFnStackAlignment(); } - /// Returns true if the function has ssp, sspstrong, or sspreq fn attrs. + /// Returns true if the function has ssp, sspstrong, sspret or sspreq fn + /// attrs. bool hasStackProtectorFnAttr() const; /// adds the dereferenceable attribute to the list of attributes for diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h index b2ed8e60bd779841f9469e5744b94cc9dddc517a..d4a22159104efc6c0691977cd48410b7acaddbbc 100644 --- a/llvm/include/llvm/LTO/Config.h +++ b/llvm/include/llvm/LTO/Config.h @@ -55,6 +55,7 @@ struct Config { CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default; CodeGenFileType CGFileType = CGFT_ObjectFile; unsigned OptLevel = 2; + bool DisableVerify = false; /// Use the standard optimization pipeline. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 1943b5db94c3e3136c6735e9dc0f0c74c26b5598..106d2b78170f1f711c181fe672dc3b5975b4dd02 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1725,6 +1725,8 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) { return 1ULL << 62; case Attribute::NoFree: return 1ULL << 63; + case Attribute::StackProtectRet: + return 1ULL << 64; default: // Other attributes are not supported in the raw format, // as we ran out of space. @@ -1949,6 +1951,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::StackAlignment; case bitc::ATTR_KIND_STACK_PROTECT: return Attribute::StackProtect; + case bitc::ATTR_KIND_STACK_PROTECT_RET: + return Attribute::StackProtectRet; case bitc::ATTR_KIND_STACK_PROTECT_REQ: return Attribute::StackProtectReq; case bitc::ATTR_KIND_STACK_PROTECT_STRONG: diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index d7e012fb6a9ed281e07f20e727941561c5c8a7a4..4fac16a7491db6db1e542d481a4af76f3bad39a1 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -728,6 +728,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_STACK_ALIGNMENT; case Attribute::StackProtect: return bitc::ATTR_KIND_STACK_PROTECT; + case Attribute::StackProtectRet: + return bitc::ATTR_KIND_STACK_PROTECT_RET; case Attribute::StackProtectReq: return bitc::ATTR_KIND_STACK_PROTECT_REQ; case Attribute::StackProtectStrong: diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 689fa9651766dd9bb585e1daa4d5168578759cda..5f0a919f97a10bc4501baff5b3aab27c8790abb0 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -206,6 +206,7 @@ add_llvm_component_library(LLVMCodeGen StackMapLivenessAnalysis.cpp StackMaps.cpp StackProtector.cpp + StackProtectorRetLowering.cpp StackSlotColoring.cpp SwiftErrorValueTracking.cpp SwitchLoweringUtils.cpp diff --git a/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp b/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp index 5f54d7cc847288c91c5927f3e9eec791e7f6d619..cbde664ef459881cef9a5863c21537028149954f 100644 --- a/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/llvm/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/Function.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/Debug.h" @@ -194,7 +195,9 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { // Make sure that the stack protector comes before the local variables on the // stack. + Function &F = Fn.getFunction(); SmallSet ProtectedObjs; + if (MFI.hasStackProtectorIndex()) { int StackProtectorFI = MFI.getStackProtectorIndex(); @@ -239,7 +242,37 @@ void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { } llvm_unreachable("Unexpected SSPLayoutKind."); } - + AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, + Offset, MaxAlign); + AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, + Offset, MaxAlign); + AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, + Offset, MaxAlign); + } else if (F.hasFnAttribute(Attribute::StackProtectRet)) { + StackObjSet LargeArrayObjs; + StackObjSet SmallArrayObjs; + StackObjSet AddrOfObjs; + // Assign large stack objects first. + for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { + if (MFI.isDeadObjectIndex(i)) + continue; + if (!TFI.isStackIdSafeForLocalArea(MFI.getStackID(i))) + continue; + switch (MFI.getObjectSSPLayout(i)) { + case MachineFrameInfo::SSPLK_None: + continue; + case MachineFrameInfo::SSPLK_SmallArray: + SmallArrayObjs.insert(i); + continue; + case MachineFrameInfo::SSPLK_AddrOf: + AddrOfObjs.insert(i); + continue; + case MachineFrameInfo::SSPLK_LargeArray: + LargeArrayObjs.insert(i); + continue; + } + llvm_unreachable("Unexpected SSPLayoutKind."); + } AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign); AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 85d051cfdbe713dff61937427b7da0e5d9a9de00..2d831819791ef0d08d3770f6d3cbf7d76cbc1835 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -212,6 +212,10 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { const Function &F = MF.getFunction(); const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + const StackProtectorRetLowering *SPRL = TFI->getStackProtectorRet(); + + if (SPRL) + SPRL->setupStackProtectorRet(MF); RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : nullptr; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF); @@ -250,6 +254,10 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { if (!F.hasFnAttribute(Attribute::Naked)) insertPrologEpilogCode(MF); + // Add StackProtectorRets if using them + if (SPRL) + SPRL->insertStackProtectorRets(MF); + // Reinsert stashed debug values at the start of the entry blocks. for (auto &I : EntryDbgValues) I.first->insert(I.first->begin(), I.second.begin(), I.second.end()); @@ -359,7 +367,9 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) { /// Compute the sets of entry and return blocks for saving and restoring /// callee-saved registers, and placing prolog and epilog code. void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { - const MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + const StackProtectorRetLowering *SPRL = TFI->getStackProtectorRet(); // Even when we do not change any CSR, we still want to insert the // prologue and epilogue of the function. @@ -375,7 +385,18 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { // epilogue. if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) RestoreBlocks.push_back(RestoreBlock); - return; + + // If we are adding stack-protector-rets ensure we can find a available + // register for CFI verification. + if (SPRL && !SPRL->determineStackProtectorRetRegister(MF)) { + // Shrinkwrapping will prevent finding a free register + SaveBlocks.clear(); + RestoreBlocks.clear(); + MFI.setSavePoint(nullptr); + MFI.setRestorePoint(nullptr); + } else { + return; + } } // Save refs to entry and return blocks. @@ -386,6 +407,9 @@ void PEI::calculateSaveRestoreBlocks(MachineFunction &MF) { if (MBB.isReturnBlock()) RestoreBlocks.push_back(&MBB); } + + if (SPRL) + SPRL->determineStackProtectorRetRegister(MF); } static void assignCalleeSavedSpillSlots(MachineFunction &F, @@ -422,6 +446,8 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, } const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); + if (TFI->getStackProtectorRet()) + TFI->getStackProtectorRet()->saveStackProtectorRetRegister(F, CSI); MachineFrameInfo &MFI = F.getFrameInfo(); if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI, MinCSFrameIndex, MaxCSFrameIndex)) { @@ -931,6 +957,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { // Make sure that the stack protector comes before the local variables on the // stack. + Function &F = MF.getFunction(); SmallSet ProtectedObjs; if (MFI.hasStackProtectorIndex()) { int StackProtectorFI = MFI.getStackProtectorIndex(); @@ -1000,6 +1027,47 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { llvm_unreachable("Found protected stack objects not pre-allocated by " "LocalStackSlotPass."); + AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, + Offset, MaxAlign, Skew); + AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, + Offset, MaxAlign, Skew); + AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown, + Offset, MaxAlign, Skew); + } else if (F.hasFnAttribute(Attribute::StackProtectRet)) { + StackObjSet LargeArrayObjs; + StackObjSet SmallArrayObjs; + StackObjSet AddrOfObjs; + // Assign large stack objects first. + for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { + if (MFI.isObjectPreAllocated(i) && MFI.getUseLocalStackAllocationBlock()) + continue; + if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) + continue; + if (RS && RS->isScavengingFrameIndex((int)i)) + continue; + if (MFI.isDeadObjectIndex(i)) + continue; + if (EHRegNodeFrameIndex == (int)i) + continue; + if (MFI.getStackID(i) != + TargetStackID::Default) // Only allocate objects on the default stack. + continue; + switch (MFI.getObjectSSPLayout(i)) { + case MachineFrameInfo::SSPLK_None: + continue; + case MachineFrameInfo::SSPLK_SmallArray: + SmallArrayObjs.insert(i); + continue; + case MachineFrameInfo::SSPLK_AddrOf: + AddrOfObjs.insert(i); + continue; + case MachineFrameInfo::SSPLK_LargeArray: + LargeArrayObjs.insert(i); + continue; + } + llvm_unreachable("Unexpected SSPLayoutKind."); + } + AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown, Offset, MaxAlign, Skew); AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown, diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp index 00a551ade2137560944468c3e74fcddd96e36104..4afe09b621813c021e8ea4548a74232d9828e4e6 100644 --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -808,7 +808,8 @@ bool SafeStack::run() { // FIXME: implement weaker forms of stack protector. if (F.hasFnAttribute(Attribute::StackProtect) || F.hasFnAttribute(Attribute::StackProtectStrong) || - F.hasFnAttribute(Attribute::StackProtectReq)) { + F.hasFnAttribute(Attribute::StackProtectReq) || + F.hasFnAttribute(Attribute::StackProtectRet)) { Value *StackGuard = getStackGuard(IRB, F); StackGuardSlot = IRB.CreateAlloca(StackPtrTy, nullptr); IRB.CreateStore(StackGuard, StackGuardSlot); diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp index 510a8e3e4ba2b02aba7e9b78aa4c2de017cafe8b..1a9e8f54461eac3db9a0f591aaf63307f4c1dce9 100644 --- a/llvm/lib/CodeGen/StackProtector.cpp +++ b/llvm/lib/CodeGen/StackProtector.cpp @@ -108,9 +108,36 @@ bool StackProtector::runOnFunction(Function &Fn) { } ++NumFunProtected; + + if (Fn.hasFnAttribute(Attribute::StackProtectRet)) { + HasIRCheck = true; + CreateSSPRetCookie(); + // StackProtectRet requires special code generation methods for backward + // cfi. + return false; + } + return InsertStackProtectors(); } +bool StackProtector::CreateSSPRetCookie() { + std::string cookiename = "__sspret_cookie"; + Type *cookietype = Type::getInt8PtrTy(M->getContext()); + GlobalVariable *cookie = dyn_cast_or_null( + M->getOrInsertGlobal(cookiename, cookietype)); + + cookie->setSection(".ohos.randomdata"); + cookie->setExternallyInitialized(true); + cookie->setInitializer(Constant::getNullValue(cookietype)); + cookie->setLinkage(GlobalVariable::LinkOnceAnyLinkage); + cookie->setVisibility(GlobalValue::HiddenVisibility); + cookie->setComdat(M->getOrInsertComdat(cookiename)); + + F->addFnAttr("sspret-randomdata", cookiename); + + return true; +} + /// \param [out] IsLarge is set to true if a protectable array is found and /// it is "large" ( >= ssp-buffer-size). In the case of a structure with /// multiple arrays, this gets set if any of them is large. @@ -296,6 +323,9 @@ bool StackProtector::RequiresStackProtector() { }); NeedsProtector = true; Strong = true; // Use the same heuristic as strong to determine SSPLayout + } else if (F->hasFnAttribute(Attribute::StackProtectRet)) { + NeedsProtector = true; + Strong = true; } else if (F->hasFnAttribute(Attribute::StackProtectStrong)) Strong = true; else if (!F->hasFnAttribute(Attribute::StackProtect)) diff --git a/llvm/lib/CodeGen/StackProtectorRetLowering.cpp b/llvm/lib/CodeGen/StackProtectorRetLowering.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b068995c7437b5b08314c5be60536749a6ffc8d --- /dev/null +++ b/llvm/lib/CodeGen/StackProtectorRetLowering.cpp @@ -0,0 +1,111 @@ +//===-- StackProtectorRetLowering.cpp ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/StackProtectorRetLowering.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +/// Check if backward CFI protection is required. +void StackProtectorRetLowering::setupStackProtectorRet(MachineFunction &MF) const { + if (MF.getFunction().hasFnAttribute(Attribute::StackProtectRet)) { + for (auto &MBB : MF) { + for (auto &T : MBB.terminators()) { + if (instrIsRet(T.getOpcode())) { + MF.getFrameInfo().setStackProtectorRetNeeded(true); + return; + } + } + } + } +} + +/// Set SSPRetReg as a callee saved register to push the computed stack guard value onto the stack. +void StackProtectorRetLowering::saveStackProtectorRetRegister( + MachineFunction &MF, std::vector &CSI) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + if (!MFI.getStackProtectorRetNeeded()) + return; + + if (!MFI.hasStackProtectorRetRegister()) + llvm_unreachable("Missing available stack-protector-ret register"); + + unsigned Reg = MFI.getStackProtectorRetRegister(); + CSI.push_back(CalleeSavedInfo(Reg)); +} + +/// Determine an available SSPRet register and feedback the determination result. +bool StackProtectorRetLowering::determineStackProtectorRetRegister(MachineFunction &MF) const { + MachineFrameInfo &MFI = MF.getFrameInfo(); + if (!MFI.getStackProtectorRetNeeded()) + return true; + + unsigned Reg = getTargetReg(); + MFI.setStackProtectorRetRegister(Reg); + + return MFI.hasStackProtectorRetRegister(); +} + +/// insertStackProtectorRets - insert stack-protector-ret instrumentation. +void StackProtectorRetLowering::insertStackProtectorRets(MachineFunction &MF) const { + MachineFrameInfo &MFI = MF.getFrameInfo(); + const Function &Fn = MF.getFunction(); + const Module *M = Fn.getParent(); + + if (!MFI.getStackProtectorRetNeeded()) + return; + + if (!MFI.hasStackProtectorRetRegister()) + llvm_unreachable("Invalid stack-protector-ret state."); + + GlobalVariable *cookie = dyn_cast_or_null(M->getGlobalVariable( + Fn.getFnAttribute("sspret-randomdata").getValueAsString(), Type::getInt8PtrTy(M->getContext()))); + + if (!cookie) + llvm_unreachable("Function needs stack-protector-ret but missing cookies available."); + + unsigned Reg = MFI.getStackProtectorRetRegister(); + + std::vector returnInstrs; + for (auto &MBB : MF) { + if (MBB.isReturnBlock()) { + for (auto &MI : MBB.terminators()) { + if (instrIsRet(MI.getOpcode())) { + returnInstrs.push_back(&MI); + if (!MBB.isLiveIn(Reg)) { + MBB.addLiveIn(Reg); + } + } + } + } + } + + if (returnInstrs.empty()) { + return; + } + + for (auto &MI : returnInstrs) { + insertStackProtectorRetEpilogue(MF, *MI, cookie); + } + + insertStackProtectorRetPrologue(MF, MF.front(), cookie); + + if (!MF.front().isLiveIn(Reg)) { + MF.front().addLiveIn(Reg); + } +} diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 6d9f94b5eefd7360de62ef19facdf65b87b47647..0143f625903c39f3c0f991cbeed19541feadd3b3 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -1910,9 +1910,16 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { AttributeMask OldSSPAttr; OldSSPAttr.addAttribute(Attribute::StackProtect) .addAttribute(Attribute::StackProtectStrong) - .addAttribute(Attribute::StackProtectReq); + .addAttribute(Attribute::StackProtectReq) + .addAttribute(Attribute::StackProtectRet); - if (Callee.hasFnAttribute(Attribute::StackProtectReq)) { + if (Callee.hasFnAttribute(Attribute::StackProtectRet) && + !Caller.hasFnAttribute(Attribute::StackProtect) && + !Caller.hasFnAttribute(Attribute::StackProtectReq) && + !Caller.hasFnAttribute(Attribute::StackProtectStrong)) { + Caller.removeFnAttrs(OldSSPAttr); + Caller.addFnAttr(Attribute::StackProtectRet); + } else if (Callee.hasFnAttribute(Attribute::StackProtectReq)) { Caller.removeFnAttrs(OldSSPAttr); Caller.addFnAttr(Attribute::StackProtectReq); } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) && diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index d4138133721e879b591b15360740a8487235017b..300592a38b16335d04a04a985182787c8af77692 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -706,7 +706,8 @@ void Function::clearGC() { bool Function::hasStackProtectorFnAttr() const { return hasFnAttribute(Attribute::StackProtect) || hasFnAttribute(Attribute::StackProtectStrong) || - hasFnAttribute(Attribute::StackProtectReq); + hasFnAttribute(Attribute::StackProtectReq) || + hasFnAttribute(Attribute::StackProtectRet); } /// Copy all additional attributes (those not needed to create a Function) from diff --git a/llvm/lib/Support/AArch64TargetParser.cpp b/llvm/lib/Support/AArch64TargetParser.cpp index e2579bf5326075d252def9d16a544588d778bf80..d0e879840e43ffb538dc16e69e6c6eb1102423df 100644 --- a/llvm/lib/Support/AArch64TargetParser.cpp +++ b/llvm/lib/Support/AArch64TargetParser.cpp @@ -171,7 +171,7 @@ void AArch64::fillValidCPUArchList(SmallVectorImpl &Values) { bool AArch64::isX18ReservedByDefault(const Triple &TT) { return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() || - TT.isOSWindows(); + TT.isOSWindows() || TT.isOHOSFamily(); } // Allows partial match, ex. "v8a" matches "armv8a". diff --git a/llvm/lib/Support/ARMTargetParser.cpp b/llvm/lib/Support/ARMTargetParser.cpp index d7294b5b107445deb96ee07e3e2e195b3eb96bc6..8e8375e735f06e27976670ff331e7549363aa016 100644 --- a/llvm/lib/Support/ARMTargetParser.cpp +++ b/llvm/lib/Support/ARMTargetParser.cpp @@ -633,7 +633,7 @@ StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) { default: if (TT.isOSNetBSD()) return "apcs-gnu"; - if (TT.isOSOpenBSD()) + if (TT.isOSOpenBSD() || TT.isOHOSFamily()) return "aapcs-linux"; return "aapcs"; } diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp index 6696d158b2c1ae3d31f0819880ec0814f74a3a16..d163bcff0d3fced5e041cc596907fbd68c7748a4 100644 --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -240,6 +240,7 @@ StringRef Triple::getOSTypeName(OSType Kind) { case Win32: return "windows"; case ZOS: return "zos"; case ShaderModel: return "shadermodel"; + case LiteOS: return "liteos"; } llvm_unreachable("Invalid OSType"); @@ -284,6 +285,7 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) { case Callable: return "callable"; case Mesh: return "mesh"; case Amplification: return "amplification"; + case OpenHOS: return "ohos"; } llvm_unreachable("Invalid EnvironmentType!"); @@ -587,6 +589,7 @@ static Triple::OSType parseOS(StringRef OSName) { .StartsWith("wasi", Triple::WASI) .StartsWith("emscripten", Triple::Emscripten) .StartsWith("shadermodel", Triple::ShaderModel) + .StartsWith("liteos", Triple::LiteOS) .Default(Triple::UnknownOS); } @@ -628,6 +631,7 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("callable", Triple::Callable) .StartsWith("mesh", Triple::Mesh) .StartsWith("amplification", Triple::Amplification) + .StartsWith("ohos", Triple::OpenHOS) .Default(Triple::UnknownEnvironment); } diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index c568f73471e181adb092381ca8c7006b746c1901..8ed54a6703cf0110566bd4abd773557b86871ace 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1402,6 +1402,17 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { return; } + case AArch64::SSP_RET_TRAP: { + MCSymbol *TempSymbol = OutContext.createTempSymbol(); + /* Compare and branch */ + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::CBZX) + .addReg(MI->getOperand(0).getReg()) + .addExpr(MCSymbolRefExpr::create( + TempSymbol, OutContext))); + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(1)); + OutStreamer->emitLabel(TempSymbol); + return; + } case AArch64::JumpTableDest32: case AArch64::JumpTableDest16: diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 78babdf9f1f0dea586563c6dc8e6693dec52d518..a7a1c969faf5e7d11c7d27b3bf639ff1d840e27f 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -189,6 +189,7 @@ #include "AArch64InstrInfo.h" #include "AArch64MachineFunctionInfo.h" #include "AArch64RegisterInfo.h" +#include "AArch64StackProtectorRetLowering.h" #include "AArch64Subtarget.h" #include "AArch64TargetMachine.h" #include "MCTargetDesc/AArch64AddressingModes.h" @@ -2968,6 +2969,10 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF, ? RegInfo->getBaseRegister() : (unsigned)AArch64::NoRegister; + if (MFI.hasStackProtectorRetRegister()) { + SavedRegs.set(MFI.getStackProtectorRetRegister()); + } + unsigned ExtraCSSpill = 0; // Figure out which callee-saved registers to save/restore. for (unsigned i = 0; CSRegs[i]; ++i) { @@ -3782,6 +3787,11 @@ unsigned AArch64FrameLowering::getWinEHFuncletFrameSize( getStackAlign()); } +const StackProtectorRetLowering * +AArch64FrameLowering::getStackProtectorRet() const { + return &SPRL; +} + namespace { struct FrameObject { bool IsValid = false; diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h index f59860a24d9ba788a6c2c9f8361ec95066ae67b0..3bfecc6cc7680e558cec2d275e41a08be6def2bd 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h @@ -13,8 +13,9 @@ #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H #define LLVM_LIB_TARGET_AARCH64_AARCH64FRAMELOWERING_H -#include "llvm/Support/TypeSize.h" +#include "AArch64StackProtectorRetLowering.h" #include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/Support/TypeSize.h" namespace llvm { @@ -22,9 +23,12 @@ class MCCFIInstruction; class AArch64FrameLowering : public TargetFrameLowering { public: + const AArch64StackProtectorRetLowering SPRL; + explicit AArch64FrameLowering() : TargetFrameLowering(StackGrowsDown, Align(16), 0, Align(16), - true /*StackRealignable*/) {} + true /*StackRealignable*/), + SPRL() {} void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const; @@ -40,6 +44,8 @@ public: void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + const StackProtectorRetLowering *getStackProtectorRet() const override; + bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 926e7305bab92167e28d4d75123570df059222e4..4976f51b82e16cee9784bab0ad4882be7ab283d6 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -853,6 +853,14 @@ def ADDlowTLS } // isReMaterializable, isCodeGenOnly +//===----------------------------------------------------------------------===// +// Pseudo instruction used by stack protector ret for backward cfi +let isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { + let Size = 8 in { + def SSP_RET_TRAP: Pseudo<(outs), (ins GPR64:$reg), []>; + } +} + def : Pat<(AArch64LOADgot tglobaltlsaddr:$addr), (LOADgot tglobaltlsaddr:$addr)>; diff --git a/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5f67968a2121d9857936748983c6a948b1b4393 --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.cpp @@ -0,0 +1,99 @@ +//===-- AArch64StackProtectorRetLowering.cpp --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "AArch64InstrInfo.h" +#include "AArch64MachineFunctionInfo.h" +#include "AArch64RegisterInfo.h" +#include "AArch64StackProtectorRetLowering.h" +#include "AArch64TargetMachine.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetOptions.h" +#include + +using namespace llvm; + +void AArch64StackProtectorRetLowering::insertStackProtectorRetPrologue( + MachineFunction &MF, MachineBasicBlock &MBB, GlobalVariable *cookie) const { + + MachineBasicBlock::instr_iterator MI = MBB.instr_begin(); + DebugLoc MBBDL = MBB.findDebugLoc(MI); + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + unsigned REG = MF.getFrameInfo().getStackProtectorRetRegister(); + + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ADRP), REG) + .addGlobalAddress(cookie, 0, AArch64II::MO_PAGE); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), REG) + .addReg(REG) + .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ANDXrr), REG) + .addReg(REG) + .addReg(AArch64::LR); +} + +void AArch64StackProtectorRetLowering::insertStackProtectorRetEpilogue( + MachineFunction &MF, MachineInstr &MI, GlobalVariable *cookie) const { + + MachineBasicBlock &MBB = *MI.getParent(); + DebugLoc MBBDL = MI.getDebugLoc(); + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + unsigned REG = MF.getFrameInfo().getStackProtectorRetRegister(); + + MBB.addLiveIn(AArch64::X9); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ADRP), AArch64::X9) + .addGlobalAddress(cookie, 0, AArch64II::MO_PAGE); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::LDRXui), AArch64::X9) + .addReg(AArch64::X9) + .addGlobalAddress(cookie, 0, AArch64II::MO_PAGEOFF | AArch64II::MO_NC); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::ANDXrr), AArch64::X9) + .addReg(AArch64::X9) + .addReg(AArch64::LR); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::SUBSXrr), REG) + .addReg(REG) + .addReg(AArch64::X9); + BuildMI(MBB, MI, MBBDL, TII->get(AArch64::SSP_RET_TRAP)) + .addReg(REG); +} + +/// Check if it is a return instruction on the AArch64 architecture. +bool AArch64StackProtectorRetLowering::instrIsRet(unsigned opcode) const { + switch (opcode) { + case AArch64::RET_ReallyLR: + case AArch64::RET: + return true; + default: + return false; + } +} + +/// Returns a caller-saved register for the AArch64 architecture. +unsigned AArch64StackProtectorRetLowering::getTargetReg(void) const { + return AArch64::X15; +} + +/// Set SSPRetReg as a callee saved register to push the computed stack guard value onto the stack. +void AArch64StackProtectorRetLowering::saveStackProtectorRetRegister( + MachineFunction &MF, std::vector &CSI) const { + + const MachineFrameInfo &MFI = MF.getFrameInfo(); + if (!MFI.getStackProtectorRetNeeded()) + return; + + if (!MFI.hasStackProtectorRetRegister()) + llvm_unreachable("Saving unset stack-protector-ret register"); + + unsigned Reg = MFI.getStackProtectorRetRegister(); + + CSI.insert(CSI.begin(), CalleeSavedInfo(Reg)); +} diff --git a/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h new file mode 100644 index 0000000000000000000000000000000000000000..835b4b90fd2a27a456dbaf907050c2f91f4b0e8c --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64StackProtectorRetLowering.h @@ -0,0 +1,39 @@ +//===-- AArch64StackProtectorRetLowering.h ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64STACKPROTECTORRETLOWERING_H +#define LLVM_LIB_TARGET_AARCH64_AARCH64STACKPROTECTORRETLOWERING_H + +#include "llvm/CodeGen/StackProtectorRetLowering.h" + +namespace llvm { + +class AArch64StackProtectorRetLowering : public StackProtectorRetLowering { +public: + /// insert stack-protector-ret instrumentation in prologue or epilogue. + virtual void + insertStackProtectorRetPrologue(MachineFunction &MF, MachineBasicBlock &MBB, + GlobalVariable *cookie) const override; + virtual void + insertStackProtectorRetEpilogue(MachineFunction &MF, MachineInstr &MI, + GlobalVariable *cookie) const override; + + /// Check if it is a return instruction. + virtual bool instrIsRet(unsigned opcode) const override; + + /// Get a caller saved temporary register for the target architecture. + virtual unsigned getTargetReg(void) const override; + + /// Set SSPRetReg as a callee saved register to push the computed stack guard value onto the stack. + virtual void saveStackProtectorRetRegister(MachineFunction &MF, + std::vector &CSI) const override; +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index ca7d53dce2bb036f6bc35bcf8b3d3c2763d17566..e7aba115d6a631bb310e9d2994df575ad07eefa0 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -75,6 +75,7 @@ add_llvm_target(AArch64CodeGen AArch64SLSHardening.cpp AArch64SelectionDAGInfo.cpp AArch64SpeculationHardening.cpp + AArch64StackProtectorRetLowering.cpp AArch64StackTagging.cpp AArch64StackTaggingPreRA.cpp AArch64StorePairSuppress.cpp diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp index 4ad93f7b0b68201f25db54bbbea58a6539934f71..e0c10cf5db15db4a1cf042c74d982f51cc081c21 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp @@ -552,8 +552,8 @@ static const char *getRegisterName(unsigned RegNum) { {0x2e09, "COMPUTE_NUM_THREAD_Z"}, {0xa2db, "VGT_TF_PARAM"}, {0xa2d6, "VGT_LS_HS_CONFIG"}, - {0xa287, "VGT_HOS_MIN_TESS_LEVEL"}, - {0xa286, "VGT_HOS_MAX_TESS_LEVEL"}, + {0xa287, "VGT_OHOS_MIN_TESS_LEVEL"}, + {0xa286, "VGT_OHOS_MAX_TESS_LEVEL"}, {0xa2f8, "PA_SC_AA_CONFIG"}, {0xa310, "PA_SC_SHADER_CONTROL"}, {0xa313, "PA_SC_CONSERVATIVE_RASTERIZATION_CNTL"}, diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index 460ec62d5a33ee35531ea13bd03967f0163c0346..f046b198afb73eca97b44a4ab6d9e0cb56527cf7 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -393,8 +393,9 @@ public: } bool isTargetMuslAEABI() const { return (TargetTriple.getEnvironment() == Triple::MuslEABI || - TargetTriple.getEnvironment() == Triple::MuslEABIHF) && - !isTargetDarwin() && !isTargetWindows(); + TargetTriple.getEnvironment() == Triple::MuslEABIHF || + TargetTriple.getEnvironment() == Triple::OpenHOS) && + !isTargetDarwin() && !isTargetWindows(); } // ARM Targets that support EHABI exception handling standard diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp index d95c21d6504b746baa6a54b984e617679625778e..88b89e560597b87d0204bda8c4674cc6c6d36e9e 100644 --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -240,7 +240,8 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT, if ((TargetTriple.getEnvironment() == Triple::GNUEABI || TargetTriple.getEnvironment() == Triple::GNUEABIHF || TargetTriple.getEnvironment() == Triple::MuslEABI || - TargetTriple.getEnvironment() == Triple::MuslEABIHF) && + TargetTriple.getEnvironment() == Triple::MuslEABIHF || + TargetTriple.getEnvironment() == Triple::OpenHOS) && !(TargetTriple.isOSWindows() || TargetTriple.isOSDarwin())) this->Options.EABIVersion = EABI::GNU; else diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index d0ca325e9c140e1d62136ccc6b969a72aba8a61f..80dbe18a526bce986afd6b0da2dd90d7770bc9b4 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -3856,6 +3856,8 @@ SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op, SDLoc DL(Op); GlobalAddressSDNode *N = cast(Op); assert(N->getOffset() == 0 && "unexpected offset in global node"); + if (DAG.getTarget().useEmulatedTLS()) + return LowerToTLSEmulatedModel(N, DAG); TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal()); diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 421f1f329f077d32424a740728600aa0515cef01..47366f0f2f2f59d5524192f997b65814312c2158 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -955,6 +955,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::SanitizeMemTag: case Attribute::SpeculativeLoadHardening: case Attribute::StackProtect: + case Attribute::StackProtectRet: case Attribute::StackProtectReq: case Attribute::StackProtectStrong: case Attribute::StrictFP: diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 5fd4e45d80fb00908ebd9589419503cac33d4426..cb83d698001edb74db93d08c88edd1557bed79ba 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1911,7 +1911,7 @@ public: "vector.memcheck"); auto DiffChecks = RtPtrChecking.getDiffChecks(); - if (DiffChecks) { + if (L->getParentLoop() == nullptr && DiffChecks) { Value *RuntimeVF = nullptr; MemRuntimeCheckCond = addDiffRuntimeChecks( MemCheckBlock->getTerminator(), L, *DiffChecks, MemCheckExp, diff --git a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll index 89fc6457482f08450b6cd70708840a083199f6c7..0ea2e20cfa522f5d3a9af8c4c5f40e57ae835351 100644 --- a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll +++ b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll @@ -2,6 +2,7 @@ ; RUN: llc -mtriple=arm64-freebsd-gnu -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=arm64-linux-gnu -o - %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-android -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 +; RUN: llc -mtriple=aarch64-linux-ohos -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=aarch64-fuchsia -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=aarch64-windows -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 diff --git a/llvm/test/CodeGen/AArch64/emutls.ll b/llvm/test/CodeGen/AArch64/emutls.ll index 4fdc99d0b7e01b7ea46d18909f0cf0a45765b90c..1ffcb03144d7c2d514e746efcf100d878c95772d 100644 --- a/llvm/test/CodeGen/AArch64/emutls.ll +++ b/llvm/test/CodeGen/AArch64/emutls.ll @@ -2,6 +2,10 @@ ; RUN: -relocation-model=pic -frame-pointer=all < %s | FileCheck -check-prefix=ARM64 %s ; RUN: llc -mtriple=aarch64-linux-android \ ; RUN: -relocation-model=pic -frame-pointer=all < %s | FileCheck -check-prefix=ARM64 %s +; RUN: llc -emulated-tls -mtriple=aarch64-linux-ohos \ +; RUN: -relocation-model=pic -frame-pointer=all < %s | FileCheck -check-prefix=ARM64 %s +; RUN: llc -mtriple=aarch64-linux-ohos \ +; RUN: -relocation-model=pic -frame-pointer=all < %s | FileCheck -check-prefix=ARM64 %s ; Copied from X86/emutls.ll diff --git a/llvm/test/CodeGen/AArch64/emutls_generic.ll b/llvm/test/CodeGen/AArch64/emutls_generic.ll index 840833972881a02065900d83b07cd8d703f8e56a..6b5819a7fc4e4c0057bd5a399a7d158b29c7a761 100644 --- a/llvm/test/CodeGen/AArch64/emutls_generic.ll +++ b/llvm/test/CodeGen/AArch64/emutls_generic.ll @@ -8,6 +8,12 @@ ; RUN: | FileCheck -check-prefix=ARM_64 %s ; RUN: llc < %s -emulated-tls -mtriple=aarch64-apple-darwin -O3 \ ; RUN: | FileCheck -check-prefix=DARWIN %s +; RUN: llc < %s -emulated-tls -mtriple=aarch64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=ARM_64 %s +; RUN: llc < %s -emulated-tls -mtriple=aarch64-linux-ohos -relocation-model=pic -O3 \ +; RUN: | FileCheck -check-prefix=ARM_64 %s +; RUN: llc < %s -emulated-tls -mtriple=aarch64-linux-ohos -O3 \ +; RUN: | FileCheck -check-prefix=ARM_64 %s ; RUN: llc < %s -mtriple=aarch64-linux-android -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=ARM_64 %s @@ -18,6 +24,12 @@ ; aarch64-windows-gnu needs explicit -emulated-tls ; RUN: llc < %s -mtriple=aarch64-apple-darwin -O3 \ ; RUN: | FileCheck -check-prefix=NoEMU %s +; RUN: llc < %s -mtriple=aarch64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=ARM_64 %s +; RUN: llc < %s -mtriple=aarch64-linux-ohos -relocation-model=pic -O3 \ +; RUN: | FileCheck -check-prefix=ARM_64 %s +; RUN: llc < %s -mtriple=aarch64-linux-ohos -O3 \ +; RUN: | FileCheck -check-prefix=ARM_64 %s ; NoEMU-NOT: __emutls diff --git a/llvm/test/CodeGen/ARM/emutls.ll b/llvm/test/CodeGen/ARM/emutls.ll index 92b656d9ba09584203c03cb56a30f6ed6beba172..29894a9efa7bb3380ebe7cd6c5aee437985bca77 100644 --- a/llvm/test/CodeGen/ARM/emutls.ll +++ b/llvm/test/CodeGen/ARM/emutls.ll @@ -2,6 +2,10 @@ ; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM32 %s ; RUN: llc -mtriple=arm-linux-android \ ; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM32 %s +; RUN: llc -emulated-tls -mtriple=arm-linux-ohos \ +; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM32 %s +; RUN: llc -mtriple=arm-linux-ohos \ +; RUN: -relocation-model=pic < %s | FileCheck -check-prefix=ARM32 %s ; Copied from X86/emutls.ll diff --git a/llvm/test/CodeGen/ARM/emutls_generic.ll b/llvm/test/CodeGen/ARM/emutls_generic.ll index 8bf0ab30124420eb6a4a16ab918a98592b0cd150..803462740f79db7b4da9e9437c988abef035b464 100644 --- a/llvm/test/CodeGen/ARM/emutls_generic.ll +++ b/llvm/test/CodeGen/ARM/emutls_generic.ll @@ -10,6 +10,8 @@ ; RUN: | FileCheck -check-prefix=DARWIN %s ; RUN: llc < %s -emulated-tls -mtriple=thumbv7-windows-gnu -O3 \ ; RUN: | FileCheck -check-prefix=WIN %s +; RUN: llc < %s -emulated-tls -mtriple=arm-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=ARM_32 %s ; RUN: llc < %s -mtriple=arm-linux-android -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=ARM_32 %s @@ -21,6 +23,8 @@ ; RUN: | FileCheck -check-prefix=ARM_32 %s ; arm-apple-darwin must use -emulated-tls ; windows must use -emulated-tls +; RUN: llc < %s -mtriple=arm-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=ARM_32 %s ; Make sure that TLS symbols are emitted in expected order. diff --git a/llvm/test/CodeGen/RISCV/emutls.ll b/llvm/test/CodeGen/RISCV/emutls.ll new file mode 100644 index 0000000000000000000000000000000000000000..441bb9897ce196f7e8aaf3c9898b3166da449637 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/emutls.ll @@ -0,0 +1,307 @@ +; RUN: llc < %s -emulated-tls -mtriple=riscv64-linux-gnu | FileCheck -check-prefix=RISCV64 %s +; RUN: llc < %s -emulated-tls -mtriple=riscv64-linux-ohos | FileCheck -check-prefix=RISCV64 %s + +; RUN: llc < %s -mtriple=riscv64-linux-gnu | FileCheck -check-prefix=NoEMU %s +; RUN: llc < %s -mtriple=riscv64-linux-ohos | FileCheck -check-prefix=RISCV64 %s + +; Copied from X86/emutls.ll + +; NoEMU-NOT: __emutls + +; Use my_emutls_get_address like __emutls_get_address. +@my_emutls_v_xyz = external global i8*, align 4 +declare i8* @my_emutls_get_address(i8*) + +define dso_local i32 @my_get_xyz() { +; RISCV64-LABEL: my_get_xyz: +; RISCV64: lui a0, %hi(my_emutls_v_xyz) +; RISCV64-NEXT: addi a0, a0, %lo(my_emutls_v_xyz) +; RISCV64-NEXT: call my_emutls_get_address@plt +; RISCV64-NEXT: lw a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %call = call i8* @my_emutls_get_address(i8* bitcast (i8** @my_emutls_v_xyz to i8*)) + %0 = bitcast i8* %call to i32* + %1 = load i32, i32* %0, align 4 + ret i32 %1 +} + +@i1 = dso_local thread_local global i32 15 +@i2 = external thread_local global i32 +@i3 = internal thread_local global i32 15 +@i4 = hidden thread_local global i32 15 +@i5 = external hidden thread_local global i32 +@s1 = dso_local thread_local global i16 15 +@b1 = dso_local thread_local global i8 0 + +define dso_local i32 @f1() { +; RISCV64-LABEL: f1: +; RISCV64: lui a0, %hi(__emutls_v.i1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lw a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i32, i32* @i1 + ret i32 %tmp1 +} + +define dso_local i32* @f2() { +; RISCV64-LABEL: f2: +; RISCV64: lui a0, %hi(__emutls_v.i1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + ret i32* @i1 +} + +define dso_local i32 @f3() nounwind { +; RISCV64-LABEL: f3: +; RISCV64: lui a0, %hi(__emutls_v.i2) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i2) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lw a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i32, i32* @i2 + ret i32 %tmp1 +} + +define dso_local i32* @f4() { +; RISCV64-LABEL: f4: +; RISCV64: lui a0, %hi(__emutls_v.i2) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i2) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + ret i32* @i2 +} + +define dso_local i32 @f5() nounwind { +; RISCV64-LABEL: f5: +; RISCV64: lui a0, %hi(__emutls_v.i3) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i3) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lw a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i32, i32* @i3 + ret i32 %tmp1 +} + +define dso_local i32* @f6() { +; RISCV64-LABEL: f6: +; RISCV64: lui a0, %hi(__emutls_v.i3) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i3) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + ret i32* @i3 +} + +define dso_local i32 @f7() { +; RISCV64-LABEL: f7: +; RISCV64: lui a0, %hi(__emutls_v.i4) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i4) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lw a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i32, i32* @i4 + ret i32 %tmp1 +} + +define dso_local i32* @f8() { +; RISCV64-LABEL: f8: +; RISCV64: lui a0, %hi(__emutls_v.i4) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i4) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + ret i32* @i4 +} + +define dso_local i32 @f9() { +; RISCV64-LABEL: f9: +; RISCV64: lui a0, %hi(__emutls_v.i5) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i5) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lw a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i32, i32* @i5 + ret i32 %tmp1 +} + +define dso_local i32* @f10() { +; RISCV64-LABEL: f10: +; RISCV64: lui a0, %hi(__emutls_v.i5) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.i5) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + ret i32* @i5 +} + +define dso_local i16 @f11() { +; RISCV64-LABEL: f11: +; RISCV64: lui a0, %hi(__emutls_v.s1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.s1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lh a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i16, i16* @s1 + ret i16 %tmp1 +} + +define dso_local i32 @f12sext() { +; RISCV64-LABEL: f12sext: +; RISCV64: lui a0, %hi(__emutls_v.s1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.s1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lh a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i16, i16* @s1 + %tmp2 = sext i16 %tmp1 to i32 + ret i32 %tmp2 +} + +define dso_local i32 @f12zext() { +; RISCV64-LABEL: f12zext: +; RISCV64: lui a0, %hi(__emutls_v.s1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.s1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lhu a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i16, i16* @s1 + %tmp2 = zext i16 %tmp1 to i32 + ret i32 %tmp2 +} + +define dso_local i8 @f13() { +; RISCV64-LABEL: f13: +; RISCV64: lui a0, %hi(__emutls_v.b1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.b1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lb a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i8, i8* @b1 + ret i8 %tmp1 +} + +define dso_local i32 @f14sext() { +; RISCV64-LABEL: f14sext: +; RISCV64: lui a0, %hi(__emutls_v.b1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.b1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lb a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i8, i8* @b1 + %tmp2 = sext i8 %tmp1 to i32 + ret i32 %tmp2 +} + +define dso_local i32 @f14zext() { +; RISCV64-LABEL: f14zext: +; RISCV64: lui a0, %hi(__emutls_v.b1) +; RISCV64-NEXT: addi a0, a0, %lo(__emutls_v.b1) +; RISCV64-NEXT: call __emutls_get_address@plt +; RISCV64-NEXT: lbu a0, 0(a0) +; RISCV64-NEXT: ld ra, 8(sp) +; RISCV64-NEXT: addi sp, sp, 16 +; RISCV64-NEXT: ret +entry: + %tmp1 = load i8, i8* @b1 + %tmp2 = zext i8 %tmp1 to i32 + ret i32 %tmp2 +} + +;;;;;;;;;;;;;; 64-bit __emutls_v. and __emutls_t. + +; RISCV64-LABEL: __emutls_v.i1: +; RISCV64-NEXT: .quad 4 +; RISCV64-NEXT: .quad 4 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad __emutls_t.i1 + +; RISCV64-LABEL: __emutls_t.i1: +; RISCV64-NEXT: .word 15 + +; RISCV64-NOT: __emutls_v.i2 + +; RISCV64-LABEL: __emutls_v.i3: +; RISCV64-NEXT: .quad 4 +; RISCV64-NEXT: .quad 4 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad __emutls_t.i3 + +; RISCV64-LABEL: __emutls_t.i3: +; RISCV64-NEXT: .word 15 + +; RISCV64-LABEL: __emutls_v.i4: +; RISCV64-NEXT: .quad 4 +; RISCV64-NEXT: .quad 4 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad __emutls_t.i4 + +; RISCV64-LABEL: __emutls_t.i4: +; RISCV64-NEXT: .word 15 + +; RISCV64-NOT: __emutls_v.i5: +; RISCV64: .hidden __emutls_v.i5 +; RISCV64-NOT: __emutls_v.i5: + +; RISCV64-LABEL: __emutls_v.s1: +; RISCV64-NEXT: .quad 2 +; RISCV64-NEXT: .quad 2 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad __emutls_t.s1 + +; RISCV64-LABEL: __emutls_t.s1: +; RISCV64-NEXT: .half 15 + +; RISCV64-LABEL: __emutls_v.b1: +; RISCV64-NEXT: .quad 1 +; RISCV64-NEXT: .quad 1 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad 0 + +; RISCV64-NOT: __emutls_t.b1 diff --git a/llvm/test/CodeGen/RISCV/emutls_generic.ll b/llvm/test/CodeGen/RISCV/emutls_generic.ll new file mode 100644 index 0000000000000000000000000000000000000000..9f2345d8e673fb69f7bd11b6f3821f153196db49 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/emutls_generic.ll @@ -0,0 +1,75 @@ +; RUN: llc < %s -emulated-tls -mtriple=riscv64-linux-gnu -O3 \ +; RUN: | FileCheck -check-prefix=RISCV64 %s +; RUN: llc < %s -emulated-tls -mtriple=riscv64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=RISCV64 %s +; RUN: llc < %s -emulated-tls -mtriple=riscv64-linux-ohos -relocation-model=pic -O3 \ +; RUN: | FileCheck -check-prefix=RISCV64 %s +; RUN: llc < %s -emulated-tls -mtriple=riscv64-linux-ohos -O3 \ +; RUN: | FileCheck -check-prefix=RISCV64 %s + +; RUN: llc < %s -mtriple=riscv64-linux-gnu -O3 \ +; RUN: | FileCheck -check-prefix=NoEMU %s +; RUN: llc < %s -mtriple=riscv64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=RISCV64 %s +; RUN: llc < %s -mtriple=riscv64-linux-ohos -relocation-model=pic -O3 \ +; RUN: | FileCheck -check-prefix=RISCV64 %s +; RUN: llc < %s -mtriple=riscv64-linux-ohos -O3 \ +; RUN: | FileCheck -check-prefix=RISCV64 %s + +; NoEMU-NOT: __emutls + +; Make sure that TLS symbols are emitted in expected order. + +@external_x = external thread_local global i32, align 8 +@external_y = thread_local global i8 7, align 2 +@internal_y = internal thread_local global i64 9, align 16 + +define i32* @get_external_x() { +entry: + ret i32* @external_x +} + +define i8* @get_external_y() { +entry: + ret i8* @external_y +} + +define i64* @get_internal_y() { +entry: + ret i64* @internal_y +} + +; RISCV64-LABEL: get_external_x: +; RISCV64: __emutls_v.external_x +; RISCV64: __emutls_get_address +; RISCV64-LABEL: get_external_y: +; RISCV64: __emutls_v.external_y +; RISCV64: __emutls_get_address +; RISCV64-LABEL: get_internal_y: +; RISCV64: __emutls_v.internal_y +; RISCV64: __emutls_get_address +; RISCV64-NOT: __emutls_t.external_x +; RISCV64-NOT: __emutls_v.external_x: +; RISCV64: .data{{$}} +; RISCV64: .globl __emutls_v.external_y +; RISCV64: .p2align 3 +; RISCV64-LABEL: __emutls_v.external_y: +; RISCV64-NEXT: .quad 1 +; RISCV64-NEXT: .quad 2 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad __emutls_t.external_y +; RISCV64-NOT: __emutls_v.external_x: +; RISCV64: .section .r{{o?}}data, +; RISCV64-LABEL: __emutls_t.external_y: +; RISCV64-NEXT: .byte 7 +; RISCV64: .data{{$}} +; RISCV64-NOT: .globl __emutls_v +; RISCV64: .p2align 3 +; RISCV64-LABEL: __emutls_v.internal_y: +; RISCV64-NEXT: .quad 8 +; RISCV64-NEXT: .quad 16 +; RISCV64-NEXT: .quad 0 +; RISCV64-NEXT: .quad __emutls_t.internal_y +; RISCV64: .section .r{{o?}}data, +; RISCV64-LABEL: __emutls_t.internal_y: +; RISCV64-NEXT: .quad 9 diff --git a/llvm/test/CodeGen/X86/emutls-pic.ll b/llvm/test/CodeGen/X86/emutls-pic.ll index d5daa3b6677e028905eb9f37c9244a283730f1c8..59c6f7b6debd4e897b4e9f040589c95856346e6e 100644 --- a/llvm/test/CodeGen/X86/emutls-pic.ll +++ b/llvm/test/CodeGen/X86/emutls-pic.ll @@ -2,11 +2,15 @@ ; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-gnu -relocation-model=pic | FileCheck -check-prefix=X64 %s ; RUN: llc < %s -emulated-tls -mtriple=i386-linux-android -relocation-model=pic | FileCheck -check-prefix=X86 %s ; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -emulated-tls -mtriple=i386-linux-ohos -relocation-model=pic | FileCheck -check-prefix=X86 %s +; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-ohos -relocation-model=pic | FileCheck -check-prefix=X64 %s ; RUN: llc < %s -mtriple=i386-linux-gnu -relocation-model=pic | FileCheck -check-prefix=NoEMU %s ; RUN: llc < %s -mtriple=x86_64-linux-gnu -relocation-model=pic | FileCheck -check-prefix=NoEMU %s ; RUN: llc < %s -mtriple=i386-linux-android -relocation-model=pic | FileCheck -check-prefix=X86 %s ; RUN: llc < %s -mtriple=x86_64-linux-android -relocation-model=pic | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -mtriple=i386-linux-ohos -relocation-model=pic | FileCheck -check-prefix=X86 %s +; RUN: llc < %s -mtriple=x86_64-linux-ohos -relocation-model=pic | FileCheck -check-prefix=X64 %s ; NoEMU-NOT: __emutls diff --git a/llvm/test/CodeGen/X86/emutls-pie.ll b/llvm/test/CodeGen/X86/emutls-pie.ll index 8563eb3a50db99b126dc365463fd6d6d857fe192..b205689ddb48b9ff54b9086307b4dad33d66de23 100644 --- a/llvm/test/CodeGen/X86/emutls-pie.ll +++ b/llvm/test/CodeGen/X86/emutls-pie.ll @@ -6,6 +6,10 @@ ; RUN: | FileCheck -check-prefix=X86 %s ; RUN: llc < %s -emulated-tls -mcpu=generic -mtriple=x86_64-linux-android -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -emulated-tls -mcpu=generic -mtriple=i386-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86 %s +; RUN: llc < %s -emulated-tls -mcpu=generic -mtriple=x86_64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X64 %s ; RUN: llc < %s -mcpu=generic -mtriple=i386-linux-gnu -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=NoEMU %s @@ -15,6 +19,10 @@ ; RUN: | FileCheck -check-prefix=X86 %s ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-android -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -mcpu=generic -mtriple=i386-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86 %s +; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X64 %s ; NoEMU-NOT: __emutls diff --git a/llvm/test/CodeGen/X86/emutls.ll b/llvm/test/CodeGen/X86/emutls.ll index a7fbc2d8531d3e4440747d8caaa9f992eb3bee81..357eda32aa52d20db0c01a9624edc85fc42ae55d 100644 --- a/llvm/test/CodeGen/X86/emutls.ll +++ b/llvm/test/CodeGen/X86/emutls.ll @@ -2,11 +2,15 @@ ; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64 %s ; RUN: llc < %s -emulated-tls -mtriple=i386-linux-android | FileCheck -check-prefix=X86 %s ; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-android | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -emulated-tls -mtriple=i386-linux-ohos | FileCheck -check-prefix=X86 %s +; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-ohos | FileCheck -check-prefix=X64 %s ; RUN: llc < %s -mtriple=i386-linux-gnu | FileCheck -check-prefix=NoEMU %s ; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=NoEMU %s ; RUN: llc < %s -mtriple=i386-linux-android | FileCheck -check-prefix=X86 %s ; RUN: llc < %s -mtriple=x86_64-linux-android | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -mtriple=i386-linux-ohos | FileCheck -check-prefix=X86 %s +; RUN: llc < %s -mtriple=x86_64-linux-ohos | FileCheck -check-prefix=X64 %s ; Copied from tls.ll; emulated TLS model is not implemented ; for *-pc-win32 and *-pc-windows targets yet. diff --git a/llvm/test/CodeGen/X86/emutls_generic.ll b/llvm/test/CodeGen/X86/emutls_generic.ll index 3c3463c0bc8c4e575bc2204bda01c07e85955804..5e6c8deb5017acd6e6a5e14657948eefaa86ae2b 100644 --- a/llvm/test/CodeGen/X86/emutls_generic.ll +++ b/llvm/test/CodeGen/X86/emutls_generic.ll @@ -6,6 +6,12 @@ ; RUN: | FileCheck -check-prefix=X86_64 %s ; RUN: llc < %s -emulated-tls -mtriple=i386-linux-gnu -relocation-model=pic \ ; RUN: | FileCheck %s +; RUN: llc < %s -emulated-tls -mtriple=i686-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86_32 %s +; RUN: llc < %s -emulated-tls -mtriple=i686-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86_32 %s +; RUN: llc < %s -emulated-tls -mtriple=x86_64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86_64 %s ; RUN: llc < %s -mtriple=i686-linux-android -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=X86_32 %s @@ -15,6 +21,12 @@ ; RUN: | FileCheck -check-prefix=X86_64 %s ; RUN: llc < %s -mtriple=i386-linux-gnu -relocation-model=pic \ ; RUN: | FileCheck -check-prefix=NoEMU %s +; RUN: llc < %s -mtriple=i686-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86_32 %s +; RUN: llc < %s -mtriple=i686-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86_32 %s +; RUN: llc < %s -mtriple=x86_64-linux-ohos -relocation-model=pic \ +; RUN: | FileCheck -check-prefix=X86_64 %s ; NoEMU-NOT: __emutls diff --git a/llvm/test/Transforms/LoopVectorize/nested-loop.ll b/llvm/test/Transforms/LoopVectorize/nested-loop.ll new file mode 100644 index 0000000000000000000000000000000000000000..d00eef9d2daea66a1d8b2aeae41565d120ba2af7 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/nested-loop.ll @@ -0,0 +1,74 @@ +; RUN: opt -loop-vectorize -S %s -o - | FileCheck %s +; CHECK: vector.memcheck: +; CHECK-NEXT: %bound0 = icmp ult ptr +; CHECK-NEXT: %bound1 = icmp ult ptr +; CHECK-NEXT: %found.conflict = and i1 %bound0, %bound1 + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 + +; Function Attrs: nofree nounwind uwtable +define dso_local void @array_magick(ptr nocapture noundef %a, ptr nocapture noundef readonly %b, i32 noundef %len) local_unnamed_addr #0 { +entry: + %cmp24 = icmp sgt i32 %len, 0 + br i1 %cmp24, label %for.cond1.preheader.us.preheader, label %for.end12 + +for.cond1.preheader.us.preheader: ; preds = %entry + %wide.trip.count30 = zext i32 %len to i64 + br label %for.cond1.preheader.us + +for.cond1.preheader.us: ; preds = %for.cond1.preheader.us.preheader, %for.cond1.for.end_crit_edge.us + %indvars.iv27 = phi i64 [ 0, %for.cond1.preheader.us.preheader ], [ %indvars.iv.next28, %for.cond1.for.end_crit_edge.us ] + %arrayidx.us = getelementptr inbounds i32, ptr %a, i64 %indvars.iv27 + %.pre = load i32, ptr %arrayidx.us, align 4, !tbaa !5 + br label %for.body3.us + +for.body3.us: ; preds = %for.cond1.preheader.us, %for.body3.us + %0 = phi i32 [ %.pre, %for.cond1.preheader.us ], [ %sub.us, %for.body3.us ] + %indvars.iv = phi i64 [ 0, %for.cond1.preheader.us ], [ %indvars.iv.next, %for.body3.us ] + %arrayidx5.us = getelementptr inbounds i32, ptr %b, i64 %indvars.iv + %1 = load i32, ptr %arrayidx5.us, align 4, !tbaa !5 + %sub.us = sub i32 %0, %1 + store i32 %sub.us, ptr %arrayidx.us, align 4, !tbaa !5 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count30 + br i1 %exitcond.not, label %for.cond1.for.end_crit_edge.us, label %for.body3.us, !llvm.loop !9 + +for.cond1.for.end_crit_edge.us: ; preds = %for.body3.us + %sub.us.lcssa = phi i32 [ %sub.us, %for.body3.us ] + %call.us = tail call i32 (ptr, ...) @printf(ptr noundef nonnull @.str, i32 noundef %sub.us.lcssa) + %indvars.iv.next28 = add nuw nsw i64 %indvars.iv27, 1 + %exitcond31.not = icmp eq i64 %indvars.iv.next28, %wide.trip.count30 + br i1 %exitcond31.not, label %for.end12.loopexit, label %for.cond1.preheader.us, !llvm.loop !12 + +for.end12.loopexit: ; preds = %for.cond1.for.end_crit_edge.us + br label %for.end12 + +for.end12: ; preds = %for.end12.loopexit, %entry + ret void +} + +; Function Attrs: nofree nounwind +declare noundef i32 @printf(ptr nocapture noundef readonly, ...) local_unnamed_addr #1 + +attributes #0 = { nofree nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nounwind "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.module.flags = !{!0, !1, !2, !3} +!llvm.ident = !{!4} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 2} +!4 = !{!"clang version 16.0.0 (https://github.com/llvm/llvm-project.git 09f608fda51ca9dd2d88c2985bad1cfc1e36251e)"} +!5 = !{!6, !6, i64 0} +!6 = !{!"int", !7, i64 0} +!7 = !{!"omnipotent char", !8, i64 0} +!8 = !{!"Simple C/C++ TBAA"} +!9 = distinct !{!9, !10, !11} +!10 = !{!"llvm.loop.mustprogress"} +!11 = !{!"llvm.loop.unroll.disable"} +!12 = distinct !{!12, !10, !11} diff --git a/llvm/test/Transforms/SafeStack/AArch64/abi.ll b/llvm/test/Transforms/SafeStack/AArch64/abi.ll index bd6710d160c55cd12526134e762bdf3f7f84ba08..45961b767180320ae7754ee0b822db98b3adabf1 100644 --- a/llvm/test/Transforms/SafeStack/AArch64/abi.ll +++ b/llvm/test/Transforms/SafeStack/AArch64/abi.ll @@ -1,8 +1,10 @@ ; RUN: opt -safe-stack -S -mtriple=aarch64-linux-android < %s -o - | FileCheck %s +; RUN: opt -safe-stack -S -mtriple=aarch64-linux-ohos < %s -o - | FileCheck %s --check-prefix=OHOS define void @foo() nounwind uwtable safestack { entry: +; OHOS-NOT: call i8* @llvm.thread.pointer() ; CHECK: %[[TP:.*]] = call i8* @llvm.thread.pointer() ; CHECK: %[[SPA0:.*]] = getelementptr i8, i8* %[[TP]], i32 72 ; CHECK: %[[SPA:.*]] = bitcast i8* %[[SPA0]] to i8** diff --git a/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll b/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll index c78b20aaa01abce5a32efcf5da2ae605cb1e6e26..9069ea50a4d58ac50cb04a66f66ec8056940c72f 100644 --- a/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll +++ b/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll @@ -1,4 +1,5 @@ ; RUN: opt -safe-stack -S -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefixes=TLS,ANDROID %s +; RUN: opt -safe-stack -S -mtriple=aarch64-linux-ohos < %s -o - | FileCheck --check-prefix=OHOS %s ; RUN: opt -safe-stack -S -mtriple=aarch64-unknown-fuchsia < %s -o - | FileCheck --check-prefixes=TLS,FUCHSIA %s define void @foo() nounwind uwtable safestack sspreq { @@ -6,6 +7,7 @@ entry: ; The first @llvm.thread.pointer is for the unsafe stack pointer, skip it. ; TLS: call i8* @llvm.thread.pointer() +; OHOS-NOT: call i8* @llvm.thread.pointer() ; TLS: %[[TP2:.*]] = call i8* @llvm.thread.pointer() ; ANDROID: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 40 ; FUCHSIA: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 -16 diff --git a/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll b/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll index 53ed690ebb09b5c69d1eff2b0433910ae750798d..7009fce7a4a43faf1633c2d84412112fe1c516a8 100644 --- a/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll +++ b/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll @@ -1,7 +1,9 @@ ; RUN: opt -safe-stack -safe-stack-coloring -S -mtriple=aarch64-linux-android < %s -o - | FileCheck %s +; RUN: opt -safe-stack -safe-stack-coloring -S -mtriple=aarch64-linux-ohos < %s -o - | FileCheck %s --check-prefix=OHOSMUSL define void @foo() nounwind uwtable safestack { entry: +; OHOSMUSL-NOT: call i8* @llvm.thread.pointer() ; CHECK: %[[TP:.*]] = call i8* @llvm.thread.pointer() ; CHECK: %[[SPA0:.*]] = getelementptr i8, i8* %[[TP]], i32 72 ; CHECK: %[[SPA:.*]] = bitcast i8* %[[SPA0]] to i8** diff --git a/llvm/test/tools/llvm-objdump/ohos-headers.test b/llvm/test/tools/llvm-objdump/ohos-headers.test new file mode 100644 index 0000000000000000000000000000000000000000..045f54fac3592edc956a1888c5579664f30f7238 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ohos-headers.test @@ -0,0 +1,16 @@ +## Check that llvm-objdump dumps OHOS program headers correctly. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump -p %t | FileCheck %s + +# CHECK: OHOS_RANDOMDATA off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0 +# CHECK-NEXT: filesz 0x0000000000000000 memsz 0x0000000000000000 flags --- + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +ProgramHeaders: + - Type: 0x6788FC60 ## PT_OHOS_RANDOMDATA diff --git a/llvm/test/tools/llvm-readobj/ELF/program-headers.test b/llvm/test/tools/llvm-readobj/ELF/program-headers.test index 2ecf33525068339473c37ea699fda34bfd6dd067..e1cf4f9fb5f51e9297623220d070c7c7a5b4f182 100644 --- a/llvm/test/tools/llvm-readobj/ELF/program-headers.test +++ b/llvm/test/tools/llvm-readobj/ELF/program-headers.test @@ -114,6 +114,7 @@ # MAPPING-NEXT: 20 .foo.begin .foo.end {{$}} # MAPPING-NEXT: 21 .foo.begin .foo.end {{$}} # MAPPING-NEXT: 22 .foo.begin .foo.end {{$}} +# MAPPING-NEXT: 23 .foo.begin .foo.end {{$}} # MAPPING-NEXT: None .unused .strtab .shstrtab {{$}} # ELF-LLVM: ProgramHeaders [ @@ -401,6 +402,18 @@ # ELF-LLVM-NEXT: ] # ELF-LLVM-NEXT: Alignment: 1 # ELF-LLVM-NEXT: } +# ELF-LLVM-NEXT: ProgramHeader { +# ELF-LLVM-NEXT: Type: PT_OHOS_RANDOMDATA (0x6788FC60) +# ELF32-LLVM-NEXT: Offset: 0x314 +# ELF64-LLVM-NEXT: Offset: 0x548 +# ELF-LLVM-NEXT: VirtualAddress: 0x1000 +# ELF-LLVM-NEXT: PhysicalAddress: 0x1000 +# ELF-LLVM-NEXT: FileSize: 3 +# ELF-LLVM-NEXT: MemSize: 3 +# ELF-LLVM-NEXT: Flags [ (0x0) +# ELF-LLVM-NEXT: ] +# ELF-LLVM-NEXT: Alignment: 1 +# ELF-LLVM-NEXT: } # ELF-LLVM-NEXT: ] --- !ELF @@ -564,6 +577,11 @@ ProgramHeaders: VAddr: 0x1000 FirstSec: .foo.begin LastSec: .foo.end +## Case 23: the PT_OHOS_RANDOMDATA segment. + - Type: 0x6788FC60 ## PT_OHOS_RANDOMDATA + VAddr: 0x1000 + FirstSec: .foo.begin + LastSec: .foo.end ## Check how we dump ARM specific program headers. # RUN: yaml2obj --docnum=1 -DBITS=64 -DMACHINE=EM_ARM %s -o %tarm.elf diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 61676b4323d2f2f530f5731c300e6f4161cba39e..dcc851ad1650c0a4695707a06840427726ccbcde 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -256,6 +256,9 @@ static void printProgramHeaders(const ELFFile &Obj, StringRef FileName) { case ELF::PT_OPENBSD_WXNEEDED: outs() << " OPENBSD_WXNEEDED "; break; + case ELF::PT_OHOS_RANDOMDATA: + outs() << " OHOS_RANDOMDATA "; + 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 ba7bae96ade36e69925071b22f942abdd4eba26c..37810feabc11e92d7aa6919f950db5a8f5e94c15 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1414,6 +1414,8 @@ static StringRef segmentTypeToString(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE); LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); + + LLVM_READOBJ_ENUM_CASE(ELF, PT_OHOS_RANDOMDATA); default: return ""; } diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py index 7dae83733f31e7e6cec76bdd426a605ad5141b09..5ef907a6de29f7892509c21dccbc08fdc092f7f2 100644 --- a/llvm/utils/lit/lit/llvm/config.py +++ b/llvm/utils/lit/lit/llvm/config.py @@ -12,7 +12,7 @@ from lit.llvm.subst import ToolSubst lit_path_displayed = False -class LLVMConfig(object): +class LLVMConfig (object): def __init__(self, lit_config, config): self.lit_config = lit_config @@ -78,6 +78,8 @@ class LLVMConfig(object): features.add('system-windows') elif platform.system() == 'Linux': features.add('system-linux') + if os.path.exists('/.dockerenv'): + features.add('ohos-ci') elif platform.system() in ['FreeBSD']: features.add('system-freebsd') elif platform.system() == 'NetBSD': diff --git a/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h b/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h index 357cffc13c8096f554f349ebdf4580f7cfc55c6d..57b93b074153573d4f6aacb760097101ce256df7 100644 --- a/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h +++ b/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h @@ -88,6 +88,9 @@ # if defined __ANDROID__ # define GTEST_OS_LINUX_ANDROID 1 # endif +# if defined __OHOS_FAMILY__ +# define GTEST_OS_LINUX_OHOS_FAMILY 1 +# endif #elif defined __MVS__ # define GTEST_OS_ZOS 1 #elif defined(__sun) && defined(__SVR4) diff --git a/llvm/utils/unittest/googletest/src/gtest-death-test.cc b/llvm/utils/unittest/googletest/src/gtest-death-test.cc index 5d1031bea257099d894b2a48a44a998e13500709..bdb4b6585624f7466420a59f1f72c279ff1c5935 100644 --- a/llvm/utils/unittest/googletest/src/gtest-death-test.cc +++ b/llvm/utils/unittest/googletest/src/gtest-death-test.cc @@ -1364,7 +1364,9 @@ static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { if (!use_fork) { static const bool stack_grows_down = StackGrowsDown(); - const auto stack_size = static_cast(getpagesize() * 2); + // HUAWEI: increase stack size for child process or we won't see + // error message in case death test fails. + const auto stack_size = static_cast(getpagesize() * 4); // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); diff --git a/llvm/utils/unittest/googletest/src/gtest-port.cc b/llvm/utils/unittest/googletest/src/gtest-port.cc index fc5ba6becc55fd2cd6bb178454a7edc56998b1ab..a79dd856272a2993424edbed244e7a44bdd76637 100644 --- a/llvm/utils/unittest/googletest/src/gtest-port.cc +++ b/llvm/utils/unittest/googletest/src/gtest-port.cc @@ -1093,7 +1093,7 @@ class CapturedStream { // directory, so we create the temporary file in the /tmp directory // instead. We use /tmp on most systems, and /sdcard on Android. // That's because Android doesn't have /tmp. -# if GTEST_OS_LINUX_ANDROID +#if GTEST_OS_LINUX_ANDROID || GTEST_OS_LINUX_OHOS_FAMILY // Note: Android applications are expected to call the framework's // Context.getExternalStorageDirectory() method through JNI to get // the location of the world-writable SD Card directory. However, diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 6aeb495d44f24a456084b281dc04ef43f09698f2..07b2a9a3ff726f4b114356f0e1106e205afc9959 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -54,9 +54,8 @@ #define KMP_CANCEL_THREADS #define KMP_THREAD_ATTR -// Android does not have pthread_cancel. Undefine KMP_CANCEL_THREADS if being // built on Android -#if defined(__ANDROID__) +#if defined(__ANDROID__) || defined(__OHOS__) #undef KMP_CANCEL_THREADS #endif diff --git a/openmp/runtime/src/kmp_i18n.cpp b/openmp/runtime/src/kmp_i18n.cpp index a164aa180dd48b6751d7d9bbd5b7c03cf0d93d02..2474810ce6bf23e74ba418b9fd023c07ad00b0ed 100644 --- a/openmp/runtime/src/kmp_i18n.cpp +++ b/openmp/runtime/src/kmp_i18n.cpp @@ -710,7 +710,8 @@ static char *sys_error(int err) { #if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \ (defined(__BIONIC__) && defined(_GNU_SOURCE) && \ - __ANDROID_API__ >= __ANDROID_API_M__) + __ANDROID_API__ >= __ANDROID_API_M__) || \ + (defined(__OHOS__) && defined(_GNU_SOURCE)) // GNU version of strerror_r. char buffer[2048]; diff --git a/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp b/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp index 430c2006a451e6831cda803d3f12026e8ce0102e..0a24809c20f3731ad9a10d72b704a9852277e230 100644 --- a/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp +++ b/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp @@ -1,5 +1,6 @@ // RUN: %libomp-cxx-compile-and-run // RUN: %libomp-cxx-compile && env OMP_NUM_THREADS=1 %libomp-run +// UNSUPPORTED: ohos-ci /* * This test aims to check whether hidden helper task can work with regular task diff --git a/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp b/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp index 881e27df723c70147a445facb33c8514bfa82f5c..5b38a913577342bc2e1ee15a7736218543395f3d 100644 --- a/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp +++ b/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp @@ -42,7 +42,9 @@ struct anon { }; } -kmp_int32 __kmp_hidden_helper_threads_num; +// OHOS specific: we use static libomp and get link error on this symbol +// probably push this to mainline +__attribute__((weak)) kmp_int32 __kmp_hidden_helper_threads_num; kmp_int32 omp_task_entry(kmp_int32 gtid, kmp_task_t_with_privates *task) { auto shareds = reinterpret_cast(task->task.shareds);