Problems selecting correct Platform

I've got a Hexagon platform, that launches the Hexagon simulator and is used
for standalone development. Now I'm working on supporting Hexagon Linux, but
it's not choosing the Linux platform, instead it's choosing the Hexagon
platform.

I want LLDB to use the Hexagon Platform if my executable's triple is
"hexagon-unknown-elf" (which is really hexagon-unknown-unknown) and use the
Linux platform if my executable's triple is "hexagon-unknown-linux".

First problem:
"target create" doesn't search platforms for one matching the executable's
triple. It used to, but when TargetList::CreateTarget was switched to call
CreateTargetInternal, "target create" was changed to call the method that
takes an ArchSpec instead of a triple. This method doesn't search for a
compatible Platform, but instead chooses the current Platform.

Is this intended behavior?

Second problem:
I change DoExecute() in CommandObjectTarget.cpp to call the ArchSpec version
if the ArchSpec is valid, and the triple version if it is not. This has LLDB
going through platforms to find a match, but there's another problem when it
gets to PlatformLinux. PlatformLinux::GetSupportedArchitectureAtIndex() will
only return host architectures. So in my case, running on Windows, it
returns x86_64-pc-windows-msvc or i386-pc-windows-msvc. Neither is a match
for Linux.

Shouldn't the Linux platform match anything with a triple *-*-linux? Or does
the platform not matter if I'm just going to use gdb-remote to connect to
gdbserver or LLGS on a remote Hexagon Linux board?

I've got a Hexagon platform, that launches the Hexagon simulator and is used
for standalone development. Now I'm working on supporting Hexagon Linux, but
it's not choosing the Linux platform, instead it's choosing the Hexagon
platform.

I want LLDB to use the Hexagon Platform if my executable's triple is
"hexagon-unknown-elf" (which is really hexagon-unknown-unknown) and use the
Linux platform if my executable's triple is "hexagon-unknown-linux".

First problem:
"target create" doesn't search platforms for one matching the executable's
triple. It used to, but when TargetList::CreateTarget was switched to call
CreateTargetInternal, "target create" was changed to call the method that
takes an ArchSpec instead of a triple. This method doesn't search for a
compatible Platform, but instead chooses the current Platform.

Is this intended behavior?

No. Sounds like you have an old snapshot of LLDB. The current one was recently fixed to search for the platform with revision 216115.

Second problem:
I change DoExecute() in CommandObjectTarget.cpp to call the ArchSpec version
if the ArchSpec is valid, and the triple version if it is not. This has LLDB
going through platforms to find a match, but there's another problem when it
gets to PlatformLinux. PlatformLinux::GetSupportedArchitectureAtIndex() will
only return host architectures.

This is a bug and should be fixed with code below...

So in my case, running on Windows, it
returns x86_64-pc-windows-msvc or i386-pc-windows-msvc. Neither is a match
for Linux.

Shouldn't the Linux platform match anything with a triple *-*-linux? Or does
the platform not matter if I'm just going to use gdb-remote to connect to
gdbserver or LLGS on a remote Hexagon Linux board?

So a platform can say what architectures it supports. This is how we match architectures up to a binary that is supplied. Each platform should give an exhaustive list of the architectures they support.

The current code is:

bool
PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
    if (idx == 0)
    {
        arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
        return arch.IsValid();
    }
    else if (idx == 1)
    {
        // If the default host architecture is 64-bit, look for a 32-bit variant
        ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
        if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
        {
            arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
            return arch.IsValid();
        }
    }
    return false;
}

This is only correct if Platform::IsHost() returns true. Otherwise linux will need to say all architectures that is supports:

x86_64-*-linux
i386-*-linux
arm*-*-linux
aarch64-*-linux
mips64-*linux

The "*" above for the vendor should be set an an "unspecified unknown". So the code should be:

