summaryrefslogtreecommitdiff
path: root/lldb/source/Target
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2020-03-17 17:59:08 -0700
committerVedant Kumar <vsk@apple.com>2020-03-24 12:54:40 -0700
commit03e29e2c19a8e1f6a225b1878df3eed4e54891e5 (patch)
tree66a8b9d09a48905180cba6df854c07e655c34a63 /lldb/source/Target
parente8d67ada2df35ca6c70dbbe8185b0edbb18c1150 (diff)
[lldb/DWARF] Reland: Use DW_AT_call_pc to determine artificial frame address
Reland with changes: the test modified in this change originally failed on a Debian/x86_64 builder, and I suspect the cause was that lldb looked up the line location for an artificial frame by subtracting 1 from the frame's address. For artificial frames, the subtraction must not happen because the address is already exact. --- lldb currently guesses the address to use when creating an artificial frame (i.e., a frame constructed by determining the sequence of (tail) calls which must have happened). Guessing the address creates problems -- use the actual address provided by the DW_AT_call_pc attribute instead. Depends on D76336. rdar://60307600 Differential Revision: https://reviews.llvm.org/D76337
Diffstat (limited to 'lldb/source/Target')
-rw-r--r--lldb/source/Target/StackFrameList.cpp49
1 files changed, 31 insertions, 18 deletions
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index e8e72203e204..1a75986a80cf 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -236,13 +236,17 @@ void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
m_frames.resize(num_frames);
}
+/// A sequence of calls that comprise some portion of a backtrace. Each frame
+/// is represented as a pair of a callee (Function *) and an address within the
+/// callee.
+using CallSequence = std::vector<std::pair<Function *, addr_t>>;
+
/// Find the unique path through the call graph from \p begin (with return PC
/// \p return_pc) to \p end. On success this path is stored into \p path, and
/// on failure \p path is unchanged.
static void FindInterveningFrames(Function &begin, Function &end,
ExecutionContext &exe_ctx, Target &target,
- addr_t return_pc,
- std::vector<Function *> &path,
+ addr_t return_pc, CallSequence &path,
ModuleList &images, Log *log) {
LLDB_LOG(log, "Finding frames between {0} and {1}, retn-pc={2:x}",
begin.GetDisplayName(), end.GetDisplayName(), return_pc);
@@ -275,24 +279,27 @@ static void FindInterveningFrames(Function &begin, Function &end,
// Fully explore the set of functions reachable from the first edge via tail
// calls in order to detect ambiguous executions.
struct DFS {
- std::vector<Function *> active_path = {};
- std::vector<Function *> solution_path = {};
+ CallSequence active_path = {};
+ CallSequence solution_path = {};
llvm::SmallPtrSet<Function *, 2> visited_nodes = {};
bool ambiguous = false;
Function *end;
ModuleList &images;
+ Target &target;
ExecutionContext &context;
- DFS(Function *end, ModuleList &images, ExecutionContext &context)
- : end(end), images(images), context(context) {}
+ DFS(Function *end, ModuleList &images, Target &target,
+ ExecutionContext &context)
+ : end(end), images(images), target(target), context(context) {}
- void search(Function &first_callee, std::vector<Function *> &path) {
- dfs(first_callee);
+ void search(CallEdge &first_edge, Function &first_callee,
+ CallSequence &path) {
+ dfs(first_edge, first_callee);
if (!ambiguous)
path = std::move(solution_path);
}
- void dfs(Function &callee) {
+ void dfs(CallEdge &current_edge, Function &callee) {
// Found a path to the target function.
if (&callee == end) {
if (solution_path.empty())
@@ -312,13 +319,16 @@ static void FindInterveningFrames(Function &begin, Function &end,
}
// Search the calls made from this callee.
- active_path.push_back(&callee);
+ active_path.emplace_back(&callee, LLDB_INVALID_ADDRESS);
for (const auto &edge : callee.GetTailCallingEdges()) {
Function *next_callee = edge->GetCallee(images, context);
if (!next_callee)
continue;
- dfs(*next_callee);
+ addr_t tail_call_pc = edge->GetCallInstPC(callee, target);
+ active_path.back().second = tail_call_pc;
+
+ dfs(*edge, *next_callee);
if (ambiguous)
return;
}
@@ -326,7 +336,7 @@ static void FindInterveningFrames(Function &begin, Function &end,
}
};
- DFS(&end, images, exe_ctx).search(*first_callee, path);
+ DFS(&end, images, target, exe_ctx).search(*first_edge, *first_callee, path);
}
/// Given that \p next_frame will be appended to the frame list, synthesize
@@ -379,7 +389,7 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
// Try to find the unique sequence of (tail) calls which led from next_frame
// to prev_frame.
- std::vector<Function *> path;
+ CallSequence path;
addr_t return_pc = next_reg_ctx_sp->GetPC();
Target &target = *target_sp.get();
ModuleList &images = next_frame.CalculateTarget()->GetImages();
@@ -389,14 +399,17 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
path, images, log);
// Push synthetic tail call frames.
- for (Function *callee : llvm::reverse(path)) {
+ for (auto calleeInfo : llvm::reverse(path)) {
+ Function *callee = calleeInfo.first;
uint32_t frame_idx = m_frames.size();
uint32_t concrete_frame_idx = next_frame.GetConcreteFrameIndex();
addr_t cfa = LLDB_INVALID_ADDRESS;
bool cfa_is_valid = false;
- addr_t pc =
- callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
- constexpr bool behaves_like_zeroth_frame = false;
+ addr_t pc = calleeInfo.second;
+ // We do not want to subtract 1 from this PC, as it's the actual address
+ // of the tail-calling branch instruction. This address is provided by the
+ // compiler via DW_AT_call_pc.
+ constexpr bool behaves_like_zeroth_frame = true;
SymbolContext sc;
callee->CalculateSymbolContext(&sc);
auto synth_frame = std::make_shared<StackFrame>(
@@ -404,7 +417,7 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
cfa_is_valid, pc, StackFrame::Kind::Artificial,
behaves_like_zeroth_frame, &sc);
m_frames.push_back(synth_frame);
- LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName());
+ LLDB_LOG(log, "Pushed frame {0} at {1:x}", callee->GetDisplayName(), pc);
}
// If any frames were created, adjust next_frame's index.