zturner added a comment. > By the way, what do you think, how can we make LLDB support aligned stacks? > As far as I know, similar alignment problems are reproducible on non-Windows > too.
When you see VFRAME, you need to look in FPO data. As you might have guessed, VFRAME only occurs in X86. I compiled your sample program with a few modifications, and I'll show some output of `llvm-pdbutil` to illustrate how analyzing FPO data works (which would also give you some insight into how this will eventually be implemented without DIA) Here is the source code I compiled: int g_var = 2222; void __fastcall with_double(short arg_0, float arg_1) { char loc_0 = 'x'; double dvar = 0.5678; } void __fastcall with_float(short arg_0, float arg_1) { char loc_0 = 'x'; float fvar = 0.5678f; } int main(int argc, char *argv[]) { bool loc_0 = true; int loc_1 = 3333; with_double(1111, 0.1234); with_float(1111, 0.1234); return 0; } Then I ran this command. $ llvm-pdbutil.exe dump -symbols -modi=0 vlt.pdb Symbols ============================================================ Mod 0000 | `D:\src\llvmbuild\cl\Debug\x64\vlt.obj`: <snip> 52 | S_GPROC32 [size = 52] `with_double` parent = 0, end = 268, addr = 0001:0000, code size = 50 type = `0x1001 (void (short, float))`, debug start = 0, debug end = 0, flags = none 104 | S_FRAMEPROC [size = 32] size = 28, padding size = 0, offset to padding = 0 bytes of callee saved registers = 0, exception handler addr = 0000:0000 local fp reg = VFRAME, param fp reg = EBP flags = <snip> 236 | S_LOCAL [size = 16] `dvar` type=0x0041 (double), flags = none 252 | S_DEFRANGE_FRAMEPOINTER_REL [size = 16] offset = -16, range = [0001:0027,+23) gaps = 2 268 | S_END [size = 4] 272 | S_GPROC32 [size = 52] `with_float` parent = 0, end = 484, addr = 0001:0064, code size = 44 type = `0x1001 (void (short, float))`, debug start = 0, debug end = 0, flags = none 324 | S_FRAMEPROC [size = 32] size = 16, padding size = 0, offset to padding = 0 bytes of callee saved registers = 0, exception handler addr = 0000:0000 local fp reg = EBP, param fp reg = EBP flags = <snip> 452 | S_LOCAL [size = 16] `fvar` type=0x0040 (float), flags = none 468 | S_DEFRANGE_FRAMEPOINTER_REL [size = 16] offset = -8, range = [0001:0087,+21) gaps = 2 484 | S_END [size = 4] the `S_GPROC32` and `S_END` records form a pair, so all relevant data for this function is inside of the matching pair. Both `dvar` and `fvar` are of type `S_DEFRANGE_FRAMEPOINTER_REL`, which means they're relative to the framepointer. So we need to search for the `S_FRAMEPROC` record inside of this function. It's immediately after the `S_GPROC32` record in both cases. In the case of `with_float` we find that it says "local fp reg = EBP". This means it's easy, nothing special to do which is why it fixed the issue for you changing to float. On the other hand, as you noticed the other one says `VFRAME`. This means we need to go to the FPO data. But first we need to find the address of this function. The `S_GPROC32` of `with_double` says it's at address `0001:0000`. So we check the section headers to find out what is section 1. $ llvm-pdbutil.exe dump -section-headers vlt.pdb Section Headers ============================================================ SECTION HEADER #1 .text name 3E3FD virtual size 1000 virtual address 3E400 size of raw data 600 file pointer to raw data 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers 60000020 flags IMAGE_SCN_CNT_CODE IMAGE_SCN_MEM_EXECUTE IMAGE_SCN_MEM_READ So now we know section 1 starts at virtual address `0x1000`, and this particular function is at offset `0000`, so it is also at virtual address `0x1000`. The function has size 50, so we are looking for an FPO record in the range of `[0x1000,0x1032)` Now let's look at the FPO data in the PDB. Old FPO Data ============================================================ RVA | Code | Locals | Params | Prolog | Saved Regs | Use BP | Has SEH | Frame Type 0000131A | 20 | 0 | 0 | 0 | 0 | false | false | FPO 00001483 | 19 | 0 | 0 | 0 | 0 | false | false | FPO <snip> New FPO Data ============================================================ RVA | Code | Locals | Params | Stack | Prolog | Saved Regs | Has SEH | Has C++EH | Start | Program 00001000 | 50 | 0 | 4 | 0 | 9 | 0 | false | false | true | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = 00001001 | 49 | 0 | 4 | 0 | 8 | 4 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = 00001003 | 47 | 0 | 4 | 0 | 6 | 4 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = 00001006 | 44 | 0 | 4 | 0 | 3 | 4 | false | false | false | $T1 $ebp 4 + = $T0 $T1 4 - 8 @ = $eip $T1 ^ = $esp $T1 4 + = $ebp $T1 4 - ^ = 00001040 | 44 | 0 | 4 | 0 | 6 | 0 | false | false | true | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = Generally speaking you can ignore anything in Old FPO data, it's only used by MASM and very old compilers. And we can see that there are 4 FPO entries for this function. How do we know which one to choose? Well, the `S_DEFRANGE_FRAMEPOINTER_REL` told us that it is at range `[0001:0027,+23)`. Confusingly, it's decimal this time, so this is actually the virtual address range [0x101B,0x1032) That corresponds to this FPO entry. 00001006 | 44 | 0 | 4 | 0 | 3 | 4 | false | false | false | $T1 $ebp 4 + = $T0 $T1 4 - 8 @ = $eip $T1 ^ = $esp $T1 4 + = $ebp $T1 4 - ^ = The important thing here is this magical string at the end. These strings are little miniature "programs" which have to be "executed". They are separated by line on equals sign, so the program becomes: $T1 $ebp 4 + $T0 $T1 4 - 8 @ $eip $T1 ^ $esp $T1 4 + $ebp $T1 4 - ^ this is using RPN notation (e.g. 4+8 is written "4 8 +"), where + means plus, - means minus, @ means align, ^ means dereference. So we can interpret this as: $T1 = $ebp + 4 $T0 = alignTo($T1 - 4, 8) $eip = *($T1) $esp = $T1 + 4 $ebp = *($T1 - 4) `$T0` is the special "vframe" register. It is always `T0`. So if you want to find out what address `VFRAME` means, it is `alignTo($ebp + 4 - 4, 8) = alignTo($ebp, 8)`. And there's your answer. How to access this via DIA-like API? That part I do not know. I know you can access FPO data, for example through this interface <https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/idiaenumframedata?view=vs-2017> It seems the `IDiaFrameData` interface <https://docs.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/idiaframedata-get-program?view=vs-2017> provides some similar functionality here. Repository: rLLDB LLDB https://reviews.llvm.org/D53086 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits