[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