| Index: src/processor/stackwalker_mips64_unittest.cc
|
| diff --git a/src/processor/stackwalker_mips_unittest.cc b/src/processor/stackwalker_mips64_unittest.cc
|
| similarity index 87%
|
| copy from src/processor/stackwalker_mips_unittest.cc
|
| copy to src/processor/stackwalker_mips64_unittest.cc
|
| index ed4be4f5b1618664de0c7f6b2381d0c41ccd0f68..531f546f640c20d59e221be68b365956a24c7016 100644
|
| --- a/src/processor/stackwalker_mips_unittest.cc
|
| +++ b/src/processor/stackwalker_mips64_unittest.cc
|
| @@ -27,9 +27,10 @@
|
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| -// Original author: Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
|
| +// Original author: Veljko Mihailovic <veljko.mihailovic@imgtec.com>
|
|
|
| -// stackwalker_mips_unittest.cc: Unit tests for StackwalkerMIPS class.
|
| +// stackwalker_mips64_unittest.cc: Unit tests for StackwalkerMIPS class for
|
| +// mips64 platforms.
|
|
|
| #include <string.h>
|
| #include <string>
|
| @@ -80,7 +81,7 @@ class StackwalkerMIPSFixture {
|
| system_info.os = "Linux";
|
| system_info.os_short = "linux";
|
| system_info.os_version = "Observant Opossum"; // Jealous Jellyfish
|
| - system_info.cpu = "mips";
|
| + system_info.cpu = "mips64";
|
| system_info.cpu_info = "";
|
|
|
| // Put distinctive values in the raw CPU context.
|
| @@ -100,7 +101,7 @@ class StackwalkerMIPSFixture {
|
| EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber());
|
|
|
| // Reset max_frames_scanned since it's static.
|
| - Stackwalker::set_max_frames_scanned(1024);
|
| + Stackwalker::set_max_frames_scanned(1024);
|
| }
|
|
|
| // Set the Breakpad symbol information that supplier should return for
|
| @@ -145,8 +146,10 @@ class StackwalkerMIPSFixture {
|
| class SanityCheck: public StackwalkerMIPSFixture, public Test { };
|
|
|
| TEST_F(SanityCheck, NoResolver) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| stack_section.start() = 0x80000000;
|
| - stack_section.D32(0).D32(0x0);
|
| + stack_section.D64(0).D64(0x0);
|
| RegionFromSection();
|
| raw_context.epc = 0x00400020;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
|
| @@ -173,8 +176,10 @@ TEST_F(SanityCheck, NoResolver) {
|
| class GetContextFrame: public StackwalkerMIPSFixture, public Test { };
|
|
|
| TEST_F(GetContextFrame, Simple) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| stack_section.start() = 0x80000000;
|
| - stack_section.D32(0).D32(0x0);
|
| + stack_section.D64(0).D64(0x0);
|
| RegionFromSection();
|
| raw_context.epc = 0x00400020;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
|
| @@ -199,6 +204,8 @@ TEST_F(GetContextFrame, Simple) {
|
| // The stackwalker should be able to produce the context frame even
|
| // without stack memory present.
|
| TEST_F(GetContextFrame, NoStackMemory) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| raw_context.epc = 0x00400020;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
|
|
|
| @@ -222,36 +229,38 @@ TEST_F(GetContextFrame, NoStackMemory) {
|
| class GetCallerFrame: public StackwalkerMIPSFixture, public Test { };
|
|
|
| TEST_F(GetCallerFrame, ScanWithoutSymbols) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| // When the stack walker resorts to scanning the stack,
|
| // only addresses located within loaded modules are
|
| // considered valid return addresses.
|
| // Force scanning through three frames to ensure that the
|
| // stack pointer is set properly in scan-recovered frames.
|
| stack_section.start() = 0x80000000;
|
| - uint32_t return_address1 = 0x00400100;
|
| - uint32_t return_address2 = 0x00400900;
|
| + uint64_t return_address1 = 0x00400100;
|
| + uint64_t return_address2 = 0x00400900;
|
| Label frame1_sp, frame2_sp;
|
| stack_section
|
| // frame 0
|
| - .Append(16, 0) // space
|
| + .Append(32, 0) // space
|
|
|
| - .D32(0x00490000) // junk that's not
|
| - .D32(0x00600000) // a return address
|
| + .D64(0x00490000) // junk that's not
|
| + .D64(0x00600000) // a return address
|
|
|
| - .D32(frame1_sp) // stack pointer
|
| - .D32(return_address1) // actual return address
|
| + .D64(frame1_sp) // stack pointer
|
| + .D64(return_address1) // actual return address
|
| // frame 1
|
| .Mark(&frame1_sp)
|
| - .Append(16, 0) // space
|
| + .Append(32, 0) // space
|
|
|
| - .D32(0xF0000000) // more junk
|
| - .D32(0x0000000D)
|
| + .D64(0xF0000000) // more junk
|
| + .D64(0x0000000D)
|
|
|
| - .D32(frame2_sp) // stack pointer
|
| - .D32(return_address2) // actual return address
|
| + .D64(frame2_sp) // stack pointer
|
| + .D64(return_address2) // actual return address
|
| // frame 2
|
| .Mark(&frame2_sp)
|
| - .Append(32, 0); // end of stack
|
| + .Append(64, 0); // end of stack
|
| RegionFromSection();
|
|
|
| raw_context.epc = 0x00405510;
|
| @@ -298,28 +307,30 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
|
| }
|
|
|
| TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| // During stack scanning, if a potential return address
|
| // is located within a loaded module that has symbols,
|
| // it is only considered a valid return address if it
|
| // lies within a function's bounds.
|
| stack_section.start() = 0x80000000;
|
| - uint32_t return_address = 0x00500200;
|
| + uint64_t return_address = 0x00500200;
|
| Label frame1_sp;
|
| stack_section
|
| // frame 0
|
| .Append(16, 0) // space
|
|
|
| - .D32(0x00490000) // junk that's not
|
| - .D32(0x00600000) // a return address
|
| -
|
| - .D32(0x00401000) // a couple of plausible addresses
|
| - .D32(0x0050F000) // that are not within functions
|
| + .D64(0x00490000) // junk that's not
|
| + .D64(0x00600000) // a return address
|
|
|
| - .D32(frame1_sp) // stack pointer
|
| - .D32(return_address) // actual return address
|
| + .D64(0x00401000) // a couple of plausible addresses
|
| + .D64(0x0050F000) // that are not within functions
|
| +
|
| + .D64(frame1_sp) // stack pointer
|
| + .D64(return_address) // actual return address
|
| // frame 1
|
| .Mark(&frame1_sp)
|
| - .Append(32, 0); // end of stack
|
| + .Append(64, 0); // end of stack
|
| RegionFromSection();
|
|
|
| raw_context.epc = 0x00400200;
|
| @@ -366,38 +377,40 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
|
| }
|
|
|
| TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| // If the stackwalker resorts to stack scanning, it will scan only
|
| // 1024 bytes of stack which correspondes to maximum size of stack frame.
|
| stack_section.start() = 0x80000000;
|
| - uint32_t return_address1 = 0x00500100;
|
| - uint32_t return_address2 = 0x00500900;
|
| + uint64_t return_address1 = 0x00500100;
|
| + uint64_t return_address2 = 0x00500900;
|
| Label frame1_sp, frame2_sp;
|
| stack_section
|
| // frame 0
|
| .Append(32, 0) // space
|
|
|
| - .D32(0x00490000) // junk that's not
|
| - .D32(0x00600000) // a return address
|
| + .D64(0x00490000) // junk that's not
|
| + .D64(0x00600000) // a return address
|
|
|
| .Append(96, 0) // more space
|
|
|
| - .D32(frame1_sp) // stack pointer
|
| - .D32(return_address1) // actual return address
|
| + .D64(frame1_sp) // stack pointer
|
| + .D64(return_address1) // actual return address
|
| // frame 1
|
| .Mark(&frame1_sp)
|
| .Append(128 * 4, 0) // space
|
|
|
| - .D32(0x00F00000) // more junk
|
| - .D32(0x0000000D)
|
| + .D64(0x00F00000) // more junk
|
| + .D64(0x0000000D)
|
|
|
| .Append(128 * 4, 0) // more space
|
|
|
| - .D32(frame2_sp) // stack pointer
|
| - .D32(return_address2) // actual return address
|
| + .D64(frame2_sp) // stack pointer
|
| + .D64(return_address2) // actual return address
|
| // (won't be found)
|
| // frame 2
|
| .Mark(&frame2_sp)
|
| - .Append(32, 0); // end of stack
|
| + .Append(64, 0); // end of stack
|
| RegionFromSection();
|
|
|
| raw_context.epc = 0x00405510;
|
| @@ -437,38 +450,40 @@ TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) {
|
| // Test that set_max_frames_scanned prevents using stack scanning
|
| // to find caller frames.
|
| TEST_F(GetCallerFrame, ScanningNotAllowed) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| // When the stack walker resorts to scanning the stack,
|
| // only fixed number of frames are allowed to be scanned out from stack
|
| stack_section.start() = 0x80000000;
|
| - uint32_t return_address1 = 0x00500100;
|
| - uint32_t return_address2 = 0x00500900;
|
| + uint64_t return_address1 = 0x00500100;
|
| + uint64_t return_address2 = 0x00500900;
|
| Label frame1_sp, frame2_sp;
|
| stack_section
|
| // frame 0
|
| .Append(32, 0) // space
|
|
|
| - .D32(0x00490000) // junk that's not
|
| - .D32(0x00600000) // a return address
|
| + .D64(0x00490000) // junk that's not
|
| + .D64(0x00600000) // a return address
|
|
|
| .Append(96, 0) // more space
|
|
|
| - .D32(frame1_sp) // stack pointer
|
| - .D32(return_address1) // actual return address
|
| + .D64(frame1_sp) // stack pointer
|
| + .D64(return_address1) // actual return address
|
| // frame 1
|
| .Mark(&frame1_sp)
|
| .Append(128 * 4, 0) // space
|
|
|
| - .D32(0x00F00000) // more junk
|
| - .D32(0x0000000D)
|
| + .D64(0x00F00000) // more junk
|
| + .D64(0x0000000D)
|
|
|
| .Append(128 * 4, 0) // more space
|
|
|
| - .D32(frame2_sp) // stack pointer
|
| - .D32(return_address2) // actual return address
|
| + .D64(frame2_sp) // stack pointer
|
| + .D64(return_address2) // actual return address
|
| // (won't be found)
|
| // frame 2
|
| .Mark(&frame2_sp)
|
| - .Append(32, 0); // end of stack
|
| + .Append(64, 0); // end of stack
|
| RegionFromSection();
|
|
|
| raw_context.epc = 0x00405510;
|
| @@ -479,7 +494,7 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) {
|
| StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
|
| &frame_symbolizer);
|
| Stackwalker::set_max_frames_scanned(0);
|
| -
|
| +
|
| vector<const CodeModule*> modules_without_symbols;
|
| vector<const CodeModule*> modules_with_corrupt_symbols;
|
| ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
|
| @@ -536,7 +551,7 @@ struct CFIFixture: public StackwalkerMIPSFixture {
|
| );
|
|
|
| // Provide some distinctive values for the caller's registers.
|
| - expected.epc = 0x00405508;
|
| + expected.epc = 0x00405500;
|
| expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0;
|
| expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1;
|
| expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2;
|
| @@ -564,6 +579,7 @@ struct CFIFixture: public StackwalkerMIPSFixture {
|
| StackFrameMIPS::CONTEXT_VALID_S7 |
|
| StackFrameMIPS::CONTEXT_VALID_SP |
|
| StackFrameMIPS::CONTEXT_VALID_FP |
|
| + StackFrameMIPS::CONTEXT_VALID_GP |
|
| StackFrameMIPS::CONTEXT_VALID_RA);
|
|
|
| // By default, context frames provide all registers, as normal.
|
| @@ -628,7 +644,7 @@ struct CFIFixture: public StackwalkerMIPSFixture {
|
| EXPECT_EQ(expected.epc, frame1->context.epc);
|
| EXPECT_EQ(expected.epc, frame1->instruction);
|
| EXPECT_EQ("epictetus", frame1->function_name);
|
| - EXPECT_EQ(0x00405000U, frame1->function_base);
|
| + EXPECT_EQ(0x00405000U, frame1->function_base);
|
| }
|
|
|
| // The values we expect to find for the caller's registers.
|
| @@ -646,12 +662,14 @@ class CFI: public CFIFixture, public Test { };
|
| // TODO(gordanac): add CFI tests
|
|
|
| TEST_F(CFI, At4004) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP];
|
| stack_section
|
| // frame0
|
| - .Append(24, 0) // space
|
| - .D32(frame1_sp) // stack pointer
|
| - .D32(0x00405510) // return address
|
| + .Append(16, 0) // space
|
| + .D64(frame1_sp) // stack pointer
|
| + .D64(0x00405510) // return address
|
| .Mark(&frame1_sp); // This effectively sets stack_section.start().
|
| raw_context.epc = 0x00404004;
|
| CheckWalk();
|
| @@ -660,10 +678,12 @@ TEST_F(CFI, At4004) {
|
| // Check that we reject rules that would cause the stack pointer to
|
| // move in the wrong direction.
|
| TEST_F(CFI, RejectBackwards) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| raw_context.epc = 0x40005000;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
|
| -
|
| +
|
| StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
|
| StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
|
| &frame_symbolizer);
|
| @@ -679,10 +699,12 @@ TEST_F(CFI, RejectBackwards) {
|
|
|
| // Check that we reject rules whose expressions' evaluation fails.
|
| TEST_F(CFI, RejectBadExpressions) {
|
| + raw_context.context_flags =
|
| + raw_context.context_flags | MD_CONTEXT_MIPS64_FULL;
|
| raw_context.epc = 0x00407000;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000;
|
| raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510;
|
| -
|
| +
|
| StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
|
| StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules,
|
| &frame_symbolizer);
|
|
|