Reland "[LLDB][NFC] Decouple dwarf location table from DWARFExpression."
This reland227dffd0b6
and562c3467a6
with failed api tests fixed by keeping function base file addres in DWARFExpressionList.
This commit is contained in:
parent
81c48436bb
commit
b74a01a80b
|
@ -42,49 +42,14 @@ public:
|
||||||
/// \param[in] data
|
/// \param[in] data
|
||||||
/// A data extractor configured to read the DWARF location expression's
|
/// A data extractor configured to read the DWARF location expression's
|
||||||
/// bytecode.
|
/// bytecode.
|
||||||
DWARFExpression(lldb::ModuleSP module, const DataExtractor &data,
|
DWARFExpression(const DataExtractor &data);
|
||||||
const DWARFUnit *dwarf_cu);
|
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~DWARFExpression();
|
virtual ~DWARFExpression();
|
||||||
|
|
||||||
/// Print the description of the expression to a stream
|
|
||||||
///
|
|
||||||
/// \param[in] s
|
|
||||||
/// The stream to print to.
|
|
||||||
///
|
|
||||||
/// \param[in] level
|
|
||||||
/// The level of verbosity to use.
|
|
||||||
///
|
|
||||||
/// \param[in] abi
|
|
||||||
/// An optional ABI plug-in that can be used to resolve register
|
|
||||||
/// names.
|
|
||||||
void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
|
|
||||||
|
|
||||||
/// Return true if the location expression contains data
|
/// Return true if the location expression contains data
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
/// Return true if a location list was provided
|
|
||||||
bool IsLocationList() const;
|
|
||||||
|
|
||||||
/// Search for a load address in the location list
|
|
||||||
///
|
|
||||||
/// \param[in] func_load_addr
|
|
||||||
/// The actual address of the function containing this location list.
|
|
||||||
///
|
|
||||||
/// \param[in] addr
|
|
||||||
/// The address to resolve
|
|
||||||
///
|
|
||||||
/// \return
|
|
||||||
/// True if IsLocationList() is true and the address was found;
|
|
||||||
/// false otherwise.
|
|
||||||
// bool
|
|
||||||
// LocationListContainsLoadAddress (Process* process, const Address &addr)
|
|
||||||
// const;
|
|
||||||
//
|
|
||||||
bool LocationListContainsAddress(lldb::addr_t func_load_addr,
|
|
||||||
lldb::addr_t addr) const;
|
|
||||||
|
|
||||||
/// If a location is not a location list, return true if the location
|
/// If a location is not a location list, return true if the location
|
||||||
/// contains a DW_OP_addr () opcode in the stream that matches \a file_addr.
|
/// contains a DW_OP_addr () opcode in the stream that matches \a file_addr.
|
||||||
/// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true
|
/// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true
|
||||||
|
@ -93,6 +58,9 @@ public:
|
||||||
/// static variable since there is no other indication from DWARF debug
|
/// static variable since there is no other indication from DWARF debug
|
||||||
/// info.
|
/// info.
|
||||||
///
|
///
|
||||||
|
/// \param[in] dwarf_cu
|
||||||
|
/// The dwarf unit this expression belongs to.
|
||||||
|
///
|
||||||
/// \param[in] op_addr_idx
|
/// \param[in] op_addr_idx
|
||||||
/// The DW_OP_addr index to retrieve in case there is more than
|
/// The DW_OP_addr index to retrieve in case there is more than
|
||||||
/// one DW_OP_addr opcode in the location byte stream.
|
/// one DW_OP_addr opcode in the location byte stream.
|
||||||
|
@ -104,36 +72,22 @@ public:
|
||||||
/// \return
|
/// \return
|
||||||
/// LLDB_INVALID_ADDRESS if the location doesn't contain a
|
/// LLDB_INVALID_ADDRESS if the location doesn't contain a
|
||||||
/// DW_OP_addr for \a op_addr_idx, otherwise a valid file address
|
/// DW_OP_addr for \a op_addr_idx, otherwise a valid file address
|
||||||
lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const;
|
lldb::addr_t GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
|
||||||
|
uint32_t op_addr_idx, bool &error) const;
|
||||||
|
|
||||||
bool Update_DW_OP_addr(lldb::addr_t file_addr);
|
bool Update_DW_OP_addr(lldb::addr_t file_addr);
|
||||||
|
|
||||||
void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
|
void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
|
||||||
uint8_t addr_byte_size);
|
uint8_t addr_byte_size);
|
||||||
|
|
||||||
void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
|
|
||||||
|
|
||||||
bool ContainsThreadLocalStorage() const;
|
bool ContainsThreadLocalStorage() const;
|
||||||
|
|
||||||
bool LinkThreadLocalStorage(
|
bool LinkThreadLocalStorage(
|
||||||
lldb::ModuleSP new_module_sp,
|
|
||||||
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
|
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
|
||||||
&link_address_callback);
|
&link_address_callback);
|
||||||
|
|
||||||
/// Tells the expression that it refers to a location list.
|
|
||||||
///
|
|
||||||
/// \param[in] cu_file_addr
|
|
||||||
/// The base address to use for interpreting relative location list
|
|
||||||
/// entries.
|
|
||||||
/// \param[in] func_file_addr
|
|
||||||
/// The file address of the function containing this location list. This
|
|
||||||
/// address will be used to relocate the location list on the fly (in
|
|
||||||
/// conjuction with the func_load_addr arguments).
|
|
||||||
void SetLocationListAddresses(lldb::addr_t cu_file_addr,
|
|
||||||
lldb::addr_t func_file_addr);
|
|
||||||
|
|
||||||
/// Return the call-frame-info style register kind
|
/// Return the call-frame-info style register kind
|
||||||
int GetRegisterKind();
|
lldb::RegisterKind GetRegisterKind() const;
|
||||||
|
|
||||||
/// Set the call-frame-info style register kind
|
/// Set the call-frame-info style register kind
|
||||||
///
|
///
|
||||||
|
@ -141,20 +95,6 @@ public:
|
||||||
/// The register kind.
|
/// The register kind.
|
||||||
void SetRegisterKind(lldb::RegisterKind reg_kind);
|
void SetRegisterKind(lldb::RegisterKind reg_kind);
|
||||||
|
|
||||||
/// Wrapper for the static evaluate function that accepts an
|
|
||||||
/// ExecutionContextScope instead of an ExecutionContext and uses member
|
|
||||||
/// variables to populate many operands
|
|
||||||
bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t func_load_addr,
|
|
||||||
const Value *initial_value_ptr, const Value *object_address_ptr,
|
|
||||||
Value &result, Status *error_ptr) const;
|
|
||||||
|
|
||||||
/// Wrapper for the static evaluate function that uses member variables to
|
|
||||||
/// populate many operands
|
|
||||||
bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
|
|
||||||
lldb::addr_t loclist_base_load_addr,
|
|
||||||
const Value *initial_value_ptr, const Value *object_address_ptr,
|
|
||||||
Value &result, Status *error_ptr) const;
|
|
||||||
|
|
||||||
/// Evaluate a DWARF location expression in a particular context
|
/// Evaluate a DWARF location expression in a particular context
|
||||||
///
|
///
|
||||||
/// \param[in] exe_ctx
|
/// \param[in] exe_ctx
|
||||||
|
@ -194,72 +134,32 @@ public:
|
||||||
/// True on success; false otherwise. If error_ptr is non-NULL,
|
/// True on success; false otherwise. If error_ptr is non-NULL,
|
||||||
/// details of the failure are provided through it.
|
/// details of the failure are provided through it.
|
||||||
static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
|
static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
|
||||||
lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes,
|
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
|
||||||
const DWARFUnit *dwarf_cu,
|
const DWARFUnit *dwarf_cu,
|
||||||
const lldb::RegisterKind reg_set,
|
const lldb::RegisterKind reg_set,
|
||||||
const Value *initial_value_ptr,
|
const Value *initial_value_ptr,
|
||||||
const Value *object_address_ptr, Value &result,
|
const Value *object_address_ptr, Value &result,
|
||||||
Status *error_ptr);
|
Status *error_ptr);
|
||||||
|
|
||||||
|
static bool ParseDWARFLocationList(const DWARFUnit *dwarf_cu,
|
||||||
|
const DataExtractor &data,
|
||||||
|
DWARFExpressionList *loc_list);
|
||||||
|
|
||||||
bool GetExpressionData(DataExtractor &data) const {
|
bool GetExpressionData(DataExtractor &data) const {
|
||||||
data = m_data;
|
data = m_data;
|
||||||
return data.GetByteSize() > 0;
|
return data.GetByteSize() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level,
|
void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
|
||||||
lldb::addr_t func_load_addr, lldb::addr_t address,
|
|
||||||
ABI *abi);
|
|
||||||
|
|
||||||
bool DumpLocations(Stream *s, lldb::DescriptionLevel level,
|
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const;
|
||||||
lldb::addr_t func_load_addr, lldb::addr_t addr, ABI *abi);
|
|
||||||
|
|
||||||
bool GetLocationExpressions(
|
|
||||||
lldb::addr_t load_function_start,
|
|
||||||
llvm::function_ref<bool(llvm::DWARFLocationExpression)> callback) const;
|
|
||||||
|
|
||||||
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op);
|
|
||||||
|
|
||||||
llvm::Optional<DataExtractor>
|
|
||||||
GetLocationExpression(lldb::addr_t load_function_start,
|
|
||||||
lldb::addr_t addr) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Pretty-prints the location expression to a stream
|
|
||||||
///
|
|
||||||
/// \param[in] s
|
|
||||||
/// The stream to use for pretty-printing.
|
|
||||||
///
|
|
||||||
/// \param[in] data
|
|
||||||
/// The data extractor.
|
|
||||||
///
|
|
||||||
/// \param[in] level
|
|
||||||
/// The level of detail to use in pretty-printing.
|
|
||||||
///
|
|
||||||
/// \param[in] abi
|
|
||||||
/// An optional ABI plug-in that can be used to resolve register
|
|
||||||
/// names.
|
|
||||||
void DumpLocation(Stream *s, const DataExtractor &data,
|
|
||||||
lldb::DescriptionLevel level, ABI *abi) const;
|
|
||||||
|
|
||||||
/// Module which defined this expression.
|
|
||||||
lldb::ModuleWP m_module_wp;
|
|
||||||
|
|
||||||
/// A data extractor capable of reading opcode bytes
|
/// A data extractor capable of reading opcode bytes
|
||||||
DataExtractor m_data;
|
DataExtractor m_data;
|
||||||
|
|
||||||
/// The DWARF compile unit this expression belongs to. It is used to evaluate
|
|
||||||
/// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
|
|
||||||
/// DW_OP_GNU_const_index)
|
|
||||||
const DWARFUnit *m_dwarf_cu = nullptr;
|
|
||||||
|
|
||||||
/// One of the defines that starts with LLDB_REGKIND_
|
/// One of the defines that starts with LLDB_REGKIND_
|
||||||
lldb::RegisterKind m_reg_kind = lldb::eRegisterKindDWARF;
|
lldb::RegisterKind m_reg_kind = lldb::eRegisterKindDWARF;
|
||||||
|
|
||||||
struct LoclistAddresses {
|
|
||||||
lldb::addr_t cu_file_addr;
|
|
||||||
lldb::addr_t func_file_addr;
|
|
||||||
};
|
|
||||||
llvm::Optional<LoclistAddresses> m_loclist_addresses;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lldb_private
|
} // namespace lldb_private
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
//===-- DWARFExpressionList.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_EXPRESSION_DWARFEXPRESSIONLIST_H
|
||||||
|
#define LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
|
||||||
|
|
||||||
|
#include "lldb/Expression/DWARFExpression.h"
|
||||||
|
#include "lldb/Utility/RangeMap.h"
|
||||||
|
#include "lldb/lldb-private.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
|
|
||||||
|
class DWARFUnit;
|
||||||
|
|
||||||
|
namespace lldb_private {
|
||||||
|
|
||||||
|
/// \class DWARFExpressionList DWARFExpressionList.h
|
||||||
|
/// "lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file
|
||||||
|
/// address range to a single DWARF location expression.
|
||||||
|
class DWARFExpressionList {
|
||||||
|
public:
|
||||||
|
DWARFExpressionList() = default;
|
||||||
|
|
||||||
|
DWARFExpressionList(lldb::ModuleSP module_sp, const DWARFUnit *dwarf_cu,
|
||||||
|
lldb::addr_t func_file_addr)
|
||||||
|
: m_module_wp(module_sp), m_dwarf_cu(dwarf_cu),
|
||||||
|
m_func_file_addr(func_file_addr) {}
|
||||||
|
|
||||||
|
DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr,
|
||||||
|
const DWARFUnit *dwarf_cu)
|
||||||
|
: m_module_wp(module_sp), m_dwarf_cu(dwarf_cu) {
|
||||||
|
AddExpression(0, LLDB_INVALID_ADDRESS, expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return true if the location expression contains data
|
||||||
|
bool IsValid() const { return !m_exprs.IsEmpty(); }
|
||||||
|
|
||||||
|
void Clear() { m_exprs.Clear(); }
|
||||||
|
|
||||||
|
// Return true if the location expression is always valid.
|
||||||
|
bool IsAlwaysValidSingleExpr() const;
|
||||||
|
|
||||||
|
bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr);
|
||||||
|
|
||||||
|
/// Get the expression data at the file address.
|
||||||
|
bool GetExpressionData(DataExtractor &data,
|
||||||
|
lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS,
|
||||||
|
lldb::addr_t file_addr = 0) const;
|
||||||
|
|
||||||
|
/// Sort m_expressions.
|
||||||
|
void Sort() { m_exprs.Sort(); }
|
||||||
|
|
||||||
|
void SetFuncFileAddress(lldb::addr_t func_file_addr) {
|
||||||
|
m_func_file_addr = func_file_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
lldb::addr_t GetFuncFileAddress() { return m_func_file_addr; }
|
||||||
|
|
||||||
|
const DWARFExpression *GetExpressionAtAddress(lldb::addr_t func_load_addr,
|
||||||
|
lldb::addr_t load_addr) const;
|
||||||
|
|
||||||
|
const DWARFExpression *GetAlwaysValidExpr() const;
|
||||||
|
|
||||||
|
DWARFExpression *GetMutableExpressionAtAddress(
|
||||||
|
lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS,
|
||||||
|
lldb::addr_t load_addr = 0);
|
||||||
|
|
||||||
|
size_t GetSize() const { return m_exprs.GetSize(); }
|
||||||
|
|
||||||
|
bool ContainsThreadLocalStorage() const;
|
||||||
|
|
||||||
|
bool LinkThreadLocalStorage(
|
||||||
|
lldb::ModuleSP new_module_sp,
|
||||||
|
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
|
||||||
|
&link_address_callback);
|
||||||
|
|
||||||
|
bool MatchesOperand(StackFrame &frame,
|
||||||
|
const Instruction::Operand &operand) const;
|
||||||
|
|
||||||
|
/// Dump locations that contains file_addr if it's valid. Otherwise. dump all
|
||||||
|
/// locations.
|
||||||
|
bool DumpLocations(Stream *s, lldb::DescriptionLevel level,
|
||||||
|
lldb::addr_t func_load_addr, lldb::addr_t file_addr,
|
||||||
|
ABI *abi) const;
|
||||||
|
|
||||||
|
/// Dump all locaitons with each seperated by new line.
|
||||||
|
void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
|
||||||
|
|
||||||
|
/// Search for a load address in the dwarf location list
|
||||||
|
///
|
||||||
|
/// \param[in] func_load_addr
|
||||||
|
/// The actual address of the function containing this location list.
|
||||||
|
///
|
||||||
|
/// \param[in] addr
|
||||||
|
/// The address to resolve.
|
||||||
|
///
|
||||||
|
/// \return
|
||||||
|
/// True if IsLocationList() is true and the address was found;
|
||||||
|
/// false otherwise.
|
||||||
|
// bool
|
||||||
|
// LocationListContainsLoadAddress (Process* process, const Address &addr)
|
||||||
|
// const;
|
||||||
|
//
|
||||||
|
bool ContainsAddress(lldb::addr_t func_load_addr, lldb::addr_t addr) const;
|
||||||
|
|
||||||
|
void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
|
||||||
|
|
||||||
|
bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
|
||||||
|
lldb::addr_t func_load_addr, const Value *initial_value_ptr,
|
||||||
|
const Value *object_address_ptr, Value &result,
|
||||||
|
Status *error_ptr) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// RangeDataVector requires a comparator for DWARFExpression, but it doesn't
|
||||||
|
// make sense to do so.
|
||||||
|
struct DWARFExpressionCompare {
|
||||||
|
public:
|
||||||
|
bool operator()(const DWARFExpression &lhs,
|
||||||
|
const DWARFExpression &rhs) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
using ExprVec = RangeDataVector<lldb::addr_t, lldb::addr_t, DWARFExpression,
|
||||||
|
0, DWARFExpressionCompare>;
|
||||||
|
using Entry = ExprVec::Entry;
|
||||||
|
|
||||||
|
// File address range mapping to single dwarf expression.
|
||||||
|
ExprVec m_exprs;
|
||||||
|
|
||||||
|
/// Module which defined this expression.
|
||||||
|
lldb::ModuleWP m_module_wp;
|
||||||
|
|
||||||
|
/// The DWARF compile unit this expression belongs to. It is used to evaluate
|
||||||
|
/// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
|
||||||
|
/// DW_OP_GNU_const_index)
|
||||||
|
const DWARFUnit *m_dwarf_cu = nullptr;
|
||||||
|
|
||||||
|
// Function base file address.
|
||||||
|
lldb::addr_t m_func_file_addr = LLDB_INVALID_ADDRESS;
|
||||||
|
|
||||||
|
using const_iterator = ExprVec::Collection::const_iterator;
|
||||||
|
const_iterator begin() const { return m_exprs.begin(); }
|
||||||
|
const_iterator end() const { return m_exprs.end(); }
|
||||||
|
};
|
||||||
|
} // namespace lldb_private
|
||||||
|
|
||||||
|
#endif // LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
|
|
@ -12,7 +12,7 @@
|
||||||
#include "lldb/Core/AddressRange.h"
|
#include "lldb/Core/AddressRange.h"
|
||||||
#include "lldb/Core/Declaration.h"
|
#include "lldb/Core/Declaration.h"
|
||||||
#include "lldb/Core/Mangled.h"
|
#include "lldb/Core/Mangled.h"
|
||||||
#include "lldb/Expression/DWARFExpression.h"
|
#include "lldb/Expression/DWARFExpressionList.h"
|
||||||
#include "lldb/Symbol/Block.h"
|
#include "lldb/Symbol/Block.h"
|
||||||
#include "lldb/Utility/UserID.h"
|
#include "lldb/Utility/UserID.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
@ -253,8 +253,8 @@ class Function;
|
||||||
/// Represent the locations of a parameter at a call site, both in the caller
|
/// Represent the locations of a parameter at a call site, both in the caller
|
||||||
/// and in the callee.
|
/// and in the callee.
|
||||||
struct CallSiteParameter {
|
struct CallSiteParameter {
|
||||||
DWARFExpression LocationInCallee;
|
DWARFExpressionList LocationInCallee;
|
||||||
DWARFExpression LocationInCaller;
|
DWARFExpressionList LocationInCaller;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A vector of \c CallSiteParameter.
|
/// A vector of \c CallSiteParameter.
|
||||||
|
@ -370,7 +370,7 @@ class IndirectCallEdge : public CallEdge {
|
||||||
public:
|
public:
|
||||||
/// Construct a call edge using a DWARFExpression to identify the callee, and
|
/// Construct a call edge using a DWARFExpression to identify the callee, and
|
||||||
/// a return PC within the calling function to identify a specific call site.
|
/// a return PC within the calling function to identify a specific call site.
|
||||||
IndirectCallEdge(DWARFExpression call_target, AddrType caller_address_type,
|
IndirectCallEdge(DWARFExpressionList call_target, AddrType caller_address_type,
|
||||||
lldb::addr_t caller_address, bool is_tail_call,
|
lldb::addr_t caller_address, bool is_tail_call,
|
||||||
CallSiteParameterArray &¶meters)
|
CallSiteParameterArray &¶meters)
|
||||||
: CallEdge(caller_address_type, caller_address, is_tail_call,
|
: CallEdge(caller_address_type, caller_address, is_tail_call,
|
||||||
|
@ -383,7 +383,7 @@ private:
|
||||||
// Used to describe an indirect call.
|
// Used to describe an indirect call.
|
||||||
//
|
//
|
||||||
// Specifies the location of the callee address in the calling frame.
|
// Specifies the location of the callee address in the calling frame.
|
||||||
DWARFExpression call_target;
|
DWARFExpressionList call_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \class Function Function.h "lldb/Symbol/Function.h"
|
/// \class Function Function.h "lldb/Symbol/Function.h"
|
||||||
|
@ -521,13 +521,13 @@ public:
|
||||||
/// \return
|
/// \return
|
||||||
/// A location expression that describes the function frame
|
/// A location expression that describes the function frame
|
||||||
/// base.
|
/// base.
|
||||||
DWARFExpression &GetFrameBaseExpression() { return m_frame_base; }
|
DWARFExpressionList &GetFrameBaseExpression() { return m_frame_base; }
|
||||||
|
|
||||||
/// Get const accessor for the frame base location.
|
/// Get const accessor for the frame base location.
|
||||||
///
|
///
|
||||||
/// \return
|
/// \return
|
||||||
/// A const compile unit object pointer.
|
/// A const compile unit object pointer.
|
||||||
const DWARFExpression &GetFrameBaseExpression() const { return m_frame_base; }
|
const DWARFExpressionList &GetFrameBaseExpression() const { return m_frame_base; }
|
||||||
|
|
||||||
ConstString GetName() const;
|
ConstString GetName() const;
|
||||||
|
|
||||||
|
@ -659,7 +659,7 @@ protected:
|
||||||
|
|
||||||
/// The frame base expression for variables that are relative to the frame
|
/// The frame base expression for variables that are relative to the frame
|
||||||
/// pointer.
|
/// pointer.
|
||||||
DWARFExpression m_frame_base;
|
DWARFExpressionList m_frame_base;
|
||||||
|
|
||||||
Flags m_flags;
|
Flags m_flags;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "lldb/Core/Declaration.h"
|
#include "lldb/Core/Declaration.h"
|
||||||
#include "lldb/Core/Mangled.h"
|
#include "lldb/Core/Mangled.h"
|
||||||
#include "lldb/Expression/DWARFExpression.h"
|
#include "lldb/Expression/DWARFExpressionList.h"
|
||||||
#include "lldb/Utility/CompletionRequest.h"
|
#include "lldb/Utility/CompletionRequest.h"
|
||||||
#include "lldb/Utility/RangeMap.h"
|
#include "lldb/Utility/RangeMap.h"
|
||||||
#include "lldb/Utility/UserID.h"
|
#include "lldb/Utility/UserID.h"
|
||||||
|
@ -32,8 +32,8 @@ public:
|
||||||
Variable(lldb::user_id_t uid, const char *name, const char *mangled,
|
Variable(lldb::user_id_t uid, const char *name, const char *mangled,
|
||||||
const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope,
|
const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope,
|
||||||
SymbolContextScope *owner_scope, const RangeList &scope_range,
|
SymbolContextScope *owner_scope, const RangeList &scope_range,
|
||||||
Declaration *decl, const DWARFExpression &location, bool external,
|
Declaration *decl, const DWARFExpressionList &location,
|
||||||
bool artificial, bool location_is_constant_data,
|
bool external, bool artificial, bool location_is_constant_data,
|
||||||
bool static_member = false);
|
bool static_member = false);
|
||||||
|
|
||||||
virtual ~Variable();
|
virtual ~Variable();
|
||||||
|
@ -73,9 +73,11 @@ public:
|
||||||
|
|
||||||
bool IsStaticMember() const { return m_static_member; }
|
bool IsStaticMember() const { return m_static_member; }
|
||||||
|
|
||||||
DWARFExpression &LocationExpression() { return m_location; }
|
DWARFExpressionList &LocationExpressionList() { return m_location_list; }
|
||||||
|
|
||||||
const DWARFExpression &LocationExpression() const { return m_location; }
|
const DWARFExpressionList &LocationExpressionList() const {
|
||||||
|
return m_location_list;
|
||||||
|
}
|
||||||
|
|
||||||
// When given invalid address, it dumps all locations. Otherwise it only dumps
|
// When given invalid address, it dumps all locations. Otherwise it only dumps
|
||||||
// the location that contains this address.
|
// the location that contains this address.
|
||||||
|
@ -128,7 +130,7 @@ protected:
|
||||||
Declaration m_declaration;
|
Declaration m_declaration;
|
||||||
/// The location of this variable that can be fed to
|
/// The location of this variable that can be fed to
|
||||||
/// DWARFExpression::Evaluate().
|
/// DWARFExpression::Evaluate().
|
||||||
DWARFExpression m_location;
|
DWARFExpressionList m_location_list;
|
||||||
/// Visible outside the containing compile unit?
|
/// Visible outside the containing compile unit?
|
||||||
unsigned m_external : 1;
|
unsigned m_external : 1;
|
||||||
/// Non-zero if the variable is not explicitly declared in source.
|
/// Non-zero if the variable is not explicitly declared in source.
|
||||||
|
|
|
@ -202,7 +202,7 @@ public:
|
||||||
/// frames may be unable to provide this value; they will return false.
|
/// frames may be unable to provide this value; they will return false.
|
||||||
bool GetFrameBaseValue(Scalar &value, Status *error_ptr);
|
bool GetFrameBaseValue(Scalar &value, Status *error_ptr);
|
||||||
|
|
||||||
/// Get the DWARFExpression corresponding to the Canonical Frame Address.
|
/// Get the DWARFExpressionList corresponding to the Canonical Frame Address.
|
||||||
///
|
///
|
||||||
/// Often a register (bp), but sometimes a register + offset.
|
/// Often a register (bp), but sometimes a register + offset.
|
||||||
///
|
///
|
||||||
|
@ -212,7 +212,7 @@ public:
|
||||||
///
|
///
|
||||||
/// \return
|
/// \return
|
||||||
/// Returns the corresponding DWARF expression, or NULL.
|
/// Returns the corresponding DWARF expression, or NULL.
|
||||||
DWARFExpression *GetFrameBaseExpression(Status *error_ptr);
|
DWARFExpressionList *GetFrameBaseExpression(Status *error_ptr);
|
||||||
|
|
||||||
/// Get the current lexical scope block for this StackFrame, if possible.
|
/// Get the current lexical scope block for this StackFrame, if possible.
|
||||||
///
|
///
|
||||||
|
|
|
@ -627,6 +627,10 @@ public:
|
||||||
return (m_entries.empty() ? nullptr : &m_entries.back());
|
return (m_entries.empty() ? nullptr : &m_entries.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using const_iterator = typename Collection::const_iterator;
|
||||||
|
const_iterator begin() const { return m_entries.begin(); }
|
||||||
|
const_iterator end() const { return m_entries.end(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Collection m_entries;
|
Collection m_entries;
|
||||||
Compare m_compare;
|
Compare m_compare;
|
||||||
|
|
|
@ -66,6 +66,7 @@ class ConstStringTable;
|
||||||
class DWARFCallFrameInfo;
|
class DWARFCallFrameInfo;
|
||||||
class DWARFDataExtractor;
|
class DWARFDataExtractor;
|
||||||
class DWARFExpression;
|
class DWARFExpression;
|
||||||
|
class DWARFExpressionList;
|
||||||
class DataBuffer;
|
class DataBuffer;
|
||||||
class WritableDataBuffer;
|
class WritableDataBuffer;
|
||||||
class DataBufferHeap;
|
class DataBufferHeap;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "lldb/Core/Declaration.h"
|
#include "lldb/Core/Declaration.h"
|
||||||
#include "lldb/Core/Module.h"
|
#include "lldb/Core/Module.h"
|
||||||
#include "lldb/Core/Value.h"
|
#include "lldb/Core/Value.h"
|
||||||
#include "lldb/Expression/DWARFExpression.h"
|
#include "lldb/Expression/DWARFExpressionList.h"
|
||||||
#include "lldb/Symbol/Function.h"
|
#include "lldb/Symbol/Function.h"
|
||||||
#include "lldb/Symbol/ObjectFile.h"
|
#include "lldb/Symbol/ObjectFile.h"
|
||||||
#include "lldb/Symbol/SymbolContext.h"
|
#include "lldb/Symbol/SymbolContext.h"
|
||||||
|
@ -127,17 +127,16 @@ bool ValueObjectVariable::UpdateValue() {
|
||||||
m_error.Clear();
|
m_error.Clear();
|
||||||
|
|
||||||
Variable *variable = m_variable_sp.get();
|
Variable *variable = m_variable_sp.get();
|
||||||
DWARFExpression &expr = variable->LocationExpression();
|
DWARFExpressionList &expr_list = variable->LocationExpressionList();
|
||||||
|
|
||||||
if (variable->GetLocationIsConstantValueData()) {
|
if (variable->GetLocationIsConstantValueData()) {
|
||||||
// expr doesn't contain DWARF bytes, it contains the constant variable
|
// expr doesn't contain DWARF bytes, it contains the constant variable
|
||||||
// value bytes themselves...
|
// value bytes themselves...
|
||||||
if (expr.GetExpressionData(m_data)) {
|
if (expr_list.GetExpressionData(m_data)) {
|
||||||
if (m_data.GetDataStart() && m_data.GetByteSize())
|
if (m_data.GetDataStart() && m_data.GetByteSize())
|
||||||
m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize());
|
m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize());
|
||||||
m_value.SetContext(Value::ContextType::Variable, variable);
|
m_value.SetContext(Value::ContextType::Variable, variable);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
m_error.SetErrorString("empty constant data");
|
m_error.SetErrorString("empty constant data");
|
||||||
// constant bytes can't be edited - sorry
|
// constant bytes can't be edited - sorry
|
||||||
m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
|
m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
|
||||||
|
@ -151,7 +150,7 @@ bool ValueObjectVariable::UpdateValue() {
|
||||||
m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
|
m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr.IsLocationList()) {
|
if (!expr_list.IsAlwaysValidSingleExpr()) {
|
||||||
SymbolContext sc;
|
SymbolContext sc;
|
||||||
variable->CalculateSymbolContext(&sc);
|
variable->CalculateSymbolContext(&sc);
|
||||||
if (sc.function)
|
if (sc.function)
|
||||||
|
@ -160,8 +159,8 @@ bool ValueObjectVariable::UpdateValue() {
|
||||||
target);
|
target);
|
||||||
}
|
}
|
||||||
Value old_value(m_value);
|
Value old_value(m_value);
|
||||||
if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr,
|
if (expr_list.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr,
|
||||||
nullptr, m_value, &m_error)) {
|
nullptr, m_value, &m_error)) {
|
||||||
m_resolved_value = m_value;
|
m_resolved_value = m_value;
|
||||||
m_value.SetContext(Value::ContextType::Variable, variable);
|
m_value.SetContext(Value::ContextType::Variable, variable);
|
||||||
|
|
||||||
|
@ -246,7 +245,7 @@ bool ValueObjectVariable::UpdateValue() {
|
||||||
m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
|
m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_error.Success();
|
return m_error.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
add_lldb_library(lldbExpression
|
add_lldb_library(lldbExpression
|
||||||
DiagnosticManager.cpp
|
DiagnosticManager.cpp
|
||||||
DWARFExpression.cpp
|
DWARFExpression.cpp
|
||||||
|
DWARFExpressionList.cpp
|
||||||
Expression.cpp
|
Expression.cpp
|
||||||
ExpressionVariable.cpp
|
ExpressionVariable.cpp
|
||||||
FunctionCaller.cpp
|
FunctionCaller.cpp
|
||||||
|
|
|
@ -45,29 +45,10 @@ using namespace lldb;
|
||||||
using namespace lldb_private;
|
using namespace lldb_private;
|
||||||
using namespace lldb_private::dwarf;
|
using namespace lldb_private::dwarf;
|
||||||
|
|
||||||
static lldb::addr_t
|
|
||||||
ReadAddressFromDebugAddrSection(const DWARFUnit *dwarf_cu,
|
|
||||||
uint32_t index) {
|
|
||||||
uint32_t index_size = dwarf_cu->GetAddressByteSize();
|
|
||||||
dw_offset_t addr_base = dwarf_cu->GetAddrBase();
|
|
||||||
lldb::offset_t offset = addr_base + index * index_size;
|
|
||||||
const DWARFDataExtractor &data =
|
|
||||||
dwarf_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadAddrData();
|
|
||||||
if (data.ValidOffsetForDataOfSize(offset, index_size))
|
|
||||||
return data.GetMaxU64_unchecked(&offset, index_size);
|
|
||||||
return LLDB_INVALID_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DWARFExpression constructor
|
// DWARFExpression constructor
|
||||||
DWARFExpression::DWARFExpression() : m_module_wp(), m_data() {}
|
DWARFExpression::DWARFExpression() : m_data() {}
|
||||||
|
|
||||||
DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
|
DWARFExpression::DWARFExpression(const DataExtractor &data) : m_data(data) {}
|
||||||
const DataExtractor &data,
|
|
||||||
const DWARFUnit *dwarf_cu)
|
|
||||||
: m_module_wp(), m_data(data), m_dwarf_cu(dwarf_cu) {
|
|
||||||
if (module_sp)
|
|
||||||
m_module_wp = module_sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
DWARFExpression::~DWARFExpression() = default;
|
DWARFExpression::~DWARFExpression() = default;
|
||||||
|
@ -86,71 +67,19 @@ void DWARFExpression::UpdateValue(uint64_t const_value,
|
||||||
m_data.SetAddressByteSize(addr_byte_size);
|
m_data.SetAddressByteSize(addr_byte_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data,
|
void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level,
|
||||||
lldb::DescriptionLevel level,
|
|
||||||
ABI *abi) const {
|
ABI *abi) const {
|
||||||
llvm::DWARFExpression(data.GetAsLLVM(), data.GetAddressByteSize())
|
llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize())
|
||||||
.print(s->AsRawOstream(), llvm::DIDumpOptions(),
|
.print(s->AsRawOstream(), llvm::DIDumpOptions(),
|
||||||
abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr);
|
abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFExpression::SetLocationListAddresses(addr_t cu_file_addr,
|
RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; }
|
||||||
addr_t func_file_addr) {
|
|
||||||
m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr};
|
|
||||||
}
|
|
||||||
|
|
||||||
int DWARFExpression::GetRegisterKind() { return m_reg_kind; }
|
|
||||||
|
|
||||||
void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
|
void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
|
||||||
m_reg_kind = reg_kind;
|
m_reg_kind = reg_kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFExpression::IsLocationList() const {
|
|
||||||
return bool(m_loclist_addresses);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
/// Implement enough of the DWARFObject interface in order to be able to call
|
|
||||||
/// DWARFLocationTable::dumpLocationList. We don't have access to a real
|
|
||||||
/// DWARFObject here because DWARFExpression is used in non-DWARF scenarios too.
|
|
||||||
class DummyDWARFObject final: public llvm::DWARFObject {
|
|
||||||
public:
|
|
||||||
DummyDWARFObject(bool IsLittleEndian) : IsLittleEndian(IsLittleEndian) {}
|
|
||||||
|
|
||||||
bool isLittleEndian() const override { return IsLittleEndian; }
|
|
||||||
|
|
||||||
llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec,
|
|
||||||
uint64_t Pos) const override {
|
|
||||||
return llvm::None;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
bool IsLittleEndian;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level,
|
|
||||||
ABI *abi) const {
|
|
||||||
if (IsLocationList()) {
|
|
||||||
// We have a location list
|
|
||||||
lldb::offset_t offset = 0;
|
|
||||||
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
|
|
||||||
m_dwarf_cu->GetLocationTable(m_data);
|
|
||||||
|
|
||||||
llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr;
|
|
||||||
llvm::DIDumpOptions DumpOpts;
|
|
||||||
DumpOpts.RecoverableErrorHandler = [&](llvm::Error E) {
|
|
||||||
s->AsRawOstream() << "error: " << toString(std::move(E));
|
|
||||||
};
|
|
||||||
loctable_up->dumpLocationList(
|
|
||||||
&offset, s->AsRawOstream(),
|
|
||||||
llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, MRI,
|
|
||||||
DummyDWARFObject(m_data.GetByteOrder() == eByteOrderLittle), nullptr,
|
|
||||||
DumpOpts, s->GetIndentLevel() + 2);
|
|
||||||
} else {
|
|
||||||
// We have a normal location that contains DW_OP location opcodes
|
|
||||||
DumpLocation(s, m_data, level, abi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
|
static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
|
||||||
lldb::RegisterKind reg_kind,
|
lldb::RegisterKind reg_kind,
|
||||||
|
@ -409,11 +338,10 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data,
|
||||||
return LLDB_INVALID_OFFSET;
|
return LLDB_INVALID_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx,
|
lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
|
||||||
|
uint32_t op_addr_idx,
|
||||||
bool &error) const {
|
bool &error) const {
|
||||||
error = false;
|
error = false;
|
||||||
if (IsLocationList())
|
|
||||||
return LLDB_INVALID_ADDRESS;
|
|
||||||
lldb::offset_t offset = 0;
|
lldb::offset_t offset = 0;
|
||||||
uint32_t curr_op_addr_idx = 0;
|
uint32_t curr_op_addr_idx = 0;
|
||||||
while (m_data.ValidOffset(offset)) {
|
while (m_data.ValidOffset(offset)) {
|
||||||
|
@ -423,19 +351,18 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx,
|
||||||
const lldb::addr_t op_file_addr = m_data.GetAddress(&offset);
|
const lldb::addr_t op_file_addr = m_data.GetAddress(&offset);
|
||||||
if (curr_op_addr_idx == op_addr_idx)
|
if (curr_op_addr_idx == op_addr_idx)
|
||||||
return op_file_addr;
|
return op_file_addr;
|
||||||
else
|
++curr_op_addr_idx;
|
||||||
++curr_op_addr_idx;
|
|
||||||
} else if (op == DW_OP_GNU_addr_index || op == DW_OP_addrx) {
|
} else if (op == DW_OP_GNU_addr_index || op == DW_OP_addrx) {
|
||||||
uint64_t index = m_data.GetULEB128(&offset);
|
uint64_t index = m_data.GetULEB128(&offset);
|
||||||
if (curr_op_addr_idx == op_addr_idx) {
|
if (curr_op_addr_idx == op_addr_idx) {
|
||||||
if (!m_dwarf_cu) {
|
if (!dwarf_cu) {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
|
return dwarf_cu->ReadAddressFromDebugAddrSection(index);
|
||||||
} else
|
}
|
||||||
++curr_op_addr_idx;
|
++curr_op_addr_idx;
|
||||||
} else {
|
} else {
|
||||||
const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
|
const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
|
||||||
if (op_arg_size == LLDB_INVALID_OFFSET) {
|
if (op_arg_size == LLDB_INVALID_OFFSET) {
|
||||||
|
@ -449,8 +376,6 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
|
bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
|
||||||
if (IsLocationList())
|
|
||||||
return false;
|
|
||||||
lldb::offset_t offset = 0;
|
lldb::offset_t offset = 0;
|
||||||
while (m_data.ValidOffset(offset)) {
|
while (m_data.ValidOffset(offset)) {
|
||||||
const uint8_t op = m_data.GetU8(&offset);
|
const uint8_t op = m_data.GetU8(&offset);
|
||||||
|
@ -487,11 +412,6 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFExpression::ContainsThreadLocalStorage() const {
|
bool DWARFExpression::ContainsThreadLocalStorage() const {
|
||||||
// We are assuming for now that any thread local variable will not have a
|
|
||||||
// location list. This has been true for all thread local variables we have
|
|
||||||
// seen so far produced by any compiler.
|
|
||||||
if (IsLocationList())
|
|
||||||
return false;
|
|
||||||
lldb::offset_t offset = 0;
|
lldb::offset_t offset = 0;
|
||||||
while (m_data.ValidOffset(offset)) {
|
while (m_data.ValidOffset(offset)) {
|
||||||
const uint8_t op = m_data.GetU8(&offset);
|
const uint8_t op = m_data.GetU8(&offset);
|
||||||
|
@ -501,27 +421,18 @@ bool DWARFExpression::ContainsThreadLocalStorage() const {
|
||||||
const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
|
const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
|
||||||
if (op_arg_size == LLDB_INVALID_OFFSET)
|
if (op_arg_size == LLDB_INVALID_OFFSET)
|
||||||
return false;
|
return false;
|
||||||
else
|
offset += op_arg_size;
|
||||||
offset += op_arg_size;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool DWARFExpression::LinkThreadLocalStorage(
|
bool DWARFExpression::LinkThreadLocalStorage(
|
||||||
lldb::ModuleSP new_module_sp,
|
|
||||||
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
|
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
|
||||||
&link_address_callback) {
|
&link_address_callback) {
|
||||||
// We are assuming for now that any thread local variable will not have a
|
|
||||||
// location list. This has been true for all thread local variables we have
|
|
||||||
// seen so far produced by any compiler.
|
|
||||||
if (IsLocationList())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
|
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
|
||||||
// We have to make a copy of the data as we don't know if this data is from a
|
// We have to make a copy of the data as we don't know if this data is from a
|
||||||
// read only memory mapped buffer, so we duplicate all of the data first,
|
// read only memory mapped buffer, so we duplicate all of the data first,
|
||||||
// then modify it, and if all goes well, we then replace the data for this
|
// then modify it, and if all goes well, we then replace the data for this
|
||||||
// expression.
|
// expression.
|
||||||
|
|
||||||
// Make en encoder that contains a copy of the location expression data so we
|
// Make en encoder that contains a copy of the location expression data so we
|
||||||
// can write the address into the buffer using the correct byte order.
|
// can write the address into the buffer using the correct byte order.
|
||||||
DataEncoder encoder(m_data.GetDataStart(), m_data.GetByteSize(),
|
DataEncoder encoder(m_data.GetDataStart(), m_data.GetByteSize(),
|
||||||
|
@ -593,42 +504,10 @@ bool DWARFExpression::LinkThreadLocalStorage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we linked the TLS address correctly, update the module so that when the
|
|
||||||
// expression is evaluated it can resolve the file address to a load address
|
|
||||||
// and read the
|
|
||||||
// TLS data
|
|
||||||
m_module_wp = new_module_sp;
|
|
||||||
m_data.SetData(encoder.GetDataBuffer());
|
m_data.SetData(encoder.GetDataBuffer());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFExpression::LocationListContainsAddress(addr_t func_load_addr,
|
|
||||||
lldb::addr_t addr) const {
|
|
||||||
if (func_load_addr == LLDB_INVALID_ADDRESS || addr == LLDB_INVALID_ADDRESS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!IsLocationList())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return GetLocationExpression(func_load_addr, addr) != llvm::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DWARFExpression::DumpLocationForAddress(Stream *s,
|
|
||||||
lldb::DescriptionLevel level,
|
|
||||||
addr_t func_load_addr,
|
|
||||||
addr_t address, ABI *abi) {
|
|
||||||
if (!IsLocationList()) {
|
|
||||||
DumpLocation(s, m_data, level, abi);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (llvm::Optional<DataExtractor> expr =
|
|
||||||
GetLocationExpression(func_load_addr, address)) {
|
|
||||||
DumpLocation(s, *expr, level, abi);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
|
static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
|
||||||
ExecutionContext *exe_ctx,
|
ExecutionContext *exe_ctx,
|
||||||
RegisterContext *reg_ctx,
|
RegisterContext *reg_ctx,
|
||||||
|
@ -824,10 +703,10 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
|
||||||
// TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value
|
// TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value
|
||||||
// subexpresion whenever llvm does.
|
// subexpresion whenever llvm does.
|
||||||
Value result;
|
Value result;
|
||||||
const DWARFExpression ¶m_expr = matched_param->LocationInCaller;
|
const DWARFExpressionList ¶m_expr = matched_param->LocationInCaller;
|
||||||
if (!param_expr.Evaluate(&parent_exe_ctx,
|
if (!param_expr.Evaluate(&parent_exe_ctx,
|
||||||
parent_frame->GetRegisterContext().get(),
|
parent_frame->GetRegisterContext().get(),
|
||||||
/*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS,
|
LLDB_INVALID_ADDRESS,
|
||||||
/*initial_value_ptr=*/nullptr,
|
/*initial_value_ptr=*/nullptr,
|
||||||
/*object_address_ptr=*/nullptr, result, error_ptr)) {
|
/*object_address_ptr=*/nullptr, result, error_ptr)) {
|
||||||
LLDB_LOG(log,
|
LLDB_LOG(log,
|
||||||
|
@ -839,63 +718,6 @@ static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope,
|
|
||||||
lldb::addr_t loclist_base_load_addr,
|
|
||||||
const Value *initial_value_ptr,
|
|
||||||
const Value *object_address_ptr, Value &result,
|
|
||||||
Status *error_ptr) const {
|
|
||||||
ExecutionContext exe_ctx(exe_scope);
|
|
||||||
return Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, initial_value_ptr,
|
|
||||||
object_address_ptr, result, error_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
|
|
||||||
RegisterContext *reg_ctx,
|
|
||||||
lldb::addr_t func_load_addr,
|
|
||||||
const Value *initial_value_ptr,
|
|
||||||
const Value *object_address_ptr, Value &result,
|
|
||||||
Status *error_ptr) const {
|
|
||||||
ModuleSP module_sp = m_module_wp.lock();
|
|
||||||
|
|
||||||
if (IsLocationList()) {
|
|
||||||
Address pc;
|
|
||||||
StackFrame *frame = nullptr;
|
|
||||||
if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
|
|
||||||
frame = exe_ctx->GetFramePtr();
|
|
||||||
if (!frame)
|
|
||||||
return false;
|
|
||||||
RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
|
|
||||||
if (!reg_ctx_sp)
|
|
||||||
return false;
|
|
||||||
reg_ctx_sp->GetPCForSymbolication(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (func_load_addr != LLDB_INVALID_ADDRESS) {
|
|
||||||
if (!pc.IsValid()) {
|
|
||||||
if (error_ptr)
|
|
||||||
error_ptr->SetErrorString("Invalid PC in frame.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Target *target = exe_ctx->GetTargetPtr();
|
|
||||||
if (llvm::Optional<DataExtractor> expr = GetLocationExpression(
|
|
||||||
func_load_addr, pc.GetLoadAddress(target))) {
|
|
||||||
return DWARFExpression::Evaluate(
|
|
||||||
exe_ctx, reg_ctx, module_sp, *expr, m_dwarf_cu, m_reg_kind,
|
|
||||||
initial_value_ptr, object_address_ptr, result, error_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error_ptr)
|
|
||||||
error_ptr->SetErrorString("variable not available");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not a location list, just a single expression.
|
|
||||||
return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, m_data,
|
|
||||||
m_dwarf_cu, m_reg_kind, initial_value_ptr,
|
|
||||||
object_address_ptr, result, error_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// The location description kinds described by the DWARF v5
|
/// The location description kinds described by the DWARF v5
|
||||||
/// specification. Composite locations are handled out-of-band and
|
/// specification. Composite locations are handled out-of-band and
|
||||||
|
@ -2670,7 +2492,7 @@ bool DWARFExpression::Evaluate(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t index = opcodes.GetULEB128(&offset);
|
uint64_t index = opcodes.GetULEB128(&offset);
|
||||||
lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index);
|
lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index);
|
||||||
stack.push_back(Scalar(value));
|
stack.push_back(Scalar(value));
|
||||||
stack.back().SetValueType(Value::ValueType::FileAddress);
|
stack.back().SetValueType(Value::ValueType::FileAddress);
|
||||||
} break;
|
} break;
|
||||||
|
@ -2690,7 +2512,7 @@ bool DWARFExpression::Evaluate(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t index = opcodes.GetULEB128(&offset);
|
uint64_t index = opcodes.GetULEB128(&offset);
|
||||||
lldb::addr_t value = ReadAddressFromDebugAddrSection(dwarf_cu, index);
|
lldb::addr_t value = dwarf_cu->ReadAddressFromDebugAddrSection(index);
|
||||||
stack.push_back(Scalar(value));
|
stack.push_back(Scalar(value));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -2743,61 +2565,16 @@ bool DWARFExpression::Evaluate(
|
||||||
return true; // Return true on success
|
return true; // Return true on success
|
||||||
}
|
}
|
||||||
|
|
||||||
static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc,
|
bool DWARFExpression::ParseDWARFLocationList(
|
||||||
ByteOrder byte_order, uint32_t addr_size) {
|
const DWARFUnit *dwarf_cu, const DataExtractor &data,
|
||||||
auto buffer_sp =
|
DWARFExpressionList *location_list) {
|
||||||
std::make_shared<DataBufferHeap>(loc.Expr.data(), loc.Expr.size());
|
location_list->Clear();
|
||||||
return DataExtractor(buffer_sp, byte_order, addr_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DWARFExpression::DumpLocations(Stream *s, lldb::DescriptionLevel level,
|
|
||||||
addr_t load_function_start, addr_t addr,
|
|
||||||
ABI *abi) {
|
|
||||||
if (!IsLocationList()) {
|
|
||||||
DumpLocation(s, m_data, level, abi);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool dump_all = addr == LLDB_INVALID_ADDRESS;
|
|
||||||
llvm::ListSeparator separator;
|
|
||||||
auto callback = [&](llvm::DWARFLocationExpression loc) -> bool {
|
|
||||||
if (loc.Range &&
|
|
||||||
(dump_all || (loc.Range->LowPC <= addr && addr < loc.Range->HighPC))) {
|
|
||||||
uint32_t addr_size = m_data.GetAddressByteSize();
|
|
||||||
DataExtractor data = ToDataExtractor(loc, m_data.GetByteOrder(),
|
|
||||||
m_data.GetAddressByteSize());
|
|
||||||
s->AsRawOstream() << separator;
|
|
||||||
s->PutCString("[");
|
|
||||||
s->AsRawOstream() << llvm::format_hex(loc.Range->LowPC,
|
|
||||||
2 + 2 * addr_size);
|
|
||||||
s->PutCString(", ");
|
|
||||||
s->AsRawOstream() << llvm::format_hex(loc.Range->HighPC,
|
|
||||||
2 + 2 * addr_size);
|
|
||||||
s->PutCString(") -> ");
|
|
||||||
DumpLocation(s, data, level, abi);
|
|
||||||
return dump_all;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
if (!GetLocationExpressions(load_function_start, callback))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DWARFExpression::GetLocationExpressions(
|
|
||||||
addr_t load_function_start,
|
|
||||||
llvm::function_ref<bool(llvm::DWARFLocationExpression)> callback) const {
|
|
||||||
if (load_function_start == LLDB_INVALID_ADDRESS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Log *log = GetLog(LLDBLog::Expressions);
|
|
||||||
|
|
||||||
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
|
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
|
||||||
m_dwarf_cu->GetLocationTable(m_data);
|
dwarf_cu->GetLocationTable(data);
|
||||||
|
Log *log = GetLog(LLDBLog::Expressions);
|
||||||
uint64_t offset = 0;
|
|
||||||
auto lookup_addr =
|
auto lookup_addr =
|
||||||
[&](uint32_t index) -> llvm::Optional<llvm::object::SectionedAddress> {
|
[&](uint32_t index) -> llvm::Optional<llvm::object::SectionedAddress> {
|
||||||
addr_t address = ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
|
addr_t address = dwarf_cu->ReadAddressFromDebugAddrSection(index);
|
||||||
if (address == LLDB_INVALID_ADDRESS)
|
if (address == LLDB_INVALID_ADDRESS)
|
||||||
return llvm::None;
|
return llvm::None;
|
||||||
return llvm::object::SectionedAddress{address};
|
return llvm::object::SectionedAddress{address};
|
||||||
|
@ -2807,18 +2584,17 @@ bool DWARFExpression::GetLocationExpressions(
|
||||||
LLDB_LOG_ERROR(log, loc.takeError(), "{0}");
|
LLDB_LOG_ERROR(log, loc.takeError(), "{0}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (loc->Range) {
|
auto buffer_sp =
|
||||||
// This relocates low_pc and high_pc by adding the difference between the
|
std::make_shared<DataBufferHeap>(loc->Expr.data(), loc->Expr.size());
|
||||||
// function file address, and the actual address it is loaded in memory.
|
DWARFExpression expr = DWARFExpression(DataExtractor(
|
||||||
addr_t slide = load_function_start - m_loclist_addresses->func_file_addr;
|
buffer_sp, data.GetByteOrder(), data.GetAddressByteSize()));
|
||||||
loc->Range->LowPC += slide;
|
location_list->AddExpression(loc->Range->LowPC, loc->Range->HighPC, expr);
|
||||||
loc->Range->HighPC += slide;
|
return true;
|
||||||
}
|
|
||||||
return callback(*loc);
|
|
||||||
};
|
};
|
||||||
llvm::Error error = loctable_up->visitAbsoluteLocationList(
|
llvm::Error error = loctable_up->visitAbsoluteLocationList(
|
||||||
offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr},
|
0, llvm::object::SectionedAddress{dwarf_cu->GetBaseAddress()},
|
||||||
lookup_addr, process_list);
|
lookup_addr, process_list);
|
||||||
|
location_list->Sort();
|
||||||
if (error) {
|
if (error) {
|
||||||
LLDB_LOG_ERROR(log, std::move(error), "{0}");
|
LLDB_LOG_ERROR(log, std::move(error), "{0}");
|
||||||
return false;
|
return false;
|
||||||
|
@ -2826,23 +2602,8 @@ bool DWARFExpression::GetLocationExpressions(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Optional<DataExtractor>
|
bool DWARFExpression::MatchesOperand(
|
||||||
DWARFExpression::GetLocationExpression(addr_t load_function_start,
|
StackFrame &frame, const Instruction::Operand &operand) const {
|
||||||
addr_t addr) const {
|
|
||||||
llvm::Optional<DataExtractor> data;
|
|
||||||
auto callback = [&](llvm::DWARFLocationExpression loc) {
|
|
||||||
if (loc.Range && loc.Range->LowPC <= addr && addr < loc.Range->HighPC) {
|
|
||||||
data = ToDataExtractor(loc, m_data.GetByteOrder(),
|
|
||||||
m_data.GetAddressByteSize());
|
|
||||||
}
|
|
||||||
return !data;
|
|
||||||
};
|
|
||||||
GetLocationExpressions(load_function_start, callback);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DWARFExpression::MatchesOperand(StackFrame &frame,
|
|
||||||
const Instruction::Operand &operand) {
|
|
||||||
using namespace OperandMatchers;
|
using namespace OperandMatchers;
|
||||||
|
|
||||||
RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
|
RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
|
||||||
|
@ -2850,28 +2611,7 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataExtractor opcodes;
|
DataExtractor opcodes(m_data);
|
||||||
if (IsLocationList()) {
|
|
||||||
SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
|
|
||||||
if (!sc.function)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
addr_t load_function_start =
|
|
||||||
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
|
||||||
if (load_function_start == LLDB_INVALID_ADDRESS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetLoadAddress(
|
|
||||||
frame.CalculateTarget().get());
|
|
||||||
|
|
||||||
if (llvm::Optional<DataExtractor> expr =
|
|
||||||
GetLocationExpression(load_function_start, pc))
|
|
||||||
opcodes = std::move(*expr);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
} else
|
|
||||||
opcodes = m_data;
|
|
||||||
|
|
||||||
|
|
||||||
lldb::offset_t op_offset = 0;
|
lldb::offset_t op_offset = 0;
|
||||||
uint8_t opcode = opcodes.GetU8(&op_offset);
|
uint8_t opcode = opcodes.GetU8(&op_offset);
|
||||||
|
@ -2879,7 +2619,7 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame,
|
||||||
if (opcode == DW_OP_fbreg) {
|
if (opcode == DW_OP_fbreg) {
|
||||||
int64_t offset = opcodes.GetSLEB128(&op_offset);
|
int64_t offset = opcodes.GetSLEB128(&op_offset);
|
||||||
|
|
||||||
DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr);
|
DWARFExpressionList *fb_expr = frame.GetFrameBaseExpression(nullptr);
|
||||||
if (!fb_expr) {
|
if (!fb_expr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
//===-- DWARFExpressionList.cpp -------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "lldb/Expression/DWARFExpressionList.h"
|
||||||
|
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
|
||||||
|
#include "lldb/Symbol/Function.h"
|
||||||
|
#include "lldb/Target/RegisterContext.h"
|
||||||
|
#include "lldb/Target/StackFrame.h"
|
||||||
|
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
|
||||||
|
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||||
|
|
||||||
|
using namespace lldb;
|
||||||
|
using namespace lldb_private;
|
||||||
|
|
||||||
|
bool DWARFExpressionList::IsAlwaysValidSingleExpr() const {
|
||||||
|
return GetAlwaysValidExpr() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DWARFExpression * DWARFExpressionList::GetAlwaysValidExpr() const {
|
||||||
|
if (m_exprs.GetSize() != 1)
|
||||||
|
return nullptr;
|
||||||
|
const auto *expr = m_exprs.GetEntryAtIndex(0);
|
||||||
|
if (expr->base == 0 && expr->size == LLDB_INVALID_ADDRESS)
|
||||||
|
return &expr->data;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,
|
||||||
|
DWARFExpression expr) {
|
||||||
|
if (IsAlwaysValidSingleExpr() || base >= end)
|
||||||
|
return false;
|
||||||
|
m_exprs.Append({base, end - base, expr});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::GetExpressionData(DataExtractor &data,
|
||||||
|
lldb::addr_t func_load_addr,
|
||||||
|
lldb::addr_t file_addr) const {
|
||||||
|
if (const DWARFExpression *expr =
|
||||||
|
GetExpressionAtAddress(func_load_addr, file_addr))
|
||||||
|
return expr->GetExpressionData(data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,
|
||||||
|
lldb::addr_t addr) const {
|
||||||
|
if (IsAlwaysValidSingleExpr())
|
||||||
|
return true;
|
||||||
|
return GetExpressionAtAddress(func_load_addr, addr) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DWARFExpression *
|
||||||
|
DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,
|
||||||
|
lldb::addr_t load_addr) const {
|
||||||
|
if (const DWARFExpression *expr = GetAlwaysValidExpr())
|
||||||
|
return expr;
|
||||||
|
if (func_load_addr == LLDB_INVALID_ADDRESS)
|
||||||
|
func_load_addr = m_func_file_addr;
|
||||||
|
addr_t addr = load_addr - func_load_addr + m_func_file_addr;
|
||||||
|
uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
|
||||||
|
if (index == UINT32_MAX)
|
||||||
|
return nullptr;
|
||||||
|
return &m_exprs.GetEntryAtIndex(index)->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWARFExpression *
|
||||||
|
DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t func_load_addr,
|
||||||
|
lldb::addr_t load_addr) {
|
||||||
|
if (IsAlwaysValidSingleExpr())
|
||||||
|
return &m_exprs.GetMutableEntryAtIndex(0)->data;
|
||||||
|
if (func_load_addr == LLDB_INVALID_ADDRESS)
|
||||||
|
func_load_addr = m_func_file_addr;
|
||||||
|
addr_t addr = load_addr - func_load_addr + m_func_file_addr;
|
||||||
|
uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
|
||||||
|
if (index == UINT32_MAX)
|
||||||
|
return nullptr;
|
||||||
|
return &m_exprs.GetMutableEntryAtIndex(index)->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::ContainsThreadLocalStorage() const {
|
||||||
|
// We are assuming for now that any thread local variable will not have a
|
||||||
|
// location list. This has been true for all thread local variables we have
|
||||||
|
// seen so far produced by any compiler.
|
||||||
|
if (!IsAlwaysValidSingleExpr())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
|
||||||
|
return expr.ContainsThreadLocalStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::LinkThreadLocalStorage(
|
||||||
|
lldb::ModuleSP new_module_sp,
|
||||||
|
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
|
||||||
|
&link_address_callback) {
|
||||||
|
// We are assuming for now that any thread local variable will not have a
|
||||||
|
// location list. This has been true for all thread local variables we have
|
||||||
|
// seen so far produced by any compiler.
|
||||||
|
if (!IsAlwaysValidSingleExpr())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
|
||||||
|
// If we linked the TLS address correctly, update the module so that when the
|
||||||
|
// expression is evaluated it can resolve the file address to a load address
|
||||||
|
// and read the TLS data
|
||||||
|
if (expr.LinkThreadLocalStorage(link_address_callback))
|
||||||
|
m_module_wp = new_module_sp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::MatchesOperand(
|
||||||
|
StackFrame &frame, const Instruction::Operand &operand) const {
|
||||||
|
RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
|
||||||
|
if (!reg_ctx_sp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const DWARFExpression *expr = nullptr;
|
||||||
|
if (IsAlwaysValidSingleExpr())
|
||||||
|
expr = &m_exprs.GetEntryAtIndex(0)->data;
|
||||||
|
else {
|
||||||
|
SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
|
||||||
|
if (!sc.function)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
addr_t load_function_start =
|
||||||
|
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
||||||
|
if (load_function_start == LLDB_INVALID_ADDRESS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress();
|
||||||
|
expr = GetExpressionAtAddress(LLDB_INVALID_ADDRESS, pc);
|
||||||
|
}
|
||||||
|
if (!expr)
|
||||||
|
return false;
|
||||||
|
return expr->MatchesOperand(frame, operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,
|
||||||
|
lldb::addr_t func_load_addr,
|
||||||
|
lldb::addr_t file_addr,
|
||||||
|
ABI *abi) const {
|
||||||
|
llvm::raw_ostream &os = s->AsRawOstream();
|
||||||
|
llvm::ListSeparator separator;
|
||||||
|
if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
|
||||||
|
expr->DumpLocation(s, level, abi);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const Entry &entry : *this) {
|
||||||
|
addr_t load_base = entry.GetRangeBase() + func_load_addr - m_func_file_addr;
|
||||||
|
addr_t load_end = entry.GetRangeEnd() + func_load_addr - m_func_file_addr;
|
||||||
|
if (file_addr != LLDB_INVALID_ADDRESS &&
|
||||||
|
(file_addr < load_base || file_addr >= load_end))
|
||||||
|
continue;
|
||||||
|
const auto &expr = entry.data;
|
||||||
|
DataExtractor data;
|
||||||
|
expr.GetExpressionData(data);
|
||||||
|
uint32_t addr_size = data.GetAddressByteSize();
|
||||||
|
|
||||||
|
os << separator;
|
||||||
|
os << "[";
|
||||||
|
os << llvm::format_hex(load_base, 2 + 2 * addr_size);
|
||||||
|
os << ", ";
|
||||||
|
os << llvm::format_hex(load_end, 2 + 2 * addr_size);
|
||||||
|
os << ") -> ";
|
||||||
|
expr.DumpLocation(s, level, abi);
|
||||||
|
if (file_addr != LLDB_INVALID_ADDRESS)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DWARFExpressionList::GetDescription(Stream *s,
|
||||||
|
lldb::DescriptionLevel level,
|
||||||
|
ABI *abi) const {
|
||||||
|
llvm::raw_ostream &os = s->AsRawOstream();
|
||||||
|
if (IsAlwaysValidSingleExpr()) {
|
||||||
|
m_exprs.Back()->data.DumpLocation(s, level, abi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
os << llvm::format("0x%8.8" PRIx64 ": ", 0);
|
||||||
|
for (const Entry &entry : *this) {
|
||||||
|
const auto &expr = entry.data;
|
||||||
|
DataExtractor data;
|
||||||
|
expr.GetExpressionData(data);
|
||||||
|
uint32_t addr_size = data.GetAddressByteSize();
|
||||||
|
os << "\n";
|
||||||
|
os.indent(s->GetIndentLevel() + 2);
|
||||||
|
os << "[";
|
||||||
|
llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeBase());
|
||||||
|
os << ", ";
|
||||||
|
llvm::DWARFFormValue::dumpAddress(os, addr_size, entry.GetRangeEnd());
|
||||||
|
os << "): ";
|
||||||
|
expr.DumpLocation(s, level, abi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DWARFExpressionList::Evaluate(ExecutionContext *exe_ctx,
|
||||||
|
RegisterContext *reg_ctx,
|
||||||
|
lldb::addr_t func_load_addr,
|
||||||
|
const Value *initial_value_ptr,
|
||||||
|
const Value *object_address_ptr,
|
||||||
|
Value &result, Status *error_ptr) const {
|
||||||
|
ModuleSP module_sp = m_module_wp.lock();
|
||||||
|
DataExtractor data;
|
||||||
|
RegisterKind reg_kind;
|
||||||
|
DWARFExpression expr;
|
||||||
|
if (IsAlwaysValidSingleExpr()) {
|
||||||
|
expr = m_exprs.Back()->data;
|
||||||
|
} else {
|
||||||
|
Address pc;
|
||||||
|
StackFrame *frame = nullptr;
|
||||||
|
if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
|
||||||
|
if (exe_ctx)
|
||||||
|
frame = exe_ctx->GetFramePtr();
|
||||||
|
if (!frame)
|
||||||
|
return false;
|
||||||
|
RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
|
||||||
|
if (!reg_ctx_sp)
|
||||||
|
return false;
|
||||||
|
reg_ctx_sp->GetPCForSymbolication(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pc.IsValid()) {
|
||||||
|
if (error_ptr)
|
||||||
|
error_ptr->SetErrorString("Invalid PC in frame.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
addr_t pc_load_addr = pc.GetLoadAddress(exe_ctx->GetTargetPtr());
|
||||||
|
const DWARFExpression *entry =
|
||||||
|
GetExpressionAtAddress(func_load_addr, pc_load_addr);
|
||||||
|
if (!entry) {
|
||||||
|
if (error_ptr) {
|
||||||
|
error_ptr->SetErrorString("variable not available");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
expr = *entry;
|
||||||
|
}
|
||||||
|
expr.GetExpressionData(data);
|
||||||
|
reg_kind = expr.GetRegisterKind();
|
||||||
|
return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,
|
||||||
|
m_dwarf_cu, reg_kind, initial_value_ptr,
|
||||||
|
object_address_ptr, result, error_ptr);
|
||||||
|
}
|
|
@ -520,7 +520,7 @@ public:
|
||||||
|
|
||||||
if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize(scope)) {
|
if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize(scope)) {
|
||||||
if (data.GetByteSize() == 0 &&
|
if (data.GetByteSize() == 0 &&
|
||||||
!m_variable_sp->LocationExpression().IsValid()) {
|
!m_variable_sp->LocationExpressionList().IsValid()) {
|
||||||
err.SetErrorStringWithFormat("the variable '%s' has no location, "
|
err.SetErrorStringWithFormat("the variable '%s' has no location, "
|
||||||
"it may have been optimized out",
|
"it may have been optimized out",
|
||||||
m_variable_sp->GetName().AsCString());
|
m_variable_sp->GetName().AsCString());
|
||||||
|
|
|
@ -1437,15 +1437,14 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFExpression &var_location_expr = var->LocationExpression();
|
DWARFExpressionList &var_location_list = var->LocationExpressionList();
|
||||||
|
|
||||||
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
|
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
|
||||||
Status err;
|
Status err;
|
||||||
|
|
||||||
if (var->GetLocationIsConstantValueData()) {
|
if (var->GetLocationIsConstantValueData()) {
|
||||||
DataExtractor const_value_extractor;
|
DataExtractor const_value_extractor;
|
||||||
|
if (var_location_list.GetExpressionData(const_value_extractor)) {
|
||||||
if (var_location_expr.GetExpressionData(const_value_extractor)) {
|
|
||||||
var_location = Value(const_value_extractor.GetDataStart(),
|
var_location = Value(const_value_extractor.GetDataStart(),
|
||||||
const_value_extractor.GetByteSize());
|
const_value_extractor.GetByteSize());
|
||||||
var_location.SetValueType(Value::ValueType::HostAddress);
|
var_location.SetValueType(Value::ValueType::HostAddress);
|
||||||
|
|
|
@ -2292,7 +2292,7 @@ DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
|
||||||
int call_file = 0;
|
int call_file = 0;
|
||||||
int call_line = 0;
|
int call_line = 0;
|
||||||
int call_column = 0;
|
int call_column = 0;
|
||||||
DWARFExpression frame_base;
|
DWARFExpressionList frame_base;
|
||||||
|
|
||||||
const dw_tag_t tag = die.Tag();
|
const dw_tag_t tag = die.Tag();
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,7 @@ bool DWARFDIE::GetDIENamesAndRanges(
|
||||||
const char *&name, const char *&mangled, DWARFRangeList &ranges,
|
const char *&name, const char *&mangled, DWARFRangeList &ranges,
|
||||||
int &decl_file, int &decl_line, int &decl_column, int &call_file,
|
int &decl_file, int &decl_line, int &decl_column, int &call_file,
|
||||||
int &call_line, int &call_column,
|
int &call_line, int &call_column,
|
||||||
lldb_private::DWARFExpression *frame_base) const {
|
lldb_private::DWARFExpressionList *frame_base) const {
|
||||||
if (IsValid()) {
|
if (IsValid()) {
|
||||||
return m_die->GetDIENamesAndRanges(
|
return m_die->GetDIENamesAndRanges(
|
||||||
GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column,
|
GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column,
|
||||||
|
|
|
@ -85,11 +85,12 @@ public:
|
||||||
DWARFDIE
|
DWARFDIE
|
||||||
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
|
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
|
||||||
|
|
||||||
bool GetDIENamesAndRanges(const char *&name, const char *&mangled,
|
bool
|
||||||
DWARFRangeList &ranges, int &decl_file,
|
GetDIENamesAndRanges(const char *&name, const char *&mangled,
|
||||||
int &decl_line, int &decl_column, int &call_file,
|
DWARFRangeList &ranges, int &decl_file, int &decl_line,
|
||||||
int &call_line, int &call_column,
|
int &decl_column, int &call_file, int &call_line,
|
||||||
lldb_private::DWARFExpression *frame_base) const;
|
int &call_column,
|
||||||
|
lldb_private::DWARFExpressionList *frame_base) const;
|
||||||
|
|
||||||
/// The range of all the children of this DIE.
|
/// The range of all the children of this DIE.
|
||||||
llvm::iterator_range<child_iterator> children() const;
|
llvm::iterator_range<child_iterator> children() const;
|
||||||
|
|
|
@ -231,7 +231,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
|
||||||
DWARFUnit *cu, const char *&name, const char *&mangled,
|
DWARFUnit *cu, const char *&name, const char *&mangled,
|
||||||
DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
|
DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
|
||||||
int &call_file, int &call_line, int &call_column,
|
int &call_file, int &call_line, int &call_column,
|
||||||
DWARFExpression *frame_base) const {
|
DWARFExpressionList *frame_base) const {
|
||||||
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
|
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
|
||||||
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
|
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
|
||||||
std::vector<DWARFDIE> dies;
|
std::vector<DWARFDIE> dies;
|
||||||
|
@ -345,21 +345,22 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
|
||||||
uint32_t block_offset =
|
uint32_t block_offset =
|
||||||
form_value.BlockData() - data.GetDataStart();
|
form_value.BlockData() - data.GetDataStart();
|
||||||
uint32_t block_length = form_value.Unsigned();
|
uint32_t block_length = form_value.Unsigned();
|
||||||
*frame_base = DWARFExpression(
|
*frame_base =
|
||||||
module, DataExtractor(data, block_offset, block_length), cu);
|
DWARFExpressionList(module,
|
||||||
|
DWARFExpression(DataExtractor(
|
||||||
|
data, block_offset, block_length)),
|
||||||
|
cu);
|
||||||
} else {
|
} else {
|
||||||
DataExtractor data = cu->GetLocationData();
|
DataExtractor data = cu->GetLocationData();
|
||||||
const dw_offset_t offset = form_value.Unsigned();
|
const dw_offset_t offset = form_value.Unsigned();
|
||||||
if (data.ValidOffset(offset)) {
|
if (data.ValidOffset(offset)) {
|
||||||
data = DataExtractor(data, offset, data.GetByteSize() - offset);
|
data = DataExtractor(data, offset, data.GetByteSize() - offset);
|
||||||
*frame_base = DWARFExpression(module, data, cu);
|
|
||||||
if (lo_pc != LLDB_INVALID_ADDRESS) {
|
if (lo_pc != LLDB_INVALID_ADDRESS) {
|
||||||
assert(lo_pc >= cu->GetBaseAddress());
|
assert(lo_pc >= cu->GetBaseAddress());
|
||||||
frame_base->SetLocationListAddresses(cu->GetBaseAddress(),
|
DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
|
||||||
lo_pc);
|
frame_base->SetFuncFileAddress(lo_pc);
|
||||||
} else {
|
} else
|
||||||
set_frame_base_loclist_addr = true;
|
set_frame_base_loclist_addr = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +385,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
|
||||||
if (set_frame_base_loclist_addr) {
|
if (set_frame_base_loclist_addr) {
|
||||||
dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
|
dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
|
||||||
assert(lowest_range_pc >= cu->GetBaseAddress());
|
assert(lowest_range_pc >= cu->GetBaseAddress());
|
||||||
frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc);
|
frame_base->SetFuncFileAddress(lowest_range_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
|
if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
|
||||||
|
|
|
@ -104,7 +104,7 @@ public:
|
||||||
DWARFUnit *cu, const char *&name, const char *&mangled,
|
DWARFUnit *cu, const char *&name, const char *&mangled,
|
||||||
DWARFRangeList &rangeList, int &decl_file, int &decl_line,
|
DWARFRangeList &rangeList, int &decl_file, int &decl_line,
|
||||||
int &decl_column, int &call_file, int &call_line, int &call_column,
|
int &decl_column, int &call_file, int &call_line, int &call_column,
|
||||||
lldb_private::DWARFExpression *frame_base = nullptr) const;
|
lldb_private::DWARFExpressionList *frame_base = nullptr) const;
|
||||||
|
|
||||||
const DWARFAbbreviationDeclaration *
|
const DWARFAbbreviationDeclaration *
|
||||||
GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const;
|
GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const;
|
||||||
|
|
|
@ -579,6 +579,17 @@ void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
|
||||||
m_str_offsets_base = str_offsets_base;
|
m_str_offsets_base = str_offsets_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dw_addr_t DWARFUnit::ReadAddressFromDebugAddrSection(uint32_t index) const {
|
||||||
|
uint32_t index_size = GetAddressByteSize();
|
||||||
|
dw_offset_t addr_base = GetAddrBase();
|
||||||
|
dw_addr_t offset = addr_base + index * index_size;
|
||||||
|
const DWARFDataExtractor &data =
|
||||||
|
m_dwarf.GetDWARFContext().getOrLoadAddrData();
|
||||||
|
if (data.ValidOffsetForDataOfSize(offset, index_size))
|
||||||
|
return data.GetMaxU64_unchecked(&offset, index_size);
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
// It may be called only with m_die_array_mutex held R/W.
|
// It may be called only with m_die_array_mutex held R/W.
|
||||||
void DWARFUnit::ClearDIEsRWLocked() {
|
void DWARFUnit::ClearDIEsRWLocked() {
|
||||||
m_die_array.clear();
|
m_die_array.clear();
|
||||||
|
|
|
@ -166,6 +166,8 @@ public:
|
||||||
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
|
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
|
||||||
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
|
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
|
||||||
|
|
||||||
|
dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const;
|
||||||
|
|
||||||
lldb::ByteOrder GetByteOrder() const;
|
lldb::ByteOrder GetByteOrder() const;
|
||||||
|
|
||||||
const DWARFDebugAranges &GetFunctionAranges();
|
const DWARFDebugAranges &GetFunctionAranges();
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "SymbolFileDWARF.h"
|
#include "SymbolFileDWARF.h"
|
||||||
|
|
||||||
#include "llvm/ADT/Optional.h"
|
#include "llvm/ADT/Optional.h"
|
||||||
|
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/Threading.h"
|
#include "llvm/Support/Threading.h"
|
||||||
|
|
||||||
|
@ -1885,11 +1886,14 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() {
|
||||||
for (size_t g = 0; g < num_globals; ++g) {
|
for (size_t g = 0; g < num_globals; ++g) {
|
||||||
VariableSP var_sp = globals_sp->GetVariableAtIndex(g);
|
VariableSP var_sp = globals_sp->GetVariableAtIndex(g);
|
||||||
if (var_sp && !var_sp->GetLocationIsConstantValueData()) {
|
if (var_sp && !var_sp->GetLocationIsConstantValueData()) {
|
||||||
const DWARFExpression &location = var_sp->LocationExpression();
|
const DWARFExpressionList &location =
|
||||||
|
var_sp->LocationExpressionList();
|
||||||
Value location_result;
|
Value location_result;
|
||||||
Status error;
|
Status error;
|
||||||
if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr,
|
ExecutionContext exe_ctx;
|
||||||
nullptr, location_result, &error)) {
|
if (location.Evaluate(&exe_ctx, nullptr, LLDB_INVALID_ADDRESS,
|
||||||
|
nullptr, nullptr, location_result,
|
||||||
|
&error)) {
|
||||||
if (location_result.GetValueType() ==
|
if (location_result.GetValueType() ==
|
||||||
Value::ValueType::FileAddress) {
|
Value::ValueType::FileAddress) {
|
||||||
lldb::addr_t file_addr =
|
lldb::addr_t file_addr =
|
||||||
|
@ -3163,7 +3167,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
const char *mangled = nullptr;
|
const char *mangled = nullptr;
|
||||||
Declaration decl;
|
Declaration decl;
|
||||||
DWARFFormValue type_die_form;
|
DWARFFormValue type_die_form;
|
||||||
DWARFExpression location;
|
DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU());
|
||||||
bool is_external = false;
|
bool is_external = false;
|
||||||
bool is_artificial = false;
|
bool is_artificial = false;
|
||||||
DWARFFormValue const_value_form, location_form;
|
DWARFFormValue const_value_form, location_form;
|
||||||
|
@ -3229,16 +3233,15 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
// present in the class declaration and DW_AT_location in the DIE defining
|
// present in the class declaration and DW_AT_location in the DIE defining
|
||||||
// the member.
|
// the member.
|
||||||
bool location_is_const_value_data = false;
|
bool location_is_const_value_data = false;
|
||||||
bool has_explicit_location = false;
|
bool has_explicit_location = location_form.IsValid();
|
||||||
bool use_type_size_for_value = false;
|
bool use_type_size_for_value = false;
|
||||||
if (location_form.IsValid()) {
|
if (location_form.IsValid()) {
|
||||||
has_explicit_location = true;
|
|
||||||
if (DWARFFormValue::IsBlockForm(location_form.Form())) {
|
if (DWARFFormValue::IsBlockForm(location_form.Form())) {
|
||||||
const DWARFDataExtractor &data = die.GetData();
|
const DWARFDataExtractor &data = die.GetData();
|
||||||
|
|
||||||
uint32_t block_offset = location_form.BlockData() - data.GetDataStart();
|
uint32_t block_offset = location_form.BlockData() - data.GetDataStart();
|
||||||
uint32_t block_length = location_form.Unsigned();
|
uint32_t block_length = location_form.Unsigned();
|
||||||
location = DWARFExpression(
|
location_list = DWARFExpressionList(
|
||||||
module, DataExtractor(data, block_offset, block_length), die.GetCU());
|
module, DataExtractor(data, block_offset, block_length), die.GetCU());
|
||||||
} else {
|
} else {
|
||||||
DataExtractor data = die.GetCU()->GetLocationData();
|
DataExtractor data = die.GetCU()->GetLocationData();
|
||||||
|
@ -3247,10 +3250,10 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1);
|
offset = die.GetCU()->GetLoclistOffset(offset).value_or(-1);
|
||||||
if (data.ValidOffset(offset)) {
|
if (data.ValidOffset(offset)) {
|
||||||
data = DataExtractor(data, offset, data.GetByteSize() - offset);
|
data = DataExtractor(data, offset, data.GetByteSize() - offset);
|
||||||
location = DWARFExpression(module, data, die.GetCU());
|
const DWARFUnit *dwarf_cu = location_form.GetUnit();
|
||||||
assert(func_low_pc != LLDB_INVALID_ADDRESS);
|
if (DWARFExpression::ParseDWARFLocationList(dwarf_cu, data,
|
||||||
location.SetLocationListAddresses(
|
&location_list))
|
||||||
location_form.GetUnit()->GetBaseAddress(), func_low_pc);
|
location_list.SetFuncFileAddress(func_low_pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (const_value_form.IsValid()) {
|
} else if (const_value_form.IsValid()) {
|
||||||
|
@ -3263,7 +3266,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
uint32_t block_offset =
|
uint32_t block_offset =
|
||||||
const_value_form.BlockData() - debug_info_data.GetDataStart();
|
const_value_form.BlockData() - debug_info_data.GetDataStart();
|
||||||
uint32_t block_length = const_value_form.Unsigned();
|
uint32_t block_length = const_value_form.Unsigned();
|
||||||
location = DWARFExpression(
|
location_list = DWARFExpressionList(
|
||||||
module, DataExtractor(debug_info_data, block_offset, block_length),
|
module, DataExtractor(debug_info_data, block_offset, block_length),
|
||||||
die.GetCU());
|
die.GetCU());
|
||||||
} else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
|
} else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
|
||||||
|
@ -3273,7 +3276,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
use_type_size_for_value = true;
|
use_type_size_for_value = true;
|
||||||
} else if (const char *str = const_value_form.AsCString()) {
|
} else if (const char *str = const_value_form.AsCString()) {
|
||||||
uint32_t string_length = strlen(str) + 1;
|
uint32_t string_length = strlen(str) + 1;
|
||||||
location = DWARFExpression(
|
location_list = DWARFExpressionList(
|
||||||
module,
|
module,
|
||||||
DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
|
DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
|
||||||
die.GetCU()->GetAddressByteSize()),
|
die.GetCU()->GetAddressByteSize()),
|
||||||
|
@ -3323,16 +3326,19 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
// with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
|
// with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
|
||||||
// so we need to look through the whole expression.
|
// so we need to look through the whole expression.
|
||||||
bool is_static_lifetime =
|
bool is_static_lifetime =
|
||||||
has_explicit_mangled || (has_explicit_location && !location.IsValid());
|
has_explicit_mangled ||
|
||||||
|
(has_explicit_location && !location_list.IsValid());
|
||||||
// Check if the location has a DW_OP_addr with any address value...
|
// Check if the location has a DW_OP_addr with any address value...
|
||||||
lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
|
lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
|
||||||
if (!location_is_const_value_data) {
|
if (!location_is_const_value_data) {
|
||||||
bool op_error = false;
|
bool op_error = false;
|
||||||
location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error);
|
const DWARFExpression* location = location_list.GetAlwaysValidExpr();
|
||||||
|
if (location)
|
||||||
|
location_DW_OP_addr = location->GetLocation_DW_OP_addr(
|
||||||
|
location_form.GetUnit(), 0, op_error);
|
||||||
if (op_error) {
|
if (op_error) {
|
||||||
StreamString strm;
|
StreamString strm;
|
||||||
location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0,
|
location->DumpLocation(&strm, eDescriptionLevelFull, nullptr);
|
||||||
nullptr);
|
|
||||||
GetObjectFile()->GetModule()->ReportError(
|
GetObjectFile()->GetModule()->ReportError(
|
||||||
"0x%8.8x: %s has an invalid location: %s", die.GetOffset(),
|
"0x%8.8x: %s has an invalid location: %s", die.GetOffset(),
|
||||||
die.GetTagAsCString(), strm.GetData());
|
die.GetTagAsCString(), strm.GetData());
|
||||||
|
@ -3345,7 +3351,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
// Set the module of the expression to the linked module
|
// Set the module of the expression to the linked module
|
||||||
// instead of the object file so the relocated address can be
|
// instead of the object file so the relocated address can be
|
||||||
// found there.
|
// found there.
|
||||||
location.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
|
location_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
|
||||||
|
|
||||||
if (is_static_lifetime) {
|
if (is_static_lifetime) {
|
||||||
if (is_external)
|
if (is_external)
|
||||||
|
@ -3386,7 +3392,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
const addr_t exe_file_addr =
|
const addr_t exe_file_addr =
|
||||||
exe_symbol->GetAddressRef().GetFileAddress();
|
exe_symbol->GetAddressRef().GetFileAddress();
|
||||||
if (exe_file_addr != LLDB_INVALID_ADDRESS) {
|
if (exe_file_addr != LLDB_INVALID_ADDRESS) {
|
||||||
if (location.Update_DW_OP_addr(exe_file_addr)) {
|
DWARFExpression *location =
|
||||||
|
location_list.GetMutableExpressionAtAddress();
|
||||||
|
if (location->Update_DW_OP_addr(exe_file_addr)) {
|
||||||
linked_oso_file_addr = true;
|
linked_oso_file_addr = true;
|
||||||
symbol_context_scope = exe_symbol;
|
symbol_context_scope = exe_symbol;
|
||||||
}
|
}
|
||||||
|
@ -3404,7 +3412,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
|
debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
|
||||||
if (exe_file_addr != LLDB_INVALID_ADDRESS) {
|
if (exe_file_addr != LLDB_INVALID_ADDRESS) {
|
||||||
// Update the file address for this variable
|
// Update the file address for this variable
|
||||||
location.Update_DW_OP_addr(exe_file_addr);
|
DWARFExpression *location =
|
||||||
|
location_list.GetMutableExpressionAtAddress();
|
||||||
|
location->Update_DW_OP_addr(exe_file_addr);
|
||||||
} else {
|
} else {
|
||||||
// Variable didn't make it into the final executable
|
// Variable didn't make it into the final executable
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -3419,8 +3429,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
scope = eValueTypeVariableLocal;
|
scope = eValueTypeVariableLocal;
|
||||||
if (debug_map_symfile) {
|
if (debug_map_symfile) {
|
||||||
// We need to check for TLS addresses that we need to fixup
|
// We need to check for TLS addresses that we need to fixup
|
||||||
if (location.ContainsThreadLocalStorage()) {
|
if (location_list.ContainsThreadLocalStorage()) {
|
||||||
location.LinkThreadLocalStorage(
|
location_list.LinkThreadLocalStorage(
|
||||||
debug_map_symfile->GetObjectFile()->GetModule(),
|
debug_map_symfile->GetObjectFile()->GetModule(),
|
||||||
[this, debug_map_symfile](
|
[this, debug_map_symfile](
|
||||||
lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
|
lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
|
||||||
|
@ -3463,14 +3473,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
|
||||||
auto type_sp = std::make_shared<SymbolFileType>(
|
auto type_sp = std::make_shared<SymbolFileType>(
|
||||||
*this, GetUID(type_die_form.Reference()));
|
*this, GetUID(type_die_form.Reference()));
|
||||||
|
|
||||||
if (use_type_size_for_value && type_sp->GetType())
|
if (use_type_size_for_value && type_sp->GetType()) {
|
||||||
location.UpdateValue(const_value_form.Unsigned(),
|
DWARFExpression *location = location_list.GetMutableExpressionAtAddress();
|
||||||
type_sp->GetType()->GetByteSize(nullptr).value_or(0),
|
location->UpdateValue(
|
||||||
die.GetCU()->GetAddressByteSize());
|
const_value_form.Unsigned(),
|
||||||
|
type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
|
||||||
|
die.GetCU()->GetAddressByteSize());
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_shared<Variable>(
|
return std::make_shared<Variable>(
|
||||||
die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
|
die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
|
||||||
scope_ranges, &decl, location, is_external, is_artificial,
|
scope_ranges, &decl, location_list, is_external, is_artificial,
|
||||||
location_is_const_value_data, is_static_member);
|
location_is_const_value_data, is_static_member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3755,8 +3768,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
|
||||||
child.Tag() != DW_TAG_GNU_call_site_parameter)
|
child.Tag() != DW_TAG_GNU_call_site_parameter)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
llvm::Optional<DWARFExpression> LocationInCallee;
|
llvm::Optional<DWARFExpressionList> LocationInCallee;
|
||||||
llvm::Optional<DWARFExpression> LocationInCaller;
|
llvm::Optional<DWARFExpressionList> LocationInCaller;
|
||||||
|
|
||||||
DWARFAttributes attributes;
|
DWARFAttributes attributes;
|
||||||
const size_t num_attributes = child.GetAttributes(attributes);
|
const size_t num_attributes = child.GetAttributes(attributes);
|
||||||
|
@ -3764,7 +3777,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
|
||||||
// Parse the location at index \p attr_index within this call site parameter
|
// Parse the location at index \p attr_index within this call site parameter
|
||||||
// DIE, or return None on failure.
|
// DIE, or return None on failure.
|
||||||
auto parse_simple_location =
|
auto parse_simple_location =
|
||||||
[&](int attr_index) -> llvm::Optional<DWARFExpression> {
|
[&](int attr_index) -> llvm::Optional<DWARFExpressionList> {
|
||||||
DWARFFormValue form_value;
|
DWARFFormValue form_value;
|
||||||
if (!attributes.ExtractFormValueAtIndex(attr_index, form_value))
|
if (!attributes.ExtractFormValueAtIndex(attr_index, form_value))
|
||||||
return {};
|
return {};
|
||||||
|
@ -3773,9 +3786,9 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
|
||||||
auto data = child.GetData();
|
auto data = child.GetData();
|
||||||
uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
|
uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
|
||||||
uint32_t block_length = form_value.Unsigned();
|
uint32_t block_length = form_value.Unsigned();
|
||||||
return DWARFExpression(module,
|
return DWARFExpressionList(
|
||||||
DataExtractor(data, block_offset, block_length),
|
module, DataExtractor(data, block_offset, block_length),
|
||||||
child.GetCU());
|
child.GetCU());
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < num_attributes; ++i) {
|
for (size_t i = 0; i < num_attributes; ++i) {
|
||||||
|
@ -3820,7 +3833,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
llvm::Optional<DWARFDIE> call_origin;
|
llvm::Optional<DWARFDIE> call_origin;
|
||||||
llvm::Optional<DWARFExpression> call_target;
|
llvm::Optional<DWARFExpressionList> call_target;
|
||||||
addr_t return_pc = LLDB_INVALID_ADDRESS;
|
addr_t return_pc = LLDB_INVALID_ADDRESS;
|
||||||
addr_t call_inst_pc = LLDB_INVALID_ADDRESS;
|
addr_t call_inst_pc = LLDB_INVALID_ADDRESS;
|
||||||
addr_t low_pc = LLDB_INVALID_ADDRESS;
|
addr_t low_pc = LLDB_INVALID_ADDRESS;
|
||||||
|
@ -3881,7 +3894,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
|
||||||
auto data = child.GetData();
|
auto data = child.GetData();
|
||||||
uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
|
uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
|
||||||
uint32_t block_length = form_value.Unsigned();
|
uint32_t block_length = form_value.Unsigned();
|
||||||
call_target = DWARFExpression(
|
call_target = DWARFExpressionList(
|
||||||
module, DataExtractor(data, block_offset, block_length),
|
module, DataExtractor(data, block_offset, block_length),
|
||||||
child.GetCU());
|
child.GetCU());
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "lldb/Core/UniqueCStringMap.h"
|
#include "lldb/Core/UniqueCStringMap.h"
|
||||||
#include "lldb/Core/dwarf.h"
|
#include "lldb/Core/dwarf.h"
|
||||||
|
#include "lldb/Expression/DWARFExpressionList.h"
|
||||||
#include "lldb/Symbol/DebugMacros.h"
|
#include "lldb/Symbol/DebugMacros.h"
|
||||||
#include "lldb/Symbol/SymbolContext.h"
|
#include "lldb/Symbol/SymbolContext.h"
|
||||||
#include "lldb/Symbol/SymbolFile.h"
|
#include "lldb/Symbol/SymbolFile.h"
|
||||||
|
|
|
@ -122,7 +122,7 @@ static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,
|
||||||
DataBufferSP buffer =
|
DataBufferSP buffer =
|
||||||
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
|
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
|
||||||
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
|
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
|
||||||
DWARFExpression result(module, extractor, nullptr);
|
DWARFExpression result(extractor);
|
||||||
result.SetRegisterKind(register_kind);
|
result.SetRegisterKind(register_kind);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -247,7 +247,7 @@ DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
|
||||||
.take_front(size);
|
.take_front(size);
|
||||||
buffer->CopyData(bytes.data(), size);
|
buffer->CopyData(bytes.data(), size);
|
||||||
DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
|
DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
|
||||||
DWARFExpression result(nullptr, extractor, nullptr);
|
DWARFExpression result(extractor);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -602,7 +602,7 @@ static RegisterId GetBaseFrameRegister(PdbIndex &index,
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableInfo lldb_private::npdb::GetVariableLocationInfo(
|
VariableInfo lldb_private::npdb::GetVariableLocationInfo(
|
||||||
PdbIndex &index, PdbCompilandSymId var_id, Block &block,
|
PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
|
||||||
lldb::ModuleSP module) {
|
lldb::ModuleSP module) {
|
||||||
|
|
||||||
CVSymbol sym = index.ReadSymbolRecord(var_id);
|
CVSymbol sym = index.ReadSymbolRecord(var_id);
|
||||||
|
@ -642,14 +642,8 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
|
||||||
|
|
||||||
Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
|
Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
|
||||||
|
|
||||||
// TODO: may be better to pass function scope and not lookup it every
|
|
||||||
// time? find nearest parent function block
|
|
||||||
Block *cur = █
|
|
||||||
while (cur->GetParent()) {
|
|
||||||
cur = cur->GetParent();
|
|
||||||
}
|
|
||||||
PdbCompilandSymId func_scope_id =
|
PdbCompilandSymId func_scope_id =
|
||||||
PdbSymUid(cur->GetID()).asCompilandSym();
|
PdbSymUid(func_block.GetID()).asCompilandSym();
|
||||||
CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
|
CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
|
||||||
lldbassert(func_block_cvs.kind() == S_GPROC32 ||
|
lldbassert(func_block_cvs.kind() == S_GPROC32 ||
|
||||||
func_block_cvs.kind() == S_LPROC32);
|
func_block_cvs.kind() == S_LPROC32);
|
||||||
|
|
|
@ -142,8 +142,8 @@ LookThroughModifierRecord(llvm::codeview::CVType modifier);
|
||||||
llvm::StringRef DropNameScope(llvm::StringRef name);
|
llvm::StringRef DropNameScope(llvm::StringRef name);
|
||||||
|
|
||||||
VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol);
|
VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol);
|
||||||
VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block& block,
|
VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id,
|
||||||
lldb::ModuleSP module);
|
Block &func_block, lldb::ModuleSP module);
|
||||||
|
|
||||||
size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
|
size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
|
||||||
lldb::BasicType
|
lldb::BasicType
|
||||||
|
|
|
@ -823,8 +823,10 @@ VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
|
||||||
|
|
||||||
m_ast->GetOrCreateVariableDecl(var_id);
|
m_ast->GetOrCreateVariableDecl(var_id);
|
||||||
|
|
||||||
DWARFExpression location = MakeGlobalLocationExpression(
|
ModuleSP module_sp = GetObjectFile()->GetModule();
|
||||||
section, offset, GetObjectFile()->GetModule());
|
DWARFExpressionList location(
|
||||||
|
module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
std::string global_name("::");
|
std::string global_name("::");
|
||||||
global_name += name;
|
global_name += name;
|
||||||
|
@ -855,8 +857,10 @@ SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
|
||||||
Declaration decl;
|
Declaration decl;
|
||||||
Variable::RangeList ranges;
|
Variable::RangeList ranges;
|
||||||
ModuleSP module = GetObjectFile()->GetModule();
|
ModuleSP module = GetObjectFile()->GetModule();
|
||||||
DWARFExpression location = MakeConstantLocationExpression(
|
DWARFExpressionList location(module,
|
||||||
constant.Type, tpi, constant.Value, module);
|
MakeConstantLocationExpression(
|
||||||
|
constant.Type, tpi, constant.Value, module),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
bool external = false;
|
bool external = false;
|
||||||
bool artificial = false;
|
bool artificial = false;
|
||||||
|
@ -1689,8 +1693,15 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
|
||||||
bool is_param) {
|
bool is_param) {
|
||||||
ModuleSP module = GetObjectFile()->GetModule();
|
ModuleSP module = GetObjectFile()->GetModule();
|
||||||
Block &block = GetOrCreateBlock(scope_id);
|
Block &block = GetOrCreateBlock(scope_id);
|
||||||
|
// Get function block.
|
||||||
|
Block *func_block = █
|
||||||
|
while (func_block->GetParent()) {
|
||||||
|
func_block = func_block->GetParent();
|
||||||
|
}
|
||||||
|
Address addr;
|
||||||
|
func_block->GetStartAddress(addr);
|
||||||
VariableInfo var_info =
|
VariableInfo var_info =
|
||||||
GetVariableLocationInfo(*m_index, var_id, block, module);
|
GetVariableLocationInfo(*m_index, var_id, *func_block, module);
|
||||||
if (!var_info.location || !var_info.ranges)
|
if (!var_info.location || !var_info.ranges)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -1709,11 +1720,12 @@ VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
|
||||||
bool artificial = false;
|
bool artificial = false;
|
||||||
bool location_is_constant_data = false;
|
bool location_is_constant_data = false;
|
||||||
bool static_member = false;
|
bool static_member = false;
|
||||||
|
DWARFExpressionList locaiton_list = DWARFExpressionList(
|
||||||
|
module, *var_info.location, nullptr);
|
||||||
VariableSP var_sp = std::make_shared<Variable>(
|
VariableSP var_sp = std::make_shared<Variable>(
|
||||||
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
|
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
|
||||||
&block, *var_info.ranges, &decl, *var_info.location, external,
|
&block, *var_info.ranges, &decl, locaiton_list, external, artificial,
|
||||||
artificial, location_is_constant_data, static_member);
|
location_is_constant_data, static_member);
|
||||||
|
|
||||||
if (!is_param)
|
if (!is_param)
|
||||||
m_ast->GetOrCreateVariableDecl(scope_id, var_id);
|
m_ast->GetOrCreateVariableDecl(scope_id, var_id);
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ DWARFExpression ConvertPDBLocationToDWARFExpression(
|
||||||
DataBufferSP buffer =
|
DataBufferSP buffer =
|
||||||
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
|
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
|
||||||
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
|
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
|
||||||
DWARFExpression result(module, extractor, nullptr);
|
DWARFExpression result(extractor);
|
||||||
result.SetRegisterKind(register_kind);
|
result.SetRegisterKind(register_kind);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1023,8 +1023,11 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData(
|
||||||
auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
|
auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
|
||||||
|
|
||||||
bool is_constant;
|
bool is_constant;
|
||||||
DWARFExpression location = ConvertPDBLocationToDWARFExpression(
|
ModuleSP module_sp = GetObjectFile()->GetModule();
|
||||||
GetObjectFile()->GetModule(), pdb_data, ranges, is_constant);
|
DWARFExpressionList location(module_sp,
|
||||||
|
ConvertPDBLocationToDWARFExpression(
|
||||||
|
module_sp, pdb_data, ranges, is_constant),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
var_sp = std::make_shared<Variable>(
|
var_sp = std::make_shared<Variable>(
|
||||||
var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
|
var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
|
||||||
|
|
|
@ -196,11 +196,10 @@ Function *IndirectCallEdge::GetCallee(ModuleList &images,
|
||||||
Log *log = GetLog(LLDBLog::Step);
|
Log *log = GetLog(LLDBLog::Step);
|
||||||
Status error;
|
Status error;
|
||||||
Value callee_addr_val;
|
Value callee_addr_val;
|
||||||
if (!call_target.Evaluate(&exe_ctx, exe_ctx.GetRegisterContext(),
|
if (!call_target.Evaluate(
|
||||||
/*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS,
|
&exe_ctx, exe_ctx.GetRegisterContext(), LLDB_INVALID_ADDRESS,
|
||||||
/*initial_value_ptr=*/nullptr,
|
/*initial_value_ptr=*/nullptr,
|
||||||
/*object_address_ptr=*/nullptr, callee_addr_val,
|
/*object_address_ptr=*/nullptr, callee_addr_val, &error)) {
|
||||||
&error)) {
|
|
||||||
LLDB_LOGF(log, "IndirectCallEdge: Could not evaluate expression: %s",
|
LLDB_LOGF(log, "IndirectCallEdge: Could not evaluate expression: %s",
|
||||||
error.AsCString());
|
error.AsCString());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -39,13 +39,13 @@ Variable::Variable(lldb::user_id_t uid, const char *name, const char *mangled,
|
||||||
const lldb::SymbolFileTypeSP &symfile_type_sp,
|
const lldb::SymbolFileTypeSP &symfile_type_sp,
|
||||||
ValueType scope, SymbolContextScope *context,
|
ValueType scope, SymbolContextScope *context,
|
||||||
const RangeList &scope_range, Declaration *decl_ptr,
|
const RangeList &scope_range, Declaration *decl_ptr,
|
||||||
const DWARFExpression &location, bool external,
|
const DWARFExpressionList &location_list, bool external,
|
||||||
bool artificial, bool location_is_constant_data,
|
bool artificial, bool location_is_constant_data,
|
||||||
bool static_member)
|
bool static_member)
|
||||||
: UserID(uid), m_name(name), m_mangled(ConstString(mangled)),
|
: UserID(uid), m_name(name), m_mangled(ConstString(mangled)),
|
||||||
m_symfile_type_sp(symfile_type_sp), m_scope(scope),
|
m_symfile_type_sp(symfile_type_sp), m_scope(scope),
|
||||||
m_owner_scope(context), m_scope_range(scope_range),
|
m_owner_scope(context), m_scope_range(scope_range),
|
||||||
m_declaration(decl_ptr), m_location(location), m_external(external),
|
m_declaration(decl_ptr), m_location_list(location_list), m_external(external),
|
||||||
m_artificial(artificial), m_loc_is_const_data(location_is_constant_data),
|
m_artificial(artificial), m_loc_is_const_data(location_is_constant_data),
|
||||||
m_static_member(static_member) {}
|
m_static_member(static_member) {}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ void Variable::Dump(Stream *s, bool show_context) const {
|
||||||
bool show_fullpaths = false;
|
bool show_fullpaths = false;
|
||||||
m_declaration.Dump(s, show_fullpaths);
|
m_declaration.Dump(s, show_fullpaths);
|
||||||
|
|
||||||
if (m_location.IsValid()) {
|
if (m_location_list.IsValid()) {
|
||||||
s->PutCString(", location = ");
|
s->PutCString(", location = ");
|
||||||
ABISP abi;
|
ABISP abi;
|
||||||
if (m_owner_scope) {
|
if (m_owner_scope) {
|
||||||
|
@ -153,7 +153,7 @@ void Variable::Dump(Stream *s, bool show_context) const {
|
||||||
if (module_sp)
|
if (module_sp)
|
||||||
abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
|
abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
|
||||||
}
|
}
|
||||||
m_location.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get());
|
m_location_list.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_external)
|
if (m_external)
|
||||||
|
@ -212,12 +212,6 @@ void Variable::CalculateSymbolContext(SymbolContext *sc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Variable::LocationIsValidForFrame(StackFrame *frame) {
|
bool Variable::LocationIsValidForFrame(StackFrame *frame) {
|
||||||
// Is the variable is described by a single location?
|
|
||||||
if (!m_location.IsLocationList()) {
|
|
||||||
// Yes it is, the location is valid.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame) {
|
if (frame) {
|
||||||
Function *function =
|
Function *function =
|
||||||
frame->GetSymbolContext(eSymbolContextFunction).function;
|
frame->GetSymbolContext(eSymbolContextFunction).function;
|
||||||
|
@ -231,7 +225,7 @@ bool Variable::LocationIsValidForFrame(StackFrame *frame) {
|
||||||
return false;
|
return false;
|
||||||
// It is a location list. We just need to tell if the location list
|
// It is a location list. We just need to tell if the location list
|
||||||
// contains the current address when converted to a load address
|
// contains the current address when converted to a load address
|
||||||
return m_location.LocationListContainsAddress(
|
return m_location_list.ContainsAddress(
|
||||||
loclist_base_load_addr,
|
loclist_base_load_addr,
|
||||||
frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get()));
|
frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get()));
|
||||||
}
|
}
|
||||||
|
@ -244,7 +238,7 @@ bool Variable::LocationIsValidForAddress(const Address &address) {
|
||||||
// function.
|
// function.
|
||||||
if (address.IsSectionOffset()) {
|
if (address.IsSectionOffset()) {
|
||||||
// We need to check if the address is valid for both scope range and value
|
// We need to check if the address is valid for both scope range and value
|
||||||
// range.
|
// range.
|
||||||
// Empty scope range means block range.
|
// Empty scope range means block range.
|
||||||
bool valid_in_scope_range =
|
bool valid_in_scope_range =
|
||||||
GetScopeRange().IsEmpty() || GetScopeRange().FindEntryThatContains(
|
GetScopeRange().IsEmpty() || GetScopeRange().FindEntryThatContains(
|
||||||
|
@ -255,7 +249,7 @@ bool Variable::LocationIsValidForAddress(const Address &address) {
|
||||||
CalculateSymbolContext(&sc);
|
CalculateSymbolContext(&sc);
|
||||||
if (sc.module_sp == address.GetModule()) {
|
if (sc.module_sp == address.GetModule()) {
|
||||||
// Is the variable is described by a single location?
|
// Is the variable is described by a single location?
|
||||||
if (!m_location.IsLocationList()) {
|
if (m_location_list.IsAlwaysValidSingleExpr()) {
|
||||||
// Yes it is, the location is valid.
|
// Yes it is, the location is valid.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -267,8 +261,8 @@ bool Variable::LocationIsValidForAddress(const Address &address) {
|
||||||
return false;
|
return false;
|
||||||
// It is a location list. We just need to tell if the location list
|
// It is a location list. We just need to tell if the location list
|
||||||
// contains the current address when converted to a load address
|
// contains the current address when converted to a load address
|
||||||
return m_location.LocationListContainsAddress(loclist_base_file_addr,
|
return m_location_list.ContainsAddress(loclist_base_file_addr,
|
||||||
address.GetFileAddress());
|
address.GetFileAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,9 +453,9 @@ bool Variable::DumpLocations(Stream *s, const Address &address) {
|
||||||
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
||||||
if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
|
if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
|
||||||
return false;
|
return false;
|
||||||
return m_location.DumpLocations(s, eDescriptionLevelBrief,
|
return m_location_list.DumpLocations(s, eDescriptionLevelBrief,
|
||||||
loclist_base_file_addr, file_addr,
|
loclist_base_file_addr, file_addr,
|
||||||
abi.get());
|
abi.get());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "lldb/Core/AddressRange.h"
|
#include "lldb/Core/AddressRange.h"
|
||||||
#include "lldb/Core/Module.h"
|
#include "lldb/Core/Module.h"
|
||||||
#include "lldb/Core/Value.h"
|
#include "lldb/Core/Value.h"
|
||||||
#include "lldb/Expression/DWARFExpression.h"
|
#include "lldb/Expression/DWARFExpressionList.h"
|
||||||
#include "lldb/Symbol/ArmUnwindInfo.h"
|
#include "lldb/Symbol/ArmUnwindInfo.h"
|
||||||
#include "lldb/Symbol/CallFrameInfo.h"
|
#include "lldb/Symbol/CallFrameInfo.h"
|
||||||
#include "lldb/Symbol/DWARFCallFrameInfo.h"
|
#include "lldb/Symbol/DWARFCallFrameInfo.h"
|
||||||
|
@ -381,7 +381,7 @@ void RegisterContextUnwind::InitializeNonZerothFrame() {
|
||||||
// symbol/function information - just stick in some reasonable defaults and
|
// symbol/function information - just stick in some reasonable defaults and
|
||||||
// hope we can unwind past this frame. If we're above a trap handler,
|
// hope we can unwind past this frame. If we're above a trap handler,
|
||||||
// we may be at a bogus address because we jumped through a bogus function
|
// we may be at a bogus address because we jumped through a bogus function
|
||||||
// pointer and trapped, so don't force the arch default unwind plan in that
|
// pointer and trapped, so don't force the arch default unwind plan in that
|
||||||
// case.
|
// case.
|
||||||
ModuleSP pc_module_sp(m_current_pc.GetModule());
|
ModuleSP pc_module_sp(m_current_pc.GetModule());
|
||||||
if ((!m_current_pc.IsValid() || !pc_module_sp) &&
|
if ((!m_current_pc.IsValid() || !pc_module_sp) &&
|
||||||
|
@ -1286,7 +1286,7 @@ RegisterContextUnwind::SavedLocationForRegister(
|
||||||
// arch default unwind plan is used as the Fast Unwind Plan, we
|
// arch default unwind plan is used as the Fast Unwind Plan, we
|
||||||
// need to recognize this & switch over to the Full Unwind Plan
|
// need to recognize this & switch over to the Full Unwind Plan
|
||||||
// to see what unwind rule that (more knoweldgeable, probably)
|
// to see what unwind rule that (more knoweldgeable, probably)
|
||||||
// UnwindPlan has. If the full UnwindPlan says the register
|
// UnwindPlan has. If the full UnwindPlan says the register
|
||||||
// location is Undefined, then it really is.
|
// location is Undefined, then it really is.
|
||||||
if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
|
if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
|
||||||
unwindplan_regloc) &&
|
unwindplan_regloc) &&
|
||||||
|
@ -1335,13 +1335,13 @@ RegisterContextUnwind::SavedLocationForRegister(
|
||||||
m_full_unwind_plan_sp->GetReturnAddressRegister() !=
|
m_full_unwind_plan_sp->GetReturnAddressRegister() !=
|
||||||
LLDB_INVALID_REGNUM) {
|
LLDB_INVALID_REGNUM) {
|
||||||
// If this is a trap handler frame, we should have access to
|
// If this is a trap handler frame, we should have access to
|
||||||
// the complete register context when the interrupt/async
|
// the complete register context when the interrupt/async
|
||||||
// signal was received, we should fetch the actual saved $pc
|
// signal was received, we should fetch the actual saved $pc
|
||||||
// value instead of the Return Address register.
|
// value instead of the Return Address register.
|
||||||
// If $pc is not available, fall back to the RA reg.
|
// If $pc is not available, fall back to the RA reg.
|
||||||
UnwindPlan::Row::RegisterLocation scratch;
|
UnwindPlan::Row::RegisterLocation scratch;
|
||||||
if (m_frame_type == eTrapHandlerFrame &&
|
if (m_frame_type == eTrapHandlerFrame &&
|
||||||
active_row->GetRegisterInfo
|
active_row->GetRegisterInfo
|
||||||
(pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
|
(pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
|
||||||
UnwindLogMsg("Providing pc register instead of rewriting to "
|
UnwindLogMsg("Providing pc register instead of rewriting to "
|
||||||
"RA reg because this is a trap handler and there is "
|
"RA reg because this is a trap handler and there is "
|
||||||
|
@ -1642,8 +1642,9 @@ RegisterContextUnwind::SavedLocationForRegister(
|
||||||
process->GetByteOrder(),
|
process->GetByteOrder(),
|
||||||
process->GetAddressByteSize());
|
process->GetAddressByteSize());
|
||||||
ModuleSP opcode_ctx;
|
ModuleSP opcode_ctx;
|
||||||
DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr);
|
DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
|
||||||
dwarfexpr.SetRegisterKind(unwindplan_registerkind);
|
dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind(
|
||||||
|
unwindplan_registerkind);
|
||||||
Value cfa_val = Scalar(m_cfa);
|
Value cfa_val = Scalar(m_cfa);
|
||||||
cfa_val.SetValueType(Value::ValueType::LoadAddress);
|
cfa_val.SetValueType(Value::ValueType::LoadAddress);
|
||||||
Value result;
|
Value result;
|
||||||
|
@ -2006,8 +2007,9 @@ bool RegisterContextUnwind::ReadFrameAddress(
|
||||||
process->GetByteOrder(),
|
process->GetByteOrder(),
|
||||||
process->GetAddressByteSize());
|
process->GetAddressByteSize());
|
||||||
ModuleSP opcode_ctx;
|
ModuleSP opcode_ctx;
|
||||||
DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr);
|
DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
|
||||||
dwarfexpr.SetRegisterKind(row_register_kind);
|
dwarfexpr.GetMutableExpressionAtAddress()->SetRegisterKind(
|
||||||
|
row_register_kind);
|
||||||
Value result;
|
Value result;
|
||||||
Status error;
|
Status error;
|
||||||
if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
|
if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
|
||||||
|
|
|
@ -1087,7 +1087,7 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
|
||||||
ExecutionContext exe_ctx(shared_from_this());
|
ExecutionContext exe_ctx(shared_from_this());
|
||||||
Value expr_value;
|
Value expr_value;
|
||||||
addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
|
addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
|
||||||
if (m_sc.function->GetFrameBaseExpression().IsLocationList())
|
if (!m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr())
|
||||||
loclist_base_addr =
|
loclist_base_addr =
|
||||||
m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
|
m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
|
||||||
exe_ctx.GetTargetPtr());
|
exe_ctx.GetTargetPtr());
|
||||||
|
@ -1116,7 +1116,7 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
|
||||||
return m_frame_base_error.Success();
|
return m_frame_base_error.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) {
|
DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) {
|
||||||
if (!m_sc.function) {
|
if (!m_sc.function) {
|
||||||
if (error_ptr) {
|
if (error_ptr) {
|
||||||
error_ptr->SetErrorString("No function in symbol context.");
|
error_ptr->SetErrorString("No function in symbol context.");
|
||||||
|
@ -1200,7 +1200,7 @@ lldb::LanguageType StackFrame::GuessLanguage() {
|
||||||
LanguageType lang_type = GetLanguage();
|
LanguageType lang_type = GetLanguage();
|
||||||
|
|
||||||
if (lang_type == eLanguageTypeUnknown) {
|
if (lang_type == eLanguageTypeUnknown) {
|
||||||
SymbolContext sc = GetSymbolContext(eSymbolContextFunction
|
SymbolContext sc = GetSymbolContext(eSymbolContextFunction
|
||||||
| eSymbolContextSymbol);
|
| eSymbolContextSymbol);
|
||||||
if (sc.function) {
|
if (sc.function) {
|
||||||
lang_type = sc.function->GetMangled().GuessLanguage();
|
lang_type = sc.function->GetMangled().GuessLanguage();
|
||||||
|
@ -1417,7 +1417,7 @@ ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,
|
||||||
|
|
||||||
Status error;
|
Status error;
|
||||||
ValueObjectSP pointee = base->Dereference(error);
|
ValueObjectSP pointee = base->Dereference(error);
|
||||||
|
|
||||||
if (!pointee) {
|
if (!pointee) {
|
||||||
return ValueObjectSP();
|
return ValueObjectSP();
|
||||||
}
|
}
|
||||||
|
@ -1505,7 +1505,7 @@ lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,
|
||||||
Instruction::Operand::BuildRegister(reg));
|
Instruction::Operand::BuildRegister(reg));
|
||||||
|
|
||||||
for (VariableSP var_sp : variables) {
|
for (VariableSP var_sp : variables) {
|
||||||
if (var_sp->LocationExpression().MatchesOperand(frame, op))
|
if (var_sp->LocationExpressionList().MatchesOperand(frame, op))
|
||||||
return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
|
return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,11 @@
|
||||||
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg5 RDI
|
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg5 RDI
|
||||||
# CHECK-NEXT: [0x0000000000000001, 0x0000000000000006): DW_OP_reg0 RAX
|
# CHECK-NEXT: [0x0000000000000001, 0x0000000000000006): DW_OP_reg0 RAX
|
||||||
# CHECK: Variable{{.*}}, name = "x1", {{.*}}, scope = parameter
|
# CHECK: Variable{{.*}}, name = "x1", {{.*}}, scope = parameter
|
||||||
# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter, location = 0x00000000: error: unexpected end of data
|
# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter
|
||||||
# CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location =
|
# CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location =
|
||||||
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX
|
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX
|
||||||
# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter, location =
|
# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter
|
||||||
# LOCLISTS-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg2 RCX
|
# LOCLISTS-EMPTY:
|
||||||
|
|
||||||
.ifdef LOC
|
.ifdef LOC
|
||||||
.macro OFFSET_PAIR lo hi
|
.macro OFFSET_PAIR lo hi
|
||||||
|
|
|
@ -19,29 +19,29 @@
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x0
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x0
|
||||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F0
|
# SYMBOLS-NEXT: Function{{.*}}, demangled = F0
|
||||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000000-0x00000001)
|
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000000-0x00000001)
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000001, 0x0000000000000001): DW_OP_reg0 RAX
|
# SYMBOLS-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX
|
||||||
# SYMBOLS-EMPTY:
|
# SYMBOLS-EMPTY:
|
||||||
# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "<not loaded>", file = '1.c'
|
# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "<not loaded>", file = '1.c'
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x2
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x2
|
||||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F1
|
# SYMBOLS-NEXT: Function{{.*}}, demangled = F1
|
||||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000001-0x00000002)
|
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000001-0x00000002)
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000001): DW_OP_reg1 RDX
|
# SYMBOLS-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX
|
||||||
# SYMBOLS-EMPTY:
|
# SYMBOLS-EMPTY:
|
||||||
# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "<not loaded>", file = '2.c'
|
# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "<not loaded>", file = '2.c'
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x4
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x4
|
||||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F2
|
# SYMBOLS-NEXT: Function{{.*}}, demangled = F2
|
||||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000002-0x00000003)
|
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000002-0x00000003)
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000001): DW_OP_reg2 RCX
|
# SYMBOLS-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX
|
||||||
# SYMBOLS-EMPTY:
|
# SYMBOLS-EMPTY:
|
||||||
# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "<not loaded>", file = '3.c'
|
# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "<not loaded>", file = '3.c'
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x6
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x6
|
||||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F3
|
# SYMBOLS-NEXT: Function{{.*}}, demangled = F3
|
||||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000003-0x00000004)
|
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000003-0x00000004)
|
||||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000007, 0x0000000000000001): DW_OP_reg3 RBX
|
# SYMBOLS-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX
|
||||||
# SYMBOLS-EMPTY:
|
# SYMBOLS-EMPTY:
|
||||||
# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "<not loaded>", file = ''
|
# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "<not loaded>", file = ''
|
||||||
# SYMBOLS-EMPTY:
|
# SYMBOLS-EMPTY:
|
||||||
|
@ -116,7 +116,7 @@ F\I:
|
||||||
.Lloc\I:
|
.Lloc\I:
|
||||||
.byte 3 # DW_LLE_startx_length
|
.byte 3 # DW_LLE_startx_length
|
||||||
.uleb128 \I*2+1
|
.uleb128 \I*2+1
|
||||||
.long 1
|
.long 1
|
||||||
.short 1 # Expression size
|
.short 1 # Expression size
|
||||||
.byte 80+\I # super-register DW_OP_reg0+\I
|
.byte 80+\I # super-register DW_OP_reg0+\I
|
||||||
.byte 0 # DW_LLE_end_of_list
|
.byte 0 # DW_LLE_end_of_list
|
||||||
|
|
|
@ -23,6 +23,7 @@ static_library("Expression") {
|
||||||
include_dirs = [ ".." ]
|
include_dirs = [ ".." ]
|
||||||
sources = [
|
sources = [
|
||||||
"DWARFExpression.cpp",
|
"DWARFExpression.cpp",
|
||||||
|
"DWARFExpressionList.cpp",
|
||||||
"DiagnosticManager.cpp",
|
"DiagnosticManager.cpp",
|
||||||
"Expression.cpp",
|
"Expression.cpp",
|
||||||
"ExpressionVariable.cpp",
|
"ExpressionVariable.cpp",
|
||||||
|
|
Loading…
Reference in New Issue