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

Side by Side Diff: src/processor/basic_source_line_resolver.cc

Issue 2029953003: Adding support for overlapping ranges to RangeMap. (Closed) Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@master
Patch Set: Created 4 years, 6 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
1 // Copyright (c) 2010 Google Inc. 1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 LogParseError("ParseStackInfo failed", line_number, &num_errors); 139 LogParseError("ParseStackInfo failed", line_number, &num_errors);
140 } 140 }
141 } else if (strncmp(buffer, "FUNC ", 5) == 0) { 141 } else if (strncmp(buffer, "FUNC ", 5) == 0) {
142 cur_func.reset(ParseFunction(buffer)); 142 cur_func.reset(ParseFunction(buffer));
143 if (!cur_func.get()) { 143 if (!cur_func.get()) {
144 LogParseError("ParseFunction failed", line_number, &num_errors); 144 LogParseError("ParseFunction failed", line_number, &num_errors);
145 } else { 145 } else {
146 // StoreRange will fail if the function has an invalid address or size. 146 // StoreRange will fail if the function has an invalid address or size.
147 // We'll silently ignore this, the function and any corresponding lines 147 // We'll silently ignore this, the function and any corresponding lines
148 // will be destroyed when cur_func is released. 148 // will be destroyed when cur_func is released.
149 functions_.StoreRange(cur_func->address, cur_func->size, cur_func); 149 functions_.StoreRange(cur_func->address, 0 /* delta */, cur_func->size,
150 cur_func);
150 } 151 }
151 } else if (strncmp(buffer, "PUBLIC ", 7) == 0) { 152 } else if (strncmp(buffer, "PUBLIC ", 7) == 0) {
152 // Clear cur_func: public symbols don't contain line number information. 153 // Clear cur_func: public symbols don't contain line number information.
153 cur_func.reset(); 154 cur_func.reset();
154 155
155 if (!ParsePublicSymbol(buffer)) { 156 if (!ParsePublicSymbol(buffer)) {
156 LogParseError("ParsePublicSymbol failed", line_number, &num_errors); 157 LogParseError("ParsePublicSymbol failed", line_number, &num_errors);
157 } 158 }
158 } else if (strncmp(buffer, "MODULE ", 7) == 0) { 159 } else if (strncmp(buffer, "MODULE ", 7) == 0) {
159 // Ignore these. They're not of any use to BasicSourceLineResolver, 160 // Ignore these. They're not of any use to BasicSourceLineResolver,
160 // which is fed modules by a SymbolSupplier. These lines are present to 161 // which is fed modules by a SymbolSupplier. These lines are present to
161 // aid other tools in properly placing symbol files so that they can 162 // aid other tools in properly placing symbol files so that they can
162 // be accessed by a SymbolSupplier. 163 // be accessed by a SymbolSupplier.
163 // 164 //
164 // MODULE <guid> <age> <filename> 165 // MODULE <guid> <age> <filename>
165 } else if (strncmp(buffer, "INFO ", 5) == 0) { 166 } else if (strncmp(buffer, "INFO ", 5) == 0) {
166 // Ignore these as well, they're similarly just for housekeeping. 167 // Ignore these as well, they're similarly just for housekeeping.
167 // 168 //
168 // INFO CODE_ID <code id> <filename> 169 // INFO CODE_ID <code id> <filename>
169 } else { 170 } else {
170 if (!cur_func.get()) { 171 if (!cur_func.get()) {
171 LogParseError("Found source line data without a function", 172 LogParseError("Found source line data without a function",
172 line_number, &num_errors); 173 line_number, &num_errors);
173 } else { 174 } else {
174 Line *line = ParseLine(buffer); 175 Line *line = ParseLine(buffer);
175 if (!line) { 176 if (!line) {
176 LogParseError("ParseLine failed", line_number, &num_errors); 177 LogParseError("ParseLine failed", line_number, &num_errors);
177 } else { 178 } else {
178 cur_func->lines.StoreRange(line->address, line->size, 179 cur_func->lines.StoreRange(line->address, 0 /* delta */, line->size,
179 linked_ptr<Line>(line)); 180 linked_ptr<Line>(line));
180 } 181 }
181 } 182 }
182 } 183 }
183 if (num_errors > kMaxErrorsBeforeBailing) { 184 if (num_errors > kMaxErrorsBeforeBailing) {
184 break; 185 break;
185 } 186 }
186 buffer = strtok_r(NULL, "\r\n", &save_ptr); 187 buffer = strtok_r(NULL, "\r\n", &save_ptr);
187 } 188 }
188 is_corrupt_ = num_errors > 0; 189 is_corrupt_ = num_errors > 0;
189 return true; 190 return true;
190 } 191 }
191 192
192 void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const { 193 void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
193 MemAddr address = frame->instruction - frame->module->base_address(); 194 MemAddr address = frame->instruction - frame->module->base_address();
194 195
195 // First, look for a FUNC record that covers address. Use 196 // First, look for a FUNC record that covers address. Use
196 // RetrieveNearestRange instead of RetrieveRange so that, if there 197 // RetrieveNearestRange instead of RetrieveRange so that, if there
197 // is no such function, we can use the next function to bound the 198 // is no such function, we can use the next function to bound the
198 // extent of the PUBLIC symbol we find, below. This does mean we 199 // extent of the PUBLIC symbol we find, below. This does mean we
199 // need to check that address indeed falls within the function we 200 // need to check that address indeed falls within the function we
200 // find; do the range comparison in an overflow-friendly way. 201 // find; do the range comparison in an overflow-friendly way.
201 linked_ptr<Function> func; 202 linked_ptr<Function> func;
202 linked_ptr<PublicSymbol> public_symbol; 203 linked_ptr<PublicSymbol> public_symbol;
203 MemAddr function_base; 204 MemAddr function_base;
204 MemAddr function_size; 205 MemAddr function_size;
205 MemAddr public_address; 206 MemAddr public_address;
206 if (functions_.RetrieveNearestRange(address, &func, 207 if (functions_.RetrieveNearestRange(address, &func, &function_base,
207 &function_base, &function_size) && 208 NULL /* delta */, &function_size) &&
208 address >= function_base && address - function_base < function_size) { 209 address >= function_base && address - function_base < function_size) {
209 frame->function_name = func->name; 210 frame->function_name = func->name;
210 frame->function_base = frame->module->base_address() + function_base; 211 frame->function_base = frame->module->base_address() + function_base;
211 212
212 linked_ptr<Line> line; 213 linked_ptr<Line> line;
213 MemAddr line_base; 214 MemAddr line_base;
214 if (func->lines.RetrieveRange(address, &line, &line_base, NULL)) { 215 if (func->lines.RetrieveRange(address, &line, &line_base, NULL, NULL)) {
215 FileMap::const_iterator it = files_.find(line->source_file_id); 216 FileMap::const_iterator it = files_.find(line->source_file_id);
216 if (it != files_.end()) { 217 if (it != files_.end()) {
217 frame->source_file_name = files_.find(line->source_file_id)->second; 218 frame->source_file_name = files_.find(line->source_file_id)->second;
218 } 219 }
219 frame->source_line = line->line; 220 frame->source_line = line->line;
220 frame->source_line_base = frame->module->base_address() + line_base; 221 frame->source_line_base = frame->module->base_address() + line_base;
221 } 222 }
222 } else if (public_symbols_.Retrieve(address, 223 } else if (public_symbols_.Retrieve(address,
223 &public_symbol, &public_address) && 224 &public_symbol, &public_address) &&
224 (!func.get() || public_address > function_base)) { 225 (!func.get() || public_address > function_base)) {
(...skipping 24 matching lines...) Expand all
249 250
250 // Even without a relevant STACK line, many functions contain 251 // Even without a relevant STACK line, many functions contain
251 // information about how much space their parameters consume on the 252 // information about how much space their parameters consume on the
252 // stack. Use RetrieveNearestRange instead of RetrieveRange, so that 253 // stack. Use RetrieveNearestRange instead of RetrieveRange, so that
253 // we can use the function to bound the extent of the PUBLIC symbol, 254 // we can use the function to bound the extent of the PUBLIC symbol,
254 // below. However, this does mean we need to check that ADDRESS 255 // below. However, this does mean we need to check that ADDRESS
255 // falls within the retrieved function's range; do the range 256 // falls within the retrieved function's range; do the range
256 // comparison in an overflow-friendly way. 257 // comparison in an overflow-friendly way.
257 linked_ptr<Function> function; 258 linked_ptr<Function> function;
258 MemAddr function_base, function_size; 259 MemAddr function_base, function_size;
259 if (functions_.RetrieveNearestRange(address, &function, 260 if (functions_.RetrieveNearestRange(address, &function, &function_base,
260 &function_base, &function_size) && 261 NULL /* delta */, &function_size) &&
261 address >= function_base && address - function_base < function_size) { 262 address >= function_base && address - function_base < function_size) {
262 result->parameter_size = function->parameter_size; 263 result->parameter_size = function->parameter_size;
263 result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE; 264 result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
264 return result.release(); 265 return result.release();
265 } 266 }
266 267
267 // PUBLIC symbols might have a parameter size. Use the function we 268 // PUBLIC symbols might have a parameter size. Use the function we
268 // found above to limit the range the public symbol covers. 269 // found above to limit the range the public symbol covers.
269 linked_ptr<PublicSymbol> public_symbol; 270 linked_ptr<PublicSymbol> public_symbol;
270 MemAddr public_address; 271 MemAddr public_address;
271 if (public_symbols_.Retrieve(address, &public_symbol, &public_address) && 272 if (public_symbols_.Retrieve(address, &public_symbol, &public_address) &&
272 (!function.get() || public_address > function_base)) { 273 (!function.get() || public_address > function_base)) {
273 result->parameter_size = public_symbol->parameter_size; 274 result->parameter_size = public_symbol->parameter_size;
274 } 275 }
275 276
276 return NULL; 277 return NULL;
277 } 278 }
278 279
279 CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo( 280 CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
280 const StackFrame *frame) const { 281 const StackFrame *frame) const {
281 MemAddr address = frame->instruction - frame->module->base_address(); 282 MemAddr address = frame->instruction - frame->module->base_address();
282 MemAddr initial_base, initial_size; 283 MemAddr initial_base, initial_size;
283 string initial_rules; 284 string initial_rules;
284 285
285 // Find the initial rule whose range covers this address. That 286 // Find the initial rule whose range covers this address. That
286 // provides an initial set of register recovery rules. Then, walk 287 // provides an initial set of register recovery rules. Then, walk
287 // forward from the initial rule's starting address to frame's 288 // forward from the initial rule's starting address to frame's
288 // instruction address, applying delta rules. 289 // instruction address, applying delta rules.
289 if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, 290 if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, &initial_base,
290 &initial_base, &initial_size)) { 291 NULL /* delta */, &initial_size)) {
291 return NULL; 292 return NULL;
292 } 293 }
293 294
294 // Create a frame info structure, and populate it with the rules from 295 // Create a frame info structure, and populate it with the rules from
295 // the STACK CFI INIT record. 296 // the STACK CFI INIT record.
296 scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo()); 297 scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo());
297 if (!ParseCFIRuleSet(initial_rules, rules.get())) 298 if (!ParseCFIRuleSet(initial_rules, rules.get()))
298 return NULL; 299 return NULL;
299 300
300 // Find the first delta rule that falls within the initial rule's range. 301 // Find the first delta rule that falls within the initial rule's range.
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 if (!address_field) return false; 443 if (!address_field) return false;
443 444
444 char *size_field = strtok_r(NULL, " \r\n", &cursor); 445 char *size_field = strtok_r(NULL, " \r\n", &cursor);
445 if (!size_field) return false; 446 if (!size_field) return false;
446 447
447 char *initial_rules = strtok_r(NULL, "\r\n", &cursor); 448 char *initial_rules = strtok_r(NULL, "\r\n", &cursor);
448 if (!initial_rules) return false; 449 if (!initial_rules) return false;
449 450
450 MemAddr address = strtoul(address_field, NULL, 16); 451 MemAddr address = strtoul(address_field, NULL, 16);
451 MemAddr size = strtoul(size_field, NULL, 16); 452 MemAddr size = strtoul(size_field, NULL, 16);
452 cfi_initial_rules_.StoreRange(address, size, initial_rules); 453 cfi_initial_rules_.StoreRange(address, 0 /* delta */, size, initial_rules);
453 return true; 454 return true;
454 } 455 }
455 456
456 // This record has the form "STACK <address> <rules...>". 457 // This record has the form "STACK <address> <rules...>".
457 char *address_field = init_or_address; 458 char *address_field = init_or_address;
458 char *delta_rules = strtok_r(NULL, "\r\n", &cursor); 459 char *delta_rules = strtok_r(NULL, "\r\n", &cursor);
459 if (!delta_rules) return false; 460 if (!delta_rules) return false;
460 MemAddr address = strtoul(address_field, NULL, 16); 461 MemAddr address = strtoul(address_field, NULL, 16);
461 cfi_delta_rules_[address] = delta_rules; 462 cfi_delta_rules_[address] = delta_rules;
462 return true; 463 return true;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 if (!IsValidAfterNumber(after_number) || 589 if (!IsValidAfterNumber(after_number) ||
589 *address == std::numeric_limits<unsigned long long>::max()) { 590 *address == std::numeric_limits<unsigned long long>::max()) {
590 return false; 591 return false;
591 } 592 }
592 *stack_param_size = strtol(tokens[1], &after_number, 16); 593 *stack_param_size = strtol(tokens[1], &after_number, 16);
593 if (!IsValidAfterNumber(after_number) || 594 if (!IsValidAfterNumber(after_number) ||
594 *stack_param_size == std::numeric_limits<long>::max() || 595 *stack_param_size == std::numeric_limits<long>::max() ||
595 *stack_param_size < 0) { 596 *stack_param_size < 0) {
596 return false; 597 return false;
597 } 598 }
598 *name = tokens[2]; 599 *name = tokens[2];
599 600
600 return true; 601 return true;
601 } 602 }
602 603
603 // static 604 // static
604 bool SymbolParseHelper::IsValidAfterNumber(char *after_number) { 605 bool SymbolParseHelper::IsValidAfterNumber(char *after_number) {
605 if (after_number != NULL && strchr(kWhitespace, *after_number) != NULL) { 606 if (after_number != NULL && strchr(kWhitespace, *after_number) != NULL) {
606 return true; 607 return true;
607 } 608 }
608 return false; 609 return false;
609 } 610 }
610 611
611 } // namespace google_breakpad 612 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698