Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COFF Debug info shows variable at the wrong lexical scope. #43205

Open
CarlosAlbertoEnciso opened this issue Oct 31, 2019 · 8 comments
Open

COFF Debug info shows variable at the wrong lexical scope. #43205

CarlosAlbertoEnciso opened this issue Oct 31, 2019 · 8 comments
Labels
bugzilla Issues migrated from bugzilla debuginfo

Comments

@CarlosAlbertoEnciso
Copy link
Member

CarlosAlbertoEnciso commented Oct 31, 2019

Bugzilla Link 43860
Version trunk
OS All
CC @dwblaikie,@gregbedwell,@JDevlieghere,@jmorse,@walkerkd,@pogo59,@rnk

Extended Description

Given the following test case:

//------------------------------------------------------------
// inlined.cpp
//------------------------------------------------------------

int inlineFunction(int Param) __attribute__((always_inline));
int inlineFunction(int Param) {
  int Var_1 = Param;
  {
    int Var_2 = Param + Var_1;
    Var_1 = Var_2;
  }
  return Var_1;
}

int testInlined(int Param_1, int Param_2) {
  int A = Param_1;
  A += inlineFunction(Param_2);
  return A;
}

//------------------------------------------------------------

Using the following command line options to generate debug info
(DWARF) and (COFF):

clang -c -g -O0 inlined.cpp -o inlined-dwarf.o
clang -c -g -O0 inlined.cpp -o inlined-coff.o -gcodeview --target=x86_64-windows

Looking at the output generated by llvm-dwarfdump and llvm-readobj,
the COFF debug info shows the variable 'Var_2' at the same lexical
scope as the variable 'Var_1' in the 'testInlined' as results of the
function 'inlineFunction' being inlined.

llvm-dwarfdump --debug-info inlined-dwarf.o

@CarlosAlbertoEnciso
Copy link
Member Author

This is the reduced output generated by llvm-dwarfdump:


inlined-dwarf.o: file format ELF64-x86-64

.debug_info contents:

DW_TAG_compile_unit

DW_TAG_subprogram
DW_TAG_formal_parameter
DW_AT_abstract_origin (0x00000074 "Param")
DW_TAG_variable
DW_AT_abstract_origin (0x0000007f "Var_1")
DW_TAG_lexical_block
DW_TAG_variable
DW_AT_abstract_origin (0x0000008b "Var_2")

DW_TAG_subprogram
DW_AT_name ("InlineFunction")
DW_TAG_formal_parameter
DW_AT_name ("Param")
DW_TAG_variable
DW_AT_name ("Var_1")
DW_TAG_lexical_block
DW_TAG_variable
DW_AT_name ("Var_2")

DW_TAG_subprogram
DW_AT_name ("testInlined")
DW_TAG_formal_parameter
DW_AT_name ("Param_1")
DW_TAG_formal_parameter
DW_AT_name ("Param_2")
DW_TAG_variable
DW_AT_name ("A")

DW_TAG_inlined_subroutine
  DW_TAG_formal_parameter
    DW_AT_abstract_origin	(0x00000074 "Param")
  DW_TAG_variable
    DW_AT_abstract_origin	(0x0000007f "Var_1") <------ (*)
  DW_TAG_lexical_block
    DW_TAG_variable
      DW_AT_abstract_origin	(0x0000008b "Var_2") <------ (*)

(*) Var_1 and Var_2 are at different lexical scopes.

@CarlosAlbertoEnciso
Copy link
Member Author

This is the reduced output generated by llvm-readobj:

outline copy (inlineFunction)

Subsection [
...
GlobalProcIdSym {
Kind: S_GPROC32_ID (0x1147)
...
DisplayName: inlineFunction
LinkageName: ?inlineFunction@@yahh@Z
}
FrameProcSym {
Kind: S_FRAMEPROC (0x1012)
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Param
}
DefRangeFramePointerRelSym {
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Var_1 <-- Var_1 ()
}
DefRangeFramePointerRelSym {
Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
...
}
BlockSym {
Kind: S_BLOCK32 (0x1103) <-- Lexical scope
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Var_2 <-- Var_2(
)
}
DefRangeFramePointerRelSym {
Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
...
}
ScopeEndSym {
Kind: S_END (0x6) <-- End lexical scope
}
ProcEnd {
Kind: S_PROC_ID_END (0x114F)
}
]

(*) Var_1 and Var_2 at different lexical scopes.

@CarlosAlbertoEnciso
Copy link
Member Author

This is the reduced output generated by llvm-readobj:

caller (testInlined)

