mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-12-23 01:25:34 +00:00
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:
parent
4458a5965a
commit
c472afe064
|
@ -241,39 +241,59 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(
|
||||||
void BasicSourceLineResolver::Module::ConstructInlineFrames(
|
void BasicSourceLineResolver::Module::ConstructInlineFrames(
|
||||||
StackFrame* frame,
|
StackFrame* frame,
|
||||||
MemAddr address,
|
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 {
|
deque<unique_ptr<StackFrame>>* inlined_frames) const {
|
||||||
linked_ptr<Inline> in;
|
vector<const linked_ptr<Inline>*> inlines;
|
||||||
MemAddr inline_base;
|
if (!inline_map.RetrieveRanges(address, inlines)) {
|
||||||
if (!inlines.RetrieveRange(address, &in, &inline_base, nullptr, nullptr))
|
|
||||||
return;
|
|
||||||
auto origin = inline_origins_.find(in->origin_id);
|
|
||||||
if (origin == inline_origins_.end())
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Update parent frame's source line (and source file if it's the new format).
|
for (const linked_ptr<Inline>* const in : inlines) {
|
||||||
frame->source_line = in->call_site_line;
|
unique_ptr<StackFrame> new_frame =
|
||||||
if (in->has_call_site_file_id) {
|
unique_ptr<StackFrame>(new StackFrame(*frame));
|
||||||
auto file = files_.find(in->call_site_file_id);
|
auto origin = inline_origins_.find(in->get()->origin_id);
|
||||||
if (file != files_.end()) {
|
if (origin != inline_origins_.end()) {
|
||||||
frame->source_file_name = file->second;
|
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(
|
void BasicSourceLineResolver::Module::LookupAddress(
|
||||||
|
@ -312,14 +332,7 @@ void BasicSourceLineResolver::Module::LookupAddress(
|
||||||
|
|
||||||
// Check if this is inlined function call.
|
// Check if this is inlined function call.
|
||||||
if (inlined_frames) {
|
if (inlined_frames) {
|
||||||
int source_line = frame->source_line;
|
|
||||||
string source_file_name = frame->source_file_name;
|
|
||||||
ConstructInlineFrames(frame, address, func->inlines, inlined_frames);
|
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,
|
} else if (public_symbols_.Retrieve(address,
|
||||||
&public_symbol, &public_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.
|
// 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)
|
if (in->inline_nest_level > last_added_inline_nest_level + 1)
|
||||||
return false;
|
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;
|
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.
|
// Store all ranges into current level of inlines.
|
||||||
for (auto range : in->inline_ranges)
|
for (auto range : in->inline_ranges)
|
||||||
current_inlines->StoreRange(range.first, range.second, in);
|
inlines.StoreRange(range.first, range.second, in);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,28 +61,26 @@ BasicSourceLineResolver::Function : public SourceLineResolverBase::Function {
|
||||||
MemAddr function_address,
|
MemAddr function_address,
|
||||||
MemAddr code_size,
|
MemAddr code_size,
|
||||||
int set_parameter_size,
|
int set_parameter_size,
|
||||||
bool is_mutiple) : Base(function_name,
|
bool is_mutiple)
|
||||||
function_address,
|
: Base(function_name,
|
||||||
code_size,
|
function_address,
|
||||||
set_parameter_size,
|
code_size,
|
||||||
is_mutiple),
|
set_parameter_size,
|
||||||
inlines(),
|
is_mutiple),
|
||||||
lines(),
|
inlines(true),
|
||||||
last_added_inline_nest_level(0) { }
|
last_added_inline_nest_level(0) {}
|
||||||
|
|
||||||
// Append inline into corresponding RangeMap.
|
// Append inline into corresponding RangeMap.
|
||||||
// This function assumes it's called in the order of reading INLINE records.
|
// This function assumes it's called in the order of reading INLINE records.
|
||||||
bool AppendInline(linked_ptr<Inline> in);
|
bool AppendInline(linked_ptr<Inline> in);
|
||||||
|
|
||||||
RangeMap<MemAddr, linked_ptr<Inline>> inlines;
|
ContainedRangeMap<MemAddr, linked_ptr<Inline>> inlines;
|
||||||
RangeMap<MemAddr, linked_ptr<Line>> lines;
|
RangeMap<MemAddr, linked_ptr<Line>> lines;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef SourceLineResolverBase::Function Base;
|
typedef SourceLineResolverBase::Function Base;
|
||||||
|
|
||||||
// A map from inline_nest_level to most recently added Inline* at that level.
|
// The last added inline_nest_level from INLINE record.
|
||||||
std::map<int, linked_ptr<Inline>> recent_inlines;
|
|
||||||
|
|
||||||
// The last added inline_nest_level in recent_inlines.
|
|
||||||
int last_added_inline_nest_level;
|
int last_added_inline_nest_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,14 +108,14 @@ class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module {
|
||||||
StackFrame* frame,
|
StackFrame* frame,
|
||||||
std::deque<std::unique_ptr<StackFrame>>* inlined_frame) const;
|
std::deque<std::unique_ptr<StackFrame>>* inlined_frame) const;
|
||||||
|
|
||||||
// Recursively construct inlined frames for |frame| and store them in
|
// Construct inlined frames for |frame| and store them in |inline_frames|.
|
||||||
// |inline_frames|. |frame|'s source line and source file name may be updated
|
// |frame|'s source line and source file name may be updated if an inlined
|
||||||
// if an inlined frame is found inside |frame|. As a result, the innermost
|
// frame is found inside |frame|. As a result, the innermost inlined frame
|
||||||
// inlined frame will be the first one in |inline_frames|.
|
// will be the first one in |inline_frames|.
|
||||||
virtual void ConstructInlineFrames(
|
virtual void ConstructInlineFrames(
|
||||||
StackFrame* frame,
|
StackFrame* frame,
|
||||||
MemAddr address,
|
MemAddr address,
|
||||||
const RangeMap<uint64_t, linked_ptr<Inline>>& inlines,
|
const ContainedRangeMap<uint64_t, linked_ptr<Inline>>& inline_map,
|
||||||
std::deque<std::unique_ptr<StackFrame>>* inline_frames) const;
|
std::deque<std::unique_ptr<StackFrame>>* inline_frames) const;
|
||||||
|
|
||||||
// If Windows stack walking information is available covering ADDRESS,
|
// If Windows stack walking information is available covering ADDRESS,
|
||||||
|
|
|
@ -103,7 +103,6 @@ struct SourceLineResolverBase::Inline {
|
||||||
int32_t call_site_file_id;
|
int32_t call_site_file_id;
|
||||||
int32_t origin_id;
|
int32_t origin_id;
|
||||||
InlineRanges inline_ranges;
|
InlineRanges inline_ranges;
|
||||||
RangeMap<MemAddr, linked_ptr<Inline>> child_inlines;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SourceLineResolverBase::Line {
|
struct SourceLineResolverBase::Line {
|
||||||
|
|
Loading…
Reference in a new issue