LLD PDB Lines zero number issue

Hello Rui,

We meet an LLD PDB issue that if we link assembly code with C code and set >= -O1 level optimization in LTO, the executable’s PDB will contain wrong zero Lines for the assembly code in DEBUG_S_LINES subsection, and then our COFF source debuggers will fail to do the source-level debug on the executable. This issue is same in both Linux and Windows, and I figure out a simple case in Linux to reproduce this issue as below. Please help to give us some advices on how to solve the zero Lines issue.

$ cat main.c

void assembly_fun();

int main()

{

int Index1;

for (Index1 = 0; Index1 == 0; assembly_fun(), Index1++){

assembly_fun();

}

assembly_fun();

}

$ cat assembly.nasm

DEFAULT REL

SECTION .text

global assembly_fun

assembly_fun:

ret

$ cat makefile_clanglto_Oz

CC_FLAGS= -g -m64 -mcmodel=small -target x86_64-unknown-windows -gcodeview -flto -Oz

CC = /home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/clang

DLINK_FLAGS = /Machine:X64 /DLL /ENTRY:main /DEBUG:GHASH /lldmap

DLINK = /home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/lld-link

SLINK = /home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/llvm-lib

build:

“$(CC)” $(CC_FLAGS) -c -o main.obj main.c

“nasm” -f win64 -o assembly.obj assembly.nasm

“$(SLINK)” /OUT:main.lib main.obj

“$(SLINK)” /OUT:assembly.lib assembly.obj

“$(DLINK)” /OUT:main.dll $(DLINK_FLAGS) main.lib assembly.lib

clean:

rm -f *.obj *.lib *.pdb *.dll *.map

$ make -f makefile_clanglto_Oz

$ llvm-pdbutil dump -l main.pdb

Lines

lld_PDB_issue_4_rui.zip (2.13 KB)

+rnk who works on COFF debugging things.

My understanding is that this has nothing to do with the linker - but is a function of LLVM optimizations creating line zero debug locations. I believe rnk & folks have disabled line zero emission for CodeView debug info in some manner - perhaps that needs a flag? or Steven hasn’t got a release with that change in it?

I think I've run into that with dwarf as well, and there AFAIK it can be gotten rid of by adding "-mllvm -use-unknown-locations=Disable".

// Martin

Hi Martin,

I tried your suggestion of adding “-mllvm -use-unknown-locations=Disable” in the clang CC flag to build test case in my previous email, but it looks still not work in my side with llvm 9.0.0. Could you give me some more advices? Do I need to use the master LLVM instead of the 9.0.0?

$ make -f makefile_clanglto_Oz

“/home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/clang” -g -m64 -mcmodel=small -target x86_64-unknown-windows -gcodeview -mllvm -use-unknown-locations=Disable -flto -Oz -c -o main.obj main.c

“nasm” -f win64 -o assembly.obj assembly.nasm

“/home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/llvm-lib” /OUT:main.lib main.obj

“/home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/llvm-lib” /OUT:assembly.lib assembly.obj

“/home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/lld-link” /OUT:main.dll /Machine:X64 /DLL /ENTRY:main /DEBUG:GHASH /lldmap main.lib assembly.lib

$ /home/jshi19/llvm/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/llvm-pdbutil dump -l main.pdb

Lines

I checked the LLVM master code and find that the “-use-unknown-locations” option and its related logic is only supported for Dwarf debug info as below. These codes are missing in the Codeview side. It looks the “-use-unknown-locations” option logic is not complex, could we port the code logic into llvm\lib\CodeGen\AsmPrinter\CodeViewDebug.cpp as well? I’ve submitted a BZ for this requirment: https://bugs.llvm.org/show_bug.cgi?id=44522

llvm-project\llvm\lib\CodeGen\AsmPrinter\DwarfDebug.cpp :

static cl::opt UnknownLocations(

“use-unknown-locations”, cl::Hidden,

cl::desc(“Make an absence of debug location information explicit.”),

cl::values(clEnumVal(Default, “At top of block or after label”),

clEnumVal(Enable, “In all cases”), clEnumVal(Disable, “Never”)),

cl::init(Default));

… …

// If user said Don’t Do That, don’t do that.

if (UnknownLocations == Disable)

return;

Could you try putting together a prototype patch and testing it locally to see if it solves your problem?

This looks like it was fixed in October:
http://github.com/llvm/llvm-project/commit/9d8f0b3519c4e9e4e2a3d3b19ea0caf9ef3f85ce

See https://llvm.org/PR43530

OK, maybe I was wrong and the “-use-unknown-locations” option is not the issue root cause.

I’m not familiar with the LLVM codebase and I appreciate any suggestion on how to debug this issue. I’d like to know is it a clang issue or a lld issue? Is there a tool which can dump the obj file debug location info?

Let me simplify the previous test case to reproduce this issue. All what you need is just a C function to invoke an empty assembly function as below.

Are you using clang 9? If so, it doesn’t have the fix. When I do what you are doing locally, I see this line table in the object file:
$ llvm-pdbutil dump -l main.obj
Lines

Are you using clang 9? If so, it doesn’t have the fix.

This will be fixed in the next release.

OK, got it. Thank you!

Thanks

Steven