[Lldb-commits] [PATCH] D11129: Fix for remote-linux test fails: use currently selected platform on target launch

Greg Clayton clayborg at gmail.com
Wed Jul 15 11:00:35 PDT 2015

> On Jul 14, 2015, at 12:56 PM, Omair Javaid <omair.javaid at linaro.org> wrote:
> On 13 July 2015 at 22:47, Greg Clayton <clayborg at gmail.com> wrote:
>> clayborg added a comment.
>> So you must select the platform first:
>>  target select remote-linux
>>  file a.out
>>  target connect connect://hostname:5432
>>  run
> Alright, but if user does something like:
> file path to some file or invokes ./lldb path to some file (This
> should create a target)
> platform select remote-linux
> target connect connect://hostname:5432
> run
> What should be the expected error message here ?
> This seems to be pretty common use-case.
> 1) we give a executable to be debugged to our debugger on command line
> and it loads symbols etc figuring out architecture and symbol format
> internally.

So your target will populate the executable and find incorrect shared libraries when it tracks down the dependent files when the platform isn't set correctly. So now you have loaded a few hundred incorrect shared libraries.

> 2) Issue a run at this stage should run the process on host platform
> if there is mismatch (Architecture or OS not compatible) then debugger
> should exit with a suitable error message.

It does.

> 3) If we want to run the same binary on a remote platform then we
> connect to that platform and issue a run which should ideally launch
> our process on remote machine where debug agent is being run.

When you do "target list" it shows you the targets and their current platforms. It is currently expected that you select the platform before you make your target. I seem to remember we used to have the ability to specify the platform on target create, but that was removed.

> At point 1) LLDB should decide on a platform for the binary image
> based on comparison of architecture and Operating System of lldb host
> and binary image target.
> Do you agree? This is not happening right now and if we agree this
> should happen I can go ahead and make those changes.

It certainly does. On MacOSX I can do this:

% cd lldb/test/lang/c/array_types
% make TRIPLE=x86_64-apple-ios
% lldb a.out
(lldb) target list 
Current targets:
* target #0: /Volumes/work/gclayton/Documents/src/lldb/tot/test/lang/c/array_types/a.out ( arch=x86_64-apple-ios, platform=ios-simulator )

Note that we detected that the current host platform wasn't compatible and we ran through all platforms and found one that matched. 

I am guessing the main problem is the ELF binary is too generic to be able to fully specify its triple, and too many platforms claim they are compatible. So you will need to improve the Platforms you care about to properly determine which binaries they can and should claim they are compatible with.

> At point 2) if we run a target built for foreign architecture or OS on
> a native local host at least for linux LLDB goes into a indefinite
> loop ending up in a crash.
> I think I should fix this too. Any thoughts?

Yes, the PlatformLinux (or which ever platform is claiming your binary) when IsHost() == true should only claim that it is compatible with native architectures. This is the bug we need to fix.
> At point 3) If we select and connect a remote platform then we cannot
> run the target that we created at point 1) and we have create a new
> target.

Yes. Or we can add a "target platform" command that can switch a target's platform. I would say to just create a new target in easiest. But hopefully we won't have to when the platforms only claim to be compatible with what they should be compatible with. If you are on Linux and you say "target create a.out" and "target list" shows that the platform is "host":

(lldb) target create a.out
(lldb) target list 
Current targets:
* target #0: /Volumes/work/gclayton/Documents/src/args/a.out ( arch=x86_64-apple-macosx, platform=host )

The platform should only be "host" if your a.out contains a native architecture. If it doesn't, the "remote-linux" should be selected as the platform automatically. Again, part of the problem is ELF files might not contain enough info to extract the full triple for the current binary. The ELF plug-in currently uses the OSABI field from the match header, various note sections, and some other info to try and figure out the correct triple for a binary, but it doesn't always work if the info is missing or not set.

So if you have an "arm64-pc-linux" executable and you are on a x86_64 linux host and you type:

(lldb) target create a.out

you should not end of having a "host" platform. This is just a bug.

> If we launch the process using same target created initially
> LLDB again goes into a crash on linux platform.
> This should also be fixed to make sure we have a standard expected output.

We shouldn't crash. 
> Finally I am still learning this code base so not sure whats the harm
> in switching platform to currently selected platform when we issue the
> run. I guess we are doing the same when we attach to a process?
> Providing a binary image on lldb commandline should be restricted to
> native debugging only?

No. As mentioned above, each platform plug-in can say which architectures they support via "bool Platform::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)". Linux implements this as:

PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
    if (IsHost())
        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();
        if (m_remote_platform_sp)
            return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);

        llvm::Triple triple;
        // Set the OS to 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;
            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
        return true;
    return false;

When we have a binary that is loaded via "target create a.out" we look at the triple that the executable contains and we ask the selected platform if it is compatible. We really need the ObjectFileELF parser to be able to determine the triple for a binary correctly so all other plug-ins that get loaded can do their job and select the correct plug-ins. So when you create a target, what does the output of "target list" show? It will show the architecture as "arch=<arch>" in the output. If it shows "arm64-*-*" then you have an ELF file that was not able to correctly figure its triple out. You can help the target specify its correct architecture in this case by doing:

(lldb) target create --arch=arm64-pc-linux a.out

And the target might then grab the correct platform.

So to sum up:
- Targets created with a binary  ("target create ... a.out") will grab the architecture from the binary if it isn't specified with "--arch <arch>" and try to pick a compatible platform based on the architecture it extracts from the ObjectFile plug-in that parses the executable (ObjectFileELF in your case I imagine)
- If the currently selected platform claims it is compatible with the current executable, that platform will be selected
- If the currently selected platform claims it is NOT compatible with the current executable, we will run through all platforms and look for one that is

So if you are not getting what you expect, look for bugs in these areas and we can and should fix those.

Greg Clayton

More information about the lldb-commits mailing list