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

Side by Side Diff: util/mac/mach_o_image_symbol_table_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_symbol_table_reader.h ('k') | util/mac/process_reader.h » ('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_symbol_table_reader.h"
16
17 #include <mach-o/loader.h>
18 #include <mach-o/nlist.h>
19
20 #include "base/memory/scoped_ptr.h"
21 #include "base/strings/stringprintf.h"
22 #include "util/mac/checked_mach_address_range.h"
23 #include "util/mach/task_memory.h"
24
25 namespace crashpad {
26
27 namespace internal {
28
29 //! \brief The internal implementation for MachOImageSymbolTableReader.
30 //!
31 //! Initialization is broken into more than one function that needs to share
32 //! data, so member variables are used. However, much of this data is irrelevant
33 //! after initialization is completed, so rather than doing it in
34 //! MachOImageSymbolTableReader, it’s handled by this class, which is a “friend”
35 //! of MachOImageSymbolTableReader.
36 class MachOImageSymbolTableReaderInitializer {
37 public:
38 MachOImageSymbolTableReaderInitializer(
39 ProcessReader* process_reader,
40 const MachOImageSegmentReader* linkedit_segment,
41 const std::string& module_info)
42 : module_info_(module_info),
43 linkedit_range_(),
44 process_reader_(process_reader),
45 linkedit_segment_(linkedit_segment) {
46 linkedit_range_.SetRange(
47 process_reader_, linkedit_segment->Address(), linkedit_segment->Size());
48 DCHECK(linkedit_range_.IsValid());
49 }
50
51 ~MachOImageSymbolTableReaderInitializer() {}
52
53 //! \brief Reads the symbol table from another process.
54 //!
55 //! \sa MachOImageSymbolTableReader::Initialize()
56 bool Initialize(const process_types::symtab_command* symtab_command,
57 const process_types::dysymtab_command* dysymtab_command,
58 MachOImageSymbolTableReader::SymbolInformationMap*
59 external_defined_symbols) {
60 mach_vm_address_t symtab_address =
61 AddressForLinkEditComponent(symtab_command->symoff);
62 uint32_t symbol_count = symtab_command->nsyms;
63 size_t nlist_size = process_types::nlist::ExpectedSize(process_reader_);
64 mach_vm_size_t symtab_size = symbol_count * nlist_size;
65 if (!IsInLinkEditSegment(symtab_address, symtab_size, "symtab")) {
66 return false;
67 }
68
69 // If a dysymtab is present, use it to filter the symtab for just the
70 // portion used for extdefsym. If no dysymtab is present, the entire symtab
71 // will need to be consulted.
72 uint32_t skip_count = 0;
73 if (dysymtab_command) {
74 if (dysymtab_command->iextdefsym >= symtab_command->nsyms ||
75 dysymtab_command->iextdefsym + dysymtab_command->nextdefsym >
76 symtab_command->nsyms) {
77 LOG(WARNING) << base::StringPrintf(
78 "dysymtab extdefsym %u + %u > symtab nsyms %u",
79 dysymtab_command->iextdefsym,
80 dysymtab_command->nextdefsym,
81 symtab_command->nsyms) << module_info_;
82 return false;
83 }
84
85 skip_count = dysymtab_command->iextdefsym;
86 mach_vm_size_t skip_size = skip_count * nlist_size;
87 symtab_address += skip_size;
88 symtab_size -= skip_size;
89 symbol_count = dysymtab_command->nextdefsym;
90 }
91
92 mach_vm_address_t strtab_address =
93 AddressForLinkEditComponent(symtab_command->stroff);
94 mach_vm_size_t strtab_size = symtab_command->strsize;
95 if (!IsInLinkEditSegment(strtab_address, strtab_size, "strtab")) {
96 return false;
97 }
98
99 scoped_ptr<process_types::nlist[]> symbols(
100 new process_types::nlist[symtab_command->nsyms]);
101 if (!process_types::nlist::ReadArrayInto(
102 process_reader_, symtab_address, symbol_count, &symbols[0])) {
103 LOG(WARNING) << "could not read symbol table" << module_info_;
104 return false;
105 }
106
107 scoped_ptr<TaskMemory::MappedMemory> string_table;
108 for (size_t symbol_index = 0; symbol_index < symbol_count; ++symbol_index) {
109 const process_types::nlist& symbol = symbols[symbol_index];
110 std::string symbol_info = base::StringPrintf(", symbol index %zu%s",
111 skip_count + symbol_index,
112 module_info_.c_str());
113 uint8_t symbol_type = symbol.n_type & N_TYPE;
114 if ((symbol.n_type & N_STAB) == 0 && (symbol.n_type & N_PEXT) == 0 &&
115 (symbol_type == N_ABS || symbol_type == N_SECT) &&
116 (symbol.n_type & N_EXT)) {
117 if (symbol.n_strx >= strtab_size) {
118 LOG(WARNING) << base::StringPrintf(
119 "string at 0x%x out of bounds (0x%llx)",
120 symbol.n_strx,
121 strtab_size) << symbol_info;
122 return false;
123 }
124
125 if (!string_table) {
126 string_table = process_reader_->Memory()->ReadMapped(
127 strtab_address, strtab_size);
128 if (!string_table) {
129 LOG(WARNING) << "could not read string table" << module_info_;
130 return false;
131 }
132 }
133
134 std::string name;
135 if (!string_table->ReadCString(symbol.n_strx, &name)) {
136 LOG(WARNING) << "could not read string" << symbol_info;
137 return false;
138 }
139
140 if (symbol_type == N_ABS && symbol.n_sect != NO_SECT) {
141 LOG(WARNING) << base::StringPrintf("N_ABS symbol %s in section %u",
142 name.c_str(),
143 symbol.n_sect) << symbol_info;
144 return false;
145 }
146
147 if (symbol_type == N_SECT && symbol.n_sect == NO_SECT) {
148 LOG(WARNING) << base::StringPrintf(
149 "N_SECT symbol %s in section NO_SECT",
150 name.c_str()) << symbol_info;
151 return false;
152 }
153
154 if (external_defined_symbols->count(name)) {
155 LOG(WARNING) << "duplicate symbol " << name << symbol_info;
156 return false;
157 }
158
159 MachOImageSymbolTableReader::SymbolInformation symbol_info;
160 symbol_info.value = symbol.n_value;
161 symbol_info.section = symbol.n_sect;
162 (*external_defined_symbols)[name] = symbol_info;
163 } else if (dysymtab_command) {
164 LOG(WARNING) << "non-external symbol in extdefsym" << symbol_info;
165 return false;
166 }
167 }
168
169 return true;
170 }
171
172 private:
173 //! \brief Computes the address for data in the `__LINKEDIT` segment
174 //! identified by its file offset in a Mach-O image.
175 //!
176 //! \param[in] fileoff The file offset relative to the beginning of an image’s
177 //! `mach_header` or `mach_header_64` of the data in the `__LINKEDIT`
178 //! segment.
179 //!
180 //! \return The address, in the remote process’ address space, of the
181 //! requested data.
182 mach_vm_address_t AddressForLinkEditComponent(uint32_t fileoff) const {
183 return linkedit_range_.Base() + fileoff - linkedit_segment_->fileoff();
184 }
185
186 //! \brief Determines whether an address range is located within the
187 //! `__LINKEDIT` segment.
188 //!
189 //! \param[in] address The base address of the range to check.
190 //! \param[in] size The size of the range to check.
191 //! \param[in] tag A string that identifies the range being checked. This is
192 //! used only for logging.
193 //!
194 //! \return `true` if the range identified by \a address + \a size lies
195 //! entirely within the `__LINKEDIT` segment. `false` if that range is
196 //! invalid, or if that range is not contained by the `__LINKEDIT`
197 //! segment, with an appropriate message logged.
198 bool IsInLinkEditSegment(mach_vm_address_t address,
199 mach_vm_size_t size,
200 const char* tag) const {
201 CheckedMachAddressRange subrange(process_reader_, address, size);
202 if (!subrange.IsValid()) {
203 LOG(WARNING) << base::StringPrintf("invalid %s range (0x%llx + 0x%llx)",
204 tag,
205 address,
206 size) << module_info_;
207 return false;
208 }
209
210 if (!linkedit_range_.ContainsRange(subrange)) {
211 LOG(WARNING) << base::StringPrintf(
212 "%s at 0x%llx + 0x%llx outside of " SEG_LINKEDIT
213 " segment at 0x%llx + 0x%llx",
214 tag,
215 address,
216 size,
217 linkedit_range_.Base(),
218 linkedit_range_.Size()) << module_info_;
219 return false;
220 }
221
222 return true;
223 }
224
225 std::string module_info_;
226 CheckedMachAddressRange linkedit_range_;
227 ProcessReader* process_reader_; // weak
228 const MachOImageSegmentReader* linkedit_segment_; // weak
229
230 DISALLOW_COPY_AND_ASSIGN(MachOImageSymbolTableReaderInitializer);
231 };
232
233 } // namespace internal
234
235 MachOImageSymbolTableReader::MachOImageSymbolTableReader()
236 : external_defined_symbols_(), initialized_() {
237 }
238
239 MachOImageSymbolTableReader::~MachOImageSymbolTableReader() {
240 }
241
242 bool MachOImageSymbolTableReader::Initialize(
243 ProcessReader* process_reader,
244 const process_types::symtab_command* symtab_command,
245 const process_types::dysymtab_command* dysymtab_command,
246 const MachOImageSegmentReader* linkedit_segment,
247 const std::string& module_info) {
248 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
249
250 internal::MachOImageSymbolTableReaderInitializer initializer(process_reader,
251 linkedit_segment,
252 module_info);
253 if (!initializer.Initialize(
254 symtab_command, dysymtab_command, &external_defined_symbols_)) {
255 return false;
256 }
257
258 INITIALIZATION_STATE_SET_VALID(initialized_);
259 return true;
260 }
261
262 const MachOImageSymbolTableReader::SymbolInformation*
263 MachOImageSymbolTableReader::LookUpExternalDefinedSymbol(
264 const std::string& name) const {
265 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
266
267 const auto& iterator = external_defined_symbols_.find(name);
268 if (iterator == external_defined_symbols_.end()) {
269 return nullptr;
270 }
271 return &iterator->second;
272 }
273
274 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/mac/mach_o_image_symbol_table_reader.h ('k') | util/mac/process_reader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698