bool
PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
{
    if (IsHost())
    {
        if (idx == 0)
        {
            arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
            return arch.IsValid();
        }
        else if (idx == 1)
       {
            // If the default host architecture is 64-bit, look for a 32-bit variant
            ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
            if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
            {
                arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
                return arch.IsValid();
            }
        }
    }
    else
    {
  llvm::Triple triple;
        // Set the OS to linux
  triple.setOS(llvm::Triple::Linux);
        // Set the architecture
        switch (idx)
        {
        case 0: arch.setArchName("x86_64"); break;
        case 1: arch.setArchName("i386"); break;
        case 2: arch.setArchName("arm"); break;
        case 3: arch.setArchName("aarch64"); break;
        case 4: arch.setArchName("mips64"); break;
        case 5: arch.setArchName("hexagon"); 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;
    }
    return false;
}

Then things should work a bit better for you.

From: Greg Clayton [mailto:gclayton@apple.com]
Sent: Thursday, March 19, 2015 4:45 PM

>
> I've got a Hexagon platform, that launches the Hexagon simulator and
> is used for standalone development. Now I'm working on supporting
> Hexagon Linux, but it's not choosing the Linux platform, instead it's
> choosing the Hexagon platform.
>
> I want LLDB to use the Hexagon Platform if my executable's triple is
> "hexagon-unknown-elf" (which is really hexagon-unknown-unknown) and
> use the Linux platform if my executable's triple is

"hexagon-unknown-linux".

>
>
> First problem:
> "target create" doesn't search platforms for one matching the
> executable's triple. It used to, but when TargetList::CreateTarget was
> switched to call CreateTargetInternal, "target create" was changed to
> call the method that takes an ArchSpec instead of a triple. This
> method doesn't search for a compatible Platform, but instead chooses the
current Platform.
>
> Is this intended behavior?

No. Sounds like you have an old snapshot of LLDB. The current one was

recently

fixed to search for the platform with revision 216115.

I've got 216115. My snapshot includes up to 227289 from 1/27/15. We're
trying to get better about staying closer to top-of-tree, but it's something
we're not good enough at yet.

226712 from 1/21/15 changed how "target create" called CreateTarget() in
TargetList.cpp. Before that rev, it called the CreateTarget() that took a
triple, but after that rev it calls the CreateTarget() that takes an
ArchSpec. These 2 methods do different things; the triple one calls the
(internal) ArchSpec one at the end. One thing that is missing in the one
that takes an ArchSpec is the chunk of code that searches for a valid
platform for the specified architecture:

        else if (platform_arch.IsValid())
        {
            // if "arch" isn't valid, yet "platform_arch" is, it means we
have an executable file with
            // a single architecture which should be used
            ArchSpec fixed_platform_arch;
            if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
&fixed_platform_arch))
            {
                platform_sp =
Platform::GetPlatformForArchitecture(platform_arch, &fixed_platform_arch);
                if (platform_sp)

debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
            }
        }

That code is not currently called by a "target create".

Vince, would changing the CreateTarget() call in CommandObjectTarget.cpp
back to the pre-226712 call break the remote-linux platform run process fix?

> Second problem:
> I change DoExecute() in CommandObjectTarget.cpp to call the ArchSpec
> version if the ArchSpec is valid, and the triple version if it is not.
> This has LLDB going through platforms to find a match, but there's
> another problem when it gets to PlatformLinux.
> PlatformLinux::GetSupportedArchitectureAtIndex() will only return host
architectures.

This is a bug and should be fixed with code below...

> So in my case, running on Windows, it
> returns x86_64-pc-windows-msvc or i386-pc-windows-msvc. Neither is a
> match for Linux.
>
> Shouldn't the Linux platform match anything with a triple *-*-linux?
> Or does the platform not matter if I'm just going to use gdb-remote to
> connect to gdbserver or LLGS on a remote Hexagon Linux board?

I added the code below to PlatformLinux.cpp and now my Windows LLDB
correctly selects the remote-linux platform for Hexagon Linux. Thanks!

So a platform can say what architectures it supports. This is how we match
architectures up to a binary that is supplied. Each platform should give

an

exhaustive list of the architectures they support.

The current code is:

bool
PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec
&arch) {
    if (idx == 0)
    {
        arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
        return arch.IsValid();
    }
    else if (idx == 1)
    {
        // If the default host architecture is 64-bit, look for a 32-bit

variant

        ArchSpec hostArch =
HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
        if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
        {
            arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
            return arch.IsValid();
        }
    }
    return false;
}

This is only correct if Platform::IsHost() returns true. Otherwise linux

will need

to say all architectures that is supports:

x86_64-*-linux
i386-*-linux
arm*-*-linux
aarch64-*-linux
mips64-*linux

The "*" above for the vendor should be set an an "unspecified unknown". So

the

code should be:

bool
PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec
&arch) {
    if (IsHost())
    {
        if (idx == 0)
        {
            arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
            return arch.IsValid();
        }
        else if (idx == 1)
       {
            // If the default host architecture is 64-bit, look for a

32-bit variant

            ArchSpec hostArch =
HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
            if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
            {
                arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
                return arch.IsValid();
            }
        }
    }
    else
    {
  llvm::Triple triple;
        // Set the OS to linux
  triple.setOS(llvm::Triple::Linux);
        // Set the architecture
        switch (idx)
        {
        case 0: arch.setArchName("x86_64"); break;
        case 1: arch.setArchName("i386"); break;
        case 2: arch.setArchName("arm"); break;
        case 3: arch.setArchName("aarch64"); break;
        case 4: arch.setArchName("mips64"); break;
        case 5: arch.setArchName("hexagon"); 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

+lldb-dev

I’ve just tried running the Linux remote tests again and I hit some problems.

“connect to debug monitor on port NNN failed”

We will look into it soon.

We’ve never tried it on Ubuntu 12.04 AFAIK. One problem with 12.04 could be causing all of those failures.

Sincerely,

Vince

I’m seeing the same issue. On the server side, I get:

Launched ‘/local/scratch/ted/plat/bin/lldb-server’ as process 1986…

Some tests are running fine; some are failing in this manner.