Change Inlines in Function to be ContainedRangeMap that is easier to serialize.

Change-Id: I565d41f7d629d7ea9b66cec6760686ca201994b3
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3294125
Reviewed-by: Ivan Penkov <ivanpe@chromium.org>
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
Zequan Wu 2021-11-30 13:54:24 -08:00 committed by Joshua Peraza
parent 4458a5965a
commit c472afe064
3 changed files with 65 additions and 62 deletions

View file

@ -241,39 +241,59 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(
void BasicSourceLineResolver::Module::ConstructInlineFrames(
StackFrame* frame,
MemAddr address,
const RangeMap<uint64_t, linked_ptr<Inline>>& inlines,
const ContainedRangeMap<uint64_t, linked_ptr<Inline>>& inline_map,
deque<unique_ptr<StackFrame>>* inlined_frames) const {
linked_ptr<Inline> 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<const linked_ptr<Inline>*> 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<Inline>* const in : inlines) {
unique_ptr<StackFrame> new_frame =
unique_ptr<StackFrame>(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 = "<name omitted>";
}
// 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<StackFrame>& 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<StackFrame>(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<Inline> 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<MemAddr, linked_ptr<Inline>>* 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;
}