Function names in backtrace from python

Hi All,

What is the expected behavior of SBFrame::GetFunctionName() in case of an inlined function (or possibly more nested inlined function)? Should it return the name of the deepest inlined function, the name of the outer most (non inlined) function or some combination of these two?

If I understand correctly, currently it returns the name of the deepest inlined function for the actual frame but TestNoreturnUnwind expect the name of the outer most (non inlined) function.

Thanks,
Tamas

The docs say:

(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.

help (lldb.SBFrame.GetFunctionName)

Help on method GetFunctionName in module lldb:

GetFunctionName(self) unbound lldb.SBFrame method
    GetFunctionName(self) -> str
    
    Get the appropriate function name for this frame. Inlined functions in
    LLDB are represented by Blocks that have inlined function information, so
    just looking at the SBFunction or SBSymbol for a frame isn't enough.
    This function will return the appropriate function, symbol or inlined
    function name for the frame.
    
    This function returns:
    - the name of the inlined function (if there is one)
    - the name of the concrete function (if there is one)
    - the name of the symbol (if there is one)
    - NULL
    
    See also IsInlined().

This is actually a little funny because usually the "Function" for a frame is the "real" function that contains all the currently active inlining, but it looks like this API is supposed to get you the inlining that this frame represents. That seems naively intuitive but a little bit counter to how we talk about this elsewhere.

Jim

No, each SBFrame represents and exact scope for the current stack frame. Lets say you have the following code in "main.c":

     1 static inline inlined1()
     2 {
     3 if (...)
     4 {
     5 puts("inlined1");
     6 }
     7 }
     8
     9 static inline inlined2()
    10 {
    11 if (...)
    12 {
    13 puts("inlined2");
    14 inlined1();
    15 }
    16 }
    17
    18 static inline inlined3()
    19 {
    20 if (...)
    21 {
    22 puts("inlined3");
    23 inlined2()
    24 }
    25 }
    26
    27 int main()
    28 {
    29 if (...)
    30 {
    31 inlined3();
    32 }
    33 }

If you set a breakpoint at on line 5 and run. If everything got inlined, you will have 4 frames:

frame = thread.GetFrameAtIndex(0);
frame.GetBlock() would return the the lexical from line 4's if statement
frame.GetFunctionName() would return "inlined1"
frame.GetFunction() would return "int main()"
frame.GetLineEntry() would return main.c:5
frame.GetFrameBlock() would return the SBBlock that represents the lexical block from line 2 for the inlined1 inlined function

frame = thread.GetFrameAtIndex(1);
frame.GetBlock() would return the the lexical from line 12's if statement
frame.GetFunctionName() would return "inlined2"
frame.GetFunction() would return "int main()"
frame.GetLineEntry() would return main.c:14
frame.GetFrameBlock() would return the SBBlock that represents the lexical block from line 10 for the inlined2 inlined function

frame = thread.GetFrameAtIndex(2);
frame.GetBlock() would return the the lexical from line 20's if statement
frame.GetFunctionName() would return "inlined3"
frame.GetFunction() would return "int main()"
frame.GetLineEntry() would return main.c:23
frame.GetFrameBlock() would return the SBBlock that represents the lexical block from line 19 for the inlined2 inlined function

frame = thread.GetFrameAtIndex(3);
frame.GetBlock() would return the the lexical from line 30's if statement
frame.GetFunctionName() would return "main"
frame.GetFunction() would return "int main()"
frame.GetLineEntry() would return main.c:31
frame.GetFrameBlock() would return the SBBlock that represents the lexical block from line 28 for the main function

So the SBFrame::GetFunctionName() will return the name of the first inlined function block above the SBFrame's block (frame.GetBlock()) if there is one, else it will return the name of the function.

So the important distinction is that a SBFrame doesn't always represent the deepest block since with inlined stack frames we might have multiple inlined functions in the same SBFunction. Each SBFrame would be represented by a separate object with a different block scope.

Does that make sense?

Greg

Thanks for the clarification. It makes sense.