[Lldb-commits] [lldb] r282683 - Add a unit test for an x86_64 assembly inspection of

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 28 21:01:44 PDT 2016


Author: jmolenda
Date: Wed Sep 28 23:01:43 2016
New Revision: 282683

URL: http://llvm.org/viewvc/llvm-project?rev=282683&view=rev
Log:
Add a unit test for an x86_64 assembly inspection of 
a large stack frame with lots of spilled registers.

While writing the i386 version of this test, it looks
like I found a bug in the 32-bit instruction profiler
code.  I may ned to fix the assembly inspection engine
before I can finish writing that test, so I'm only
committing the 64-bit one tonight.

<rdar://problem/28509178> 


Modified:
    lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp

Modified: lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp?rev=282683&r1=282682&r2=282683&view=diff
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp (original)
+++ lldb/trunk/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp Wed Sep 28 23:01:43 2016
@@ -43,27 +43,28 @@ protected:
 // names should match the constants below.  These will be the eRegisterKindLLDB
 // register numbers.
 
-const char *x86_64_reg_names[] = {"rax", "rcx", "rdx", "rsp", "rbp", "rsi",
-                                  "rdi", "r8",  "r9",  "r10", "r11", "r12",
-                                  "r13", "r14", "r15", "rip"};
+const char *x86_64_reg_names[] = {"rax", "rbx", "rcx", "rdx", "rsp", "rbp",
+                                  "rsi", "rdi", "r8",  "r9",  "r10", "r11",
+                                  "r12", "r13", "r14", "r15", "rip"};
 
 enum x86_64_regs {
   k_rax = 0,
-  k_rcx = 1,
-  k_rdx = 2,
-  k_rsp = 3,
-  k_rbp = 4,
-  k_rsi = 5,
-  k_rdi = 6,
-  k_r8 = 7,
-  k_r9 = 8,
-  k_r10 = 9,
-  k_r11 = 10,
-  k_r12 = 11,
-  k_r13 = 12,
-  k_r14 = 13,
-  k_r15 = 14,
-  k_rip = 15
+  k_rbx = 1,
+  k_rcx = 2,
+  k_rdx = 3,
+  k_rsp = 4,
+  k_rbp = 5,
+  k_rsi = 6,
+  k_rdi = 7,
+  k_r8 = 8,
+  k_r9 = 9,
+  k_r10 = 10,
+  k_r11 = 11,
+  k_r12 = 12,
+  k_r13 = 13,
+  k_r14 = 14,
+  k_r15 = 15,
+  k_rip = 16
 };
 
 // names should match the constants below.  These will be the eRegisterKindLLDB
