OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |