Skip to content

Commit 3dcce7c

Browse files
committed
[lldb] Add support for the DW_AT_trampoline attribute with a boolean
This patch adds support for the DW_AT_trampoline attribute whose value is a boolean. Which is a "generic trampoline". Stepping into a generic trampoline by default will step through the function, checking at every branch, until we stop in a function which makes sense to stop at (a function with debug info, which isn't a trampoline, for example). Differential Revision: https://reviews.llvm.org/D147292 (cherry picked from commit 4a8e545) (cherry picked from commit 2af4818)
1 parent 8b5fc30 commit 3dcce7c

28 files changed

+499
-43
lines changed

lldb/include/lldb/Symbol/Function.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ class Function : public UserID, public SymbolContextScope {
442442
Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
443443
lldb::user_id_t func_type_uid, const Mangled &mangled,
444444
Type *func_type, const AddressRange &range,
445-
bool can_throw = false);
445+
bool can_throw = false, bool generic_trampoline = false);
446446

447447
/// Destructor.
448448
~Function() override;
@@ -554,6 +554,10 @@ class Function : public UserID, public SymbolContextScope {
554554
/// A type object pointer.
555555
Type *GetType();
556556

557+
bool IsGenericTrampoline() const {
558+
return m_is_generic_trampoline;
559+
}
560+
557561
/// Get const accessor for the type that describes the function return value
558562
/// type, and parameter types.
559563
///
@@ -659,6 +663,8 @@ class Function : public UserID, public SymbolContextScope {
659663
/// information.
660664
Mangled m_mangled;
661665

666+
bool m_is_generic_trampoline;
667+
662668
/// All lexical blocks contained in this function.
663669
Block m_block;
664670

lldb/include/lldb/Target/Target.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ class TargetProperties : public Properties {
289289

290290
bool GetDebugUtilityExpression() const;
291291

292+
/// Trampoline support includes stepping through trampolines directly to their
293+
/// targets, stepping out of trampolines directly to their callers, and
294+
/// automatically filtering out trampolines as possible breakpoint locations
295+
/// when set by name.
296+
bool GetEnableTrampolineSupport() const;
297+
292298
private:
293299
// Callbacks for m_launch_info.
294300
void Arg0ValueChangedCallback();

lldb/include/lldb/Target/Thread.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,27 @@ class Thread : public std::enable_shared_from_this<Thread>,
904904
bool abort_other_plans, bool stop_other_threads,
905905
Status &status);
906906

907+
/// Gets the plan used to step through a function with a generic trampoline. A
908+
/// generic trampoline is one without a function target, which the thread plan
909+
/// will attempt to step through until it finds a place where it makes sense
910+
/// to stop at.
911+
/// \param[in] abort_other_plans
912+
/// \b true if we discard the currently queued plans and replace them with
913+
/// this one.
914+
/// Otherwise this plan will go on the end of the plan stack.
915+
///
916+
/// \param[in] stop_other_threads
917+
/// \b true if we will stop other threads while we single step this one.
918+
///
919+
/// \param[out] status
920+
/// A status with an error if queuing failed.
921+
///
922+
/// \return
923+
/// A shared pointer to the newly queued thread plan, or nullptr if the
924+
/// plan could not be queued.
925+
virtual lldb::ThreadPlanSP QueueThreadPlanForStepThroughGenericTrampoline(
926+
bool abort_other_plans, lldb::RunMode stop_other_threads, Status &status);
927+
907928
/// Gets the plan used to continue from the current PC.
908929
/// This is a simple plan, mostly useful as a backstop when you are continuing
909930
/// for some particular purpose.

lldb/include/lldb/Target/ThreadPlan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
302302
eKindStepInRange,
303303
eKindRunToAddress,
304304
eKindStepThrough,
305+
eKindStepThroughGenericTrampoline,
305306
eKindStepUntil
306307
};
307308

lldb/include/lldb/Target/ThreadPlanStepOverRange.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ class ThreadPlanStepOverRange : public ThreadPlanStepRange,
3030
bool ShouldStop(Event *event_ptr) override;
3131

3232
protected:
33-
bool DoPlanExplainsStop(Event *event_ptr) override;
3433
bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
3534

3635
void SetFlagsToDefault() override {

lldb/include/lldb/Target/ThreadPlanStepRange.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class ThreadPlanStepRange : public ThreadPlan {
4141
void AddRange(const AddressRange &new_range);
4242

4343
protected:
44+
bool DoPlanExplainsStop(Event *event_ptr) override;
4445
bool InRange();
4546
lldb::FrameComparison CompareCurrentFrameToStartFrame();
4647
bool InSymbol();
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===-- ThreadPlanStepInRange.h ---------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_TARGET_THREADPLANSTEPTHROUGHGENERICTRAMPOLINE_H
10+
#define LLDB_TARGET_THREADPLANSTEPTHROUGHGENERICTRAMPOLINE_H
11+
12+
#include "lldb/Target/Thread.h"
13+
#include "lldb/Target/ThreadPlanShouldStopHere.h"
14+
#include "lldb/Target/ThreadPlanStepRange.h"
15+
16+
namespace lldb_private {
17+
18+
class ThreadPlanStepThroughGenericTrampoline : public ThreadPlanStepRange,
19+
public ThreadPlanShouldStopHere {
20+
public:
21+
ThreadPlanStepThroughGenericTrampoline(Thread &thread,
22+
lldb::RunMode stop_others);
23+
24+
~ThreadPlanStepThroughGenericTrampoline() override;
25+
26+
void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
27+
28+
bool ShouldStop(Event *event_ptr) override;
29+
bool ValidatePlan(Stream *error) override;
30+
31+
protected:
32+
void SetFlagsToDefault() override {
33+
GetFlags().Set(
34+
ThreadPlanStepThroughGenericTrampoline::s_default_flag_values);
35+
}
36+
37+
private:
38+
// Need an appropriate marker for the current stack so we can tell step out
39+
// from step in.
40+
41+
static uint32_t
42+
s_default_flag_values; // These are the default flag values
43+
// for the ThreadPlanStepThroughGenericTrampoline.
44+
ThreadPlanStepThroughGenericTrampoline(
45+
const ThreadPlanStepThroughGenericTrampoline &) = delete;
46+
const ThreadPlanStepThroughGenericTrampoline &
47+
operator=(const ThreadPlanStepThroughGenericTrampoline &) = delete;
48+
};
49+
50+
} // namespace lldb_private
51+
52+
#endif // LLDB_TARGET_THREADPLANSTEPTHROUGHGENERICTRAMPOLINE_H

lldb/source/Core/Module.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,12 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
805805
if (!sc_list.GetContextAtIndex(i, sc))
806806
break;
807807

808+
bool is_trampoline =
809+
Target::GetGlobalProperties().GetEnableTrampolineSupport() &&
810+
sc.function && sc.function->IsGenericTrampoline();
811+
808812
bool keep_it =
813+
!is_trampoline &&
809814
NameMatchesLookupInfo(sc.GetFunctionName(), sc.GetLanguage());
810815
if (keep_it)
811816
++i;

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2440,12 +2440,16 @@ DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
24402440

24412441
assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
24422442

2443+
bool is_generic_trampoline = die.IsGenericTrampoline();
2444+
24432445
const user_id_t func_user_id = die.GetID();
24442446
func_sp =
24452447
std::make_shared<Function>(&comp_unit,
24462448
func_user_id, // UserID is the DIE offset
24472449
func_user_id, func_name, func_type,
2448-
func_range); // first address range
2450+
func_range, // first address range
2451+
false, // canThrow
2452+
is_generic_trampoline);
24492453

24502454
if (func_sp.get() != nullptr) {
24512455
if (frame_base.IsValid())

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserSwift.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,11 @@ Function *DWARFASTParserSwift::ParseFunctionFromDWARF(
274274
decl_column));
275275

276276
const user_id_t func_user_id = die.GetID();
277+
bool is_generic_trampoline = die.IsGenericTrampoline();
277278
func_sp.reset(new Function(&comp_unit, func_user_id, func_user_id,
278-
func_name, nullptr, func_range,
279-
can_throw)); // first address range
279+
func_name, nullptr,
280+
func_range, // first address range
281+
can_throw, is_generic_trampoline));
280282

281283
if (func_sp.get() != NULL) {
282284
if (frame_base.IsValid())

0 commit comments

Comments
 (0)