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

Side by Side Diff: components/metrics/leak_detector/gnu_build_id_reader.cc

Issue 2159013002: Read Chrome build ID and store it in leak reports (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/metrics/leak_detector/gnu_build_id_reader.h"
6
7 #include <libelf.h>
8 #include <string.h>
9
10 #if defined(OS_CHROMEOS)
11 #include <link.h> // for dl_iterate_phdr
12 #else
13 #error "Getting binary mapping info is not supported on this platform."
14 #endif // defined(OS_CHROMEOS)
15
16 namespace metrics {
17 namespace leak_detector {
18
19 namespace {
20
21 // Given a pointer and an offset, add the offset to the pointer and round it up
22 // to the next uint32_t.
23 const void* AlignPtrAndOffsetToUint32(const void* ptr, intptr_t offset) {
24 uintptr_t addr = reinterpret_cast<uintptr_t>(ptr) + offset;
25 uintptr_t aligned_addr =
26 (addr + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
27 return reinterpret_cast<const void*>(aligned_addr);
28 }
29
30 // Searches for the ELF note containing the build ID within the data range
31 // specified by [start, end). Returns the build ID in |*result|. If the build ID
32 // is not found, |*result| will be unchanged.
33 void GetBuildIdFromNotes(const void* start,
34 const void* end,
35 std::vector<uint8_t>* result) {
36 using NoteHeaderPtr = const Elf32_Nhdr*;
37 NoteHeaderPtr note = reinterpret_cast<NoteHeaderPtr>(start);
38
39 while (note < end) {
40 NoteHeaderPtr name_ptr = &note[1];
41 if (name_ptr > end) {
42 return;
43 }
44 // |desc_ptr| points the to the actual build ID data.
45 const uint8_t* desc_ptr = reinterpret_cast<const uint8_t*>(
46 AlignPtrAndOffsetToUint32(name_ptr, note->n_namesz));
47 if (note->n_type == NT_GNU_BUILD_ID &&
Will Harris 2016/07/18 22:03:53 where is this build id set in the binary?
Simon Que 2016/07/19 00:29:34 What do you mean? It's set by the build process.
Will Harris 2016/07/19 00:33:42 that's what I mean. Where is this set? Is this a s
Simon Que 2016/07/19 00:36:36 AFAICT it is set as part of the standard build pro
48 note->n_namesz == sizeof(ELF_NOTE_GNU) &&
49 memcmp((const char*)name_ptr, ELF_NOTE_GNU, sizeof(ELF_NOTE_GNU)) ==
50 0) {
51 result->assign(desc_ptr, desc_ptr + note->n_descsz);
52 }
53 NoteHeaderPtr next_ptr = reinterpret_cast<NoteHeaderPtr>(
54 AlignPtrAndOffsetToUint32(desc_ptr, note->n_descsz));
55 note = next_ptr;
56 }
57 }
58
59 // Callback for dl_iterate_phdr(). Finds the notes section and looks for the
60 // build ID in there. Returns the build ID in |data|, which should point to a
61 // std::vector<uint8_t>.
62 int FindNotesAndGetBuildID(struct dl_phdr_info* info,
63 size_t /* size */,
64 void* data) {
65 uintptr_t mapping_addr = reinterpret_cast<uintptr_t>(info->dlpi_addr);
66 const ElfW(Ehdr)* file_header =
67 reinterpret_cast<const ElfW(Ehdr)*>(mapping_addr);
68
69 // Make sure that a valid |mapping_addr| was read.
70 if (!file_header || file_header->e_phentsize != sizeof(ElfW(Phdr))) {
71 return 1;
72 }
73
74 for (int i = 0; i < info->dlpi_phnum; i++) {
75 // Find the ELF segment header for the NOTES section.
76 for (int i = 0; i < info->dlpi_phnum; ++i) {
77 const ElfW(Phdr)& segment_header = info->dlpi_phdr[i];
78 if (segment_header.p_type == PT_NOTE) {
79 // Elf64_Nhdr is the same as Elf32_Nhdr so we can use either here.
80 const void* note = reinterpret_cast<const void*>(
81 mapping_addr + segment_header.p_offset);
82 const void* note_end = reinterpret_cast<const void*>(
83 mapping_addr + segment_header.p_offset + segment_header.p_memsz);
84 std::vector<uint8_t>* result =
85 reinterpret_cast<std::vector<uint8_t>*>(data);
86 GetBuildIdFromNotes(note, note_end, result);
87 }
88 }
89 }
90 return 1;
91 }
92
93 } // namespace
94
95 GNUBuildIDReader::GNUBuildIDReader() {
96 ReadBuildID();
97 }
98
99 GNUBuildIDReader::~GNUBuildIDReader() {}
100
101 void GNUBuildIDReader::ReadBuildID() {
102 #if defined(OS_CHROMEOS)
103 dl_iterate_phdr(FindNotesAndGetBuildID, &build_id_);
104 #endif // defined(OS_CHROMEOS)
105 }
106
107 } // namespace leak_detector
108 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698