llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.57k stars 11.81k forks source link

LLDB cannot demangle function names on Windows. #22551

Open tedwoodward opened 9 years ago

tedwoodward commented 9 years ago
Bugzilla Link 22177
Version unspecified
OS Windows NT
Attachments testcase
CC @majnemer,@emaste

Extended Description

Build the attached file. Note that I had to build it on Linux because clang on Windows didn't produce a native executable with symbols that LLDB could read.

clang -g expr_test.cpp -o expr_test.elf

Run Windows LLDB on expr_test.elf, and run these commands:

p main p foo p _Z3fooi

With Windows LLDB I see: (lldb) p main (int ()()) $0 = 0x00000000004004f0 (lldb) p foo error: use of undeclared identifier 'foo' error: 1 errors parsing expression (lldb) p _Z3fooi (int ()(int)) $1 = 0x00000000004004d0

With Linux LLDB I see: (lldb) p main (int ()()) $0 = 0x00000000004004f0 (lldb) p foo (int ()(int)) $1 = 0x00000000004004d0 (lldb) p _Z3fooi (int (*)(int)) $2 = 0x00000000004004d0

Windows LLDB is not correctly demangling _Z3fooi and resolving that as foo.

tedwoodward commented 9 years ago

Possibly fixed by http://reviews.llvm.org/D9754 .

llvmbot commented 9 years ago

It might not be, but it could be related to the ABI. Lots checks that are actually ABI checks are performed behind OS #defines, which is not the right thing to do. However, I'm concerned primarily with making MS ABI executables debuggable. So I can fix the case of an MS ABI executable and make sure that works. And that may or may not fix the problem for Hexagaon binaries or binaries built with GCC on Windows (which also use the Itanium ABI), but if it doesn't someone else will probably need to look into it.

FWIW, I'm looking at other issues at the moment. I need to get stepping inside the debugger working on Windows, and then fix some other high impact bugs that will fix a lot of tests. This one is still on my radar though, and I'll still get to it sooner or later. But just to be clear, I'm going to consider this fixed (at least for my part) once "p foo" and "p ?foo@@YAHH@Z" both work for a binary built with clang and linked with LLD on Windows.

tedwoodward commented 9 years ago

I installed the latest gcc from cygwin.org and built my testcase with it. I see the same issue with that file - it can't parse "foo", but can parse "_Z3fooi".

U:\lldb_test>gcc -g infinite.cpp -o infinite.coff

U:\lldb_test>file infinite.coff infinite.coff: PE32 executable (console) Intel 80386, for MS Windows

U:\lldb_test>c:\Qualcomm\HEXAGON_Tools\7.2\Tools\bin\hexagon-lldb infinite.coff Current executable set to 'infinite.coff' (i386). Hexagon utilities (run, start, pagetable, tlb, pv) loaded (lldb) p foo error: use of undeclared identifier 'foo' error: 1 errors parsing expression (lldb) p _Z3fooi (int (*)(int)) $0 = 0x004011c0

The LLDB used here doesn't have any fixes for the name mangling issue - it's the original version we found the problem in.

I don't believe this is a COFF vs ELF issue.

tedwoodward commented 9 years ago

The expr_test.elf I'm using is a Linux executable built with clang for Linux. I figured that would be the most portable test. I also see the issue with Hexagon ELF files built with clang on Windows.

Typically the Hexagon binaries are built on Windows and loaded into a simulator running on Windows, or pushed down to Android on an ARM using adb and copied to a directory that the Hexagon loader will read from.

llvmbot commented 9 years ago

So is expr_test.elf physically located on a Windows machine or a Hexagon machine? I was under the impression you copied it to a Windows machine and loaded it in LLDB that way. If not, then yes it should work.

Unfortunately I probably won't be able to debug into that myself.

That said, I tested it with a Windows executable and using the full name also doesn't work, because some of the characters like ? and @​s that show in mangled MS ABI names confuse command interpreter tokenization.

For the purposes of this bug, I will work on fixing it so that it works with MS ABI Windows executables so that both base names and full names work, but after that it will probably be up to someone else to fix any remaining issues with Windows connecting to a Linux/Hexagon/etc remote.

tedwoodward commented 9 years ago

I'd agree about the ELF issue if this was a Windows executable, but it's not. It's a Hexagon executable, with the debugger running on Windows and connecting to a simulator or target via gdb-remote. Hexagon is always ELF.

llvmbot commented 9 years ago

Sorry, missed the point where you said you tried the with base name change.

I'm kind of not convinced we should really be trying to support ELF binaries on Windows. Doesn't really make sense. Try the same thing with an EXE generated by clang, and use the full MS-ABI name, which will start with a ?

llvmbot commented 9 years ago

Right, the "p foo" issue is different. You can read about it in this thread: http://lists.cs.uiuc.edu/pipermail/lldb-dev/2015-January/006233.html

In short, I know what the cause is, I have a fix locally, but I'm not sure if it's the best fix and the person who can really review my patch is out. Jim is thinking about it in the meantime, but we may have to wait.

As an aside, this only happens with global functions. Other types of functions work.

