diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc index 5dc73801..4a565f11 100644 --- a/src/processor/basic_source_line_resolver.cc +++ b/src/processor/basic_source_line_resolver.cc @@ -241,39 +241,59 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory( void BasicSourceLineResolver::Module::ConstructInlineFrames( StackFrame* frame, MemAddr address, - const RangeMap>& inlines, + const ContainedRangeMap>& inline_map, deque>* inlined_frames) const { - linked_ptr in; - MemAddr inline_base; - if (!inlines.RetrieveRange(address, &in, &inline_base, nullptr, nullptr)) - return; - auto origin = inline_origins_.find(in->origin_id); - if (origin == inline_origins_.end()) + vector*> inlines; + if (!inline_map.RetrieveRanges(address, inlines)) { return; + } - // Update parent frame's source line (and source file if it's the new format). - frame->source_line = in->call_site_line; - if (in->has_call_site_file_id) { - auto file = files_.find(in->call_site_file_id); - if (file != files_.end()) { - frame->source_file_name = file->second; + for (const linked_ptr* const in : inlines) { + unique_ptr new_frame = + unique_ptr(new StackFrame(*frame)); + auto origin = inline_origins_.find(in->get()->origin_id); + if (origin != inline_origins_.end()) { + new_frame->function_name = origin->second->name; + } else { + new_frame->function_name = ""; + } + + // Store call site file and line in current frame, which will be updated + // later. + new_frame->source_line = in->get()->call_site_line; + if (in->get()->has_call_site_file_id) { + auto file = files_.find(in->get()->call_site_file_id); + if (file != files_.end()) { + new_frame->source_file_name = file->second; + } + } + + // Use the starting address of the inlined range as inlined function base. + new_frame->function_base = new_frame->module->base_address(); + for (const auto& range : in->get()->inline_ranges) { + if (address >= range.first && address < range.first + range.second) { + new_frame->function_base += range.first; + break; + } + } + new_frame->trust = StackFrame::FRAME_TRUST_INLINE; + + // The inlines vector has an order from innermost entry to outermost entry. + // By push_back, we will have inlined_frames with the same order. + inlined_frames->push_back(std::move(new_frame)); + } + + // Update the source file and source line for each inlined frame. + if (!inlined_frames->empty()) { + string parent_frame_source_file_name = frame->source_file_name; + int parent_frame_source_line = frame->source_line; + frame->source_file_name = inlined_frames->back()->source_file_name; + frame->source_line = inlined_frames->back()->source_line; + for (unique_ptr& inlined_frame : *inlined_frames) { + std::swap(inlined_frame->source_file_name, parent_frame_source_file_name); + std::swap(inlined_frame->source_line, parent_frame_source_line); } } - - StackFrame new_frame = StackFrame(*frame); - new_frame.function_name = origin->second->name; - if (origin->second->has_file_id) { - auto file = files_.find(origin->second->source_file_id); - if (file != files_.end()) - new_frame.source_file_name = file->second; - } - // Use the starting adress of the inlined range as inlined function base. - new_frame.function_base = new_frame.module->base_address() + inline_base; - new_frame.trust = StackFrame::FRAME_TRUST_INLINE; - ConstructInlineFrames(&new_frame, address, in->child_inlines, inlined_frames); - // Add child_frame after ConstructInlineFrames so that the innermost frame is - // the first frame inside inlined_frames. - inlined_frames->push_back(unique_ptr(new StackFrame(new_frame))); } void BasicSourceLineResolver::Module::LookupAddress( @@ -312,14 +332,7 @@ void BasicSourceLineResolver::Module::LookupAddress( // Check if this is inlined function call. if (inlined_frames) { - int source_line = frame->source_line; - string source_file_name = frame->source_file_name; ConstructInlineFrames(frame, address, func->inlines, inlined_frames); - if (!inlined_frames->empty()) { - // Update the inner most frame's source line and source file name. - inlined_frames->front()->source_line = source_line; - inlined_frames->front()->source_file_name = source_file_name; - } } } else if (public_symbols_.Retrieve(address, &public_symbol, &public_address) && @@ -606,19 +619,12 @@ bool BasicSourceLineResolver::Function::AppendInline(linked_ptr in) { // This happends if in's parent wasn't added due to a malformed INLINE record. if (in->inline_nest_level > last_added_inline_nest_level + 1) return false; - RangeMap>* current_inlines = &this->inlines; - auto iter = recent_inlines.find(in->inline_nest_level - 1); - if (iter != recent_inlines.end()) - current_inlines = &iter->second->child_inlines; - else - assert(in->inline_nest_level == 0); last_added_inline_nest_level = in->inline_nest_level; - recent_inlines[last_added_inline_nest_level] = in; // Store all ranges into current level of inlines. for (auto range : in->inline_ranges) - current_inlines->StoreRange(range.first, range.second, in); + inlines.StoreRange(range.first, range.second, in); return true; } diff --git a/src/processor/basic_source_line_resolver_types.h b/src/processor/basic_source_line_resolver_types.h index 7d9d5cb5..6bd6968c 100644 --- a/src/processor/basic_source_line_resolver_types.h +++ b/src/processor/basic_source_line_resolver_types.h @@ -61,28 +61,26 @@ BasicSourceLineResolver::Function : public SourceLineResolverBase::Function { MemAddr function_address, MemAddr code_size, int set_parameter_size, - bool is_mutiple) : Base(function_name, - function_address, - code_size, - set_parameter_size, - is_mutiple), - inlines(), - lines(), - last_added_inline_nest_level(0) { } + bool is_mutiple) + : Base(function_name, + function_address, + code_size, + set_parameter_size, + is_mutiple), + inlines(true), + last_added_inline_nest_level(0) {} + // Append inline into corresponding RangeMap. // This function assumes it's called in the order of reading INLINE records. bool AppendInline(linked_ptr in); - RangeMap> inlines; + ContainedRangeMap> inlines; RangeMap> lines; private: typedef SourceLineResolverBase::Function Base; - // A map from inline_nest_level to most recently added Inline* at that level. - std::map> recent_inlines; - - // The last added inline_nest_level in recent_inlines. + // The last added inline_nest_level from INLINE record. int last_added_inline_nest_level; }; @@ -110,14 +108,14 @@ class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module { StackFrame* frame, std::deque>* inlined_frame) const; - // Recursively construct inlined frames for |frame| and store them in - // |inline_frames|. |frame|'s source line and source file name may be updated - // if an inlined frame is found inside |frame|. As a result, the innermost - // inlined frame will be the first one in |inline_frames|. + // Construct inlined frames for |frame| and store them in |inline_frames|. + // |frame|'s source line and source file name may be updated if an inlined + // frame is found inside |frame|. As a result, the innermost inlined frame + // will be the first one in |inline_frames|. virtual void ConstructInlineFrames( StackFrame* frame, MemAddr address, - const RangeMap>& inlines, + const ContainedRangeMap>& inline_map, std::deque>* inline_frames) const; // If Windows stack walking information is available covering ADDRESS, diff --git a/src/processor/source_line_resolver_base_types.h b/src/processor/source_line_resolver_base_types.h index bac91802..4d3ce066 100644 --- a/src/processor/source_line_resolver_base_types.h +++ b/src/processor/source_line_resolver_base_types.h @@ -103,7 +103,6 @@ struct SourceLineResolverBase::Inline { int32_t call_site_file_id; int32_t origin_id; InlineRanges inline_ranges; - RangeMap> child_inlines; }; struct SourceLineResolverBase::Line {