Index: lldb/trunk/include/lldb/Core/Module.h =================================================================== --- lldb/trunk/include/lldb/Core/Module.h +++ lldb/trunk/include/lldb/Core/Module.h @@ -703,7 +703,7 @@ //------------------------------------------------------------------ virtual void SectionFileAddressesChanged(); - uint32_t GetVersion(uint32_t *versions, uint32_t num_versions); + llvm::VersionTuple GetVersion(); //------------------------------------------------------------------ /// Load an object file from memory. Index: lldb/trunk/include/lldb/Host/freebsd/HostInfoFreeBSD.h =================================================================== --- lldb/trunk/include/lldb/Host/freebsd/HostInfoFreeBSD.h +++ lldb/trunk/include/lldb/Host/freebsd/HostInfoFreeBSD.h @@ -12,12 +12,13 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { class HostInfoFreeBSD : public HostInfoPosix { public: - static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); static FileSpec GetProgramFileSpec(); Index: lldb/trunk/include/lldb/Host/linux/HostInfoLinux.h =================================================================== --- lldb/trunk/include/lldb/Host/linux/HostInfoLinux.h +++ lldb/trunk/include/lldb/Host/linux/HostInfoLinux.h @@ -12,8 +12,8 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" - #include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" #include @@ -30,7 +30,7 @@ public: static void Initialize(); - static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); static llvm::StringRef GetDistributionId(); Index: lldb/trunk/include/lldb/Host/macosx/HostInfoMacOSX.h =================================================================== --- lldb/trunk/include/lldb/Host/macosx/HostInfoMacOSX.h +++ lldb/trunk/include/lldb/Host/macosx/HostInfoMacOSX.h @@ -12,6 +12,7 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -26,7 +27,7 @@ ~HostInfoMacOSX(); public: - static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); static FileSpec GetProgramFileSpec(); Index: lldb/trunk/include/lldb/Host/netbsd/HostInfoNetBSD.h =================================================================== --- lldb/trunk/include/lldb/Host/netbsd/HostInfoNetBSD.h +++ lldb/trunk/include/lldb/Host/netbsd/HostInfoNetBSD.h @@ -12,12 +12,13 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { class HostInfoNetBSD : public HostInfoPosix { public: - static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); static FileSpec GetProgramFileSpec(); Index: lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h =================================================================== --- lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h +++ lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h @@ -12,6 +12,7 @@ #include "lldb/Host/HostInfoBase.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -29,7 +30,7 @@ static size_t GetPageSize(); - static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); static bool GetHostname(std::string &s); Index: lldb/trunk/include/lldb/Interpreter/OptionGroupPlatform.h =================================================================== --- lldb/trunk/include/lldb/Interpreter/OptionGroupPlatform.h +++ lldb/trunk/include/lldb/Interpreter/OptionGroupPlatform.h @@ -16,6 +16,7 @@ // Project includes #include "lldb/Interpreter/Options.h" #include "lldb/Utility/ConstString.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -28,8 +29,6 @@ public: OptionGroupPlatform(bool include_platform_option) : OptionGroup(), m_platform_name(), m_sdk_sysroot(), - m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX), - m_os_version_update(UINT32_MAX), m_include_platform_option(include_platform_option) {} ~OptionGroupPlatform() override = default; @@ -72,9 +71,7 @@ std::string m_platform_name; ConstString m_sdk_sysroot; ConstString m_sdk_build; - uint32_t m_os_version_major; - uint32_t m_os_version_minor; - uint32_t m_os_version_update; + llvm::VersionTuple m_os_version; bool m_include_platform_option; }; Index: lldb/trunk/include/lldb/Symbol/ObjectFile.h =================================================================== --- lldb/trunk/include/lldb/Symbol/ObjectFile.h +++ lldb/trunk/include/lldb/Symbol/ObjectFile.h @@ -20,6 +20,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-private.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -653,45 +654,12 @@ /// minor and build, but there may be more. This function will extract the /// versions from object files if they are available. /// - /// If \a versions is NULL, or if \a num_versions is 0, the return value - /// will indicate how many version numbers are available in this object - /// file. Then a subsequent call can be made to this function with a value - /// of \a versions and \a num_versions that has enough storage to store some - /// or all version numbers. - /// - /// @param[out] versions - /// A pointer to an array of uint32_t types that is \a num_versions - /// long. If this value is NULL, the return value will indicate - /// how many version numbers are required for a subsequent call - /// to this function so that all versions can be retrieved. If - /// the value is non-NULL, then at most \a num_versions of the - /// existing versions numbers will be filled into \a versions. - /// If there is no version information available, \a versions - /// will be filled with \a num_versions UINT32_MAX values - /// and zero will be returned. - /// - /// @param[in] num_versions - /// The maximum number of entries to fill into \a versions. If - /// this value is zero, then the return value will indicate - /// how many version numbers there are in total so another call - /// to this function can be make with adequate storage in - /// \a versions to get all of the version numbers. If \a - /// num_versions is less than the actual number of version - /// numbers in this object file, only \a num_versions will be - /// filled into \a versions (if \a versions is non-NULL). - /// - /// @return - /// This function always returns the number of version numbers - /// that this object file has regardless of the number of - /// version numbers that were copied into \a versions. + /// @return + /// This function returns extracted version numbers as a + /// llvm::VersionTuple. In case of error an empty VersionTuple is + /// returned. //------------------------------------------------------------------ - virtual uint32_t GetVersion(uint32_t *versions, uint32_t num_versions) { - if (versions && num_versions) { - for (uint32_t i = 0; i < num_versions; ++i) - versions[i] = UINT32_MAX; - } - return 0; - } + virtual llvm::VersionTuple GetVersion() { return llvm::VersionTuple(); } //------------------------------------------------------------------ /// Get the minimum OS version this object file can run on. @@ -699,45 +667,13 @@ /// Some object files have information that specifies the minimum OS version /// that they can be used on. /// - /// If \a versions is NULL, or if \a num_versions is 0, the return value - /// will indicate how many version numbers are available in this object - /// file. Then a subsequent call can be made to this function with a value - /// of \a versions and \a num_versions that has enough storage to store some - /// or all version numbers. - /// - /// @param[out] versions - /// A pointer to an array of uint32_t types that is \a num_versions - /// long. If this value is NULL, the return value will indicate - /// how many version numbers are required for a subsequent call - /// to this function so that all versions can be retrieved. If - /// the value is non-NULL, then at most \a num_versions of the - /// existing versions numbers will be filled into \a versions. - /// If there is no version information available, \a versions - /// will be filled with \a num_versions UINT32_MAX values - /// and zero will be returned. - /// - /// @param[in] num_versions - /// The maximum number of entries to fill into \a versions. If - /// this value is zero, then the return value will indicate - /// how many version numbers there are in total so another call - /// to this function can be make with adequate storage in - /// \a versions to get all of the version numbers. If \a - /// num_versions is less than the actual number of version - /// numbers in this object file, only \a num_versions will be - /// filled into \a versions (if \a versions is non-NULL). - /// - /// @return - /// This function always returns the number of version numbers - /// that this object file has regardless of the number of - /// version numbers that were copied into \a versions. + /// @return + /// This function returns extracted version numbers as a + /// llvm::VersionTuple. In case of error an empty VersionTuple is + /// returned. //------------------------------------------------------------------ - virtual uint32_t GetMinimumOSVersion(uint32_t *versions, - uint32_t num_versions) { - if (versions && num_versions) { - for (uint32_t i = 0; i < num_versions; ++i) - versions[i] = UINT32_MAX; - } - return 0; + virtual llvm::VersionTuple GetMinimumOSVersion() { + return llvm::VersionTuple(); } //------------------------------------------------------------------ Index: lldb/trunk/include/lldb/Target/Platform.h =================================================================== --- lldb/trunk/include/lldb/Target/Platform.h +++ lldb/trunk/include/lldb/Target/Platform.h @@ -30,6 +30,7 @@ #include "lldb/Utility/Timeout.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-public.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -225,10 +226,9 @@ /// simulator might be simulating a different OS. The \a process parameter /// might be specified to help to determine the OS version. //------------------------------------------------------------------ - virtual bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update, - Process *process = nullptr); + virtual llvm::VersionTuple GetOSVersion(Process *process = nullptr); - bool SetOSVersion(uint32_t major, uint32_t minor, uint32_t update); + bool SetOSVersion(llvm::VersionTuple os_version); bool GetOSBuildString(std::string &s); @@ -874,9 +874,7 @@ // modules that have no install path set std::string m_remote_url; std::string m_name; - uint32_t m_major_os_version; - uint32_t m_minor_os_version; - uint32_t m_update_os_version; + llvm::VersionTuple m_os_version; ArchSpec m_system_arch; // The architecture of the kernel or the remote platform typedef std::map IDToNameMap; Index: lldb/trunk/include/lldb/Target/Process.h =================================================================== --- lldb/trunk/include/lldb/Target/Process.h +++ lldb/trunk/include/lldb/Target/Process.h @@ -54,6 +54,7 @@ #include "lldb/lldb-private.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { @@ -1447,26 +1448,11 @@ /// platform that might itself be running natively, but have different /// heuristics for figuring out which OS is is emulating. /// - /// @param[out] major - /// The major OS version, or UINT32_MAX if it can't be determined - /// - /// @param[out] minor - /// The minor OS version, or UINT32_MAX if it can't be determined - /// - /// @param[out] update - /// The update OS version, or UINT32_MAX if it can't be determined - /// /// @return - /// Returns \b true if the host OS version info was filled in - /// and \b false otherwise. + /// Returns the version tuple of the host OS. In case of failure an empty + /// VersionTuple is returner. //------------------------------------------------------------------ - virtual bool GetHostOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { - major = UINT32_MAX; - minor = UINT32_MAX; - update = UINT32_MAX; - return false; - } + virtual llvm::VersionTuple GetHostOSVersion() { return llvm::VersionTuple(); } //------------------------------------------------------------------ /// Get the target object pointer for this module. Index: lldb/trunk/include/lldb/Utility/Args.h =================================================================== --- lldb/trunk/include/lldb/Utility/Args.h +++ lldb/trunk/include/lldb/Utility/Args.h @@ -324,9 +324,6 @@ static uint32_t StringToGenericRegister(llvm::StringRef s); - static bool StringToVersion(llvm::StringRef string, uint32_t &major, - uint32_t &minor, uint32_t &update); - static const char *GetShellSafeArgument(const FileSpec &shell, const char *unsafe_arg, std::string &safe_arg); Index: lldb/trunk/source/API/SBModule.cpp =================================================================== --- lldb/trunk/source/API/SBModule.cpp +++ lldb/trunk/source/API/SBModule.cpp @@ -531,16 +531,29 @@ } uint32_t SBModule::GetVersion(uint32_t *versions, uint32_t num_versions) { - ModuleSP module_sp(GetSP()); - if (module_sp) - return module_sp->GetVersion(versions, num_versions); - else { - if (versions && num_versions) { - for (uint32_t i = 0; i < num_versions; ++i) - versions[i] = UINT32_MAX; - } - return 0; - } + llvm::VersionTuple version; + if (ModuleSP module_sp = GetSP()) + version = module_sp->GetVersion(); + uint32_t result = 0; + if (!version.empty()) + ++result; + if (version.getMinor()) + ++result; + if(version.getSubminor()) + ++result; + + if (!versions) + return result; + + if (num_versions > 0) + versions[0] = version.empty() ? UINT32_MAX : version.getMajor(); + if (num_versions > 1) + versions[1] = version.getMinor().getValueOr(UINT32_MAX); + if (num_versions > 2) + versions[2] = version.getSubminor().getValueOr(UINT32_MAX); + for (uint32_t i = 3; i < num_versions; ++i) + versions[i] = UINT32_MAX; + return result; } lldb::SBFileSpec SBModule::GetSymbolFileSpec() const { Index: lldb/trunk/source/API/SBPlatform.cpp =================================================================== --- lldb/trunk/source/API/SBPlatform.cpp +++ lldb/trunk/source/API/SBPlatform.cpp @@ -330,27 +330,24 @@ } uint32_t SBPlatform::GetOSMajorVersion() { - uint32_t major, minor, update; - PlatformSP platform_sp(GetSP()); - if (platform_sp && platform_sp->GetOSVersion(major, minor, update)) - return major; - return UINT32_MAX; + llvm::VersionTuple version; + if (PlatformSP platform_sp = GetSP()) + version = platform_sp->GetOSVersion(); + return version.empty() ? UINT32_MAX : version.getMajor(); } uint32_t SBPlatform::GetOSMinorVersion() { - uint32_t major, minor, update; - PlatformSP platform_sp(GetSP()); - if (platform_sp && platform_sp->GetOSVersion(major, minor, update)) - return minor; - return UINT32_MAX; + llvm::VersionTuple version; + if (PlatformSP platform_sp = GetSP()) + version = platform_sp->GetOSVersion(); + return version.getMinor().getValueOr(UINT32_MAX); } uint32_t SBPlatform::GetOSUpdateVersion() { - uint32_t major, minor, update; - PlatformSP platform_sp(GetSP()); - if (platform_sp && platform_sp->GetOSVersion(major, minor, update)) - return update; - return UINT32_MAX; + llvm::VersionTuple version; + if (PlatformSP platform_sp = GetSP()) + version = platform_sp->GetOSVersion(); + return version.getSubminor().getValueOr(UINT32_MAX); } SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) { Index: lldb/trunk/source/Core/Module.cpp =================================================================== --- lldb/trunk/source/Core/Module.cpp +++ lldb/trunk/source/Core/Module.cpp @@ -1640,16 +1640,10 @@ return m_source_mappings.RemapPath(path, new_path); } -uint32_t Module::GetVersion(uint32_t *versions, uint32_t num_versions) { - ObjectFile *obj_file = GetObjectFile(); - if (obj_file) - return obj_file->GetVersion(versions, num_versions); - - if (versions != nullptr && num_versions != 0) { - for (uint32_t i = 0; i < num_versions; ++i) - versions[i] = LLDB_INVALID_MODULE_VERSION; - } - return 0; +llvm::VersionTuple Module::GetVersion() { + if (ObjectFile *obj_file = GetObjectFile()) + return obj_file->GetVersion(); + return llvm::VersionTuple(); } bool Module::GetIsDynamicLinkEditor() { Index: lldb/trunk/source/Host/freebsd/HostInfoFreeBSD.cpp =================================================================== --- lldb/trunk/source/Host/freebsd/HostInfoFreeBSD.cpp +++ lldb/trunk/source/Host/freebsd/HostInfoFreeBSD.cpp @@ -18,16 +18,17 @@ using namespace lldb_private; -bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoFreeBSD::GetOSVersion() { struct utsname un; ::memset(&un, 0, sizeof(utsname)); if (uname(&un) < 0) return false; - int status = sscanf(un.release, "%u.%u", &major, &minor); - return status == 2; + unsigned major, minor; + if (2 == sscanf(un.release, "%u.%u", &major, &minor)) + return llvm::VersionTuple(major, minor); + return llvm::VersionTuple(); } bool HostInfoFreeBSD::GetOSBuildString(std::string &s) { @@ -73,4 +74,4 @@ } } return g_program_filespec; -} \ No newline at end of file +} Index: lldb/trunk/source/Host/linux/HostInfoLinux.cpp =================================================================== --- lldb/trunk/source/Host/linux/HostInfoLinux.cpp +++ lldb/trunk/source/Host/linux/HostInfoLinux.cpp @@ -26,12 +26,8 @@ namespace { struct HostInfoLinuxFields { - HostInfoLinuxFields() : m_os_major(0), m_os_minor(0), m_os_update(0) {} - std::string m_distribution_id; - uint32_t m_os_major; - uint32_t m_os_minor; - uint32_t m_os_update; + llvm::VersionTuple m_os_version; }; HostInfoLinuxFields *g_fields = nullptr; @@ -43,34 +39,21 @@ g_fields = new HostInfoLinuxFields(); } -bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { - static bool success = false; +llvm::VersionTuple HostInfoLinux::GetOSVersion() { static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { - struct utsname un; - if (uname(&un) == 0) { - int status = sscanf(un.release, "%u.%u.%u", &g_fields->m_os_major, - &g_fields->m_os_minor, &g_fields->m_os_update); - if (status == 3) - success = true; - else { - // Some kernels omit the update version, so try looking for just "X.Y" - // and set update to 0. - g_fields->m_os_update = 0; - status = sscanf(un.release, "%u.%u", &g_fields->m_os_major, - &g_fields->m_os_minor); - if (status == 2) - success = true; - } - } + if (uname(&un) != 0) + return; + + llvm::StringRef release = un.release; + // The kernel release string can include a lot of stuff (e.g. + // 4.9.0-6-amd64). We're only interested in the numbered prefix. + release = release.substr(0, release.find_first_not_of("0123456789.")); + g_fields->m_os_version.tryParse(release); }); - major = g_fields->m_os_major; - minor = g_fields->m_os_minor; - update = g_fields->m_os_update; - return success; + return g_fields->m_os_version; } bool HostInfoLinux::GetOSBuildString(std::string &s) { Index: lldb/trunk/source/Host/macosx/objcxx/HostInfoMacOSX.mm =================================================================== --- lldb/trunk/source/Host/macosx/objcxx/HostInfoMacOSX.mm +++ lldb/trunk/source/Host/macosx/objcxx/HostInfoMacOSX.mm @@ -76,32 +76,21 @@ return false; } -bool HostInfoMacOSX::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { - static uint32_t g_major = 0; - static uint32_t g_minor = 0; - static uint32_t g_update = 0; +llvm::VersionTuple HostInfoMacOSX::GetOSVersion() { + static llvm::VersionTuple g_version; - if (g_major == 0) { + if (g_version.empty()) { @autoreleasepool { NSDictionary *version_info = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/CoreServices/SystemVersion.plist"]; NSString *version_value = [version_info objectForKey:@"ProductVersion"]; const char *version_str = [version_value UTF8String]; - if (version_str) - Args::StringToVersion(llvm::StringRef(version_str), g_major, g_minor, - g_update); + g_version.tryParse(version_str); } } - if (g_major != 0) { - major = g_major; - minor = g_minor; - update = g_update; - return true; - } - return false; + return g_version; } FileSpec HostInfoMacOSX::GetProgramFileSpec() { Index: lldb/trunk/source/Host/netbsd/HostInfoNetBSD.cpp =================================================================== --- lldb/trunk/source/Host/netbsd/HostInfoNetBSD.cpp +++ lldb/trunk/source/Host/netbsd/HostInfoNetBSD.cpp @@ -21,8 +21,7 @@ using namespace lldb_private; -bool HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoNetBSD::GetOSVersion() { struct utsname un; ::memset(&un, 0, sizeof(un)); @@ -33,18 +32,14 @@ int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major, &minor, &update); switch (status) { - case 0: - return false; case 1: - minor = 0; - /* FALLTHROUGH */ + return llvm::VersionTuple(major); case 2: - update = 0; - /* FALLTHROUGH */ + return llvm::VersionTuple(major, minor); case 3: - default: - return true; + return llvm::VersionTuple(major, minor, update); } + return llvm::VersionTuple(); } bool HostInfoNetBSD::GetOSBuildString(std::string &s) { Index: lldb/trunk/source/Host/windows/HostInfoWindows.cpp =================================================================== --- lldb/trunk/source/Host/windows/HostInfoWindows.cpp +++ lldb/trunk/source/Host/windows/HostInfoWindows.cpp @@ -42,8 +42,7 @@ return systemInfo.dwPageSize; } -bool HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoWindows::GetOSVersion() { OSVERSIONINFOEX info; ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); @@ -54,16 +53,12 @@ // in favor of the new Windows Version Helper APIs. Since we don't specify a // minimum SDK version, it's easier to simply disable the warning rather than // try to support both APIs. - if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) { - return false; - } + if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) + return llvm::VersionTuple(); #pragma warning(pop) - major = info.dwMajorVersion; - minor = info.dwMinorVersion; - update = info.wServicePackMajor; - - return true; + return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, + info.wServicePackMajor); } bool HostInfoWindows::GetOSBuildString(std::string &s) { Index: lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp =================================================================== --- lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp +++ lldb/trunk/source/Interpreter/OptionGroupPlatform.cpp @@ -44,10 +44,8 @@ if (platform_sp) { interpreter.GetDebugger().GetPlatformList().Append(platform_sp, make_selected); - if (m_os_version_major != UINT32_MAX) { - platform_sp->SetOSVersion(m_os_version_major, m_os_version_minor, - m_os_version_update); - } + if (!m_os_version.empty()) + platform_sp->SetOSVersion(m_os_version); if (m_sdk_sysroot) platform_sp->SetSDKRootDirectory(m_sdk_sysroot); @@ -64,9 +62,7 @@ m_platform_name.clear(); m_sdk_sysroot.Clear(); m_sdk_build.Clear(); - m_os_version_major = UINT32_MAX; - m_os_version_minor = UINT32_MAX; - m_os_version_update = UINT32_MAX; + m_os_version = llvm::VersionTuple(); } static OptionDefinition g_option_table[] = { @@ -108,10 +104,9 @@ break; case 'v': - if (!Args::StringToVersion(option_arg, m_os_version_major, - m_os_version_minor, m_os_version_update)) - error.SetErrorStringWithFormat("invalid version string '%s'", - option_arg.str().c_str()); + if (m_os_version.tryParse(option_arg)) + error.SetErrorStringWithFormatv("invalid version string '{0}'", + option_arg); break; case 'b': @@ -143,17 +138,8 @@ if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory()) return false; - if (m_os_version_major != UINT32_MAX) { - uint32_t major, minor, update; - if (platform_sp->GetOSVersion(major, minor, update)) { - if (m_os_version_major != major) - return false; - if (m_os_version_minor != minor) - return false; - if (m_os_version_update != update) - return false; - } - } + if (!m_os_version.empty() && m_os_version != platform_sp->GetOSVersion()) + return false; return true; } return false; Index: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp =================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -1122,34 +1122,29 @@ bool DynamicLoaderDarwin::UseDYLDSPI(Process *process) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - uint32_t major, minor, update; - bool use_new_spi_interface = false; - if (process->GetHostOSVersion(major, minor, update)) { + llvm::VersionTuple version = process->GetHostOSVersion(); + if (!version.empty()) { const llvm::Triple::OSType os_type = process->GetTarget().GetArchitecture().GetTriple().getOS(); // macOS 10.12 and newer if (os_type == llvm::Triple::MacOSX && - (major > 10 || (major == 10 && minor >= 12))) { + version >= llvm::VersionTuple(10, 12)) use_new_spi_interface = true; - } // iOS 10 and newer - if (os_type == llvm::Triple::IOS && major >= 10) { + if (os_type == llvm::Triple::IOS && version >= llvm::VersionTuple(10)) use_new_spi_interface = true; - } // tvOS 10 and newer - if (os_type == llvm::Triple::TvOS && major >= 10) { + if (os_type == llvm::Triple::TvOS && version >= llvm::VersionTuple(10)) use_new_spi_interface = true; - } // watchOS 3 and newer - if (os_type == llvm::Triple::WatchOS && major >= 3) { + if (os_type == llvm::Triple::WatchOS && version >= llvm::VersionTuple(3)) use_new_spi_interface = true; - } } if (log) { Index: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp =================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -454,9 +454,8 @@ static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) { // On Android L (API 21, 22) the load address of the "/system/bin/linker" // isn't filled in correctly. - uint32_t os_major = 0, os_minor = 0, os_update = 0; + unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor(); if (target.GetArchitecture().GetTriple().isAndroid() && - target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && (os_major == 21 || os_major == 22) && (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) { Index: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp =================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -293,16 +293,14 @@ uint32_t AppleObjCRuntime::GetFoundationVersion() { if (!m_Foundation_major.hasValue()) { const ModuleList &modules = m_process->GetTarget().GetImages(); - uint32_t major = UINT32_MAX; for (uint32_t idx = 0; idx < modules.GetSize(); idx++) { lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx); if (!module_sp) continue; if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""), "Foundation") == 0) { - module_sp->GetVersion(&major, 1); - m_Foundation_major = major; - return major; + m_Foundation_major = module_sp->GetVersion().getMajor(); + return *m_Foundation_major; } } return LLDB_INVALID_MODULE_VERSION; Index: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -123,10 +123,9 @@ ObjectFile::Strata CalculateStrata() override; - uint32_t GetVersion(uint32_t *versions, uint32_t num_versions) override; + llvm::VersionTuple GetVersion() override; - uint32_t GetMinimumOSVersion(uint32_t *versions, - uint32_t num_versions) override; + llvm::VersionTuple GetMinimumOSVersion() override; uint32_t GetSDKVersion(uint32_t *versions, uint32_t num_versions) override; @@ -209,7 +208,7 @@ llvm::MachO::dysymtab_command m_dysymtab; std::vector m_mach_segments; std::vector m_mach_sections; - std::vector m_min_os_versions; + llvm::Optional m_min_os_version; std::vector m_sdk_versions; typedef lldb_private::RangeVector FileRangeArray; lldb_private::Address m_entry_point_address; Index: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5549,8 +5549,7 @@ return eStrataUnknown; } -uint32_t ObjectFileMachO::GetVersion(uint32_t *versions, - uint32_t num_versions) { +llvm::VersionTuple ObjectFileMachO::GetVersion() { ModuleSP module_sp(GetModule()); if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); @@ -5578,23 +5577,13 @@ } if (version_cmd == LC_ID_DYLIB) { - if (versions != NULL && num_versions > 0) { - if (num_versions > 0) - versions[0] = (version & 0xFFFF0000ull) >> 16; - if (num_versions > 1) - versions[1] = (version & 0x0000FF00ull) >> 8; - if (num_versions > 2) - versions[2] = (version & 0x000000FFull); - // Fill in an remaining version numbers with invalid values - for (i = 3; i < num_versions; ++i) - versions[i] = UINT32_MAX; - } - // The LC_ID_DYLIB load command has a version with 3 version numbers in - // it, so always return 3 - return 3; + unsigned major = (version & 0xFFFF0000ull) >> 16; + unsigned minor = (version & 0x0000FF00ull) >> 8; + unsigned subminor = (version & 0x000000FFull); + return llvm::VersionTuple(major, minor, subminor); } } - return false; + return llvm::VersionTuple(); } bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) { @@ -5708,12 +5697,10 @@ #endif } -uint32_t ObjectFileMachO::GetMinimumOSVersion(uint32_t *versions, - uint32_t num_versions) { - if (m_min_os_versions.empty()) { +llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() { + if (!m_min_os_version) { lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - bool success = false; - for (uint32_t i = 0; success == false && i < m_header.ncmds; ++i) { + for (uint32_t i = 0; i < m_header.ncmds; ++i) { const lldb::offset_t load_cmd_offset = offset; version_min_command lc; @@ -5729,35 +5716,21 @@ const uint32_t yy = (lc.version >> 8) & 0xffu; const uint32_t zz = lc.version & 0xffu; if (xxxx) { - m_min_os_versions.push_back(xxxx); - m_min_os_versions.push_back(yy); - m_min_os_versions.push_back(zz); + m_min_os_version = llvm::VersionTuple(xxxx, yy, zz); + break; } - success = true; } } offset = load_cmd_offset + lc.cmdsize; } - if (success == false) { - // Push an invalid value so we don't keep trying to - m_min_os_versions.push_back(UINT32_MAX); + if (!m_min_os_version) { + // Set version to an empty value so we don't keep trying to + m_min_os_version = llvm::VersionTuple(); } } - if (m_min_os_versions.size() > 1 || m_min_os_versions[0] != UINT32_MAX) { - if (versions != NULL && num_versions > 0) { - for (size_t i = 0; i < num_versions; ++i) { - if (i < m_min_os_versions.size()) - versions[i] = m_min_os_versions[i]; - else - versions[i] = 0; - } - } - return m_min_os_versions.size(); - } - // Call the superclasses version that will empty out the data - return ObjectFile::GetMinimumOSVersion(versions, num_versions); + return *m_min_os_version; } uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions, Index: lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -360,10 +360,8 @@ } bool PlatformAndroid::GetRemoteOSVersion() { - m_major_os_version = GetSdkVersion(); - m_minor_os_version = 0; - m_update_os_version = 0; - return m_major_os_version != 0; + m_os_version = llvm::VersionTuple(GetSdkVersion()); + return !m_os_version.empty(); } llvm::StringRef Index: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h =================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -69,8 +69,8 @@ void CalculateTrapHandlerSymbolNames() override; - bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update, - lldb_private::Process *process = nullptr) override; + llvm::VersionTuple + GetOSVersion(lldb_private::Process *process = nullptr) override; bool SupportsModules() override { return true; } @@ -82,7 +82,7 @@ lldb_private::Status LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; - static std::tuple + static std::tuple ParseVersionBuildDir(llvm::StringRef str); protected: @@ -101,8 +101,7 @@ iPhoneOS, }; - static bool SDKSupportsModules(SDKType sdk_type, uint32_t major, - uint32_t minor, uint32_t micro); + static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version); static bool SDKSupportsModules(SDKType desired_type, const lldb_private::FileSpec &sdk_path); Index: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1382,18 +1382,14 @@ return g_xcode_filespec; } -bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, uint32_t major, - uint32_t minor, uint32_t micro) { +bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, + llvm::VersionTuple version) { switch (sdk_type) { case SDKType::MacOSX: - if (major > 10 || (major == 10 && minor >= 10)) - return true; - break; + return version >= llvm::VersionTuple(10, 10); case SDKType::iPhoneOS: case SDKType::iPhoneSimulator: - if (major >= 8) - return true; - break; + return version >= llvm::VersionTuple(8); } return false; @@ -1415,32 +1411,10 @@ return false; } - const size_t major_dot_offset = version_part.find('.'); - if (major_dot_offset == llvm::StringRef::npos) - return false; - - const llvm::StringRef major_version = - version_part.slice(0, major_dot_offset); - const llvm::StringRef minor_part = - version_part.drop_front(major_dot_offset + 1); - - const size_t minor_dot_offset = minor_part.find('.'); - if (minor_dot_offset == llvm::StringRef::npos) - return false; - - const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset); - - unsigned int major = 0; - unsigned int minor = 0; - unsigned int micro = 0; - - if (major_version.getAsInteger(10, major)) - return false; - - if (minor_version.getAsInteger(10, minor)) + llvm::VersionTuple version; + if (version.tryParse(version_part)) return false; - - return SDKSupportsModules(desired_type, major, minor, micro); + return SDKSupportsModules(desired_type, version); } return false; @@ -1512,18 +1486,17 @@ sdks_spec.AppendPathComponent("SDKs"); if (sdk_type == SDKType::MacOSX) { - uint32_t major = 0; - uint32_t minor = 0; - uint32_t micro = 0; + llvm::VersionTuple version = HostInfo::GetOSVersion(); - if (HostInfo::GetOSVersion(major, minor, micro)) { - if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro)) { + if (!version.empty()) { + if (SDKSupportsModules(SDKType::MacOSX, version)) { // We slightly prefer the exact SDK for this machine. See if it is // there. FileSpec native_sdk_spec = sdks_spec; StreamString native_sdk_name; - native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor); + native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(), + version.getMinor().getValueOr(0)); native_sdk_spec.AppendPathComponent(native_sdk_name.GetString()); if (native_sdk_spec.Exists()) { @@ -1536,14 +1509,14 @@ return FindSDKInXcodeForModules(sdk_type, sdks_spec); } -std::tuple +std::tuple PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { - uint32_t major, minor, update; llvm::StringRef build; llvm::StringRef version_str; llvm::StringRef build_str; std::tie(version_str, build_str) = dir.split(' '); - if (Args::StringToVersion(version_str, major, minor, update) || + llvm::VersionTuple version; + if (!version.tryParse(version_str) || build_str.empty()) { if (build_str.consume_front("(")) { size_t pos = build_str.find(')'); @@ -1551,7 +1524,7 @@ } } - return std::make_tuple(major, minor, update, build); + return std::make_tuple(version, build); } void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( @@ -1563,7 +1536,6 @@ options.insert(options.end(), apple_arguments.begin(), apple_arguments.end()); StreamString minimum_version_option; - uint32_t versions[3] = {0, 0, 0}; bool use_current_os_version = false; switch (sdk_type) { case SDKType::iPhoneOS: @@ -1587,9 +1559,9 @@ break; } - bool versions_valid = false; + llvm::VersionTuple version; if (use_current_os_version) - versions_valid = GetOSVersion(versions[0], versions[1], versions[2]); + version = GetOSVersion(); else if (target) { // Our OS doesn't match our executable so we need to get the min OS version // from the object file @@ -1597,35 +1569,23 @@ if (exe_module_sp) { ObjectFile *object_file = exe_module_sp->GetObjectFile(); if (object_file) - versions_valid = object_file->GetMinimumOSVersion(versions, 3) > 0; + version = object_file->GetMinimumOSVersion(); } } // Only add the version-min options if we got a version from somewhere - if (versions_valid && versions[0] != UINT32_MAX) { - // Make any invalid versions be zero if needed - if (versions[1] == UINT32_MAX) - versions[1] = 0; - if (versions[2] == UINT32_MAX) - versions[2] = 0; - + if (!version.empty()) { switch (sdk_type) { case SDKType::iPhoneOS: minimum_version_option.PutCString("-mios-version-min="); - minimum_version_option.PutCString( - llvm::VersionTuple(versions[0], versions[1], versions[2]) - .getAsString()); + minimum_version_option.PutCString(version.getAsString()); break; case SDKType::iPhoneSimulator: minimum_version_option.PutCString("-mios-simulator-version-min="); - minimum_version_option.PutCString( - llvm::VersionTuple(versions[0], versions[1], versions[2]) - .getAsString()); + minimum_version_option.PutCString(version.getAsString()); break; case SDKType::MacOSX: minimum_version_option.PutCString("-mmacosx-version-min="); - minimum_version_option.PutCString( - llvm::VersionTuple(versions[0], versions[1], versions[2]) - .getAsString()); + minimum_version_option.PutCString(version.getAsString()); } options.push_back(minimum_version_option.GetString()); } @@ -1652,16 +1612,15 @@ return ConstString(stream.GetString()); } -bool PlatformDarwin::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update, Process *process) { +llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) { if (process && strstr(GetPluginName().GetCString(), "-simulator")) { lldb_private::ProcessInstanceInfo proc_info; if (Host::GetProcessInfo(process->GetID(), proc_info)) { const Environment &env = proc_info.GetEnvironment(); - if (Args::StringToVersion(env.lookup("SIMULATOR_RUNTIME_VERSION"), major, - minor, update)) - return true; + llvm::VersionTuple result; + if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION"))) + return result; std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH"); if (!dyld_root_path.empty()) { @@ -1670,17 +1629,18 @@ std::string product_version; if (system_version_plist.GetValueAsString("ProductVersion", product_version)) { - return Args::StringToVersion(product_version, major, minor, update); + if (!result.tryParse(product_version)) + return result; } } } // For simulator platforms, do NOT call back through // Platform::GetOSVersion() as it might call Process::GetHostOSVersion() // which we don't want as it will be incorrect - return false; + return llvm::VersionTuple(); } - return Platform::GetOSVersion(major, minor, update, process); + return Platform::GetOSVersion(process); } lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { Index: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h =================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h @@ -60,9 +60,7 @@ SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec); lldb_private::FileSpec directory; lldb_private::ConstString build; - uint32_t version_major; - uint32_t version_minor; - uint32_t version_update; + llvm::VersionTuple version; bool user_cached; }; Index: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -31,12 +31,10 @@ PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo( const lldb_private::FileSpec &sdk_dir) - : directory(sdk_dir), build(), version_major(0), version_minor(0), - version_update(0), user_cached(false) { + : directory(sdk_dir), build(), user_cached(false) { llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); llvm::StringRef build_str; - std::tie(version_major, version_minor, version_update, build_str) = - ParseVersionBuildDir(dirname_str); + std::tie(version, build_str) = ParseVersionBuildDir(dirname_str); build.SetString(build_str); } @@ -255,24 +253,23 @@ // If we are connected we can find the version of the OS the platform us // running on and select the right SDK - uint32_t major, minor, update; - if (GetOSVersion(major, minor, update)) { + llvm::VersionTuple version = GetOSVersion(); + if (!version.empty()) { if (UpdateSDKDirectoryInfosIfNeeded()) { // First try for an exact match of major, minor and update for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version_major == major && - m_sdk_directory_infos[i].version_minor == minor && - m_sdk_directory_infos[i].version_update == update) { + if (m_sdk_directory_infos[i].version == version) return &m_sdk_directory_infos[i]; - } } } // First try for an exact match of major and minor for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version_major == major && - m_sdk_directory_infos[i].version_minor == minor) { + if (m_sdk_directory_infos[i].version.getMajor() == + version.getMajor() && + m_sdk_directory_infos[i].version.getMinor() == + version.getMinor()) { return &m_sdk_directory_infos[i]; } } @@ -280,7 +277,8 @@ // Lastly try to match of major version only.. for (i = 0; i < num_sdk_infos; ++i) { if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version_major == major) { + if (m_sdk_directory_infos[i].version.getMajor() == + version.getMajor()) { return &m_sdk_directory_infos[i]; } } @@ -300,25 +298,13 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() { const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL; if (UpdateSDKDirectoryInfosIfNeeded()) { - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - // First try for an exact match of major, minor and update - for (uint32_t i = 0; i < num_sdk_infos; ++i) { - const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; - if (sdk_dir_info.version_major != UINT32_MAX) { - if (result == NULL || - sdk_dir_info.version_major > result->version_major) { - result = &sdk_dir_info; - } else if (sdk_dir_info.version_major == result->version_major) { - if (sdk_dir_info.version_minor > result->version_minor) { - result = &sdk_dir_info; - } else if (sdk_dir_info.version_minor == result->version_minor) { - if (sdk_dir_info.version_update > result->version_update) { - result = &sdk_dir_info; - } - } - } - } - } + auto max = std::max_element( + m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(), + [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) { + return a.version < b.version; + }); + if (max != m_sdk_directory_infos.end()) + result = &*max; } return result; } Index: lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ lldb/trunk/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -653,9 +653,10 @@ } bool PlatformPOSIX::GetRemoteOSVersion() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetOSVersion( - m_major_os_version, m_minor_os_version, m_update_os_version); + if (m_remote_platform_sp) { + m_os_version = m_remote_platform_sp->GetOSVersion(); + return !m_os_version.empty(); + } return false; } Index: lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp +++ lldb/trunk/source/Plugins/Platform/Windows/PlatformWindows.cpp @@ -280,9 +280,10 @@ } bool PlatformWindows::GetRemoteOSVersion() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetOSVersion( - m_major_os_version, m_minor_os_version, m_update_os_version); + if (m_remote_platform_sp) { + m_os_version = m_remote_platform_sp->GetOSVersion(); + return !m_os_version.empty(); + } return false; } Index: lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ lldb/trunk/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -236,14 +236,8 @@ } bool PlatformRemoteGDBServer::GetRemoteOSVersion() { - uint32_t major, minor, update; - if (m_gdb_client.GetOSVersion(major, minor, update)) { - m_major_os_version = major; - m_minor_os_version = minor; - m_update_os_version = update; - return true; - } - return false; + m_os_version = m_gdb_client.GetOSVersion(); + return !m_os_version.empty(); } bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) { Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -266,7 +266,7 @@ bool GetDefaultThreadId(lldb::tid_t &tid); - bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + llvm::VersionTuple GetOSVersion(); bool GetOSBuildString(std::string &s); @@ -573,9 +573,7 @@ ArchSpec m_host_arch; ArchSpec m_process_arch; - uint32_t m_os_version_major; - uint32_t m_os_version_minor; - uint32_t m_os_version_update; + llvm::VersionTuple m_os_version; std::string m_os_build; std::string m_os_kernel; std::string m_hostname; Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -100,11 +100,10 @@ m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID), m_curr_tid_run(LLDB_INVALID_THREAD_ID), m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(), - m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX), - m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(), - m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX), - m_default_packet_timeout(0), m_max_packet_size(0), - m_qSupported_response(), m_supported_async_json_packets_is_valid(false), + m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(), + m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0), + m_max_packet_size(0), m_qSupported_response(), + m_supported_async_json_packets_is_valid(false), m_supported_async_json_packets_sp(), m_qXfer_memory_map(), m_qXfer_memory_map_loaded(false) {} @@ -323,9 +322,7 @@ m_qSymbol_requests_done = false; m_supports_qModuleInfo = true; m_host_arch.Clear(); - m_os_version_major = UINT32_MAX; - m_os_version_minor = UINT32_MAX; - m_os_version_update = UINT32_MAX; + m_os_version = llvm::VersionTuple(); m_os_build.clear(); m_os_kernel.clear(); m_hostname.clear(); @@ -944,18 +941,9 @@ return -1; } -bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major, - uint32_t &minor, - uint32_t &update) { - if (GetHostInfo()) { - if (m_os_version_major != UINT32_MAX) { - major = m_os_version_major; - minor = m_os_version_minor; - update = m_os_version_update; - return true; - } - } - return false; +llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() { + GetHostInfo(); + return m_os_version; } bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) { @@ -1218,9 +1206,7 @@ // "version" key instead of // "os_version"... { - Args::StringToVersion(value, m_os_version_major, m_os_version_minor, - m_os_version_update); - if (m_os_version_major != UINT32_MAX) + if (!m_os_version.tryParse(value)) ++num_keys_decoded; } else if (name.equals("watchpoint_exceptions_received")) { m_watchpoints_trigger_after_instruction = Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -269,19 +269,10 @@ break; } - uint32_t major = UINT32_MAX; - uint32_t minor = UINT32_MAX; - uint32_t update = UINT32_MAX; - if (HostInfo::GetOSVersion(major, minor, update)) { - if (major != UINT32_MAX) { - response.Printf("os_version:%u", major); - if (minor != UINT32_MAX) { - response.Printf(".%u", minor); - if (update != UINT32_MAX) - response.Printf(".%u", update); - } - response.PutChar(';'); - } + llvm::VersionTuple version = HostInfo::GetOSVersion(); + if (!version.empty()) { + response.Format("os_version:{0}", version.getAsString()); + response.PutChar(';'); } std::string s; Index: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -217,8 +217,7 @@ void PrefetchModuleSpecs(llvm::ArrayRef module_file_specs, const llvm::Triple &triple) override; - bool GetHostOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) override; + llvm::VersionTuple GetHostOSVersion() override; size_t LoadModules(LoadedModuleInfoList &module_list) override; Index: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -4241,13 +4241,8 @@ } } -bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { - if (m_gdb_comm.GetOSVersion(major, minor, update)) - return true; - // We failed to get the host OS version, defer to the base implementation to - // correctly invalidate the arguments. - return Process::GetHostOSVersion(major, minor, update); +llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() { + return m_gdb_comm.GetOSVersion(); } namespace { Index: lldb/trunk/source/Target/Platform.cpp =================================================================== --- lldb/trunk/source/Target/Platform.cpp +++ lldb/trunk/source/Target/Platform.cpp @@ -369,13 +369,11 @@ Platform::Platform(bool is_host) : m_is_host(is_host), m_os_version_set_while_connected(false), m_system_arch_set_while_connected(false), m_sdk_sysroot(), m_sdk_build(), - m_working_dir(), m_remote_url(), m_name(), m_major_os_version(UINT32_MAX), - m_minor_os_version(UINT32_MAX), m_update_os_version(UINT32_MAX), - m_system_arch(), m_mutex(), m_uid_map(), m_gid_map(), - m_max_uid_name_len(0), 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_working_dir(), m_remote_url(), m_name(), m_system_arch(), m_mutex(), + m_uid_map(), m_gid_map(), m_max_uid_name_len(0), 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_module_cache(llvm::make_unique()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log) @@ -395,9 +393,6 @@ } void Platform::GetStatus(Stream &strm) { - uint32_t major = UINT32_MAX; - uint32_t minor = UINT32_MAX; - uint32_t update = UINT32_MAX; std::string s; strm.Printf(" Platform: %s\n", GetPluginName().GetCString()); @@ -410,12 +405,9 @@ } } - if (GetOSVersion(major, minor, update)) { - strm.Printf("OS Version: %u", major); - if (minor != UINT32_MAX) - strm.Printf(".%u", minor); - if (update != UINT32_MAX) - strm.Printf(".%u", update); + llvm::VersionTuple os_version = GetOSVersion(); + if (!os_version.empty()) { + strm.Format("OS Version: {0}", os_version.getAsString()); if (GetOSBuildString(s)) strm.Printf(" (%s)", s.c_str()); @@ -447,17 +439,14 @@ strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); } -bool Platform::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update, - Process *process) { +llvm::VersionTuple Platform::GetOSVersion(Process *process) { std::lock_guard guard(m_mutex); - bool success = m_major_os_version != UINT32_MAX; if (IsHost()) { - if (!success) { + if (m_os_version.empty()) { // We have a local host platform - success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version, - m_update_os_version); - m_os_version_set_while_connected = success; + m_os_version = HostInfo::GetOSVersion(); + m_os_version_set_while_connected = !m_os_version.empty(); } } else { // We have a remote platform. We can only fetch the remote @@ -467,7 +456,7 @@ const bool is_connected = IsConnected(); bool fetch = false; - if (success) { + if (!m_os_version.empty()) { // We have valid OS version info, check to make sure it wasn't manually // set prior to connecting. If it was manually set prior to connecting, // then lets fetch the actual OS version info if we are now connected. @@ -478,22 +467,18 @@ fetch = is_connected; } - if (fetch) { - success = GetRemoteOSVersion(); - m_os_version_set_while_connected = success; - } + if (fetch) + m_os_version_set_while_connected = GetRemoteOSVersion(); } - if (success) { - major = m_major_os_version; - minor = m_minor_os_version; - update = m_update_os_version; - } else if (process) { + if (!m_os_version.empty()) + return m_os_version; + if (process) { // Check with the process in case it can answer the question if a process // was provided - return process->GetHostOSVersion(major, minor, update); + return process->GetHostOSVersion(); } - return success; + return llvm::VersionTuple(); } bool Platform::GetOSBuildString(std::string &s) { @@ -859,7 +844,7 @@ return nullptr; } -bool Platform::SetOSVersion(uint32_t major, uint32_t minor, uint32_t update) { +bool Platform::SetOSVersion(llvm::VersionTuple version) { if (IsHost()) { // We don't need anyone setting the OS version for the host platform, we // should be able to figure it out by calling HostInfo::GetOSVersion(...). @@ -874,9 +859,7 @@ // We aren't connected and we might want to set the OS version ahead of // time before we connect so we can peruse files and use a local SDK or // PDK cache of support files to disassemble or do other things. - m_major_os_version = major; - m_minor_os_version = minor; - m_update_os_version = update; + m_os_version = version; return true; } } Index: lldb/trunk/source/Utility/Args.cpp =================================================================== --- lldb/trunk/source/Utility/Args.cpp +++ lldb/trunk/source/Utility/Args.cpp @@ -409,29 +409,6 @@ return s.c_str(); } -bool Args::StringToVersion(llvm::StringRef string, uint32_t &major, - uint32_t &minor, uint32_t &update) { - major = UINT32_MAX; - minor = UINT32_MAX; - update = UINT32_MAX; - - if (string.empty()) - return false; - - llvm::StringRef major_str, minor_str, update_str; - - std::tie(major_str, minor_str) = string.split('.'); - std::tie(minor_str, update_str) = minor_str.split('.'); - if (major_str.getAsInteger(10, major)) - return false; - if (!minor_str.empty() && minor_str.getAsInteger(10, minor)) - return false; - if (!update_str.empty() && update_str.getAsInteger(10, update)) - return false; - - return true; -} - const char *Args::GetShellSafeArgument(const FileSpec &shell, const char *unsafe_arg, std::string &safe_arg) { Index: lldb/trunk/unittests/Platform/PlatformDarwinTest.cpp =================================================================== --- lldb/trunk/unittests/Platform/PlatformDarwinTest.cpp +++ lldb/trunk/unittests/Platform/PlatformDarwinTest.cpp @@ -19,38 +19,29 @@ using namespace lldb_private; TEST(PlatformDarwinTest, TestParseVersionBuildDir) { - uint32_t A, B, C; + llvm::VersionTuple V; llvm::StringRef D; - std::tie(A, B, C, D) = PlatformDarwin::ParseVersionBuildDir("1.2.3 (test1)"); - EXPECT_EQ(1u, A); - EXPECT_EQ(2u, B); - EXPECT_EQ(3u, C); + std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("1.2.3 (test1)"); + EXPECT_EQ(llvm::VersionTuple(1, 2, 3), V); EXPECT_EQ("test1", D); - std::tie(A, B, C, D) = PlatformDarwin::ParseVersionBuildDir("2.3 (test2)"); - EXPECT_EQ(2u, A); - EXPECT_EQ(3u, B); + std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("2.3 (test2)"); + EXPECT_EQ(llvm::VersionTuple(2, 3), V); EXPECT_EQ("test2", D); - std::tie(A, B, C, D) = PlatformDarwin::ParseVersionBuildDir("3 (test3)"); - EXPECT_EQ(3u, A); + std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("3 (test3)"); + EXPECT_EQ(llvm::VersionTuple(3), V); EXPECT_EQ("test3", D); - std::tie(A, B, C, D) = PlatformDarwin::ParseVersionBuildDir("1.2.3 (test"); - EXPECT_EQ(1u, A); - EXPECT_EQ(2u, B); - EXPECT_EQ(3u, C); + std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("1.2.3 (test"); + EXPECT_EQ(llvm::VersionTuple(1, 2, 3), V); EXPECT_EQ("test", D); - std::tie(A, B, C, D) = PlatformDarwin::ParseVersionBuildDir("2.3.4 test"); - EXPECT_EQ(2u, A); - EXPECT_EQ(3u, B); - EXPECT_EQ(4u, C); + std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("2.3.4 test"); + EXPECT_EQ(llvm::VersionTuple(2, 3, 4), V); EXPECT_EQ("", D); - std::tie(A, B, C, D) = PlatformDarwin::ParseVersionBuildDir("3.4.5"); - EXPECT_EQ(3u, A); - EXPECT_EQ(4u, B); - EXPECT_EQ(5u, C); + std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("3.4.5"); + EXPECT_EQ(llvm::VersionTuple(3, 4, 5), V); }