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

Side by Side Diff: util/mac/mach_o_image_annotations_reader.cc

Issue 651283003: Add crashpad_info, MachOImageAnnotationsReader, and its test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Refactor to reduce deep nesting Created 6 years, 2 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 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/mac/mach_o_image_annotations_reader.h"
16
17 #include <mach-o/loader.h>
18 #include <mach/mach.h>
19
20 #include "base/logging.h"
21 #include "util/mac/mach_o_image_reader.h"
22 #include "util/mac/process_reader.h"
23 #include "util/mac/process_types.h"
24 #include "util/mach/task_memory.h"
25 #include "util/stdlib/strnlen.h"
26
27 namespace crashpad {
28
29 MachOImageAnnotationsReader::MachOImageAnnotationsReader(
30 ProcessReader* process_reader,
31 const MachOImageReader* image_reader,
32 const std::string& name)
33 : name_(name),
34 process_reader_(process_reader),
35 image_reader_(image_reader) {
36 }
37
38 std::vector<std::string> MachOImageAnnotationsReader::Vector() const {
39 std::vector<std::string> vector_annotations;
40
41 ReadCrashReporterClientAnnotations(&vector_annotations);
42 ReadDyldErrorStringAnnotation(&vector_annotations);
43
44 return vector_annotations;
45 }
46
47 std::map<std::string, std::string> MachOImageAnnotationsReader::SimpleMap()
48 const {
49 std::map<std::string, std::string> simple_map_annotations;
50
51 ReadCrashpadSimpleAnnotations(&simple_map_annotations);
52
53 return simple_map_annotations;
54 }
55
56 void MachOImageAnnotationsReader::ReadCrashReporterClientAnnotations(
57 std::vector<std::string>* vector_annotations) const {
58 mach_vm_address_t crash_info_address;
59 const process_types::section* crash_info_section =
60 image_reader_->GetSectionByName(
61 SEG_DATA, "__crash_info", &crash_info_address);
62 if (!crash_info_section) {
63 return;
64 }
65
66 process_types::crashreporter_annotations_t crash_info;
67 if (crash_info_section->size < crash_info.ExpectedSize(process_reader_)) {
68 LOG(WARNING) << "small crash info section size " << crash_info_section->size
69 << " in " << name_;
70 return;
71 }
72
73 if (!crash_info.Read(process_reader_, crash_info_address)) {
74 LOG(WARNING) << "could not read crash info from " << name_;
75 return;
76 }
77
78 if (crash_info.version != 4) {
79 LOG(WARNING) << "unexpected crash info version " << crash_info.version
80 << " in " << name_;
81 return;
82 }
83
84 // This number was totally made up out of nowhere, but it seems prudent to
85 // enforce some limit.
86 const size_t kMaxMessageSize = 1024;
87 if (crash_info.message) {
88 std::string message;
89 if (process_reader_->Memory()
90 ->ReadCStringSizeLimited(
Robert Sesek 2014/10/15 20:25:20 nit: break after ( instead of -> ?
91 crash_info.message, kMaxMessageSize, &message)) {
92 vector_annotations->push_back(message);
93 } else {
94 LOG(WARNING) << "could not read crash message in " << name_;
95 }
96 }
97
98 if (crash_info.message2) {
99 std::string message;
100 if (process_reader_->Memory()
101 ->ReadCStringSizeLimited(
102 crash_info.message2, kMaxMessageSize, &message)) {
103 vector_annotations->push_back(message);
104 } else {
105 LOG(WARNING) << "could not read crash message 2 in " << name_;
106 }
107 }
108 }
109
110 void MachOImageAnnotationsReader::ReadDyldErrorStringAnnotation(
111 std::vector<std::string>* vector_annotations) const {
112 // dyld stores its error string at the external symbol for |const char
113 // error_string[1024]|. See 10.9.5 dyld-239.4/src/dyld.cpp error_string.
114 if (image_reader_->FileType() != MH_DYLINKER) {
115 return;
116 }
117
118 mach_vm_address_t error_string_address;
119 if (!image_reader_->LookUpExternalDefinedSymbol("_error_string",
120 &error_string_address)) {
121 return;
122 }
123
124 std::string message;
125 if (process_reader_->Memory()
126 ->ReadCStringSizeLimited(error_string_address, 1024, &message)) {
Robert Sesek 2014/10/15 20:25:20 Globalize and use the kMaxMessageSize from above.
Mark Mentovai 2014/10/15 21:20:21 Robert Sesek wrote:
127 if (!message.empty()) {
128 vector_annotations->push_back(message);
129 }
130 } else {
131 LOG(WARNING) << "could not read dylinker error string from " << name_;
132 }
133 }
134
135 void MachOImageAnnotationsReader::ReadCrashpadSimpleAnnotations(
136 std::map<std::string, std::string>* simple_map_annotations) const {
137 mach_vm_address_t crashpad_info_address;
138 const process_types::section* crashpad_info_section =
139 image_reader_->GetSectionByName(
140 SEG_DATA, "__crashpad_info", &crashpad_info_address);
141 if (!crashpad_info_section) {
142 return;
143 }
144
145 process_types::CrashpadInfo crashpad_info;
146 if (crashpad_info_section->size <
147 crashpad_info.ExpectedSize(process_reader_)) {
148 LOG(WARNING) << "small crashpad info section size "
149 << crashpad_info_section->size << " in " << name_;
150 return;
151 }
152
153 if (!crashpad_info.Read(process_reader_, crashpad_info_address)) {
154 LOG(WARNING) << "could not read crashpad info from " << name_;
155 return;
156 }
157
158 if (crashpad_info.signature != 'cpad' ||
159 crashpad_info.size != crashpad_info_section->size ||
160 crashpad_info.version < 1) {
161 LOG(WARNING) << "unexpected crashpad info data in " << name_;
162 return;
163 }
164
165 if (!crashpad_info.simple_annotations) {
166 return;
167 }
168
169 struct Entry {
Robert Sesek 2014/10/15 20:25:20 Why not use SimpleStringDictionary::Entry here?
Mark Mentovai 2014/10/15 21:20:21 Robert Sesek wrote:
170 char key[256];
171 char value[256];
172 };
173 const size_t kNumEntries = 64;
Robert Sesek 2014/10/15 20:25:20 Similarly, SimpleStringDictionary::num_entries.
174 std::vector<Entry> simple_annotations(kNumEntries);
175 if (!process_reader_->Memory()
176 ->Read(crashpad_info.simple_annotations,
177 sizeof(Entry) * kNumEntries,
178 &simple_annotations[0])) {
179 LOG(WARNING) << "could not read simple annotations from " << name_;
180 return;
181 }
182
183 for (const auto& entry : simple_annotations) {
184 size_t key_length = strnlen(entry.key, sizeof(entry.key));
185 if (key_length) {
186 std::string key(entry.key, key_length);
187 std::string value(entry.value, strnlen(entry.value, sizeof(entry.value)));
188 if (!simple_map_annotations->count(key)) {
189 simple_map_annotations->insert(
190 std::pair<std::string, std::string>(key, value));
191 } else {
192 LOG(INFO) << "duplicate simple annotation " << key << " in " << name_;
193 }
194 }
195 }
196 }
197
198 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698