@@ -133,6 +134,7 @@ std::unique_ptr<x86AssemblyInspectionEng
 TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) {
   std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
 
+  // 'int main() { }' compiled for x86_64-apple-macosx with clang
   uint8_t data[] = {
       0x55,             // offset 0 -- pushq %rbp
       0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp
@@ -208,6 +210,7 @@ TEST_F(Testx86AssemblyInspectionEngine,
 TEST_F(Testx86AssemblyInspectionEngine, TestSimple32bitFrameFunction) {
   std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
 
+  // 'int main() { }' compiled for i386-apple-macosx with clang
   uint8_t data[] = {
       0x55,       // offset 0 -- pushl %ebp
       0x89, 0xe5, // offset 1 -- movl %esp, %ebp
@@ -279,3 +282,159 @@ TEST_F(Testx86AssemblyInspectionEngine,
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_TRUE(regloc.GetOffset() == -4);
 }
+
+TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessBigStackFrame) {
+  std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
+
+  // this source file:
+  //
+  // #include <stdio.h>
+  // int main (int argc, char **argv)
+  // {
+  //
+  //     const int arrsize = 60;
+  //     int buf[arrsize * arrsize];
+  //     int accum = argc;
+  //     for (int i = 0; i < arrsize; i++)
+  //         for (int j = 0; j < arrsize; j++)
+  //         {
+  //             if (i > 0 && j > 0)
+  //             {
+  //                 int n = buf[(i-1) * (j-1)] * 2;
+  //                 int m = buf[(i-1) * (j-1)] / 2;
+  //                 int j = buf[(i-1) * (j-1)] + 2;
+  //                 int k = buf[(i-1) * (j-1)] - 2;
+  //                 printf ("%d ", n + m + j + k);
+  //                 buf[(i-1) * (j-1)] += n - m + j - k;
+  //             }
+  //             buf[i*j] = accum++;
+  //         }
+  //
+  //     return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize *
+  //     arrsize) - 3]);
+  // }
+  //
+  // compiled 'clang -fomit-frame-pointer -Os' for x86_64-apple-macosx
+
+  uint8_t data[] = {
+      0x55,       // offset 0  -- pushq %rbp
+      0x41, 0x57, // offset 1  -- pushq %r15
+      0x41, 0x56, // offset 3  -- pushq %r14
+      0x41, 0x55, // offset 5  -- pushq %r13
+      0x41, 0x54, // offset 7  -- pushq %r12
+      0x53,       // offset 9  -- pushq %rbx
+      0x48, 0x81, 0xec, 0x68, 0x38, 0x00,
+      0x00, // offset 10 -- subq $0x3868, %rsp
+
+      // ....
+
+      0x48, 0x81, 0xc4, 0x68, 0x38, 0x00,
+      0x00,                        // offset 17 -- addq $0x3868, %rsp
+      0x5b,                        // offset 24 -- popq %rbx
+      0x41, 0x5c,                  // offset 25 -- popq %r12
+      0x41, 0x5d,                  // offset 27 -- popq %r13
+      0x41, 0x5e,                  // offset 29 -- popq %r14
+      0x41, 0x5f,                  // offset 31 -- popq %r15
+      0x5d,                        // offset 33 -- popq %rbp
+      0xc3,                        // offset 34 -- retq
+      0xe8, 0x00, 0x00, 0x00, 0x00 // offset 35 -- callq whatever
+  };
+
+  AddressRange sample_range(0x1000, sizeof(data));
+
+  UnwindPlan unwind_plan(eRegisterKindLLDB);
+  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+      data, sizeof(data), sample_range, unwind_plan));
+
+  // Unwind rules should look like
+  // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
+  // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
+  // 3: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8]
+  // 5: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24]
+  // rip=[CFA-8
+  // 7: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32]
+  // r15=[CFA-24] rip=[CFA-8]
+  // 9: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40]
+  // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
+  // 10: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
+  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
+  // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
+  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
+
+  // 24: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
+  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
+  // 25: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40]
+  // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
+  // 27: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32]
+  // r15=[CFA-24] rip=[CFA-8]
+  // 29: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24]
+  // rip=[CFA-8]
+  // 31: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8]
+  // 33: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
+  // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
+
+  UnwindPlan::Row::RegisterLocation regloc;
+
+  // grab the Row for when the prologue has finished executing:
+  // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48]
+  // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8]
+
+  UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(17);
+
+  EXPECT_TRUE(row_sp->GetOffset() == 17);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 14496);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -8);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -16);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -24);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -32);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -40);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -48);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -56);
+
+  // grab the Row for when the epiloge has finished executing:
+  // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
+
+  row_sp = unwind_plan.GetRowForFunctionOffset(34);
+
+  EXPECT_TRUE(row_sp->GetOffset() == 34);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 8);
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_TRUE(regloc.GetOffset() == -8);
+
+  // these could be set to IsSame and be valid -- meaning that the
+  // register value is the same as the caller's -- but I'd rather
+  // they not be mentioned at all.
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc) == false);
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc) == false);
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc) == false);
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc) == false);
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc) == false);
+  EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc) == false);
+}




More information about the lldb-commits mailing list