| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/debug/proc_maps_linux.h" | 5 #include "base/debug/proc_maps_linux.h" |
| 6 #include "base/files/file_path.h" | 6 #include "base/files/file_path.h" |
| 7 #include "base/path_service.h" | 7 #include "base/path_service.h" |
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 9 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 10 #include "base/threading/platform_thread.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 12 |
| 12 namespace base { | 13 namespace base { |
| 13 namespace debug { | 14 namespace debug { |
| 14 | 15 |
| 15 TEST(ProcMapsTest, Empty) { | 16 TEST(ProcMapsTest, Empty) { |
| 16 std::vector<MappedMemoryRegion> regions; | 17 std::vector<MappedMemoryRegion> regions; |
| 17 EXPECT_TRUE(ParseProcMaps("", ®ions)); | 18 EXPECT_TRUE(ParseProcMaps("", ®ions)); |
| 18 EXPECT_EQ(0u, regions.size()); | 19 EXPECT_EQ(0u, regions.size()); |
| 19 } | 20 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 191 |
| 191 // We should be able to find both the current executable as well as the stack | 192 // We should be able to find both the current executable as well as the stack |
| 192 // mapped into memory. Use the address of |proc_maps| as a way of finding the | 193 // mapped into memory. Use the address of |proc_maps| as a way of finding the |
| 193 // stack. | 194 // stack. |
| 194 FilePath exe_path; | 195 FilePath exe_path; |
| 195 EXPECT_TRUE(PathService::Get(FILE_EXE, &exe_path)); | 196 EXPECT_TRUE(PathService::Get(FILE_EXE, &exe_path)); |
| 196 uintptr_t address = reinterpret_cast<uintptr_t>(&proc_maps); | 197 uintptr_t address = reinterpret_cast<uintptr_t>(&proc_maps); |
| 197 bool found_exe = false; | 198 bool found_exe = false; |
| 198 bool found_stack = false; | 199 bool found_stack = false; |
| 199 bool found_address = false; | 200 bool found_address = false; |
| 201 |
| 202 // Valgrind uses its own allocated stacks instead of the kernel-provided stack |
| 203 // without letting the kernel know via prctl(PR_SET_MM_START_STACK). This |
| 204 // causes the kernel to use [stack:TID] format. See http://crbug.com/431702 |
| 205 // for details. |
| 206 std::string stack_with_tid = |
| 207 StringPrintf("[stack:%d]", PlatformThread::CurrentId()); |
| 208 |
| 200 for (size_t i = 0; i < regions.size(); ++i) { | 209 for (size_t i = 0; i < regions.size(); ++i) { |
| 201 if (regions[i].path == exe_path.value()) { | 210 if (regions[i].path == exe_path.value()) { |
| 202 // It's OK to find the executable mapped multiple times as there'll be | 211 // It's OK to find the executable mapped multiple times as there'll be |
| 203 // multiple sections (e.g., text, data). | 212 // multiple sections (e.g., text, data). |
| 204 found_exe = true; | 213 found_exe = true; |
| 205 } | 214 } |
| 206 | 215 |
| 216 bool is_correct_stack = false; |
| 207 if (regions[i].path == "[stack]") { | 217 if (regions[i].path == "[stack]") { |
| 208 // Only check if |address| lies within the real stack when not running | 218 is_correct_stack = true; |
| 209 // Valgrind, otherwise |address| will be on a stack that Valgrind creates. | 219 EXPECT_FALSE(RunningOnValgrind()); |
| 210 if (!RunningOnValgrind()) { | 220 EXPECT_GE(address, regions[i].start); |
| 211 EXPECT_GE(address, regions[i].start); | 221 EXPECT_LT(address, regions[i].end); |
| 212 EXPECT_LT(address, regions[i].end); | 222 } else if (regions[i].path == stack_with_tid) { |
| 213 } | 223 is_correct_stack = true; |
| 224 EXPECT_TRUE(RunningOnValgrind()); |
| 225 } |
| 214 | 226 |
| 227 if (is_correct_stack) { |
| 228 // Note that the stack is executable when it is created by Valgrind. |
| 215 EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::READ); | 229 EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::READ); |
| 216 EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::WRITE); | 230 EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::WRITE); |
| 217 EXPECT_FALSE(regions[i].permissions & MappedMemoryRegion::EXECUTE); | 231 EXPECT_EQ(RunningOnValgrind(), |
| 232 (regions[i].permissions & MappedMemoryRegion::EXECUTE) != 0); |
| 218 EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::PRIVATE); | 233 EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::PRIVATE); |
| 219 EXPECT_FALSE(found_stack) << "Found duplicate stacks"; | 234 EXPECT_FALSE(found_stack) << "Found duplicate stacks"; |
| 220 found_stack = true; | 235 found_stack = true; |
| 221 } | 236 } |
| 222 | 237 |
| 223 if (address >= regions[i].start && address < regions[i].end) { | 238 if (address >= regions[i].start && address < regions[i].end) { |
| 224 EXPECT_FALSE(found_address) << "Found same address in multiple regions"; | 239 EXPECT_FALSE(found_address) << "Found same address in multiple regions"; |
| 225 found_address = true; | 240 found_address = true; |
| 226 } | 241 } |
| 227 } | 242 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 EXPECT_EQ(5ULL, regions.size()); | 319 EXPECT_EQ(5ULL, regions.size()); |
| 305 EXPECT_EQ("/bin/cat", regions[0].path); | 320 EXPECT_EQ("/bin/cat", regions[0].path); |
| 306 EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path); | 321 EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path); |
| 307 EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path); | 322 EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path); |
| 308 EXPECT_EQ("\"vd so\"", regions[3].path); | 323 EXPECT_EQ("\"vd so\"", regions[3].path); |
| 309 EXPECT_EQ("[vsys call]", regions[4].path); | 324 EXPECT_EQ("[vsys call]", regions[4].path); |
| 310 } | 325 } |
| 311 | 326 |
| 312 } // namespace debug | 327 } // namespace debug |
| 313 } // namespace base | 328 } // namespace base |
| OLD | NEW |