| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- //===-- StackFrame.h --------------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLDB_TARGET_STACKFRAME_H
- #define LLDB_TARGET_STACKFRAME_H
- #include <memory>
- #include <mutex>
- #include "lldb/Utility/Flags.h"
- #include "lldb/Core/ValueObjectList.h"
- #include "lldb/Symbol/SymbolContext.h"
- #include "lldb/Target/ExecutionContextScope.h"
- #include "lldb/Target/StackID.h"
- #include "lldb/Utility/Scalar.h"
- #include "lldb/Utility/Status.h"
- #include "lldb/Utility/StreamString.h"
- #include "lldb/Utility/UserID.h"
- namespace lldb_private {
- /// \class StackFrame StackFrame.h "lldb/Target/StackFrame.h"
- ///
- /// This base class provides an interface to stack frames.
- ///
- /// StackFrames may have a Canonical Frame Address (CFA) or not.
- /// A frame may have a plain pc value or it may indicate a specific point in
- /// the debug session so the correct section load list is used for
- /// symbolication.
- ///
- /// Local variables may be available, or not. A register context may be
- /// available, or not.
- class StackFrame : public ExecutionContextScope,
- public std::enable_shared_from_this<StackFrame> {
- public:
- enum ExpressionPathOption {
- eExpressionPathOptionCheckPtrVsMember = (1u << 0),
- eExpressionPathOptionsNoFragileObjcIvar = (1u << 1),
- eExpressionPathOptionsNoSyntheticChildren = (1u << 2),
- eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3),
- eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4),
- eExpressionPathOptionsInspectAnonymousUnions = (1u << 5)
- };
- enum class Kind {
- /// A regular stack frame with access to registers and local variables.
- Regular,
- /// A historical stack frame -- possibly without CFA or registers or
- /// local variables.
- History,
- /// An artificial stack frame (e.g. a synthesized result of inferring
- /// missing tail call frames from a backtrace) with limited support for
- /// local variables.
- Artificial
- };
- /// Construct a StackFrame object without supplying a RegisterContextSP.
- ///
- /// This is the one constructor that doesn't take a RegisterContext
- /// parameter. This ctor may be called when creating a history StackFrame;
- /// these are used if we've collected a stack trace of pc addresses at some
- /// point in the past. We may only have pc values. We may have a CFA,
- /// or more likely, we won't.
- ///
- /// \param [in] thread_sp
- /// The Thread that this frame belongs to.
- ///
- /// \param [in] frame_idx
- /// This StackFrame's frame index number in the Thread. If inlined stack
- /// frames are being created, this may differ from the concrete_frame_idx
- /// which is the frame index without any inlined stack frames.
- ///
- /// \param [in] concrete_frame_idx
- /// The StackFrame's frame index number in the Thread without any inlined
- /// stack frames being included in the index.
- ///
- /// \param [in] cfa
- /// The Canonical Frame Address (this terminology from DWARF) for this
- /// stack frame. The CFA for a stack frame does not change over the
- /// span of the stack frame's existence. It is often the value of the
- /// caller's stack pointer before the call instruction into this frame's
- /// function. It is usually not the same as the frame pointer register's
- /// value.
- ///
- /// \param [in] cfa_is_valid
- /// A history stack frame may not have a CFA value collected. We want to
- /// distinguish between "no CFA available" and a CFA of
- /// LLDB_INVALID_ADDRESS.
- ///
- /// \param [in] pc
- /// The current pc value of this stack frame.
- ///
- /// \param [in] sc_ptr
- /// Optionally seed the StackFrame with the SymbolContext information that
- /// has
- /// already been discovered.
- StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
- lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa,
- bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind,
- bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr);
- StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
- lldb::user_id_t concrete_frame_idx,
- const lldb::RegisterContextSP ®_context_sp, lldb::addr_t cfa,
- lldb::addr_t pc, bool behaves_like_zeroth_frame,
- const SymbolContext *sc_ptr);
- StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
- lldb::user_id_t concrete_frame_idx,
- const lldb::RegisterContextSP ®_context_sp, lldb::addr_t cfa,
- const Address &pc, bool behaves_like_zeroth_frame,
- const SymbolContext *sc_ptr);
- ~StackFrame() override;
- lldb::ThreadSP GetThread() const { return m_thread_wp.lock(); }
- StackID &GetStackID();
- /// Get an Address for the current pc value in this StackFrame.
- ///
- /// May not be the same as the actual PC value for inlined stack frames.
- ///
- /// \return
- /// The Address object set to the current PC value.
- const Address &GetFrameCodeAddress();
- /// Get the current code Address suitable for symbolication,
- /// may not be the same as GetFrameCodeAddress().
- ///
- /// For a frame in the middle of the stack, the return-pc is the
- /// current code address, but for symbolication purposes the
- /// return address after a noreturn call may point to the next
- /// function, a DWARF location list entry that is a completely
- /// different code path, or the wrong source line.
- ///
- /// The address returned should be used for symbolication (source line,
- /// block, function, DWARF location entry selection) but should NOT
- /// be shown to the user. It may not point to an actual instruction
- /// boundary.
- ///
- /// \return
- /// The Address object set to the current PC value.
- Address GetFrameCodeAddressForSymbolication();
- /// Change the pc value for a given thread.
- ///
- /// Change the current pc value for the frame on this thread.
- ///
- /// \param[in] pc
- /// The load address that the pc will be set to.
- ///
- /// \return
- /// true if the pc was changed. false if this failed -- possibly
- /// because this frame is not a live StackFrame.
- bool ChangePC(lldb::addr_t pc);
- /// Provide a SymbolContext for this StackFrame's current pc value.
- ///
- /// The StackFrame maintains this SymbolContext and adds additional
- /// information to it on an as-needed basis. This helps to avoid different
- /// functions looking up symbolic information for a given pc value multiple
- /// times.
- ///
- /// \params [in] resolve_scope
- /// Flags from the SymbolContextItem enumerated type which specify what
- /// type of symbol context is needed by this caller.
- ///
- /// \return
- /// A SymbolContext reference which includes the types of information
- /// requested by resolve_scope, if they are available.
- const SymbolContext &GetSymbolContext(lldb::SymbolContextItem resolve_scope);
- /// Return the Canonical Frame Address (DWARF term) for this frame.
- ///
- /// The CFA is typically the value of the stack pointer register before the
- /// call invocation is made. It will not change during the lifetime of a
- /// stack frame. It is often not the same thing as the frame pointer
- /// register value.
- ///
- /// Live StackFrames will always have a CFA but other types of frames may
- /// not be able to supply one.
- ///
- /// \param [out] value
- /// The address of the CFA for this frame, if available.
- ///
- /// \param [out] error_ptr
- /// If there is an error determining the CFA address, this may contain a
- /// string explaining the failure.
- ///
- /// \return
- /// Returns true if the CFA value was successfully set in value. Some
- /// frames may be unable to provide this value; they will return false.
- bool GetFrameBaseValue(Scalar &value, Status *error_ptr);
- /// Get the DWARFExpression corresponding to the Canonical Frame Address.
- ///
- /// Often a register (bp), but sometimes a register + offset.
- ///
- /// \param [out] error_ptr
- /// If there is an error determining the CFA address, this may contain a
- /// string explaining the failure.
- ///
- /// \return
- /// Returns the corresponding DWARF expression, or NULL.
- DWARFExpression *GetFrameBaseExpression(Status *error_ptr);
- /// Get the current lexical scope block for this StackFrame, if possible.
- ///
- /// If debug information is available for this stack frame, return a pointer
- /// to the innermost lexical Block that the frame is currently executing.
- ///
- /// \return
- /// A pointer to the current Block. nullptr is returned if this can
- /// not be provided.
- Block *GetFrameBlock();
- /// Get the RegisterContext for this frame, if possible.
- ///
- /// Returns a shared pointer to the RegisterContext for this stack frame.
- /// Only a live StackFrame object will be able to return a RegisterContext -
- /// callers must be prepared for an empty shared pointer being returned.
- ///
- /// Even a live StackFrame RegisterContext may not be able to provide all
- /// registers. Only the currently executing frame (frame 0) can reliably
- /// provide every register in the register context.
- ///
- /// \return
- /// The RegisterContext shared point for this frame.
- lldb::RegisterContextSP GetRegisterContext();
- const lldb::RegisterContextSP &GetRegisterContextSP() const {
- return m_reg_context_sp;
- }
- /// Retrieve the list of variables that are in scope at this StackFrame's
- /// pc.
- ///
- /// A frame that is not live may return an empty VariableList for a given
- /// pc value even though variables would be available at this point if it
- /// were a live stack frame.
- ///
- /// \param[in] get_file_globals
- /// Whether to also retrieve compilation-unit scoped variables
- /// that are visible to the entire compilation unit (e.g. file
- /// static in C, globals that are homed in this CU).
- ///
- /// \return
- /// A pointer to a list of variables.
- VariableList *GetVariableList(bool get_file_globals);
- /// Retrieve the list of variables that are in scope at this StackFrame's
- /// pc.
- ///
- /// A frame that is not live may return an empty VariableListSP for a
- /// given pc value even though variables would be available at this point if
- /// it were a live stack frame.
- ///
- /// \param[in] get_file_globals
- /// Whether to also retrieve compilation-unit scoped variables
- /// that are visible to the entire compilation unit (e.g. file
- /// static in C, globals that are homed in this CU).
- ///
- /// \return
- /// A pointer to a list of variables.
- lldb::VariableListSP
- GetInScopeVariableList(bool get_file_globals,
- bool must_have_valid_location = false);
- /// Create a ValueObject for a variable name / pathname, possibly including
- /// simple dereference/child selection syntax.
- ///
- /// \param[in] var_expr
- /// The string specifying a variable to base the VariableObject off
- /// of.
- ///
- /// \param[in] use_dynamic
- /// Whether the correct dynamic type of an object pointer should be
- /// determined before creating the object, or if the static type is
- /// sufficient. One of the DynamicValueType enumerated values.
- ///
- /// \param[in] options
- /// An unsigned integer of flags, values from
- /// StackFrame::ExpressionPathOption
- /// enum.
- /// \param[in] var_sp
- /// A VariableSP that will be set to the variable described in the
- /// var_expr path.
- ///
- /// \param[in] error
- /// Record any errors encountered while evaluating var_expr.
- ///
- /// \return
- /// A shared pointer to the ValueObject described by var_expr.
- lldb::ValueObjectSP GetValueForVariableExpressionPath(
- llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
- uint32_t options, lldb::VariableSP &var_sp, Status &error);
- /// Determine whether this StackFrame has debug information available or not.
- ///
- /// \return
- /// true if debug information is available for this frame (function,
- /// compilation unit, block, etc.)
- bool HasDebugInformation();
- /// Return the disassembly for the instructions of this StackFrame's
- /// function as a single C string.
- ///
- /// \return
- /// C string with the assembly instructions for this function.
- const char *Disassemble();
- /// Print a description for this frame using the frame-format formatter
- /// settings.
- ///
- /// \param [in] strm
- /// The Stream to print the description to.
- ///
- /// \param [in] show_unique
- /// Whether to print the function arguments or not for backtrace unique.
- ///
- /// \param [in] frame_marker
- /// Optional string that will be prepended to the frame output description.
- void DumpUsingSettingsFormat(Stream *strm, bool show_unique = false,
- const char *frame_marker = nullptr);
- /// Print a description for this frame using a default format.
- ///
- /// \param [in] strm
- /// The Stream to print the description to.
- ///
- /// \param [in] show_frame_index
- /// Whether to print the frame number or not.
- ///
- /// \param [in] show_fullpaths
- /// Whether to print the full source paths or just the file base name.
- void Dump(Stream *strm, bool show_frame_index, bool show_fullpaths);
- /// Print a description of this stack frame and/or the source
- /// context/assembly for this stack frame.
- ///
- /// \param[in] strm
- /// The Stream to send the output to.
- ///
- /// \param[in] show_frame_info
- /// If true, print the frame info by calling DumpUsingSettingsFormat().
- ///
- /// \param[in] show_source
- /// If true, print source or disassembly as per the user's settings.
- ///
- /// \param[in] show_unique
- /// If true, print using backtrace unique style, without function
- /// arguments as per the user's settings.
- ///
- /// \param[in] frame_marker
- /// Passed to DumpUsingSettingsFormat() for the frame info printing.
- ///
- /// \return
- /// Returns true if successful.
- bool GetStatus(Stream &strm, bool show_frame_info, bool show_source,
- bool show_unique = false, const char *frame_marker = nullptr);
- /// Query whether this frame is a concrete frame on the call stack, or if it
- /// is an inlined frame derived from the debug information and presented by
- /// the debugger.
- ///
- /// \return
- /// true if this is an inlined frame.
- bool IsInlined();
- /// Query whether this frame is part of a historical backtrace.
- bool IsHistorical() const;
- /// Query whether this frame is artificial (e.g a synthesized result of
- /// inferring missing tail call frames from a backtrace). Artificial frames
- /// may have limited support for inspecting variables.
- bool IsArtificial() const;
- /// Query this frame to find what frame it is in this Thread's
- /// StackFrameList.
- ///
- /// \return
- /// StackFrame index 0 indicates the currently-executing function. Inline
- /// frames are included in this frame index count.
- uint32_t GetFrameIndex() const;
- /// Set this frame's synthetic frame index.
- void SetFrameIndex(uint32_t index) { m_frame_index = index; }
- /// Query this frame to find what frame it is in this Thread's
- /// StackFrameList, not counting inlined frames.
- ///
- /// \return
- /// StackFrame index 0 indicates the currently-executing function. Inline
- /// frames are not included in this frame index count; their concrete
- /// frame index will be the same as the concrete frame that they are
- /// derived from.
- uint32_t GetConcreteFrameIndex() const { return m_concrete_frame_index; }
- /// Create a ValueObject for a given Variable in this StackFrame.
- ///
- /// \params [in] variable_sp
- /// The Variable to base this ValueObject on
- ///
- /// \params [in] use_dynamic
- /// Whether the correct dynamic type of the variable should be
- /// determined before creating the ValueObject, or if the static type
- /// is sufficient. One of the DynamicValueType enumerated values.
- ///
- /// \return
- /// A ValueObject for this variable.
- lldb::ValueObjectSP
- GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp,
- lldb::DynamicValueType use_dynamic);
- /// Query this frame to determine what the default language should be when
- /// parsing expressions given the execution context.
- ///
- /// \return
- /// The language of the frame if known, else lldb::eLanguageTypeUnknown.
- lldb::LanguageType GetLanguage();
- // similar to GetLanguage(), but is allowed to take a potentially incorrect
- // guess if exact information is not available
- lldb::LanguageType GuessLanguage();
- /// Attempt to econstruct the ValueObject for a given raw address touched by
- /// the current instruction. The ExpressionPath should indicate how to get
- /// to this value using "frame variable."
- ///
- /// \params [in] addr
- /// The raw address.
- ///
- /// \return
- /// The ValueObject if found. If valid, it has a valid ExpressionPath.
- lldb::ValueObjectSP GuessValueForAddress(lldb::addr_t addr);
- /// Attempt to reconstruct the ValueObject for the address contained in a
- /// given register plus an offset. The ExpressionPath should indicate how
- /// to get to this value using "frame variable."
- ///
- /// \params [in] reg
- /// The name of the register.
- ///
- /// \params [in] offset
- /// The offset from the register. Particularly important for sp...
- ///
- /// \return
- /// The ValueObject if found. If valid, it has a valid ExpressionPath.
- lldb::ValueObjectSP GuessValueForRegisterAndOffset(ConstString reg,
- int64_t offset);
- /// Attempt to reconstruct the ValueObject for a variable with a given \a name
- /// from within the current StackFrame, within the current block. The search
- /// for the variable starts in the deepest block corresponding to the current
- /// PC in the stack frame and traverse through all parent blocks stopping at
- /// inlined function boundaries.
- ///
- /// \params [in] name
- /// The name of the variable.
- ///
- /// \return
- /// The ValueObject if found.
- lldb::ValueObjectSP FindVariable(ConstString name);
- // lldb::ExecutionContextScope pure virtual functions
- lldb::TargetSP CalculateTarget() override;
- lldb::ProcessSP CalculateProcess() override;
- lldb::ThreadSP CalculateThread() override;
- lldb::StackFrameSP CalculateStackFrame() override;
- void CalculateExecutionContext(ExecutionContext &exe_ctx) override;
- lldb::RecognizedStackFrameSP GetRecognizedFrame();
- protected:
- friend class StackFrameList;
- void SetSymbolContextScope(SymbolContextScope *symbol_scope);
- void UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame);
- void UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame);
- bool HasCachedData() const;
- private:
- // For StackFrame only
- lldb::ThreadWP m_thread_wp;
- uint32_t m_frame_index;
- uint32_t m_concrete_frame_index;
- lldb::RegisterContextSP m_reg_context_sp;
- StackID m_id;
- Address m_frame_code_addr; // The frame code address (might not be the same as
- // the actual PC for inlined frames) as a
- // section/offset address
- SymbolContext m_sc;
- Flags m_flags;
- Scalar m_frame_base;
- Status m_frame_base_error;
- bool m_cfa_is_valid; // Does this frame have a CFA? Different from CFA ==
- // LLDB_INVALID_ADDRESS
- Kind m_stack_frame_kind;
- // Whether this frame behaves like the zeroth frame, in the sense
- // that its pc value might not immediately follow a call (and thus might
- // be the first address of its function). True for actual frame zero as
- // well as any other frame with the same trait.
- bool m_behaves_like_zeroth_frame;
- lldb::VariableListSP m_variable_list_sp;
- ValueObjectList m_variable_list_value_objects; // Value objects for each
- // variable in
- // m_variable_list_sp
- lldb::RecognizedStackFrameSP m_recognized_frame_sp;
- StreamString m_disassembly;
- std::recursive_mutex m_mutex;
- StackFrame(const StackFrame &) = delete;
- const StackFrame &operator=(const StackFrame &) = delete;
- };
- } // namespace lldb_private
- #endif // LLDB_TARGET_STACKFRAME_H
|