| OLD | NEW |
| 1 // Copyright (c) 2013, Google Inc. | 1 // Copyright (c) 2013, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| 11 // copyright notice, this list of conditions and the following disclaimer | 11 // copyright notice, this list of conditions and the following disclaimer |
| 12 // in the documentation and/or other materials provided with the | 12 // in the documentation and/or other materials provided with the |
| 13 // distribution. | 13 // distribution. |
| 14 // * Neither the name of Google Inc. nor the names of its | 14 // * Neither the name of Google Inc. nor the names of its |
| 15 // contributors may be used to endorse or promote products derived from | 15 // contributors may be used to endorse or promote products derived from |
| 16 // this software without specific prior written permission. | 16 // this software without specific prior written permission. |
| 17 // | 17 // |
| 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 // Original author: Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com> | 30 // Original author: Veljko Mihailovic <veljko.mihailovic@imgtec.com> |
| 31 | 31 |
| 32 // stackwalker_mips_unittest.cc: Unit tests for StackwalkerMIPS class. | 32 // stackwalker_mips64_unittest.cc: Unit tests for StackwalkerMIPS class for |
| 33 // mips64 platforms. |
| 33 | 34 |
| 34 #include <string.h> | 35 #include <string.h> |
| 35 #include <string> | 36 #include <string> |
| 36 #include <vector> | 37 #include <vector> |
| 37 | 38 |
| 38 #include "breakpad_googletest_includes.h" | 39 #include "breakpad_googletest_includes.h" |
| 39 #include "common/test_assembler.h" | 40 #include "common/test_assembler.h" |
| 40 #include "common/using_std_string.h" | 41 #include "common/using_std_string.h" |
| 41 #include "google_breakpad/common/minidump_format.h" | 42 #include "google_breakpad/common/minidump_format.h" |
| 42 #include "google_breakpad/processor/basic_source_line_resolver.h" | 43 #include "google_breakpad/processor/basic_source_line_resolver.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 73 StackwalkerMIPSFixture() | 74 StackwalkerMIPSFixture() |
| 74 : stack_section(kLittleEndian), | 75 : stack_section(kLittleEndian), |
| 75 // Give the two modules reasonable standard locations and names | 76 // Give the two modules reasonable standard locations and names |
| 76 // for tests to play with. | 77 // for tests to play with. |
| 77 module1(0x00400000, 0x10000, "module1", "version1"), | 78 module1(0x00400000, 0x10000, "module1", "version1"), |
| 78 module2(0x00500000, 0x10000, "module2", "version2") { | 79 module2(0x00500000, 0x10000, "module2", "version2") { |
| 79 // Identify the system as a Linux system. | 80 // Identify the system as a Linux system. |
| 80 system_info.os = "Linux"; | 81 system_info.os = "Linux"; |
| 81 system_info.os_short = "linux"; | 82 system_info.os_short = "linux"; |
| 82 system_info.os_version = "Observant Opossum"; // Jealous Jellyfish | 83 system_info.os_version = "Observant Opossum"; // Jealous Jellyfish |
| 83 system_info.cpu = "mips"; | 84 system_info.cpu = "mips64"; |
| 84 system_info.cpu_info = ""; | 85 system_info.cpu_info = ""; |
| 85 | 86 |
| 86 // Put distinctive values in the raw CPU context. | 87 // Put distinctive values in the raw CPU context. |
| 87 BrandContext(&raw_context); | 88 BrandContext(&raw_context); |
| 88 | 89 |
| 89 // Create some modules with some stock debugging information. | 90 // Create some modules with some stock debugging information. |
| 90 modules.Add(&module1); | 91 modules.Add(&module1); |
| 91 modules.Add(&module2); | 92 modules.Add(&module2); |
| 92 | 93 |
| 93 // By default, none of the modules have symbol info; call | 94 // By default, none of the modules have symbol info; call |
| 94 // SetModuleSymbols to override this. | 95 // SetModuleSymbols to override this. |
| 95 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) | 96 EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) |
| 96 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); | 97 .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); |
| 97 | 98 |
| 98 // Avoid GMOCK WARNING "Uninteresting mock function call - returning | 99 // Avoid GMOCK WARNING "Uninteresting mock function call - returning |
| 99 // directly" for FreeSymbolData(). | 100 // directly" for FreeSymbolData(). |
| 100 EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); | 101 EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); |
| 101 | 102 |
| 102 // Reset max_frames_scanned since it's static. | 103 // Reset max_frames_scanned since it's static. |
| 103 Stackwalker::set_max_frames_scanned(1024); | 104 Stackwalker::set_max_frames_scanned(1024); |
| 104 } | 105 } |
| 105 | 106 |
| 106 // Set the Breakpad symbol information that supplier should return for | 107 // Set the Breakpad symbol information that supplier should return for |
| 107 // MODULE to INFO. | 108 // MODULE to INFO. |
| 108 void SetModuleSymbols(MockCodeModule* module, const string& info) { | 109 void SetModuleSymbols(MockCodeModule* module, const string& info) { |
| 109 size_t buffer_size; | 110 size_t buffer_size; |
| 110 char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); | 111 char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); |
| 111 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) | 112 EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) |
| 112 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), | 113 .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), |
| 113 SetArgumentPointee<4>(buffer_size), | 114 SetArgumentPointee<4>(buffer_size), |
| (...skipping 24 matching lines...) Expand all Loading... |
| 138 MockCodeModules modules; | 139 MockCodeModules modules; |
| 139 MockSymbolSupplier supplier; | 140 MockSymbolSupplier supplier; |
| 140 BasicSourceLineResolver resolver; | 141 BasicSourceLineResolver resolver; |
| 141 CallStack call_stack; | 142 CallStack call_stack; |
| 142 const vector<StackFrame*>* frames; | 143 const vector<StackFrame*>* frames; |
| 143 }; | 144 }; |
| 144 | 145 |
| 145 class SanityCheck: public StackwalkerMIPSFixture, public Test { }; | 146 class SanityCheck: public StackwalkerMIPSFixture, public Test { }; |
| 146 | 147 |
| 147 TEST_F(SanityCheck, NoResolver) { | 148 TEST_F(SanityCheck, NoResolver) { |
| 149 raw_context.context_flags = |
| 150 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 148 stack_section.start() = 0x80000000; | 151 stack_section.start() = 0x80000000; |
| 149 stack_section.D32(0).D32(0x0); | 152 stack_section.D64(0).D64(0x0); |
| 150 RegionFromSection(); | 153 RegionFromSection(); |
| 151 raw_context.epc = 0x00400020; | 154 raw_context.epc = 0x00400020; |
| 152 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; | 155 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; |
| 153 | 156 |
| 154 StackFrameSymbolizer frame_symbolizer(NULL, NULL); | 157 StackFrameSymbolizer frame_symbolizer(NULL, NULL); |
| 155 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 158 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 156 &frame_symbolizer); | 159 &frame_symbolizer); |
| 157 // This should succeed, even without a resolver or supplier. | 160 // This should succeed, even without a resolver or supplier. |
| 158 vector<const CodeModule*> modules_without_symbols; | 161 vector<const CodeModule*> modules_without_symbols; |
| 159 vector<const CodeModule*> modules_with_corrupt_symbols; | 162 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 160 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 163 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 161 &modules_with_corrupt_symbols)); | 164 &modules_with_corrupt_symbols)); |
| 162 ASSERT_EQ(1U, modules_without_symbols.size()); | 165 ASSERT_EQ(1U, modules_without_symbols.size()); |
| 163 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 166 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
| 164 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 167 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 165 frames = call_stack.frames(); | 168 frames = call_stack.frames(); |
| 166 ASSERT_EQ(1U, frames->size()); | 169 ASSERT_EQ(1U, frames->size()); |
| 167 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); | 170 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); |
| 168 // Check that the values from the original raw context made it | 171 // Check that the values from the original raw context made it |
| 169 // through to the context in the stack frame. | 172 // through to the context in the stack frame. |
| 170 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); | 173 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); |
| 171 } | 174 } |
| 172 | 175 |
| 173 class GetContextFrame: public StackwalkerMIPSFixture, public Test { }; | 176 class GetContextFrame: public StackwalkerMIPSFixture, public Test { }; |
| 174 | 177 |
| 175 TEST_F(GetContextFrame, Simple) { | 178 TEST_F(GetContextFrame, Simple) { |
| 179 raw_context.context_flags = |
| 180 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 176 stack_section.start() = 0x80000000; | 181 stack_section.start() = 0x80000000; |
| 177 stack_section.D32(0).D32(0x0); | 182 stack_section.D64(0).D64(0x0); |
| 178 RegionFromSection(); | 183 RegionFromSection(); |
| 179 raw_context.epc = 0x00400020; | 184 raw_context.epc = 0x00400020; |
| 180 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; | 185 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; |
| 181 | 186 |
| 182 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 187 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 183 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 188 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 184 &frame_symbolizer); | 189 &frame_symbolizer); |
| 185 vector<const CodeModule*> modules_without_symbols; | 190 vector<const CodeModule*> modules_without_symbols; |
| 186 vector<const CodeModule*> modules_with_corrupt_symbols; | 191 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 187 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 192 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 188 &modules_with_corrupt_symbols)); | 193 &modules_with_corrupt_symbols)); |
| 189 ASSERT_EQ(1U, modules_without_symbols.size()); | 194 ASSERT_EQ(1U, modules_without_symbols.size()); |
| 190 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 195 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
| 191 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 196 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 192 frames = call_stack.frames(); | 197 frames = call_stack.frames(); |
| 193 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); | 198 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); |
| 194 // Check that the values from the original raw context made it | 199 // Check that the values from the original raw context made it |
| 195 // through to the context in the stack frame. | 200 // through to the context in the stack frame. |
| 196 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); | 201 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); |
| 197 } | 202 } |
| 198 | 203 |
| 199 // The stackwalker should be able to produce the context frame even | 204 // The stackwalker should be able to produce the context frame even |
| 200 // without stack memory present. | 205 // without stack memory present. |
| 201 TEST_F(GetContextFrame, NoStackMemory) { | 206 TEST_F(GetContextFrame, NoStackMemory) { |
| 207 raw_context.context_flags = |
| 208 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 202 raw_context.epc = 0x00400020; | 209 raw_context.epc = 0x00400020; |
| 203 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; | 210 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; |
| 204 | 211 |
| 205 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 212 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 206 StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules, | 213 StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules, |
| 207 &frame_symbolizer); | 214 &frame_symbolizer); |
| 208 vector<const CodeModule*> modules_without_symbols; | 215 vector<const CodeModule*> modules_without_symbols; |
| 209 vector<const CodeModule*> modules_with_corrupt_symbols; | 216 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 210 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 217 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 211 &modules_with_corrupt_symbols)); | 218 &modules_with_corrupt_symbols)); |
| 212 ASSERT_EQ(1U, modules_without_symbols.size()); | 219 ASSERT_EQ(1U, modules_without_symbols.size()); |
| 213 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 220 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
| 214 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 221 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 215 frames = call_stack.frames(); | 222 frames = call_stack.frames(); |
| 216 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); | 223 StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); |
| 217 // Check that the values from the original raw context made it | 224 // Check that the values from the original raw context made it |
| 218 // through to the context in the stack frame. | 225 // through to the context in the stack frame. |
| 219 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); | 226 EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); |
| 220 } | 227 } |
| 221 | 228 |
| 222 class GetCallerFrame: public StackwalkerMIPSFixture, public Test { }; | 229 class GetCallerFrame: public StackwalkerMIPSFixture, public Test { }; |
| 223 | 230 |
| 224 TEST_F(GetCallerFrame, ScanWithoutSymbols) { | 231 TEST_F(GetCallerFrame, ScanWithoutSymbols) { |
| 232 raw_context.context_flags = |
| 233 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 225 // When the stack walker resorts to scanning the stack, | 234 // When the stack walker resorts to scanning the stack, |
| 226 // only addresses located within loaded modules are | 235 // only addresses located within loaded modules are |
| 227 // considered valid return addresses. | 236 // considered valid return addresses. |
| 228 // Force scanning through three frames to ensure that the | 237 // Force scanning through three frames to ensure that the |
| 229 // stack pointer is set properly in scan-recovered frames. | 238 // stack pointer is set properly in scan-recovered frames. |
| 230 stack_section.start() = 0x80000000; | 239 stack_section.start() = 0x80000000; |
| 231 uint32_t return_address1 = 0x00400100; | 240 uint64_t return_address1 = 0x00400100; |
| 232 uint32_t return_address2 = 0x00400900; | 241 uint64_t return_address2 = 0x00400900; |
| 233 Label frame1_sp, frame2_sp; | 242 Label frame1_sp, frame2_sp; |
| 234 stack_section | 243 stack_section |
| 235 // frame 0 | 244 // frame 0 |
| 236 .Append(16, 0) // space | 245 .Append(32, 0) // space |
| 237 | 246 |
| 238 .D32(0x00490000) // junk that's not | 247 .D64(0x00490000) // junk that's not |
| 239 .D32(0x00600000) // a return address | 248 .D64(0x00600000) // a return address |
| 240 | 249 |
| 241 .D32(frame1_sp) // stack pointer | 250 .D64(frame1_sp) // stack pointer |
| 242 .D32(return_address1) // actual return address | 251 .D64(return_address1) // actual return address |
| 243 // frame 1 | 252 // frame 1 |
| 244 .Mark(&frame1_sp) | 253 .Mark(&frame1_sp) |
| 245 .Append(16, 0) // space | 254 .Append(32, 0) // space |
| 246 | 255 |
| 247 .D32(0xF0000000) // more junk | 256 .D64(0xF0000000) // more junk |
| 248 .D32(0x0000000D) | 257 .D64(0x0000000D) |
| 249 | 258 |
| 250 .D32(frame2_sp) // stack pointer | 259 .D64(frame2_sp) // stack pointer |
| 251 .D32(return_address2) // actual return address | 260 .D64(return_address2) // actual return address |
| 252 // frame 2 | 261 // frame 2 |
| 253 .Mark(&frame2_sp) | 262 .Mark(&frame2_sp) |
| 254 .Append(32, 0); // end of stack | 263 .Append(64, 0); // end of stack |
| 255 RegionFromSection(); | 264 RegionFromSection(); |
| 256 | 265 |
| 257 raw_context.epc = 0x00405510; | 266 raw_context.epc = 0x00405510; |
| 258 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); | 267 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); |
| 259 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; | 268 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; |
| 260 | 269 |
| 261 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 270 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 262 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 271 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 263 &frame_symbolizer); | 272 &frame_symbolizer); |
| 264 vector<const CodeModule*> modules_without_symbols; | 273 vector<const CodeModule*> modules_without_symbols; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 291 ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC | | 300 ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC | |
| 292 StackFrameMIPS::CONTEXT_VALID_SP | | 301 StackFrameMIPS::CONTEXT_VALID_SP | |
| 293 StackFrameMIPS::CONTEXT_VALID_FP | | 302 StackFrameMIPS::CONTEXT_VALID_FP | |
| 294 StackFrameMIPS::CONTEXT_VALID_RA), | 303 StackFrameMIPS::CONTEXT_VALID_RA), |
| 295 frame2->context_validity); | 304 frame2->context_validity); |
| 296 EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc); | 305 EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc); |
| 297 EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]); | 306 EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]); |
| 298 } | 307 } |
| 299 | 308 |
| 300 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { | 309 TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { |
| 310 raw_context.context_flags = |
| 311 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 301 // During stack scanning, if a potential return address | 312 // During stack scanning, if a potential return address |
| 302 // is located within a loaded module that has symbols, | 313 // is located within a loaded module that has symbols, |
| 303 // it is only considered a valid return address if it | 314 // it is only considered a valid return address if it |
| 304 // lies within a function's bounds. | 315 // lies within a function's bounds. |
| 305 stack_section.start() = 0x80000000; | 316 stack_section.start() = 0x80000000; |
| 306 uint32_t return_address = 0x00500200; | 317 uint64_t return_address = 0x00500200; |
| 307 Label frame1_sp; | 318 Label frame1_sp; |
| 308 stack_section | 319 stack_section |
| 309 // frame 0 | 320 // frame 0 |
| 310 .Append(16, 0) // space | 321 .Append(16, 0) // space |
| 311 | 322 |
| 312 .D32(0x00490000) // junk that's not | 323 .D64(0x00490000) // junk that's not |
| 313 .D32(0x00600000) // a return address | 324 .D64(0x00600000) // a return address |
| 314 | |
| 315 .D32(0x00401000) // a couple of plausible addresses | |
| 316 .D32(0x0050F000) // that are not within functions | |
| 317 | 325 |
| 318 .D32(frame1_sp) // stack pointer | 326 .D64(0x00401000) // a couple of plausible addresses |
| 319 .D32(return_address) // actual return address | 327 .D64(0x0050F000) // that are not within functions |
| 328 |
| 329 .D64(frame1_sp) // stack pointer |
| 330 .D64(return_address) // actual return address |
| 320 // frame 1 | 331 // frame 1 |
| 321 .Mark(&frame1_sp) | 332 .Mark(&frame1_sp) |
| 322 .Append(32, 0); // end of stack | 333 .Append(64, 0); // end of stack |
| 323 RegionFromSection(); | 334 RegionFromSection(); |
| 324 | 335 |
| 325 raw_context.epc = 0x00400200; | 336 raw_context.epc = 0x00400200; |
| 326 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); | 337 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); |
| 327 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address; | 338 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address; |
| 328 | 339 |
| 329 SetModuleSymbols(&module1, | 340 SetModuleSymbols(&module1, |
| 330 // The youngest frame's function. | 341 // The youngest frame's function. |
| 331 "FUNC 100 400 10 monotreme\n"); | 342 "FUNC 100 400 10 monotreme\n"); |
| 332 SetModuleSymbols(&module2, | 343 SetModuleSymbols(&module2, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 359 StackFrameMIPS::CONTEXT_VALID_FP | | 370 StackFrameMIPS::CONTEXT_VALID_FP | |
| 360 StackFrameMIPS::CONTEXT_VALID_RA), | 371 StackFrameMIPS::CONTEXT_VALID_RA), |
| 361 frame1->context_validity); | 372 frame1->context_validity); |
| 362 EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc); | 373 EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc); |
| 363 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); | 374 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); |
| 364 EXPECT_EQ("marsupial", frame1->function_name); | 375 EXPECT_EQ("marsupial", frame1->function_name); |
| 365 EXPECT_EQ(0x00500100U, frame1->function_base); | 376 EXPECT_EQ(0x00500100U, frame1->function_base); |
| 366 } | 377 } |
| 367 | 378 |
| 368 TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) { | 379 TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) { |
| 380 raw_context.context_flags = |
| 381 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 369 // If the stackwalker resorts to stack scanning, it will scan only | 382 // If the stackwalker resorts to stack scanning, it will scan only |
| 370 // 1024 bytes of stack which correspondes to maximum size of stack frame. | 383 // 1024 bytes of stack which correspondes to maximum size of stack frame. |
| 371 stack_section.start() = 0x80000000; | 384 stack_section.start() = 0x80000000; |
| 372 uint32_t return_address1 = 0x00500100; | 385 uint64_t return_address1 = 0x00500100; |
| 373 uint32_t return_address2 = 0x00500900; | 386 uint64_t return_address2 = 0x00500900; |
| 374 Label frame1_sp, frame2_sp; | 387 Label frame1_sp, frame2_sp; |
| 375 stack_section | 388 stack_section |
| 376 // frame 0 | 389 // frame 0 |
| 377 .Append(32, 0) // space | 390 .Append(32, 0) // space |
| 378 | 391 |
| 379 .D32(0x00490000) // junk that's not | 392 .D64(0x00490000) // junk that's not |
| 380 .D32(0x00600000) // a return address | 393 .D64(0x00600000) // a return address |
| 381 | 394 |
| 382 .Append(96, 0) // more space | 395 .Append(96, 0) // more space |
| 383 | 396 |
| 384 .D32(frame1_sp) // stack pointer | 397 .D64(frame1_sp) // stack pointer |
| 385 .D32(return_address1) // actual return address | 398 .D64(return_address1) // actual return address |
| 386 // frame 1 | 399 // frame 1 |
| 387 .Mark(&frame1_sp) | 400 .Mark(&frame1_sp) |
| 388 .Append(128 * 4, 0) // space | 401 .Append(128 * 4, 0) // space |
| 389 | 402 |
| 390 .D32(0x00F00000) // more junk | 403 .D64(0x00F00000) // more junk |
| 391 .D32(0x0000000D) | 404 .D64(0x0000000D) |
| 392 | 405 |
| 393 .Append(128 * 4, 0) // more space | 406 .Append(128 * 4, 0) // more space |
| 394 | 407 |
| 395 .D32(frame2_sp) // stack pointer | 408 .D64(frame2_sp) // stack pointer |
| 396 .D32(return_address2) // actual return address | 409 .D64(return_address2) // actual return address |
| 397 // (won't be found) | 410 // (won't be found) |
| 398 // frame 2 | 411 // frame 2 |
| 399 .Mark(&frame2_sp) | 412 .Mark(&frame2_sp) |
| 400 .Append(32, 0); // end of stack | 413 .Append(64, 0); // end of stack |
| 401 RegionFromSection(); | 414 RegionFromSection(); |
| 402 | 415 |
| 403 raw_context.epc = 0x00405510; | 416 raw_context.epc = 0x00405510; |
| 404 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); | 417 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); |
| 405 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; | 418 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; |
| 406 | 419 |
| 407 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 420 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 408 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 421 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 409 &frame_symbolizer); | 422 &frame_symbolizer); |
| 410 vector<const CodeModule*> modules_without_symbols; | 423 vector<const CodeModule*> modules_without_symbols; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 430 StackFrameMIPS::CONTEXT_VALID_FP | | 443 StackFrameMIPS::CONTEXT_VALID_FP | |
| 431 StackFrameMIPS::CONTEXT_VALID_RA), | 444 StackFrameMIPS::CONTEXT_VALID_RA), |
| 432 frame1->context_validity); | 445 frame1->context_validity); |
| 433 EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc); | 446 EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc); |
| 434 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); | 447 EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); |
| 435 } | 448 } |
| 436 | 449 |
| 437 // Test that set_max_frames_scanned prevents using stack scanning | 450 // Test that set_max_frames_scanned prevents using stack scanning |
| 438 // to find caller frames. | 451 // to find caller frames. |
| 439 TEST_F(GetCallerFrame, ScanningNotAllowed) { | 452 TEST_F(GetCallerFrame, ScanningNotAllowed) { |
| 453 raw_context.context_flags = |
| 454 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 440 // When the stack walker resorts to scanning the stack, | 455 // When the stack walker resorts to scanning the stack, |
| 441 // only fixed number of frames are allowed to be scanned out from stack | 456 // only fixed number of frames are allowed to be scanned out from stack |
| 442 stack_section.start() = 0x80000000; | 457 stack_section.start() = 0x80000000; |
| 443 uint32_t return_address1 = 0x00500100; | 458 uint64_t return_address1 = 0x00500100; |
| 444 uint32_t return_address2 = 0x00500900; | 459 uint64_t return_address2 = 0x00500900; |
| 445 Label frame1_sp, frame2_sp; | 460 Label frame1_sp, frame2_sp; |
| 446 stack_section | 461 stack_section |
| 447 // frame 0 | 462 // frame 0 |
| 448 .Append(32, 0) // space | 463 .Append(32, 0) // space |
| 449 | 464 |
| 450 .D32(0x00490000) // junk that's not | 465 .D64(0x00490000) // junk that's not |
| 451 .D32(0x00600000) // a return address | 466 .D64(0x00600000) // a return address |
| 452 | 467 |
| 453 .Append(96, 0) // more space | 468 .Append(96, 0) // more space |
| 454 | 469 |
| 455 .D32(frame1_sp) // stack pointer | 470 .D64(frame1_sp) // stack pointer |
| 456 .D32(return_address1) // actual return address | 471 .D64(return_address1) // actual return address |
| 457 // frame 1 | 472 // frame 1 |
| 458 .Mark(&frame1_sp) | 473 .Mark(&frame1_sp) |
| 459 .Append(128 * 4, 0) // space | 474 .Append(128 * 4, 0) // space |
| 460 | 475 |
| 461 .D32(0x00F00000) // more junk | 476 .D64(0x00F00000) // more junk |
| 462 .D32(0x0000000D) | 477 .D64(0x0000000D) |
| 463 | 478 |
| 464 .Append(128 * 4, 0) // more space | 479 .Append(128 * 4, 0) // more space |
| 465 | 480 |
| 466 .D32(frame2_sp) // stack pointer | 481 .D64(frame2_sp) // stack pointer |
| 467 .D32(return_address2) // actual return address | 482 .D64(return_address2) // actual return address |
| 468 // (won't be found) | 483 // (won't be found) |
| 469 // frame 2 | 484 // frame 2 |
| 470 .Mark(&frame2_sp) | 485 .Mark(&frame2_sp) |
| 471 .Append(32, 0); // end of stack | 486 .Append(64, 0); // end of stack |
| 472 RegionFromSection(); | 487 RegionFromSection(); |
| 473 | 488 |
| 474 raw_context.epc = 0x00405510; | 489 raw_context.epc = 0x00405510; |
| 475 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); | 490 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); |
| 476 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; | 491 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; |
| 477 | 492 |
| 478 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 493 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 479 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 494 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 480 &frame_symbolizer); | 495 &frame_symbolizer); |
| 481 Stackwalker::set_max_frames_scanned(0); | 496 Stackwalker::set_max_frames_scanned(0); |
| 482 | 497 |
| 483 vector<const CodeModule*> modules_without_symbols; | 498 vector<const CodeModule*> modules_without_symbols; |
| 484 vector<const CodeModule*> modules_with_corrupt_symbols; | 499 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 485 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 500 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 486 &modules_with_corrupt_symbols)); | 501 &modules_with_corrupt_symbols)); |
| 487 ASSERT_EQ(1U, modules_without_symbols.size()); | 502 ASSERT_EQ(1U, modules_without_symbols.size()); |
| 488 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); | 503 ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); |
| 489 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 504 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 490 frames = call_stack.frames(); | 505 frames = call_stack.frames(); |
| 491 ASSERT_EQ(1U, frames->size()); | 506 ASSERT_EQ(1U, frames->size()); |
| 492 | 507 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 "FUNC 6000 1000 20 palinal\n" | 544 "FUNC 6000 1000 20 palinal\n" |
| 530 "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n" | 545 "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n" |
| 531 | 546 |
| 532 // A function with CFI expressions that can't be | 547 // A function with CFI expressions that can't be |
| 533 // evaluated. | 548 // evaluated. |
| 534 "FUNC 7000 1000 20 rhetorical\n" | 549 "FUNC 7000 1000 20 rhetorical\n" |
| 535 "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n" | 550 "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n" |
| 536 ); | 551 ); |
| 537 | 552 |
| 538 // Provide some distinctive values for the caller's registers. | 553 // Provide some distinctive values for the caller's registers. |
| 539 expected.epc = 0x00405508; | 554 expected.epc = 0x00405500; |
| 540 expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0; | 555 expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0; |
| 541 expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1; | 556 expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1; |
| 542 expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2; | 557 expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2; |
| 543 expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3; | 558 expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3; |
| 544 expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4; | 559 expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4; |
| 545 expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5; | 560 expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5; |
| 546 expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6; | 561 expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6; |
| 547 expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7; | 562 expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7; |
| 548 expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; | 563 expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; |
| 549 expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000; | 564 expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000; |
| 550 expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; | 565 expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; |
| 551 | 566 |
| 552 // Expect CFI to recover all callee-save registers. Since CFI is the | 567 // Expect CFI to recover all callee-save registers. Since CFI is the |
| 553 // only stack frame construction technique we have, aside from the | 568 // only stack frame construction technique we have, aside from the |
| 554 // context frame itself, there's no way for us to have a set of valid | 569 // context frame itself, there's no way for us to have a set of valid |
| 555 // registers smaller than this. | 570 // registers smaller than this. |
| 556 expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC | | 571 expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC | |
| 557 StackFrameMIPS::CONTEXT_VALID_S0 | | 572 StackFrameMIPS::CONTEXT_VALID_S0 | |
| 558 StackFrameMIPS::CONTEXT_VALID_S1 | | 573 StackFrameMIPS::CONTEXT_VALID_S1 | |
| 559 StackFrameMIPS::CONTEXT_VALID_S2 | | 574 StackFrameMIPS::CONTEXT_VALID_S2 | |
| 560 StackFrameMIPS::CONTEXT_VALID_S3 | | 575 StackFrameMIPS::CONTEXT_VALID_S3 | |
| 561 StackFrameMIPS::CONTEXT_VALID_S4 | | 576 StackFrameMIPS::CONTEXT_VALID_S4 | |
| 562 StackFrameMIPS::CONTEXT_VALID_S5 | | 577 StackFrameMIPS::CONTEXT_VALID_S5 | |
| 563 StackFrameMIPS::CONTEXT_VALID_S6 | | 578 StackFrameMIPS::CONTEXT_VALID_S6 | |
| 564 StackFrameMIPS::CONTEXT_VALID_S7 | | 579 StackFrameMIPS::CONTEXT_VALID_S7 | |
| 565 StackFrameMIPS::CONTEXT_VALID_SP | | 580 StackFrameMIPS::CONTEXT_VALID_SP | |
| 566 StackFrameMIPS::CONTEXT_VALID_FP | | 581 StackFrameMIPS::CONTEXT_VALID_FP | |
| 582 StackFrameMIPS::CONTEXT_VALID_GP | |
| 567 StackFrameMIPS::CONTEXT_VALID_RA); | 583 StackFrameMIPS::CONTEXT_VALID_RA); |
| 568 | 584 |
| 569 // By default, context frames provide all registers, as normal. | 585 // By default, context frames provide all registers, as normal. |
| 570 context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL; | 586 context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL; |
| 571 | 587 |
| 572 // By default, registers are unchanged. | 588 // By default, registers are unchanged. |
| 573 raw_context = expected; | 589 raw_context = expected; |
| 574 } | 590 } |
| 575 | 591 |
| 576 // Walk the stack, using stack_section as the contents of the stack | 592 // Walk the stack, using stack_section as the contents of the stack |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]); | 637 frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]); |
| 622 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP], | 638 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP], |
| 623 frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]); | 639 frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]); |
| 624 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA], | 640 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA], |
| 625 frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]); | 641 frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]); |
| 626 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP], | 642 EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP], |
| 627 frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); | 643 frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); |
| 628 EXPECT_EQ(expected.epc, frame1->context.epc); | 644 EXPECT_EQ(expected.epc, frame1->context.epc); |
| 629 EXPECT_EQ(expected.epc, frame1->instruction); | 645 EXPECT_EQ(expected.epc, frame1->instruction); |
| 630 EXPECT_EQ("epictetus", frame1->function_name); | 646 EXPECT_EQ("epictetus", frame1->function_name); |
| 631 EXPECT_EQ(0x00405000U, frame1->function_base); | 647 EXPECT_EQ(0x00405000U, frame1->function_base); |
| 632 } | 648 } |
| 633 | 649 |
| 634 // The values we expect to find for the caller's registers. | 650 // The values we expect to find for the caller's registers. |
| 635 MDRawContextMIPS expected; | 651 MDRawContextMIPS expected; |
| 636 | 652 |
| 637 // The validity mask for expected. | 653 // The validity mask for expected. |
| 638 int expected_validity; | 654 int expected_validity; |
| 639 | 655 |
| 640 // The validity mask to impose on the context frame. | 656 // The validity mask to impose on the context frame. |
| 641 int context_frame_validity; | 657 int context_frame_validity; |
| 642 }; | 658 }; |
| 643 | 659 |
| 644 class CFI: public CFIFixture, public Test { }; | 660 class CFI: public CFIFixture, public Test { }; |
| 645 | 661 |
| 646 // TODO(gordanac): add CFI tests | 662 // TODO(gordanac): add CFI tests |
| 647 | 663 |
| 648 TEST_F(CFI, At4004) { | 664 TEST_F(CFI, At4004) { |
| 665 raw_context.context_flags = |
| 666 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 649 Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP]; | 667 Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP]; |
| 650 stack_section | 668 stack_section |
| 651 // frame0 | 669 // frame0 |
| 652 .Append(24, 0) // space | 670 .Append(16, 0) // space |
| 653 .D32(frame1_sp) // stack pointer | 671 .D64(frame1_sp) // stack pointer |
| 654 .D32(0x00405510) // return address | 672 .D64(0x00405510) // return address |
| 655 .Mark(&frame1_sp); // This effectively sets stack_section.start(). | 673 .Mark(&frame1_sp); // This effectively sets stack_section.start(). |
| 656 raw_context.epc = 0x00404004; | 674 raw_context.epc = 0x00404004; |
| 657 CheckWalk(); | 675 CheckWalk(); |
| 658 } | 676 } |
| 659 | 677 |
| 660 // Check that we reject rules that would cause the stack pointer to | 678 // Check that we reject rules that would cause the stack pointer to |
| 661 // move in the wrong direction. | 679 // move in the wrong direction. |
| 662 TEST_F(CFI, RejectBackwards) { | 680 TEST_F(CFI, RejectBackwards) { |
| 681 raw_context.context_flags = |
| 682 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 663 raw_context.epc = 0x40005000; | 683 raw_context.epc = 0x40005000; |
| 664 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; | 684 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; |
| 665 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; | 685 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; |
| 666 | 686 |
| 667 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 687 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 668 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 688 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 669 &frame_symbolizer); | 689 &frame_symbolizer); |
| 670 vector<const CodeModule*> modules_without_symbols; | 690 vector<const CodeModule*> modules_without_symbols; |
| 671 vector<const CodeModule*> modules_with_corrupt_symbols; | 691 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 672 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 692 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 673 &modules_with_corrupt_symbols)); | 693 &modules_with_corrupt_symbols)); |
| 674 ASSERT_EQ(0U, modules_without_symbols.size()); | 694 ASSERT_EQ(0U, modules_without_symbols.size()); |
| 675 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 695 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 676 frames = call_stack.frames(); | 696 frames = call_stack.frames(); |
| 677 ASSERT_EQ(1U, frames->size()); | 697 ASSERT_EQ(1U, frames->size()); |
| 678 } | 698 } |
| 679 | 699 |
| 680 // Check that we reject rules whose expressions' evaluation fails. | 700 // Check that we reject rules whose expressions' evaluation fails. |
| 681 TEST_F(CFI, RejectBadExpressions) { | 701 TEST_F(CFI, RejectBadExpressions) { |
| 702 raw_context.context_flags = |
| 703 raw_context.context_flags | MD_CONTEXT_MIPS64_FULL; |
| 682 raw_context.epc = 0x00407000; | 704 raw_context.epc = 0x00407000; |
| 683 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; | 705 raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; |
| 684 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; | 706 raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; |
| 685 | 707 |
| 686 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); | 708 StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); |
| 687 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, | 709 StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, |
| 688 &frame_symbolizer); | 710 &frame_symbolizer); |
| 689 vector<const CodeModule*> modules_without_symbols; | 711 vector<const CodeModule*> modules_without_symbols; |
| 690 vector<const CodeModule*> modules_with_corrupt_symbols; | 712 vector<const CodeModule*> modules_with_corrupt_symbols; |
| 691 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, | 713 ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, |
| 692 &modules_with_corrupt_symbols)); | 714 &modules_with_corrupt_symbols)); |
| 693 ASSERT_EQ(0U, modules_without_symbols.size()); | 715 ASSERT_EQ(0U, modules_without_symbols.size()); |
| 694 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); | 716 ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); |
| 695 frames = call_stack.frames(); | 717 frames = call_stack.frames(); |
| 696 ASSERT_EQ(1U, frames->size()); | 718 ASSERT_EQ(1U, frames->size()); |
| 697 } | 719 } |
| OLD | NEW |