Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1138)

Side by Side Diff: base/profiler/native_stack_sampler_mac.cc

Issue 2882453003: Fix the module IDs from the Mac stack sampler. (Closed)
Patch Set: strlcpy Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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/profiler/native_stack_sampler.h" 5 #include "base/profiler/native_stack_sampler.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #include <libkern/OSByteOrder.h> 8 #include <libkern/OSByteOrder.h>
9 #include <libunwind.h> 9 #include <libunwind.h>
10 #include <mach-o/swap.h> 10 #include <mach-o/swap.h>
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 } 157 }
158 158
159 const char* LibSystemKernelName() { 159 const char* LibSystemKernelName() {
160 static char path[PATH_MAX]; 160 static char path[PATH_MAX];
161 static char* name = nullptr; 161 static char* name = nullptr;
162 if (name) 162 if (name)
163 return name; 163 return name;
164 164
165 Dl_info info; 165 Dl_info info;
166 dladdr(reinterpret_cast<void*>(_exit), &info); 166 dladdr(reinterpret_cast<void*>(_exit), &info);
167 strncpy(path, info.dli_fname, PATH_MAX); 167 strlcpy(path, info.dli_fname, PATH_MAX);
168 name = path; 168 name = path;
169 169
170 #if !defined(ADDRESS_SANITIZER) 170 #if !defined(ADDRESS_SANITIZER)
171 DCHECK_EQ(std::string(name), 171 DCHECK_EQ(std::string(name),
172 std::string("/usr/lib/system/libsystem_kernel.dylib")); 172 std::string("/usr/lib/system/libsystem_kernel.dylib"));
173 #endif 173 #endif
174 return name; 174 return name;
175 } 175 }
176 176
177 // Walks the stack represented by |thread_state|, calling back to the provided 177 // Walks the stack represented by |thread_state|, calling back to the provided
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 strcmp(info.dli_fname, LibSystemKernelName()) == 0) { 215 strcmp(info.dli_fname, LibSystemKernelName()) == 0) {
216 rip = *reinterpret_cast<uint64_t*>(rsp); 216 rip = *reinterpret_cast<uint64_t*>(rsp);
217 rsp += 8; 217 rsp += 8;
218 WalkStackFromContext(&unwind_context, &frame_count, callback); 218 WalkStackFromContext(&unwind_context, &frame_count, callback);
219 } 219 }
220 } 220 }
221 } 221 }
222 222
223 // Module identifiers --------------------------------------------------------- 223 // Module identifiers ---------------------------------------------------------
224 224
225 // Returns the hex encoding of a 16-byte ID for the binary loaded at 225 // Returns the unique build ID for a module loaded at |module_addr|. Returns the
226 // |module_addr|. Returns an empty string if the UUID cannot be found at 226 // empty string if the function fails to get the build ID.
227 // |module_addr|. 227 //
228 // Build IDs are created by the concatenation of the module's GUID (Windows) /
229 // UUID (Mac) and an "age" field that indicates how many times that GUID/UUID
230 // has been reused. In Windows binaries, the "age" field is present in the
231 // module header, but on the Mac, UUIDs are never reused and so the "age" value
232 // appended to the UUID is always 0.
228 std::string GetUniqueId(const void* module_addr) { 233 std::string GetUniqueId(const void* module_addr) {
229 const mach_header_64* mach_header = 234 const mach_header_64* mach_header =
230 reinterpret_cast<const mach_header_64*>(module_addr); 235 reinterpret_cast<const mach_header_64*>(module_addr);
231 DCHECK_EQ(MH_MAGIC_64, mach_header->magic); 236 DCHECK_EQ(MH_MAGIC_64, mach_header->magic);
232 237
233 size_t offset = sizeof(mach_header_64); 238 size_t offset = sizeof(mach_header_64);
234 size_t offset_limit = sizeof(mach_header_64) + mach_header->sizeofcmds; 239 size_t offset_limit = sizeof(mach_header_64) + mach_header->sizeofcmds;
235 for (uint32_t i = 0; (i < mach_header->ncmds) && 240 for (uint32_t i = 0; (i < mach_header->ncmds) &&
236 (offset + sizeof(load_command) < offset_limit); 241 (offset + sizeof(load_command) < offset_limit);
237 ++i) { 242 ++i) {
238 const load_command* current_cmd = reinterpret_cast<const load_command*>( 243 const load_command* current_cmd = reinterpret_cast<const load_command*>(
239 reinterpret_cast<const uint8_t*>(mach_header) + offset); 244 reinterpret_cast<const uint8_t*>(mach_header) + offset);
240 245
241 if (offset + current_cmd->cmdsize > offset_limit) { 246 if (offset + current_cmd->cmdsize > offset_limit) {
242 // This command runs off the end of the command list. This is malformed. 247 // This command runs off the end of the command list. This is malformed.
243 return std::string(); 248 return std::string();
244 } 249 }
245 250
246 if (current_cmd->cmd == LC_UUID) { 251 if (current_cmd->cmd == LC_UUID) {
247 if (current_cmd->cmdsize < sizeof(uuid_command)) { 252 if (current_cmd->cmdsize < sizeof(uuid_command)) {
248 // This "UUID command" is too small. This is malformed. 253 // This "UUID command" is too small. This is malformed.
249 return std::string(); 254 return std::string();
250 } 255 }
251 256
252 const uuid_command* uuid_cmd = 257 const uuid_command* uuid_cmd =
253 reinterpret_cast<const uuid_command*>(current_cmd); 258 reinterpret_cast<const uuid_command*>(current_cmd);
254 static_assert(sizeof(uuid_cmd->uuid) == sizeof(uuid_t), 259 static_assert(sizeof(uuid_cmd->uuid) == sizeof(uuid_t),
255 "UUID field of UUID command should be 16 bytes."); 260 "UUID field of UUID command should be 16 bytes.");
256 return HexEncode(&uuid_cmd->uuid, sizeof(uuid_cmd->uuid)); 261 // The ID is comprised of the UUID concatenated with the Mac's "age" value
262 // which is always 0.
263 return HexEncode(&uuid_cmd->uuid, sizeof(uuid_cmd->uuid)) + "0";
257 } 264 }
258 offset += current_cmd->cmdsize; 265 offset += current_cmd->cmdsize;
259 } 266 }
260 return std::string(); 267 return std::string();
261 } 268 }
262 269
263 // Gets the index for the Module containing |instruction_pointer| in 270 // Gets the index for the Module containing |instruction_pointer| in
264 // |modules|, adding it if it's not already present. Returns 271 // |modules|, adding it if it's not already present. Returns
265 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be 272 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be
266 // determined for |module|. 273 // determined for |module|.
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 469
463 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create( 470 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
464 PlatformThreadId thread_id, 471 PlatformThreadId thread_id,
465 AnnotateCallback annotator, 472 AnnotateCallback annotator,
466 NativeStackSamplerTestDelegate* test_delegate) { 473 NativeStackSamplerTestDelegate* test_delegate) {
467 return base::MakeUnique<NativeStackSamplerMac>(thread_id, annotator, 474 return base::MakeUnique<NativeStackSamplerMac>(thread_id, annotator,
468 test_delegate); 475 test_delegate);
469 } 476 }
470 477
471 } // namespace base 478 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698