Subsection [
...
GlobalProcIdSym {
Kind: S_GPROC32_ID (0x1147)
...
DisplayName: testInlined
LinkageName: ?testInlined@@yahhh@Z
}
FrameProcSym {
Kind: S_FRAMEPROC (0x1012)
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Param_1
}
DefRangeFramePointerRelSym {
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Param_2
}
DefRangeFramePointerRelSym {
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: A
}
DefRangeFramePointerRelSym {
Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
...
}
InlineSiteSym {
Kind: S_INLINESITE (0x114D) <-- Lexical scope for inlined function
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Param
}
DefRangeFramePointerRelSym {
Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Var_1 <-- Var_1 ()
}
DefRangeFramePointerRelSym {
Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
...
}
LocalSym {
Kind: S_LOCAL (0x113E)
...
VarName: Var_2 <-- Var_2 (
)
}
DefRangeFramePointerRelSym {
Kind: S_DEFRANGE_FRAMEPOINTER_REL (0x1142)
...
}
InlineSiteEnd {
Kind: S_INLINESITE_END (0x114E) <-- End lexical scope inlined function
}
ProcEnd {
Kind: S_PROC_ID_END (0x114F)
}
]
]

(*) Var_1 and Var_2 at the same lexical scope.

@CarlosAlbertoEnciso
Copy link
Member Author

This is the ouput from llvm-diva (tool under development).

llvm-diva --print=scopes,symbols,types inlined-dwarf.o inlined-coff.o --attribute=level,format

Logical View:
[000] {File} 'inlined-dwarf.o' -> ELF64-x86-64

[001] {CompileUnit} 'inlined.cpp'
[002] 2 {Function} inlined 'inlineFunction' -> 'int'
[003] {Block}
[004] 5 {Variable} 'Var_2' -> 'int'
[003] 2 {Parameter} 'Param' -> 'int'
[003] 3 {Variable} 'Var_1' -> 'int'
[002] 2 {Function} extern inlined 'inlineFunction' -> 'int'
[003] {Block}
[004] 5 {Variable} 'Var_2' -> 'int'
[003] 2 {Parameter} 'Param' -> 'int'
[003] 3 {Variable} 'Var_1' -> 'int'
[002] 11 {Function} extern not_inlined 'testInlined' -> 'int'
[003] 13 {InlinedFunction} inlined 'inlineFunction' -> 'int'
[004] {Block}
[005] 5 {Variable} 'Var_2' -> 'int' <-- Var_2 ()
[004] 2 {Parameter} 'Param' -> 'int'
[004] 3 {Variable} 'Var_1' -> 'int' <-- Var_1 (
)
[003] 11 {Parameter} 'Param_1' -> 'int'
[003] 11 {Parameter} 'Param_2' -> 'int'
[003] 12 {Variable} 'A' -> 'int'

Logical View:
[000] {File} 'inlined-coff.o' -> COFF-x86-64

[001] {CompileUnit} 'inlined.cpp'
[002] {Function} not_inlined 'inlineFunction' -> 'int'
[003] {Block}
[004] {Variable} 'Var_2' -> 'int'
[003] {Parameter} 'Param' -> 'int'
[003] {Variable} 'Var_1' -> 'int'
[002] {Function} not_inlined 'testInlined' -> 'int'
[003] {Variable} 'A' -> 'int'
[003] {Parameter} 'Param_1' -> 'int'
[003] {Parameter} 'Param_2' -> 'int'
[003] {InlinedFunction} inlined 'inlineFunction' -> 'int'
[004] {Parameter} 'Param' -> 'int'
[004] {Variable} 'Var_1' -> 'int' <-- () Var_1
[004] {Variable} 'Var_2' -> 'int' <-- (
) Var_2

The logical view for the DWARF debug info, shows 'Var_1' and 'Var_2'
at different lexical scopes:

() Var_1, scope [004]
(
) Var_2, scope [005]

The logical view for the COFF debug-info, shows 'Var_1' and 'Var_2'
at the same lexical scopes.

() Var_1, scope [004]
(
) Var_2, scope [004]

@rnk
Copy link
Collaborator

rnk commented Nov 1, 2019

Would it be correct to say that the bug is: lexical scopes disappear from codeview after inlining?

There are some conditions under which lexical scopes may be ignored:
https://github.com/llvm/llvm-project/blob/master/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp#L2754

Perhaps this example hits one of those cases.

@CarlosAlbertoEnciso
Copy link
Member Author

There are some conditions under which lexical scopes may be ignored:
https://github.com/llvm/llvm-project/blob/master/llvm/lib/CodeGen/AsmPrinter/
CodeViewDebug.cpp#L2754

Thanks very much for the link.

For the given case,

https://github.com/llvm/llvm-project/blob/master/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp#L2769

const DILexicalBlock *DILB = dyn_cast(Scope.getScopeNode());

DILB is null.

From my understanding, the lexical blocks created due to the inlining
are not treated as standard ones and they have been ignored.

@CarlosAlbertoEnciso
Copy link
Member Author

Would it be correct to say that the bug is: lexical scopes disappear from
codeview after inlining?

Yes. That would be a better description for the bug.

@CarlosAlbertoEnciso
Copy link
Member Author

I am just starting to get familiar with the CodeView format and the
main question I have now is: Why the lexical scopes created during
inlining are treated in a different way as in DWARF?

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla debuginfo
Projects
None yet
Development

No branches or pull requests

2 participants