[lldb] Simplify specifying of platform supported architectures

The GetSupportedArchitectureAtIndex pattern forces the use of
complicated patterns in both the implementations of the function and in
the various callers.

This patch creates a new method (GetSupportedArchitectures), which
returns a list (vector) of architectures. The
GetSupportedArchitectureAtIndex is kept in order to enable incremental
rollout. Base Platform class contains implementations of both of these
methods, using the other method as the source of truth. Platforms
without infinite stacks should implement at least one of them.

This patch also ports Linux, FreeBSD and NetBSD platforms to the new
API. A new helper function (CreateArchList) is added to simplify the
common task of creating a list of ArchSpecs with the same OS but
different architectures.

Differential Revision: https://reviews.llvm.org/D113608
This commit is contained in:
Pavel Labath 2021-11-10 17:44:37 +01:00
parent 33c0f93f6c
commit 669e57ebd1
8 changed files with 100 additions and 178 deletions

View File

@ -322,7 +322,13 @@ public:
/// \b true if \a arch was filled in and is valid, \b false
/// otherwise.
virtual bool GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) = 0;
ArchSpec &arch);
/// Get the platform's supported architectures in the order in which they
/// should be searched.
/// NB: This implementation is mutually recursive with
/// GetSupportedArchitectureAtIndex. Subclasses should implement one of them.
virtual std::vector<ArchSpec> GetSupportedArchitectures();
virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target,
BreakpointSite *bp_site);
@ -876,6 +882,12 @@ public:
}
protected:
/// Create a list of ArchSpecs with the given OS and a architectures. The
/// vendor field is left as an "unspecified unknown".
static std::vector<ArchSpec>
CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,
llvm::Triple::OSType os);
/// Private implementation of connecting to a process. If the stream is set
/// we connect synchronously.
lldb::ProcessSP DoConnectProcess(llvm::StringRef connect_url,

View File

@ -111,72 +111,27 @@ void PlatformFreeBSD::Terminate() {
/// Default Constructor
PlatformFreeBSD::PlatformFreeBSD(bool is_host)
: PlatformPOSIX(is_host) // This is the local host platform
{}
bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (IsHost()) {
{
if (is_host) {
ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
if (hostArch.GetTriple().isOSFreeBSD()) {
if (idx == 0) {
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
// If the default host architecture is 64-bit, look for a 32-bit
// variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
}
m_supported_architectures.push_back(hostArch);
if (hostArch.GetTriple().isArch64Bit()) {
m_supported_architectures.push_back(
HostInfo::GetArchitecture(HostInfo::eArchKind32));
}
} else {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
llvm::Triple triple;
// Set the OS to FreeBSD
triple.setOS(llvm::Triple::FreeBSD);
// Set the architecture
switch (idx) {
case 0:
triple.setArchName("x86_64");
break;
case 1:
triple.setArchName("i386");
break;
case 2:
triple.setArchName("aarch64");
break;
case 3:
triple.setArchName("arm");
break;
case 4:
triple.setArchName("mips64");
break;
case 5:
triple.setArchName("mips");
break;
case 6:
triple.setArchName("ppc64");
break;
case 7:
triple.setArchName("ppc");
break;
default:
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
// vendor by calling triple.SetVendorName("unknown") so that it is a
// "unspecified unknown". This means when someone calls
// triple.GetVendorName() it will return an empty string which indicates
// that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
return true;
m_supported_architectures = CreateArchList(
{llvm::Triple::x86_64, llvm::Triple::x86, llvm::Triple::aarch64,
llvm::Triple::arm, llvm::Triple::mips64, llvm::Triple::ppc64,
llvm::Triple::ppc},
llvm::Triple::FreeBSD);
}
return false;
}
std::vector<ArchSpec> PlatformFreeBSD::GetSupportedArchitectures() {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectures();
return m_supported_architectures;
}
void PlatformFreeBSD::GetStatus(Stream &strm) {

View File

@ -42,7 +42,7 @@ public:
void GetStatus(Stream &strm) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
std::vector<ArchSpec> GetSupportedArchitectures() override;
bool CanDebugProcess() override;
@ -52,6 +52,8 @@ public:
lldb::addr_t length, unsigned prot,
unsigned flags, lldb::addr_t fd,
lldb::addr_t offset) override;
std::vector<ArchSpec> m_supported_architectures;
};
} // namespace platform_freebsd

View File

@ -109,78 +109,28 @@ void PlatformLinux::Terminate() {
/// Default Constructor
PlatformLinux::PlatformLinux(bool is_host)
: PlatformPOSIX(is_host) // This is the local host platform
{}
bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (IsHost()) {
{
if (is_host) {
ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
if (hostArch.GetTriple().isOSLinux()) {
if (idx == 0) {
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
// If the default host architecture is 64-bit, look for a 32-bit
// variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
}
m_supported_architectures.push_back(hostArch);
if (hostArch.GetTriple().isArch64Bit()) {
m_supported_architectures.push_back(
HostInfo::GetArchitecture(HostInfo::eArchKind32));
}
} else {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
llvm::Triple triple;
// Set the OS to linux
triple.setOS(llvm::Triple::Linux);
// Set the architecture
switch (idx) {
case 0:
triple.setArchName("x86_64");
break;
case 1:
triple.setArchName("i386");
break;
case 2:
triple.setArchName("arm");
break;
case 3:
triple.setArchName("aarch64");
break;
case 4:
triple.setArchName("mips64");
break;
case 5:
triple.setArchName("hexagon");
break;
case 6:
triple.setArchName("mips");
break;
case 7:
triple.setArchName("mips64el");
break;
case 8:
triple.setArchName("mipsel");
break;
case 9:
triple.setArchName("s390x");
break;
default:
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
// vendor by calling triple.SetVendorName("unknown") so that it is a
// "unspecified unknown". This means when someone calls
// triple.GetVendorName() it will return an empty string which indicates
// that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
return true;
m_supported_architectures = CreateArchList(
{llvm::Triple::x86_64, llvm::Triple::x86, llvm::Triple::arm,
llvm::Triple::aarch64, llvm::Triple::mips64, llvm::Triple::mips64,
llvm::Triple::hexagon, llvm::Triple::mips, llvm::Triple::mips64el,
llvm::Triple::mipsel, llvm::Triple::systemz},
llvm::Triple::Linux);
}
return false;
}
std::vector<ArchSpec> PlatformLinux::GetSupportedArchitectures() {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectures();
return m_supported_architectures;
}
void PlatformLinux::GetStatus(Stream &strm) {

View File

@ -42,7 +42,7 @@ public:
void GetStatus(Stream &strm) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
std::vector<ArchSpec> GetSupportedArchitectures() override;
uint32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override;
@ -57,6 +57,8 @@ public:
lldb::addr_t length, unsigned prot,
unsigned flags, lldb::addr_t fd,
lldb::addr_t offset) override;
std::vector<ArchSpec> m_supported_architectures;
};
} // namespace platform_linux

View File

@ -100,54 +100,24 @@ void PlatformNetBSD::Terminate() {
/// Default Constructor
PlatformNetBSD::PlatformNetBSD(bool is_host)
: PlatformPOSIX(is_host) // This is the local host platform
{}
bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (IsHost()) {
{
if (is_host) {
ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
if (hostArch.GetTriple().isOSNetBSD()) {
if (idx == 0) {
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
// If the default host architecture is 64-bit, look for a 32-bit
// variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
}
m_supported_architectures.push_back(hostArch);
if (hostArch.GetTriple().isArch64Bit()) {
m_supported_architectures.push_back(
HostInfo::GetArchitecture(HostInfo::eArchKind32));
}
} else {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
llvm::Triple triple;
// Set the OS to NetBSD
triple.setOS(llvm::Triple::NetBSD);
// Set the architecture
switch (idx) {
case 0:
triple.setArchName("x86_64");
break;
case 1:
triple.setArchName("i386");
break;
default:
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
// vendor by calling triple.SetVendorName("unknown") so that it is a
// "unspecified unknown". This means when someone calls
// triple.GetVendorName() it will return an empty string which indicates
// that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
return true;
m_supported_architectures = CreateArchList(
{llvm::Triple::x86_64, llvm::Triple::x86}, llvm::Triple::NetBSD);
}
return false;
}
std::vector<ArchSpec> PlatformNetBSD::GetSupportedArchitectures() {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectures();
return m_supported_architectures;
}
void PlatformNetBSD::GetStatus(Stream &strm) {

View File

@ -42,7 +42,7 @@ public:
void GetStatus(Stream &strm) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
std::vector<ArchSpec> GetSupportedArchitectures() override;
uint32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override;
@ -54,6 +54,8 @@ public:
lldb::addr_t length, unsigned prot,
unsigned flags, lldb::addr_t fd,
lldb::addr_t offset) override;
std::vector<ArchSpec> m_supported_architectures;
};
} // namespace platform_netbsd

View File

@ -1144,6 +1144,35 @@ Platform::GetPlatformForArchitecture(const ArchSpec &arch,
return platform_sp;
}
std::vector<ArchSpec>
Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,
llvm::Triple::OSType os) {
std::vector<ArchSpec> list;
for(auto arch : archs) {
llvm::Triple triple;
triple.setArch(arch);
triple.setOS(os);
list.push_back(ArchSpec(triple));
}
return list;
}
bool Platform::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) {
const auto &archs = GetSupportedArchitectures();
if (idx >= archs.size())
return false;
arch = archs[idx];
return true;
}
std::vector<ArchSpec> Platform::GetSupportedArchitectures() {
std::vector<ArchSpec> result;
ArchSpec arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(idx, arch); ++idx)
result.push_back(arch);
return result;
}
/// Lets a platform answer if it is compatible with a given
/// architecture and the target triple contained within.
bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,