tedwoodward commented 9 years ago

r226017 doesn't fix my "p foo" issue.

Before applying it, I could set breakpoints on the line number, foo, and _Z3fooi: (lldb) breakpoint set -l 1 Breakpoint 4: where = infinite_win_Z3fooi + 12 at infinite.cpp:3, address = 0x000050cc (lldb) b foo Breakpoint 5: where = infinite_win_Z3fooi + 12 at infinite.cpp:3, address = 0x000050cc (lldb) b _Z3fooi Breakpoint 6: where = infinite_win`_Z3fooi + 12 at infinite.cpp:3, address = 0x000050cc (lldb)

After applying it I see the same behavior.

I did try the eFunctionNameTypeBase that Zachary mentioned on the lldb dev list, and it worked for my case, but had a side effect. It can resolve foo, but can't resolve _Z3fooi: (lldb) p foo (int (*)(int)) $0 = 0x000050c0 (lldb) p _Z3fooi error: '_Z3fooi' has unknown type; cast it to its declared type to use it error: 1 errors parsing expression

llvmbot commented 9 years ago

Is Mangled.cpp still broken on windows? I remember it was disabled due to cpp features not being available in msvc. There certainly used to be a problem with it, anyway.

Side note, but but this is now fixed in r226017.

d:\src\llvm\tools\lldb\test\lang\cpp\class_types>d:\src\llvm\build\ninja\bin\lldb.exe (lldb) file a.out Current executable set to 'a.out' (i386). (lldb) breakpoint set -l 121 Breakpoint 1: where = a.out`int D::foo(void) + 7 at main.cpp:121, address = 0x00417347 (lldb) quit

tedwoodward commented 9 years ago

The reason most of Mangled.cpp is disabled on Windows is because Visual Studio 2013 doesn't support some of the C++11 features in the code. MS put out a preview compiler in November of 2013 with support for them, but hasn't productized it yet. The features are in the Visual Studio 2015 preview, so should be in VS 2015 when it's released.

llvmbot commented 9 years ago

For some reason ClangExpressionDeclMap::FindExternalVisibleDecls has a weird piece of code that checks if this is a namespace lookup, and if it's not a namespace lookup treats the argument to the "p" command as a fully mangled name. I'm not sure why this works on other platforms, but on Windows the fully mangled name of foo is something like ?foo@@YAHH@Z, so it doesn't find it. I've tested a fix locally that makes it search for the base name (e.g. "foo") instead of the mangled name, and the fix appears to work, but waiting for confirmation from others that this is a reasonable fix before moving forward with it.

llvmbot commented 9 years ago

Yes, most of that file is still disabled on Windows. But I'm not sure that's the underlying cause. That appears to be nothing more than a fast path for demangling. I know we can still demangle sometimes, because "breakpoint set -n foo" works fine. So it's something having to do with going through the expression evaluator / AST Context. Maybe debug info isn't correctly hooked up through the AST Context. But that also doesn't seem quite right, because if I have this code:

void foo(int x) { return; }

And put a breakpoint on the return statement, then "print x" works, but "print foo" doesn't work. So there's something else at play. Not real familiar with the clang/llvm side, so it might take some work to figure out, but I'm still looking into it.

llvmbot commented 9 years ago

Is Mangled.cpp still broken on windows? I remember it was disabled due to cpp features not being available in msvc. There certainly used to be a problem with it, anyway.

llvmbot commented 9 years ago

Looks like I'm wrong and it actually is related to demangling. I talked to majnemer@ offline and it looks like it is actually an LLDB bug. I will look into it.

llvmbot commented 9 years ago

Reassigning to Rui. I thought I did that the first time, but I guess not.

llvmbot commented 9 years ago

So the problem is not that it can't demangle names. In fact, it can demangle names just fine. You can see it demangling main. And if you change the signature of main in expr_test.cpp to int main(int, char**) then you will get this from LLDB (note that I'm using a PE file here, generated with -fuse-ld=lld):

d:\testexe>d:\src\llvm\build\ninja\bin\lldb (lldb) file expr_test.exe Current executable set to 'expr_test.exe' (i386). (lldb) p main (int (*)(int, char **)) $0 = 0x00415020

But it still can't handle foo even LLD's debug info. The problem seems to be that LLD isn't building the symbol table correctly.

d:\testexe>d:\src\llvm\build\ninja\bin\llvm-readobj.exe --symbols expr_test.exe

File: expr_test.exe Format: COFF-i386 Arch: i386 AddressSize: 32bit Symbols [ ]

I don't know what I'm supposed to see here, but I would expect to see "main" and "foo" in that list in some form or another.

I guess it just happens to be finding main because it's the entry point, so we got lucky. This sounds like an issue for someone who works on LLD.

llvmbot commented 9 years ago

I suspect this coudl be due to the fact that it's an ELF file on Windows. At some point we'll want to make that work, but for now we're focusing on PE files on Windows.

Try building on Windows with clang by passing -fuse-ld=lld. Make sure you've built LLD as well before trying this. This should cause an executable to be produced which has DWARF. You can verify by running llvm-readobj --sections