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

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

Issue 666483002: Create snapshot/mac and move some files from snapshot and util to there (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad/+/master
Patch Set: Move process_reader, process_types, and mach_o_image*_reader from util/mac to snapshot/mac 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
« no previous file with comments | « util/mac/mach_o_image_segment_reader.h ('k') | util/mac/mach_o_image_segment_reader_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_segment_reader.h"
16
17 #include <mach-o/loader.h>
18
19 #include "base/logging.h"
20 #include "base/strings/stringprintf.h"
21 #include "util/mac/checked_mach_address_range.h"
22 #include "util/mac/process_reader.h"
23 #include "util/stdlib/strnlen.h"
24
25 namespace crashpad {
26
27 namespace {
28
29 std::string SizeLimitedCString(const char* c_string, size_t max_length) {
30 return std::string(c_string, strnlen(c_string, max_length));
31 }
32
33 } // namespace
34
35 MachOImageSegmentReader::MachOImageSegmentReader()
36 : segment_command_(),
37 sections_(),
38 section_map_(),
39 slide_(0),
40 initialized_(),
41 initialized_slide_() {
42 }
43
44 MachOImageSegmentReader::~MachOImageSegmentReader() {
45 }
46
47 bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader,
48 mach_vm_address_t load_command_address,
49 const std::string& load_command_info) {
50 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
51
52 if (!segment_command_.Read(process_reader, load_command_address)) {
53 LOG(WARNING) << "could not read segment_command" << load_command_info;
54 return false;
55 }
56
57 const uint32_t kExpectedSegmentCommand =
58 process_reader->Is64Bit() ? LC_SEGMENT_64 : LC_SEGMENT;
59 DCHECK_EQ(segment_command_.cmd, kExpectedSegmentCommand);
60 DCHECK_GE(segment_command_.cmdsize, segment_command_.Size());
61 const size_t kSectionStructSize =
62 process_types::section::ExpectedSize(process_reader);
63 const size_t kRequiredSize =
64 segment_command_.Size() + segment_command_.nsects * kSectionStructSize;
65 if (segment_command_.cmdsize < kRequiredSize) {
66 LOG(WARNING) << base::StringPrintf(
67 "segment command cmdsize 0x%x insufficient for %u "
68 "section%s (0x%zx)",
69 segment_command_.cmdsize,
70 segment_command_.nsects,
71 segment_command_.nsects == 1 ? "" : "s",
72 kRequiredSize) << load_command_info;
73 return false;
74 }
75
76 std::string segment_name = NameInternal();
77 std::string segment_info = base::StringPrintf(
78 ", segment %s%s", segment_name.c_str(), load_command_info.c_str());
79
80 // This checks the unslid segment range. The slid range (as loaded into
81 // memory) will be checked later by MachOImageReader.
82 CheckedMachAddressRange segment_range(
83 process_reader, segment_command_.vmaddr, segment_command_.vmsize);
84 if (!segment_range.IsValid()) {
85 LOG(WARNING) << base::StringPrintf("invalid segment range 0x%llx + 0x%llx",
86 segment_command_.vmaddr,
87 segment_command_.vmsize) << segment_info;
88 return false;
89 }
90
91 sections_.resize(segment_command_.nsects);
92 if (!process_types::section::ReadArrayInto(
93 process_reader,
94 load_command_address + segment_command_.Size(),
95 segment_command_.nsects,
96 &sections_[0])) {
97 LOG(WARNING) << "could not read sections" << segment_info;
98 return false;
99 }
100
101 for (size_t section_index = 0;
102 section_index < sections_.size();
103 ++section_index) {
104 const process_types::section& section = sections_[section_index];
105 std::string section_segment_name = SegmentNameString(section.segname);
106 std::string section_name = SectionNameString(section.sectname);
107 std::string section_full_name =
108 SegmentAndSectionNameString(section.segname, section.sectname);
109
110 std::string section_info = base::StringPrintf(", section %s %zu/%zu%s",
111 section_full_name.c_str(),
112 section_index,
113 sections_.size(),
114 load_command_info.c_str());
115
116 if (section_segment_name != segment_name) {
117 LOG(WARNING) << "section.segname incorrect in segment " << segment_name
118 << section_info;
119 return false;
120 }
121
122 CheckedMachAddressRange section_range(
123 process_reader, section.addr, section.size);
124 if (!section_range.IsValid()) {
125 LOG(WARNING) << base::StringPrintf(
126 "invalid section range 0x%llx + 0x%llx",
127 section.addr,
128 section.size) << section_info;
129 return false;
130 }
131
132 if (!segment_range.ContainsRange(section_range)) {
133 LOG(WARNING) << base::StringPrintf(
134 "section at 0x%llx + 0x%llx outside of segment at "
135 "0x%llx + 0x%llx",
136 section.addr,
137 section.size,
138 segment_command_.vmaddr,
139 segment_command_.vmsize) << section_info;
140 return false;
141 }
142
143 uint32_t section_type = (section.flags & SECTION_TYPE);
144 bool zero_fill = section_type == S_ZEROFILL ||
145 section_type == S_GB_ZEROFILL ||
146 section_type == S_THREAD_LOCAL_ZEROFILL;
147
148 // Zero-fill section types aren’t mapped from the file, so their |offset|
149 // fields are irrelevant and are typically 0.
150 if (!zero_fill &&
151 section.offset - segment_command_.fileoff !=
152 section.addr - segment_command_.vmaddr) {
153 LOG(WARNING) << base::StringPrintf(
154 "section type 0x%x at 0x%llx has unexpected offset "
155 "0x%x in segment at 0x%llx with offset 0x%llx",
156 section_type,
157 section.addr,
158 section.offset,
159 segment_command_.vmaddr,
160 segment_command_.fileoff) << section_info;
161 return false;
162 }
163
164 const auto& iterator = section_map_.find(section_name);
165 if (iterator != section_map_.end()) {
166 LOG(WARNING) << base::StringPrintf("duplicate section name at %zu",
167 iterator->second) << section_info;
168 return false;
169 }
170
171 section_map_[section_name] = section_index;
172 }
173
174 INITIALIZATION_STATE_SET_VALID(initialized_);
175 return true;
176 }
177
178 std::string MachOImageSegmentReader::Name() const {
179 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
180 return NameInternal();
181 }
182
183 mach_vm_address_t MachOImageSegmentReader::Address() const {
184 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
185 INITIALIZATION_STATE_DCHECK_VALID(initialized_slide_);
186 return vmaddr() + (SegmentSlides() ? slide_ : 0);
187 }
188
189 mach_vm_size_t MachOImageSegmentReader::Size() const {
190 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
191 INITIALIZATION_STATE_DCHECK_VALID(initialized_slide_);
192 return vmsize() + (SegmentSlides() ? 0 : slide_);
193 }
194
195 const process_types::section* MachOImageSegmentReader::GetSectionByName(
196 const std::string& section_name,
197 mach_vm_address_t* address) const {
198 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
199
200 const auto& iterator = section_map_.find(section_name);
201 if (iterator == section_map_.end()) {
202 return nullptr;
203 }
204
205 return GetSectionAtIndex(iterator->second, address);
206 }
207
208 const process_types::section* MachOImageSegmentReader::GetSectionAtIndex(
209 size_t index,
210 mach_vm_address_t* address) const {
211 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
212 CHECK_LT(index, sections_.size());
213
214 const process_types::section* section = &sections_[index];
215
216 if (address) {
217 INITIALIZATION_STATE_DCHECK_VALID(initialized_slide_);
218 *address = section->addr + (SegmentSlides() ? slide_ : 0);
219 }
220
221 return section;
222 }
223
224 bool MachOImageSegmentReader::SegmentSlides() const {
225 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
226
227 // These are the same rules that the kernel uses to identify __PAGEZERO. See
228 // 10.9.4 xnu-2422.110.17/bsd/kern/mach_loader.c load_segment().
229 return !(segment_command_.vmaddr == 0 && segment_command_.filesize == 0 &&
230 segment_command_.vmsize != 0 &&
231 (segment_command_.initprot & VM_PROT_ALL) == VM_PROT_NONE &&
232 (segment_command_.maxprot & VM_PROT_ALL) == VM_PROT_NONE);
233 }
234
235 // static
236 std::string MachOImageSegmentReader::SegmentNameString(
237 const char* segment_name_c) {
238 // This is used to interpret the segname field of both the segment_command and
239 // section structures, so be sure that they’re identical.
240 static_assert(sizeof(process_types::segment_command::segname) ==
241 sizeof(process_types::section::segname),
242 "sizes must be equal");
243
244 return SizeLimitedCString(segment_name_c,
245 sizeof(process_types::segment_command::segname));
246 }
247
248 // static
249 std::string MachOImageSegmentReader::SectionNameString(
250 const char* section_name_c) {
251 return SizeLimitedCString(section_name_c,
252 sizeof(process_types::section::sectname));
253 }
254
255 // static
256 std::string MachOImageSegmentReader::SegmentAndSectionNameString(
257 const char* segment_name_c,
258 const char* section_name_c) {
259 return base::StringPrintf("%s,%s",
260 SegmentNameString(segment_name_c).c_str(),
261 SectionNameString(section_name_c).c_str());
262 }
263
264 std::string MachOImageSegmentReader::NameInternal() const {
265 return SegmentNameString(segment_command_.segname);
266 }
267
268 void MachOImageSegmentReader::SetSlide(mach_vm_size_t slide) {
269 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
270 INITIALIZATION_STATE_SET_INITIALIZING(initialized_slide_);
271 slide_ = slide;
272 INITIALIZATION_STATE_SET_VALID(initialized_slide_);
273 }
274
275 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/mac/mach_o_image_segment_reader.h ('k') | util/mac/mach_o_image_segment_reader_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698