Isolate Target-specific functionality of DataExtractor.

In an effort to move the various DataBuffer / DataExtractor
classes from Core -> Utility, we have to separate the low-level
functionality from the higher level functionality.  Only a
few functions required anything other than reading/writing
raw bytes, so those functions are separated out into a
more appropriate area.  Specifically, Dump() and DumpHexBytes()
are moved into free functions in Core/DumpDataExtractor.cpp,
and GetGNUEHPointer is moved into a static function in the
only file that it's referenced from.

Differential Revision: https://reviews.llvm.org/D30560

llvm-svn: 296910
This commit is contained in:
Zachary Turner 2017-03-03 20:57:05 +00:00
parent 6f9e690199
commit 29cb868aa4
25 changed files with 1149 additions and 1143 deletions

View File

@ -43,8 +43,6 @@ public:
//------------------------------------------------------------------
/// @typedef DataExtractor::Type
/// @brief Type enumerations used in the dump routines.
/// @see DataExtractor::Dump()
/// @see DataExtractor::DumpRawHexBytes()
//------------------------------------------------------------------
typedef enum {
TypeUInt8, ///< Format output as unsigned 8 bit integers
@ -57,12 +55,6 @@ public:
TypeSLEB128 ///< Format output as SLEB128 numbers
} Type;
static void DumpHexBytes(Stream *s, const void *src, size_t src_len,
uint32_t bytes_per_line,
lldb::addr_t base_addr); // Pass LLDB_INVALID_ADDRESS
// to not show address at
// start of line
//------------------------------------------------------------------
/// Default constructor.
///
@ -172,7 +164,9 @@ public:
/// reference count on the data will be decremented, and if zero,
/// the data will be freed.
//------------------------------------------------------------------
~DataExtractor();
virtual ~DataExtractor();
uint32_t getTargetByteSize() const { return m_target_byte_size; }
//------------------------------------------------------------------
/// Clears the object state.
@ -224,73 +218,6 @@ public:
uint32_t num_per_line, Type type,
const char *type_format = nullptr) const;
//------------------------------------------------------------------
/// Dumps \a item_count objects into the stream \a s.
///
/// Dumps \a item_count objects using \a item_format, each of which
/// are \a item_byte_size bytes long starting at offset \a offset
/// bytes into the contained data, into the stream \a s. \a
/// num_per_line objects will be dumped on each line before a new
/// line will be output. If \a base_addr is a valid address, then
/// each new line of output will be preceded by the address value
/// plus appropriate offset, and a colon and space. Bitfield values
/// can be dumped by calling this function multiple times with the
/// same start offset, format and size, yet differing \a
/// item_bit_size and \a item_bit_offset values.
///
/// @param[in] s
/// The stream to dump the output to. This value can not be nullptr.
///
/// @param[in] offset
/// The offset into the data at which to start dumping.
///
/// @param[in] item_format
/// The format to use when dumping each item.
///
/// @param[in] item_byte_size
/// The byte size of each item.
///
/// @param[in] item_count
/// The number of items to dump.
///
/// @param[in] num_per_line
/// The number of items to display on each line.
///
/// @param[in] base_addr
/// The base address that gets added to the offset displayed on
/// each line if the value is valid. Is \a base_addr is
/// LLDB_INVALID_ADDRESS then no address values will be prepended
/// to any lines.
///
/// @param[in] item_bit_size
/// If the value to display is a bitfield, this value should
/// be the number of bits that the bitfield item has within the
/// item's byte size value. This function will need to be called
/// multiple times with identical \a offset and \a item_byte_size
/// values in order to display multiple bitfield values that
/// exist within the same integer value. If the items being
/// displayed are not bitfields, this value should be zero.
///
/// @param[in] item_bit_offset
/// If the value to display is a bitfield, this value should
/// be the offset in bits, or shift right amount, that the
/// bitfield item occupies within the item's byte size value.
/// This function will need to be called multiple times with
/// identical \a offset and \a item_byte_size values in order
/// to display multiple bitfield values that exist within the
/// same integer value. If the items being displayed are not
/// bitfields, this value should be zero.
///
/// @return
/// The offset at which dumping ended.
//------------------------------------------------------------------
lldb::offset_t Dump(Stream *s, lldb::offset_t offset,
lldb::Format item_format, size_t item_byte_size,
size_t item_count, size_t num_per_line,
uint64_t base_addr, uint32_t item_bit_size,
uint32_t item_bit_offset,
ExecutionContextScope *exe_scope = nullptr) const;
//------------------------------------------------------------------
/// Dump a UUID value at \a offset.
///
@ -572,38 +499,6 @@ public:
long double GetLongDouble(lldb::offset_t *offset_ptr) const;
//------------------------------------------------------------------
/// Extract a GNU encoded pointer value from \a *offset_ptr.
///
/// @param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
/// by the appropriate number of bytes if the value is extracted
/// correctly. If the offset is out of bounds or there are not
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
/// @param[in] eh_ptr_enc
/// The GNU pointer encoding type.
///
/// @param[in] pc_rel_addr
/// The PC relative address to use when the encoding is
/// \c DW_GNU_EH_PE_pcrel.
///
/// @param[in] text_addr
/// The text (code) relative address to use when the encoding is
/// \c DW_GNU_EH_PE_textrel.
///
/// @param[in] data_addr
/// The data relative address to use when the encoding is
/// \c DW_GNU_EH_PE_datarel.
///
/// @return
/// The extracted GNU encoded pointer value.
//------------------------------------------------------------------
uint64_t GetGNUEHPointer(lldb::offset_t *offset_ptr, uint32_t eh_ptr_enc,
lldb::addr_t pc_rel_addr, lldb::addr_t text_addr,
lldb::addr_t data_addr);
//------------------------------------------------------------------
/// Extract an integer of size \a byte_size from \a *offset_ptr.
///

View File

@ -0,0 +1,88 @@
//===-- DumpDataExtractor.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_CORE_DUMPDATAEXTRACTOR_H
#define LLDB_CORE_DUMPDATAEXTRACTOR_H
#include "lldb/lldb-types.h"
namespace lldb_private {
class DataExtractor;
class ExecutionContextScope;
class Stream;
//------------------------------------------------------------------
/// Dumps \a item_count objects into the stream \a s.
///
/// Dumps \a item_count objects using \a item_format, each of which
/// are \a item_byte_size bytes long starting at offset \a offset
/// bytes into the contained data, into the stream \a s. \a
/// num_per_line objects will be dumped on each line before a new
/// line will be output. If \a base_addr is a valid address, then
/// each new line of output will be preceded by the address value
/// plus appropriate offset, and a colon and space. Bitfield values
/// can be dumped by calling this function multiple times with the
/// same start offset, format and size, yet differing \a
/// item_bit_size and \a item_bit_offset values.
///
/// @param[in] s
/// The stream to dump the output to. This value can not be nullptr.
///
/// @param[in] offset
/// The offset into the data at which to start dumping.
///
/// @param[in] item_format
/// The format to use when dumping each item.
///
/// @param[in] item_byte_size
/// The byte size of each item.
///
/// @param[in] item_count
/// The number of items to dump.
///
/// @param[in] num_per_line
/// The number of items to display on each line.
///
/// @param[in] base_addr
/// The base address that gets added to the offset displayed on
/// each line if the value is valid. Is \a base_addr is
/// LLDB_INVALID_ADDRESS then no address values will be prepended
/// to any lines.
///
/// @param[in] item_bit_size
/// If the value to display is a bitfield, this value should
/// be the number of bits that the bitfield item has within the
/// item's byte size value. This function will need to be called
/// multiple times with identical \a offset and \a item_byte_size
/// values in order to display multiple bitfield values that
/// exist within the same integer value. If the items being
/// displayed are not bitfields, this value should be zero.
///
/// @param[in] item_bit_offset
/// If the value to display is a bitfield, this value should
/// be the offset in bits, or shift right amount, that the
/// bitfield item occupies within the item's byte size value.
/// This function will need to be called multiple times with
/// identical \a offset and \a item_byte_size values in order
/// to display multiple bitfield values that exist within the
/// same integer value. If the items being displayed are not
/// bitfields, this value should be zero.
///
/// @return
/// The offset at which dumping ended.
//------------------------------------------------------------------
lldb::offset_t
DumpDataExtractor(const DataExtractor &DE, Stream *s, lldb::offset_t offset,
lldb::Format item_format, size_t item_byte_size,
size_t item_count, size_t num_per_line, uint64_t base_addr,
uint32_t item_bit_size, uint32_t item_bit_offset,
ExecutionContextScope *exe_scope = nullptr);
}
#endif

View File

@ -23,6 +23,8 @@
namespace lldb_private {
class DataExtractor;
//----------------------------------------------------------------------
// A class that can carry around a clang ASTContext and a opaque clang
// QualType. A clang::QualType can be easily reconstructed from an

View File

@ -14,7 +14,6 @@
#include <mutex>
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Core/RangeMap.h"

View File

@ -23,7 +23,6 @@
#include <set>
namespace lldb_private {
//----------------------------------------------------------------------
// CompilerContext allows an array of these items to be passed to
// perform detailed lookups in SymbolVendor and SymbolFile functions.

View File

@ -15,6 +15,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
@ -347,7 +348,7 @@ bool SBData::GetDescription(lldb::SBStream &description,
Stream &strm = description.ref();
if (m_opaque_sp) {
m_opaque_sp->Dump(&strm, 0, lldb::eFormatBytesWithASCII, 1,
DumpDataExtractor(*m_opaque_sp, &strm, 0, lldb::eFormatBytesWithASCII, 1,
m_opaque_sp->GetByteSize(), 16, base_addr, 0, 0);
} else
strm.PutCString("No value");

View File

@ -18,8 +18,8 @@
#include "CommandObjectMemory.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObjectMemory.h"
@ -861,10 +861,10 @@ protected:
}
assert(output_stream);
size_t bytes_dumped =
data.Dump(output_stream, 0, format, item_byte_size, item_count,
num_per_line / target->GetArchitecture().GetDataByteSize(),
addr, 0, 0, exe_scope);
size_t bytes_dumped = DumpDataExtractor(
data, output_stream, 0, format, item_byte_size, item_count,
num_per_line / target->GetArchitecture().GetDataByteSize(), addr, 0, 0,
exe_scope);
m_next_addr = addr + bytes_dumped;
output_stream->EOL();
return true;
@ -1131,10 +1131,10 @@ protected:
DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(),
process->GetByteOrder(),
process->GetAddressByteSize());
data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1,
dumpbuffer.GetByteSize(), 16,
found_location + m_memory_options.m_offset.GetCurrentValue(),
0, 0);
DumpDataExtractor(
data, &result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1,
dumpbuffer.GetByteSize(), 16,
found_location + m_memory_options.m_offset.GetCurrentValue(), 0, 0);
result.GetOutputStream().EOL();
}

View File

@ -15,6 +15,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
@ -143,15 +144,15 @@ static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address,
if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {
DataExtractor data(&buf.front(), buf.size(), byte_order, addr_size);
data.Dump(strm,
0, // Start offset in "data"
eFormatHex, // Print as characters
buf.size(), // Size of item
1, // Items count
UINT32_MAX, // num per line
LLDB_INVALID_ADDRESS, // base address
0, // bitfield bit size
0); // bitfield bit offset
DumpDataExtractor(data, strm,
0, // Start offset in "data"
eFormatHex, // Print as characters
buf.size(), // Size of item
1, // Items count
UINT32_MAX, // num per line
LLDB_INVALID_ADDRESS, // base address
0, // bitfield bit size
0); // bitfield bit offset
return true;
}
@ -181,16 +182,16 @@ static size_t ReadCStringFromMemory(ExecutionContextScope *exe_scope,
if (len > bytes_read)
len = bytes_read;
data.Dump(strm,
0, // Start offset in "data"
eFormatChar, // Print as characters
1, // Size of item (1 byte for a char!)
len, // How many bytes to print?
UINT32_MAX, // num per line
LLDB_INVALID_ADDRESS, // base address
0, // bitfield bit size
DumpDataExtractor(data, strm,
0, // Start offset in "data"
eFormatChar, // Print as characters
1, // Size of item (1 byte for a char!)
len, // How many bytes to print?
UINT32_MAX, // num per line
LLDB_INVALID_ADDRESS, // base address
0, // bitfield bit size
0); // bitfield bit offset
0); // bitfield bit offset
total_len += bytes_read;

View File

@ -15,6 +15,7 @@ add_lldb_library(lldbCore
DataExtractor.cpp
Debugger.cpp
Disassembler.cpp
DumpDataExtractor.cpp
DynamicLoader.cpp
EmulateInstruction.cpp
Event.cpp

View File

@ -9,35 +9,22 @@
// C Includes
// C++ Includes
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <sstream>
#include <string>
// Other libraries and framework includes
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "clang/AST/ASTContext.h"
// Project includes
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/UUID.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
@ -111,8 +98,6 @@ static inline uint64_t ReadSwapInt64(const void *ptr) {
return llvm::ByteSwap_64(value);
}
#define NON_PRINTABLE_CHAR '.'
DataExtractor::DataExtractor()
: m_start(nullptr), m_end(nullptr),
m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
@ -785,129 +770,6 @@ uint64_t DataExtractor::GetPointer(offset_t *offset_ptr) const {
return GetMaxU64(offset_ptr, m_addr_size);
}
//----------------------------------------------------------------------
// GetDwarfEHPtr
//
// Used for calls when the value type is specified by a DWARF EH Frame
// pointer encoding.
//----------------------------------------------------------------------
uint64_t DataExtractor::GetGNUEHPointer(
offset_t *offset_ptr, uint32_t eh_ptr_enc, lldb::addr_t pc_rel_addr,
lldb::addr_t text_addr,
lldb::addr_t data_addr) //, BSDRelocs *data_relocs) const
{
if (eh_ptr_enc == DW_EH_PE_omit)
return ULLONG_MAX; // Value isn't in the buffer...
uint64_t baseAddress = 0;
uint64_t addressValue = 0;
const uint32_t addr_size = GetAddressByteSize();
#ifdef LLDB_CONFIGURATION_DEBUG
assert(addr_size == 4 || addr_size == 8);
#endif
bool signExtendValue = false;
// Decode the base part or adjust our offset
switch (eh_ptr_enc & 0x70) {
case DW_EH_PE_pcrel:
signExtendValue = true;
baseAddress = *offset_ptr;
if (pc_rel_addr != LLDB_INVALID_ADDRESS)
baseAddress += pc_rel_addr;
// else
// Log::GlobalWarning ("PC relative pointer encoding found with
// invalid pc relative address.");
break;
case DW_EH_PE_textrel:
signExtendValue = true;
if (text_addr != LLDB_INVALID_ADDRESS)
baseAddress = text_addr;
// else
// Log::GlobalWarning ("text relative pointer encoding being
// decoded with invalid text section address, setting base address
// to zero.");
break;
case DW_EH_PE_datarel:
signExtendValue = true;
if (data_addr != LLDB_INVALID_ADDRESS)
baseAddress = data_addr;
// else
// Log::GlobalWarning ("data relative pointer encoding being
// decoded with invalid data section address, setting base address
// to zero.");
break;
case DW_EH_PE_funcrel:
signExtendValue = true;
break;
case DW_EH_PE_aligned: {
// SetPointerSize should be called prior to extracting these so the
// pointer size is cached
assert(addr_size != 0);
if (addr_size) {
// Align to a address size boundary first
uint32_t alignOffset = *offset_ptr % addr_size;
if (alignOffset)
offset_ptr += addr_size - alignOffset;
}
} break;
default:
break;
}
// Decode the value part
switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) {
case DW_EH_PE_absptr: {
addressValue = GetAddress(offset_ptr);
// if (data_relocs)
// addressValue = data_relocs->Relocate(*offset_ptr -
// addr_size, *this, addressValue);
} break;
case DW_EH_PE_uleb128:
addressValue = GetULEB128(offset_ptr);
break;
case DW_EH_PE_udata2:
addressValue = GetU16(offset_ptr);
break;
case DW_EH_PE_udata4:
addressValue = GetU32(offset_ptr);
break;
case DW_EH_PE_udata8:
addressValue = GetU64(offset_ptr);
break;
case DW_EH_PE_sleb128:
addressValue = GetSLEB128(offset_ptr);
break;
case DW_EH_PE_sdata2:
addressValue = (int16_t)GetU16(offset_ptr);
break;
case DW_EH_PE_sdata4:
addressValue = (int32_t)GetU32(offset_ptr);
break;
case DW_EH_PE_sdata8:
addressValue = (int64_t)GetU64(offset_ptr);
break;
default:
// Unhandled encoding type
assert(eh_ptr_enc);
break;
}
// Since we promote everything to 64 bit, we may need to sign extend
if (signExtendValue && addr_size < sizeof(baseAddress)) {
uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);
if (sign_bit & addressValue) {
uint64_t mask = ~sign_bit + 1;
addressValue |= mask;
}
}
return baseAddress + addressValue;
}
size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length,
ByteOrder dst_byte_order, void *dst) const {
@ -1199,759 +1061,6 @@ uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
return bytes_consumed;
}
static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr,
lldb::offset_t byte_size, llvm::APInt &result) {
llvm::SmallVector<uint64_t, 2> uint64_array;
lldb::offset_t bytes_left = byte_size;
uint64_t u64;
const lldb::ByteOrder byte_order = data.GetByteOrder();
if (byte_order == lldb::eByteOrderLittle) {
while (bytes_left > 0) {
if (bytes_left >= 8) {
u64 = data.GetU64(offset_ptr);
bytes_left -= 8;
} else {
u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
bytes_left = 0;
}
uint64_array.push_back(u64);
}
result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
return true;
} else if (byte_order == lldb::eByteOrderBig) {
lldb::offset_t be_offset = *offset_ptr + byte_size;
lldb::offset_t temp_offset;
while (bytes_left > 0) {
if (bytes_left >= 8) {
be_offset -= 8;
temp_offset = be_offset;
u64 = data.GetU64(&temp_offset);
bytes_left -= 8;
} else {
be_offset -= bytes_left;
temp_offset = be_offset;
u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
bytes_left = 0;
}
uint64_array.push_back(u64);
}
*offset_ptr += byte_size;
result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
return true;
}
return false;
}
static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
lldb::offset_t offset, lldb::offset_t byte_size,
bool is_signed, unsigned radix) {
llvm::APInt apint;
if (GetAPInt(data, &offset, byte_size, apint)) {
std::string apint_str(apint.toString(radix, is_signed));
switch (radix) {
case 2:
s->Write("0b", 2);
break;
case 8:
s->Write("0", 1);
break;
case 10:
break;
}
s->Write(apint_str.c_str(), apint_str.size());
}
return offset;
}
static float half2float(uint16_t half) {
union {
float f;
uint32_t u;
} u;
int32_t v = (int16_t)half;
if (0 == (v & 0x7c00)) {
u.u = v & 0x80007FFFU;
return u.f * ldexpf(1, 125);
}
v <<= 13;
u.u = v | 0x70000000U;
return u.f * ldexpf(1, -112);
}
lldb::offset_t DataExtractor::Dump(
Stream *s, offset_t start_offset, lldb::Format item_format,
size_t item_byte_size, size_t item_count, size_t num_per_line,
uint64_t base_addr,
uint32_t item_bit_size, // If zero, this is not a bitfield value, if
// non-zero, the value is a bitfield
uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
// shift amount to apply to a bitfield
ExecutionContextScope *exe_scope) const {
if (s == nullptr)
return start_offset;
if (item_format == eFormatPointer) {
if (item_byte_size != 4 && item_byte_size != 8)
item_byte_size = s->GetAddressByteSize();
}
offset_t offset = start_offset;
if (item_format == eFormatInstruction) {
TargetSP target_sp;
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
if (target_sp) {
DisassemblerSP disassembler_sp(Disassembler::FindPlugin(
target_sp->GetArchitecture(), nullptr, nullptr));
if (disassembler_sp) {
lldb::addr_t addr = base_addr + start_offset;
lldb_private::Address so_addr;
bool data_from_file = true;
if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
data_from_file = false;
} else {
if (target_sp->GetSectionLoadList().IsEmpty() ||
!target_sp->GetImages().ResolveFileAddress(addr, so_addr))
so_addr.SetRawAddress(addr);
}
size_t bytes_consumed = disassembler_sp->DecodeInstructions(
so_addr, *this, start_offset, item_count, false, data_from_file);
if (bytes_consumed) {
offset += bytes_consumed;
const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
const bool show_bytes = true;
ExecutionContext exe_ctx;
exe_scope->CalculateExecutionContext(exe_ctx);
disassembler_sp->GetInstructionList().Dump(s, show_address,
show_bytes, &exe_ctx);
}
}
} else
s->Printf("invalid target");
return offset;
}
if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
item_byte_size > 8)
item_format = eFormatHex;
lldb::offset_t line_start_offset = start_offset;
for (uint32_t count = 0; ValidOffset(offset) && count < item_count; ++count) {
if ((count % num_per_line) == 0) {
if (count > 0) {
if (item_format == eFormatBytesWithASCII &&
offset > line_start_offset) {
s->Printf("%*s",
static_cast<int>(
(num_per_line - (offset - line_start_offset)) * 3 + 2),
"");
Dump(s, line_start_offset, eFormatCharPrintable, 1,
offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0,
0);
}
s->EOL();
}
if (base_addr != LLDB_INVALID_ADDRESS)
s->Printf("0x%8.8" PRIx64 ": ",
(uint64_t)(base_addr +
(offset - start_offset) / m_target_byte_size));
line_start_offset = offset;
} else if (item_format != eFormatChar &&
item_format != eFormatCharPrintable &&
item_format != eFormatCharArray && count > 0) {
s->PutChar(' ');
}
switch (item_format) {
case eFormatBoolean:
if (item_byte_size <= 8)
s->Printf("%s", GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset)
? "true"
: "false");
else {
s->Printf("error: unsupported byte size (%" PRIu64
") for boolean format",
(uint64_t)item_byte_size);
return offset;
}
break;
case eFormatBinary:
if (item_byte_size <= 8) {
uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
// Avoid std::bitset<64>::to_string() since it is missing in
// earlier C++ libraries
std::string binary_value(64, '0');
std::bitset<64> bits(uval64);
for (uint32_t i = 0; i < 64; ++i)
if (bits[i])
binary_value[64 - 1 - i] = '1';
if (item_bit_size > 0)
s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
else if (item_byte_size > 0 && item_byte_size <= 8)
s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
} else {
const bool is_signed = false;
const unsigned radix = 2;
offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatBytes:
case eFormatBytesWithASCII:
for (uint32_t i = 0; i < item_byte_size; ++i) {
s->Printf("%2.2x", GetU8(&offset));
}
// Put an extra space between the groups of bytes if more than one
// is being dumped in a group (item_byte_size is more than 1).
if (item_byte_size > 1)
s->PutChar(' ');
break;
case eFormatChar:
case eFormatCharPrintable:
case eFormatCharArray: {
// If we are only printing one character surround it with single
// quotes
if (item_count == 1 && item_format == eFormatChar)
s->PutChar('\'');
const uint64_t ch = GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
if (isprint(ch))
s->Printf("%c", (char)ch);
else if (item_format != eFormatCharPrintable) {
switch (ch) {
case '\033':
s->Printf("\\e");
break;
case '\a':
s->Printf("\\a");
break;
case '\b':
s->Printf("\\b");
break;
case '\f':
s->Printf("\\f");
break;
case '\n':
s->Printf("\\n");
break;
case '\r':
s->Printf("\\r");
break;
case '\t':
s->Printf("\\t");
break;
case '\v':
s->Printf("\\v");
break;
case '\0':
s->Printf("\\0");
break;
default:
if (item_byte_size == 1)
s->Printf("\\x%2.2x", (uint8_t)ch);
else
s->Printf("%" PRIu64, ch);
break;
}
} else {
s->PutChar(NON_PRINTABLE_CHAR);
}
// If we are only printing one character surround it with single quotes
if (item_count == 1 && item_format == eFormatChar)
s->PutChar('\'');
} break;
case eFormatEnum: // Print enum value as a signed integer when we don't get
// the enum type
case eFormatDecimal:
if (item_byte_size <= 8)
s->Printf("%" PRId64,
GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
else {
const bool is_signed = true;
const unsigned radix = 10;
offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatUnsigned:
if (item_byte_size <= 8)
s->Printf("%" PRIu64,
GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
else {
const bool is_signed = false;
const unsigned radix = 10;
offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatOctal:
if (item_byte_size <= 8)
s->Printf("0%" PRIo64,
GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
else {
const bool is_signed = false;
const unsigned radix = 8;
offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatOSType: {
uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
s->PutChar('\'');
for (uint32_t i = 0; i < item_byte_size; ++i) {
uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));
if (isprint(ch))
s->Printf("%c", ch);
else {
switch (ch) {
case '\033':
s->Printf("\\e");
break;
case '\a':
s->Printf("\\a");
break;
case '\b':
s->Printf("\\b");
break;
case '\f':
s->Printf("\\f");
break;
case '\n':
s->Printf("\\n");
break;
case '\r':
s->Printf("\\r");
break;
case '\t':
s->Printf("\\t");
break;
case '\v':
s->Printf("\\v");
break;
case '\0':
s->Printf("\\0");
break;
default:
s->Printf("\\x%2.2x", ch);
break;
}
}
}
s->PutChar('\'');
} break;
case eFormatCString: {
const char *cstr = GetCStr(&offset);
if (!cstr) {
s->Printf("NULL");
offset = LLDB_INVALID_OFFSET;
} else {
s->PutChar('\"');
while (const char c = *cstr) {
if (isprint(c)) {
s->PutChar(c);
} else {
switch (c) {
case '\033':
s->Printf("\\e");
break;
case '\a':
s->Printf("\\a");
break;
case '\b':
s->Printf("\\b");
break;
case '\f':
s->Printf("\\f");
break;
case '\n':
s->Printf("\\n");
break;
case '\r':
s->Printf("\\r");
break;
case '\t':
s->Printf("\\t");
break;
case '\v':
s->Printf("\\v");
break;
default:
s->Printf("\\x%2.2x", c);
break;
}
}
++cstr;
}
s->PutChar('\"');
}
} break;
case eFormatPointer:
s->Address(GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset),
sizeof(addr_t));
break;
case eFormatComplexInteger: {
size_t complex_int_byte_size = item_byte_size / 2;
if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {
s->Printf("%" PRIu64,
GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
s->Printf(" + %" PRIu64 "i",
GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for complex integer format",
(uint64_t)item_byte_size);
return offset;
}
} break;
case eFormatComplex:
if (sizeof(float) * 2 == item_byte_size) {
float f32_1 = GetFloat(&offset);
float f32_2 = GetFloat(&offset);
s->Printf("%g + %gi", f32_1, f32_2);
break;
} else if (sizeof(double) * 2 == item_byte_size) {
double d64_1 = GetDouble(&offset);
double d64_2 = GetDouble(&offset);
s->Printf("%lg + %lgi", d64_1, d64_2);
break;
} else if (sizeof(long double) * 2 == item_byte_size) {
long double ld64_1 = GetLongDouble(&offset);
long double ld64_2 = GetLongDouble(&offset);
s->Printf("%Lg + %Lgi", ld64_1, ld64_2);
break;
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for complex float format",
(uint64_t)item_byte_size);
return offset;
}
break;
default:
case eFormatDefault:
case eFormatHex:
case eFormatHexUppercase: {
bool wantsuppercase = (item_format == eFormatHexUppercase);
switch (item_byte_size) {
case 1:
case 2:
case 4:
case 8:
s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
(int)(2 * item_byte_size), (int)(2 * item_byte_size),
GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
break;
default: {
assert(item_bit_size == 0 && item_bit_offset == 0);
const uint8_t *bytes =
(const uint8_t *)GetData(&offset, item_byte_size);
if (bytes) {
s->PutCString("0x");
uint32_t idx;
if (m_byte_order == eByteOrderBig) {
for (idx = 0; idx < item_byte_size; ++idx)
s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
} else {
for (idx = 0; idx < item_byte_size; ++idx)
s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
bytes[item_byte_size - 1 - idx]);
}
}
} break;
}
} break;
case eFormatFloat: {
TargetSP target_sp;
bool used_apfloat = false;
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
if (target_sp) {
ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
if (clang_ast) {
clang::ASTContext *ast = clang_ast->getASTContext();
if (ast) {
llvm::SmallVector<char, 256> sv;
// Show full precision when printing float values
const unsigned format_precision = 0;
const unsigned format_max_padding = 100;
size_t item_bit_size = item_byte_size * 8;
if (item_bit_size == ast->getTypeSize(ast->FloatTy)) {
llvm::APInt apint(item_bit_size,
this->GetMaxU64(&offset, item_byte_size));
llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy),
apint);
apfloat.toString(sv, format_precision, format_max_padding);
} else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) {
llvm::APInt apint;
if (GetAPInt(*this, &offset, item_byte_size, apint)) {
llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy),
apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
} else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) {
const auto &semantics =
ast->getFloatTypeSemantics(ast->LongDoubleTy);
const auto byte_size =
(llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
llvm::APInt apint;
if (GetAPInt(*this, &offset, byte_size, apint)) {
llvm::APFloat apfloat(semantics, apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
} else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) {
llvm::APInt apint(item_bit_size, this->GetU16(&offset));
llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy),
apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
if (!sv.empty()) {
s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data());
used_apfloat = true;
}
}
}
}
if (!used_apfloat) {
std::ostringstream ss;
if (item_byte_size == sizeof(float) || item_byte_size == 2) {
float f;
if (item_byte_size == 2) {
uint16_t half = this->GetU16(&offset);
f = half2float(half);
} else {
f = GetFloat(&offset);
}
ss.precision(std::numeric_limits<float>::digits10);
ss << f;
} else if (item_byte_size == sizeof(double)) {
ss.precision(std::numeric_limits<double>::digits10);
ss << GetDouble(&offset);
} else if (item_byte_size == sizeof(long double) ||
item_byte_size == 10) {
ss.precision(std::numeric_limits<long double>::digits10);
ss << GetLongDouble(&offset);
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for float format",
(uint64_t)item_byte_size);
return offset;
}
ss.flush();
s->Printf("%s", ss.str().c_str());
}
} break;
case eFormatUnicode16:
s->Printf("U+%4.4x", GetU16(&offset));
break;
case eFormatUnicode32:
s->Printf("U+0x%8.8x", GetU32(&offset));
break;
case eFormatAddressInfo: {
addr_t addr = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset);
s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
(int)(2 * item_byte_size), addr);
if (exe_scope) {
TargetSP target_sp(exe_scope->CalculateTarget());
lldb_private::Address so_addr;
if (target_sp) {
if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr,
so_addr)) {
s->PutChar(' ');
so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
Address::DumpStyleModuleWithFileAddress);
} else {
so_addr.SetOffset(addr);
so_addr.Dump(s, exe_scope,
Address::DumpStyleResolvedPointerDescription);
}
}
}
} break;
case eFormatHexFloat:
if (sizeof(float) == item_byte_size) {
char float_cstr[256];
llvm::APFloat ap_float(GetFloat(&offset));
ap_float.convertToHexString(float_cstr, 0, false,
llvm::APFloat::rmNearestTiesToEven);
s->Printf("%s", float_cstr);
break;
} else if (sizeof(double) == item_byte_size) {
char float_cstr[256];
llvm::APFloat ap_float(GetDouble(&offset));
ap_float.convertToHexString(float_cstr, 0, false,
llvm::APFloat::rmNearestTiesToEven);
s->Printf("%s", float_cstr);
break;
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for hex float format",
(uint64_t)item_byte_size);
return offset;
}
break;
// please keep the single-item formats below in sync with
// FormatManager::GetSingleItemFormat
// if you fail to do so, users will start getting different outputs
// depending on internal
// implementation details they should not care about ||
case eFormatVectorOfChar: // ||
s->PutChar('{'); // \/
offset = Dump(s, offset, eFormatCharArray, 1, item_byte_size,
item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt8:
s->PutChar('{');
offset = Dump(s, offset, eFormatDecimal, 1, item_byte_size,
item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt8:
s->PutChar('{');
offset = Dump(s, offset, eFormatHex, 1, item_byte_size, item_byte_size,
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt16:
s->PutChar('{');
offset =
Dump(s, offset, eFormatDecimal, sizeof(uint16_t),
item_byte_size / sizeof(uint16_t),
item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt16:
s->PutChar('{');
offset =
Dump(s, offset, eFormatHex, sizeof(uint16_t),
item_byte_size / sizeof(uint16_t),
item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt32:
s->PutChar('{');
offset =
Dump(s, offset, eFormatDecimal, sizeof(uint32_t),
item_byte_size / sizeof(uint32_t),
item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt32:
s->PutChar('{');
offset =
Dump(s, offset, eFormatHex, sizeof(uint32_t),
item_byte_size / sizeof(uint32_t),
item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt64:
s->PutChar('{');
offset =
Dump(s, offset, eFormatDecimal, sizeof(uint64_t),
item_byte_size / sizeof(uint64_t),
item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt64:
s->PutChar('{');
offset =
Dump(s, offset, eFormatHex, sizeof(uint64_t),
item_byte_size / sizeof(uint64_t),
item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfFloat16:
s->PutChar('{');
offset = Dump(s, offset, eFormatFloat, 2, item_byte_size / 2,
item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfFloat32:
s->PutChar('{');
offset = Dump(s, offset, eFormatFloat, 4, item_byte_size / 4,
item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfFloat64:
s->PutChar('{');
offset = Dump(s, offset, eFormatFloat, 8, item_byte_size / 8,
item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt128:
s->PutChar('{');
offset = Dump(s, offset, eFormatHex, 16, item_byte_size / 16,
item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
}
}
if (item_format == eFormatBytesWithASCII && offset > line_start_offset) {
s->Printf("%*s", static_cast<int>(
(num_per_line - (offset - line_start_offset)) * 3 + 2),
"");
Dump(s, line_start_offset, eFormatCharPrintable, 1,
offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0);
}
return offset; // Return the offset at which we ended up
}
//----------------------------------------------------------------------
// Dumps bytes from this object's data to the stream "s" starting
// "start_offset" bytes into this data, and ending with the byte
@ -2043,19 +1152,6 @@ void DataExtractor::DumpUUID(Stream *s, offset_t offset) const {
}
}
void DataExtractor::DumpHexBytes(Stream *s, const void *src, size_t src_len,
uint32_t bytes_per_line, addr_t base_addr) {
DataExtractor data(src, src_len, eByteOrderLittle, 4);
data.Dump(s,
0, // Offset into "src"
eFormatBytes, // Dump as hex bytes
1, // Size of each item is 1 for single bytes
src_len, // Number of bytes
bytes_per_line, // Num bytes per line
base_addr, // Base address
0, 0); // Bitfield info
}
size_t DataExtractor::Copy(DataExtractor &dest_data) const {
if (m_data_sp) {
// we can pass along the SP to the data

View File

@ -0,0 +1,788 @@
//===-- DumpDataExtractor.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Stream.h"
#include <bitset>
#include <sstream>
using namespace lldb_private;
using namespace lldb;
#define NON_PRINTABLE_CHAR '.'
static float half2float(uint16_t half) {
union {
float f;
uint32_t u;
} u;
int32_t v = (int16_t)half;
if (0 == (v & 0x7c00)) {
u.u = v & 0x80007FFFU;
return u.f * ldexpf(1, 125);
}
v <<= 13;
u.u = v | 0x70000000U;
return u.f * ldexpf(1, -112);
}
static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr,
lldb::offset_t byte_size, llvm::APInt &result) {
llvm::SmallVector<uint64_t, 2> uint64_array;
lldb::offset_t bytes_left = byte_size;
uint64_t u64;
const lldb::ByteOrder byte_order = data.GetByteOrder();
if (byte_order == lldb::eByteOrderLittle) {
while (bytes_left > 0) {
if (bytes_left >= 8) {
u64 = data.GetU64(offset_ptr);
bytes_left -= 8;
} else {
u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
bytes_left = 0;
}
uint64_array.push_back(u64);
}
result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
return true;
} else if (byte_order == lldb::eByteOrderBig) {
lldb::offset_t be_offset = *offset_ptr + byte_size;
lldb::offset_t temp_offset;
while (bytes_left > 0) {
if (bytes_left >= 8) {
be_offset -= 8;
temp_offset = be_offset;
u64 = data.GetU64(&temp_offset);
bytes_left -= 8;
} else {
be_offset -= bytes_left;
temp_offset = be_offset;
u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
bytes_left = 0;
}
uint64_array.push_back(u64);
}
*offset_ptr += byte_size;
result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
return true;
}
return false;
}
static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
lldb::offset_t offset, lldb::offset_t byte_size,
bool is_signed, unsigned radix) {
llvm::APInt apint;
if (GetAPInt(data, &offset, byte_size, apint)) {
std::string apint_str(apint.toString(radix, is_signed));
switch (radix) {
case 2:
s->Write("0b", 2);
break;
case 8:
s->Write("0", 1);
break;
case 10:
break;
}
s->Write(apint_str.c_str(), apint_str.size());
}
return offset;
}
lldb::offset_t lldb_private::DumpDataExtractor(
const DataExtractor &DE, Stream *s, offset_t start_offset,
lldb::Format item_format, size_t item_byte_size, size_t item_count,
size_t num_per_line, uint64_t base_addr,
uint32_t item_bit_size, // If zero, this is not a bitfield value, if
// non-zero, the value is a bitfield
uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
// shift amount to apply to a bitfield
ExecutionContextScope *exe_scope) {
if (s == nullptr)
return start_offset;
if (item_format == eFormatPointer) {
if (item_byte_size != 4 && item_byte_size != 8)
item_byte_size = s->GetAddressByteSize();
}
offset_t offset = start_offset;
if (item_format == eFormatInstruction) {
TargetSP target_sp;
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
if (target_sp) {
DisassemblerSP disassembler_sp(Disassembler::FindPlugin(
target_sp->GetArchitecture(), nullptr, nullptr));
if (disassembler_sp) {
lldb::addr_t addr = base_addr + start_offset;
lldb_private::Address so_addr;
bool data_from_file = true;
if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
data_from_file = false;
} else {
if (target_sp->GetSectionLoadList().IsEmpty() ||
!target_sp->GetImages().ResolveFileAddress(addr, so_addr))
so_addr.SetRawAddress(addr);
}
size_t bytes_consumed = disassembler_sp->DecodeInstructions(
so_addr, DE, start_offset, item_count, false, data_from_file);
if (bytes_consumed) {
offset += bytes_consumed;
const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
const bool show_bytes = true;
ExecutionContext exe_ctx;
exe_scope->CalculateExecutionContext(exe_ctx);
disassembler_sp->GetInstructionList().Dump(s, show_address,
show_bytes, &exe_ctx);
}
}
} else
s->Printf("invalid target");
return offset;
}
if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
item_byte_size > 8)
item_format = eFormatHex;
lldb::offset_t line_start_offset = start_offset;
for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
++count) {
if ((count % num_per_line) == 0) {
if (count > 0) {
if (item_format == eFormatBytesWithASCII &&
offset > line_start_offset) {
s->Printf("%*s",
static_cast<int>(
(num_per_line - (offset - line_start_offset)) * 3 + 2),
"");
DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
offset - line_start_offset, SIZE_MAX,
LLDB_INVALID_ADDRESS, 0, 0);
}
s->EOL();
}
if (base_addr != LLDB_INVALID_ADDRESS)
s->Printf("0x%8.8" PRIx64 ": ",
(uint64_t)(base_addr +
(offset - start_offset) / DE.getTargetByteSize()));
line_start_offset = offset;
} else if (item_format != eFormatChar &&
item_format != eFormatCharPrintable &&
item_format != eFormatCharArray && count > 0) {
s->PutChar(' ');
}
switch (item_format) {
case eFormatBoolean:
if (item_byte_size <= 8)
s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset)
? "true"
: "false");
else {
s->Printf("error: unsupported byte size (%" PRIu64
") for boolean format",
(uint64_t)item_byte_size);
return offset;
}
break;
case eFormatBinary:
if (item_byte_size <= 8) {
uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
// Avoid std::bitset<64>::to_string() since it is missing in
// earlier C++ libraries
std::string binary_value(64, '0');
std::bitset<64> bits(uval64);
for (uint32_t i = 0; i < 64; ++i)
if (bits[i])
binary_value[64 - 1 - i] = '1';
if (item_bit_size > 0)
s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
else if (item_byte_size > 0 && item_byte_size <= 8)
s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
} else {
const bool is_signed = false;
const unsigned radix = 2;
offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatBytes:
case eFormatBytesWithASCII:
for (uint32_t i = 0; i < item_byte_size; ++i) {
s->Printf("%2.2x", DE.GetU8(&offset));
}
// Put an extra space between the groups of bytes if more than one
// is being dumped in a group (item_byte_size is more than 1).
if (item_byte_size > 1)
s->PutChar(' ');
break;
case eFormatChar:
case eFormatCharPrintable:
case eFormatCharArray: {
// If we are only printing one character surround it with single
// quotes
if (item_count == 1 && item_format == eFormatChar)
s->PutChar('\'');
const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
if (isprint(ch))
s->Printf("%c", (char)ch);
else if (item_format != eFormatCharPrintable) {
switch (ch) {
case '\033':
s->Printf("\\e");
break;
case '\a':
s->Printf("\\a");
break;
case '\b':
s->Printf("\\b");
break;
case '\f':
s->Printf("\\f");
break;
case '\n':
s->Printf("\\n");
break;
case '\r':
s->Printf("\\r");
break;
case '\t':
s->Printf("\\t");
break;
case '\v':
s->Printf("\\v");
break;
case '\0':
s->Printf("\\0");
break;
default:
if (item_byte_size == 1)
s->Printf("\\x%2.2x", (uint8_t)ch);
else
s->Printf("%" PRIu64, ch);
break;
}
} else {
s->PutChar(NON_PRINTABLE_CHAR);
}
// If we are only printing one character surround it with single quotes
if (item_count == 1 && item_format == eFormatChar)
s->PutChar('\'');
} break;
case eFormatEnum: // Print enum value as a signed integer when we don't get
// the enum type
case eFormatDecimal:
if (item_byte_size <= 8)
s->Printf("%" PRId64,
DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
else {
const bool is_signed = true;
const unsigned radix = 10;
offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatUnsigned:
if (item_byte_size <= 8)
s->Printf("%" PRIu64,
DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
else {
const bool is_signed = false;
const unsigned radix = 10;
offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatOctal:
if (item_byte_size <= 8)
s->Printf("0%" PRIo64,
DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
else {
const bool is_signed = false;
const unsigned radix = 8;
offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
}
break;
case eFormatOSType: {
uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
item_bit_size, item_bit_offset);
s->PutChar('\'');
for (uint32_t i = 0; i < item_byte_size; ++i) {
uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));
if (isprint(ch))
s->Printf("%c", ch);
else {
switch (ch) {
case '\033':
s->Printf("\\e");
break;
case '\a':
s->Printf("\\a");
break;
case '\b':
s->Printf("\\b");
break;
case '\f':
s->Printf("\\f");
break;
case '\n':
s->Printf("\\n");
break;
case '\r':
s->Printf("\\r");
break;
case '\t':
s->Printf("\\t");
break;
case '\v':
s->Printf("\\v");
break;
case '\0':
s->Printf("\\0");
break;
default:
s->Printf("\\x%2.2x", ch);
break;
}
}
}
s->PutChar('\'');
} break;
case eFormatCString: {
const char *cstr = DE.GetCStr(&offset);
if (!cstr) {
s->Printf("NULL");
offset = LLDB_INVALID_OFFSET;
} else {
s->PutChar('\"');
while (const char c = *cstr) {
if (isprint(c)) {
s->PutChar(c);
} else {
switch (c) {
case '\033':
s->Printf("\\e");
break;
case '\a':
s->Printf("\\a");
break;
case '\b':
s->Printf("\\b");
break;
case '\f':
s->Printf("\\f");
break;
case '\n':
s->Printf("\\n");
break;
case '\r':
s->Printf("\\r");
break;
case '\t':
s->Printf("\\t");
break;
case '\v':
s->Printf("\\v");
break;
default:
s->Printf("\\x%2.2x", c);
break;
}
}
++cstr;
}
s->PutChar('\"');
}
} break;
case eFormatPointer:
s->Address(DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset),
sizeof(addr_t));
break;
case eFormatComplexInteger: {
size_t complex_int_byte_size = item_byte_size / 2;
if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {
s->Printf("%" PRIu64,
DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
s->Printf(" + %" PRIu64 "i",
DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for complex integer format",
(uint64_t)item_byte_size);
return offset;
}
} break;
case eFormatComplex:
if (sizeof(float) * 2 == item_byte_size) {
float f32_1 = DE.GetFloat(&offset);
float f32_2 = DE.GetFloat(&offset);
s->Printf("%g + %gi", f32_1, f32_2);
break;
} else if (sizeof(double) * 2 == item_byte_size) {
double d64_1 = DE.GetDouble(&offset);
double d64_2 = DE.GetDouble(&offset);
s->Printf("%lg + %lgi", d64_1, d64_2);
break;
} else if (sizeof(long double) * 2 == item_byte_size) {
long double ld64_1 = DE.GetLongDouble(&offset);
long double ld64_2 = DE.GetLongDouble(&offset);
s->Printf("%Lg + %Lgi", ld64_1, ld64_2);
break;
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for complex float format",
(uint64_t)item_byte_size);
return offset;
}
break;
default:
case eFormatDefault:
case eFormatHex:
case eFormatHexUppercase: {
bool wantsuppercase = (item_format == eFormatHexUppercase);
switch (item_byte_size) {
case 1:
case 2:
case 4:
case 8:
s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
(int)(2 * item_byte_size), (int)(2 * item_byte_size),
DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset));
break;
default: {
assert(item_bit_size == 0 && item_bit_offset == 0);
const uint8_t *bytes =
(const uint8_t *)DE.GetData(&offset, item_byte_size);
if (bytes) {
s->PutCString("0x");
uint32_t idx;
if (DE.GetByteOrder() == eByteOrderBig) {
for (idx = 0; idx < item_byte_size; ++idx)
s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
} else {
for (idx = 0; idx < item_byte_size; ++idx)
s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
bytes[item_byte_size - 1 - idx]);
}
}
} break;
}
} break;
case eFormatFloat: {
TargetSP target_sp;
bool used_apfloat = false;
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
if (target_sp) {
ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
if (clang_ast) {
clang::ASTContext *ast = clang_ast->getASTContext();
if (ast) {
llvm::SmallVector<char, 256> sv;
// Show full precision when printing float values
const unsigned format_precision = 0;
const unsigned format_max_padding = 100;
size_t item_bit_size = item_byte_size * 8;
if (item_bit_size == ast->getTypeSize(ast->FloatTy)) {
llvm::APInt apint(item_bit_size,
DE.GetMaxU64(&offset, item_byte_size));
llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy),
apint);
apfloat.toString(sv, format_precision, format_max_padding);
} else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) {
llvm::APInt apint;
if (GetAPInt(DE, &offset, item_byte_size, apint)) {
llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy),
apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
} else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) {
const auto &semantics =
ast->getFloatTypeSemantics(ast->LongDoubleTy);
const auto byte_size =
(llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
llvm::APInt apint;
if (GetAPInt(DE, &offset, byte_size, apint)) {
llvm::APFloat apfloat(semantics, apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
} else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) {
llvm::APInt apint(item_bit_size, DE.GetU16(&offset));
llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy),
apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
if (!sv.empty()) {
s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data());
used_apfloat = true;
}
}
}
}
if (!used_apfloat) {
std::ostringstream ss;
if (item_byte_size == sizeof(float) || item_byte_size == 2) {
float f;
if (item_byte_size == 2) {
uint16_t half = DE.GetU16(&offset);
f = half2float(half);
} else {
f = DE.GetFloat(&offset);
}
ss.precision(std::numeric_limits<float>::digits10);
ss << f;
} else if (item_byte_size == sizeof(double)) {
ss.precision(std::numeric_limits<double>::digits10);
ss << DE.GetDouble(&offset);
} else if (item_byte_size == sizeof(long double) ||
item_byte_size == 10) {
ss.precision(std::numeric_limits<long double>::digits10);
ss << DE.GetLongDouble(&offset);
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for float format",
(uint64_t)item_byte_size);
return offset;
}
ss.flush();
s->Printf("%s", ss.str().c_str());
}
} break;
case eFormatUnicode16:
s->Printf("U+%4.4x", DE.GetU16(&offset));
break;
case eFormatUnicode32:
s->Printf("U+0x%8.8x", DE.GetU32(&offset));
break;
case eFormatAddressInfo: {
addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
item_bit_offset);
s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
(int)(2 * item_byte_size), addr);
if (exe_scope) {
TargetSP target_sp(exe_scope->CalculateTarget());
lldb_private::Address so_addr;
if (target_sp) {
if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr,
so_addr)) {
s->PutChar(' ');
so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
Address::DumpStyleModuleWithFileAddress);
} else {
so_addr.SetOffset(addr);
so_addr.Dump(s, exe_scope,
Address::DumpStyleResolvedPointerDescription);
}
}
}
} break;
case eFormatHexFloat:
if (sizeof(float) == item_byte_size) {
char float_cstr[256];
llvm::APFloat ap_float(DE.GetFloat(&offset));
ap_float.convertToHexString(float_cstr, 0, false,
llvm::APFloat::rmNearestTiesToEven);
s->Printf("%s", float_cstr);
break;
} else if (sizeof(double) == item_byte_size) {
char float_cstr[256];
llvm::APFloat ap_float(DE.GetDouble(&offset));
ap_float.convertToHexString(float_cstr, 0, false,
llvm::APFloat::rmNearestTiesToEven);
s->Printf("%s", float_cstr);
break;
} else {
s->Printf("error: unsupported byte size (%" PRIu64
") for hex float format",
(uint64_t)item_byte_size);
return offset;
}
break;
// please keep the single-item formats below in sync with
// FormatManager::GetSingleItemFormat
// if you fail to do so, users will start getting different outputs
// depending on internal
// implementation details they should not care about ||
case eFormatVectorOfChar: // ||
s->PutChar('{'); // \/
offset =
DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,
item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt8:
s->PutChar('{');
offset =
DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,
item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt8:
s->PutChar('{');
offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,
item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt16:
s->PutChar('{');
offset = DumpDataExtractor(
DE, s, offset, eFormatDecimal, sizeof(uint16_t),
item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt16:
s->PutChar('{');
offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),
item_byte_size / sizeof(uint16_t),
item_byte_size / sizeof(uint16_t),
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt32:
s->PutChar('{');
offset = DumpDataExtractor(
DE, s, offset, eFormatDecimal, sizeof(uint32_t),
item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt32:
s->PutChar('{');
offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),
item_byte_size / sizeof(uint32_t),
item_byte_size / sizeof(uint32_t),
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfSInt64:
s->PutChar('{');
offset = DumpDataExtractor(
DE, s, offset, eFormatDecimal, sizeof(uint64_t),
item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt64:
s->PutChar('{');
offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),
item_byte_size / sizeof(uint64_t),
item_byte_size / sizeof(uint64_t),
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfFloat16:
s->PutChar('{');
offset =
DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,
item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfFloat32:
s->PutChar('{');
offset =
DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,
item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfFloat64:
s->PutChar('{');
offset =
DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,
item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
case eFormatVectorOfUInt128:
s->PutChar('{');
offset =
DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,
item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('}');
break;
}
}
if (item_format == eFormatBytesWithASCII && offset > line_start_offset) {
s->Printf("%*s", static_cast<int>(
(num_per_line - (offset - line_start_offset)) * 3 + 2),
"");
DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
offset - line_start_offset, SIZE_MAX,
LLDB_INVALID_ADDRESS, 0, 0);
}
return offset; // Return the offset at which we ended up
}

View File

@ -15,6 +15,7 @@
// Project includes
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
@ -140,8 +141,8 @@ void EventDataBytes::Dump(Stream *s) const {
} else if (!m_bytes.empty()) {
DataExtractor data;
data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder());
data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS,
0, 0);
DumpDataExtractor(data, s, 0, eFormatBytes, 1, m_bytes.size(), 32,
LLDB_INVALID_ADDRESS, 0, 0);
}
}

View File

@ -19,6 +19,7 @@
// Project includes
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
@ -76,15 +77,15 @@ bool RegisterValue::Dump(Stream *s, const RegisterInfo *reg_info,
if (format == eFormatDefault)
format = reg_info->format;
data.Dump(s,
0, // Offset in "data"
format, // Format to use when dumping
reg_info->byte_size, // item_byte_size
1, // item_count
UINT32_MAX, // num_per_line
LLDB_INVALID_ADDRESS, // base_addr
0, // item_bit_size
0); // item_bit_offset
DumpDataExtractor(data, s,
0, // Offset in "data"
format, // Format to use when dumping
reg_info->byte_size, // item_byte_size
1, // item_count
UINT32_MAX, // num_per_line
LLDB_INVALID_ADDRESS, // base_addr
0, // item_bit_size
0); // item_bit_offset
return true;
}
return false;

View File

@ -19,6 +19,8 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/SymbolContext.h"
@ -60,9 +62,9 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
return false;
StreamString reg_sstr;
data.Dump(&reg_sstr, 0, GetFormat(), reg_info->byte_size, 1, UINT32_MAX,
LLDB_INVALID_ADDRESS, 0, 0,
exe_ctx.GetBestExecutionContextScope());
DumpDataExtractor(data, &reg_sstr, 0, GetFormat(), reg_info->byte_size,
1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0,
exe_ctx.GetBestExecutionContextScope());
dest = reg_sstr.GetString();
}
} else {

View File

@ -12,6 +12,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Expression/Materializer.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
@ -29,6 +30,19 @@
using namespace lldb_private;
static void DumpHexBytes(Stream *s, const void *src, size_t src_len,
uint32_t bytes_per_line, lldb::addr_t base_addr) {
DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);
DumpDataExtractor(data, s,
0, // Offset into "src"
lldb::eFormatBytes, // Dump as hex bytes
1, // Size of each item is 1 for single bytes
src_len, // Number of bytes
bytes_per_line, // Num bytes per line
base_addr, // Base address
0, 0); // Bitfield info
}
uint32_t Materializer::AddStructMember(Entity &entity) {
uint32_t size = entity.GetSize();
uint32_t alignment = entity.GetAlignment();
@ -370,11 +384,8 @@ public:
if (!err.Success()) {
dump_stream.Printf(" <could not be read>\n");
} else {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
dump_stream.PutChar('\n');
}
@ -398,11 +409,8 @@ public:
if (!err.Success()) {
dump_stream.Printf(" <could not be read>\n");
} else {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, target_address);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
target_address);
dump_stream.PutChar('\n');
}
@ -711,8 +719,8 @@ public:
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
lldb::offset_t offset;
@ -739,11 +747,8 @@ public:
if (!err.Success()) {
dump_stream.Printf(" <could not be read>\n");
} else {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
dump_stream.PutChar('\n');
}
@ -981,8 +986,8 @@ public:
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
lldb::offset_t offset;
@ -1009,11 +1014,8 @@ public:
if (!err.Success()) {
dump_stream.Printf(" <could not be read>\n");
} else {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
dump_stream.PutChar('\n');
}
@ -1146,11 +1148,8 @@ public:
if (!err.Success()) {
dump_stream.Printf(" <could not be read>\n");
} else {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
dump_stream.PutChar('\n');
}
@ -1322,11 +1321,8 @@ public:
if (!err.Success()) {
dump_stream.Printf(" <could not be read>\n");
} else {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
map.GetByteOrder(), map.GetAddressByteSize());
extractor.DumpHexBytes(&dump_stream, data.GetBytes(),
data.GetByteSize(), 16, load_addr);
DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
load_addr);
dump_stream.PutChar('\n');
}

View File

@ -18,6 +18,7 @@
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
@ -3409,8 +3410,9 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
// Print the results to our stream.
expr_result->Dump(strm, expr_options);
} else {
alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1,
LLDB_INVALID_ADDRESS, 0, 0);
DumpDataExtractor(alloc_data, &strm, offset, format,
data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0,
0);
}
offset += data_size;
}

View File

@ -10,6 +10,7 @@
#include "DWARFCompileUnit.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Timer.h"
@ -328,10 +329,9 @@ bool DWARFCompileUnit::Verify(Stream *s) const {
return true;
} else {
s->Printf(" 0x%8.8x: ", m_offset);
m_dwarf2Data->get_debug_info_data().Dump(s, m_offset, lldb::eFormatHex, 1,
Size(), 32, LLDB_INVALID_ADDRESS,
0, 0);
DumpDataExtractor(m_dwarf2Data->get_debug_info_data(), s, m_offset,
lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0,
0);
s->EOL();
if (valid_offset) {
if (!length_OK)

View File

@ -16,7 +16,7 @@
namespace lldb_private {
class DWARFDataExtractor : public lldb_private::DataExtractor {
class DWARFDataExtractor : public DataExtractor {
public:
DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) {}

View File

@ -14,6 +14,7 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/ExecutionContext.h"
@ -408,7 +409,8 @@ size_t UnwindAssemblyInstEmulation::WriteMemory(
StreamString strm;
strm.PutCString("UnwindAssemblyInstEmulation::WriteMemory (");
data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
DumpDataExtractor(data, &strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX,
addr, 0, 0);
strm.PutCString(", context = ");
context.Dump(strm, instruction);
log->PutString(strm.GetString());

View File

@ -73,6 +73,8 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
@ -8826,7 +8828,7 @@ ClangASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
void ClangASTContext::DumpValue(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
lldb::Format format, const lldb_private::DataExtractor &data,
lldb::Format format, const DataExtractor &data,
lldb::offset_t data_byte_offset, size_t data_byte_size,
uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
bool show_summary, bool verbose, uint32_t depth) {
@ -9034,8 +9036,9 @@ void ClangASTContext::DumpValue(
if (is_array_of_characters) {
s->PutChar('"');
data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size,
element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
DumpDataExtractor(data, s, data_byte_offset, lldb::eFormatChar,
element_byte_size, element_count, UINT32_MAX,
LLDB_INVALID_ADDRESS, 0, 0);
s->PutChar('"');
return;
} else {
@ -9191,8 +9194,9 @@ void ClangASTContext::DumpValue(
default:
// We are down to a scalar type that we just need to display.
data.Dump(s, data_byte_offset, format, data_byte_size, 1, UINT32_MAX,
LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset);
DumpDataExtractor(data, s, data_byte_offset, format, data_byte_size, 1,
UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset);
if (show_summary)
DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
@ -9202,8 +9206,8 @@ void ClangASTContext::DumpValue(
bool ClangASTContext::DumpTypeValue(
lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
const lldb_private::DataExtractor &data, lldb::offset_t byte_offset,
size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size,
uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
ExecutionContextScope *exe_scope) {
if (!type)
return false;
@ -9341,9 +9345,10 @@ bool ClangASTContext::DumpTypeValue(
byte_size = 4;
break;
}
return data.Dump(s, byte_offset, format, byte_size, item_count,
UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
return DumpDataExtractor(data, s, byte_offset, format, byte_size,
item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
bitfield_bit_size, bitfield_bit_offset,
exe_scope);
}
break;
}
@ -9369,8 +9374,8 @@ void ClangASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
else
buf.resize(256);
lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(),
process->GetByteOrder(), 4);
DataExtractor cstr_data(&buf.front(), buf.size(),
process->GetByteOrder(), 4);
buf.back() = '\0';
size_t bytes_read;
size_t total_cstr_len = 0;
@ -9382,8 +9387,8 @@ void ClangASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
break;
if (total_cstr_len == 0)
s->PutCString(" \"");
cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX,
LLDB_INVALID_ADDRESS, 0, 0);
DumpDataExtractor(cstr_data, s, 0, lldb::eFormatChar, 1, len,
UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
total_cstr_len += len;
if (len < buf.size())
break;

View File

@ -744,8 +744,7 @@ size_t CompilerType::ConvertStringToFloatValue(const char *s, uint8_t *dst,
#define DEPTH_INCREMENT 2
void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s,
lldb::Format format,
const lldb_private::DataExtractor &data,
lldb::Format format, const DataExtractor &data,
lldb::offset_t data_byte_offset,
size_t data_byte_size, uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset, bool show_types,
@ -759,7 +758,7 @@ void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s,
}
bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format,
const lldb_private::DataExtractor &data,
const DataExtractor &data,
lldb::offset_t byte_offset, size_t byte_size,
uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset,
@ -772,7 +771,7 @@ bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format,
}
void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s,
const lldb_private::DataExtractor &data,
const DataExtractor &data,
lldb::offset_t data_byte_offset,
size_t data_byte_size) {
if (IsValid())

View File

@ -14,8 +14,8 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/ObjectFile.h"
@ -27,6 +27,129 @@
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// GetDwarfEHPtr
//
// Used for calls when the value type is specified by a DWARF EH Frame
// pointer encoding.
//----------------------------------------------------------------------
static uint64_t
GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr,
uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr,
addr_t data_addr) //, BSDRelocs *data_relocs) const
{
if (eh_ptr_enc == DW_EH_PE_omit)
return ULLONG_MAX; // Value isn't in the buffer...
uint64_t baseAddress = 0;
uint64_t addressValue = 0;
const uint32_t addr_size = DE.GetAddressByteSize();
#ifdef LLDB_CONFIGURATION_DEBUG
assert(addr_size == 4 || addr_size == 8);
#endif
bool signExtendValue = false;
// Decode the base part or adjust our offset
switch (eh_ptr_enc & 0x70) {
case DW_EH_PE_pcrel:
signExtendValue = true;
baseAddress = *offset_ptr;
if (pc_rel_addr != LLDB_INVALID_ADDRESS)
baseAddress += pc_rel_addr;
// else
// Log::GlobalWarning ("PC relative pointer encoding found with
// invalid pc relative address.");
break;
case DW_EH_PE_textrel:
signExtendValue = true;
if (text_addr != LLDB_INVALID_ADDRESS)
baseAddress = text_addr;
// else
// Log::GlobalWarning ("text relative pointer encoding being
// decoded with invalid text section address, setting base address
// to zero.");
break;
case DW_EH_PE_datarel:
signExtendValue = true;
if (data_addr != LLDB_INVALID_ADDRESS)
baseAddress = data_addr;
// else
// Log::GlobalWarning ("data relative pointer encoding being
// decoded with invalid data section address, setting base address
// to zero.");
break;
case DW_EH_PE_funcrel:
signExtendValue = true;
break;
case DW_EH_PE_aligned: {
// SetPointerSize should be called prior to extracting these so the
// pointer size is cached
assert(addr_size != 0);
if (addr_size) {
// Align to a address size boundary first
uint32_t alignOffset = *offset_ptr % addr_size;
if (alignOffset)
offset_ptr += addr_size - alignOffset;
}
} break;
default:
break;
}
// Decode the value part
switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) {
case DW_EH_PE_absptr: {
addressValue = DE.GetAddress(offset_ptr);
// if (data_relocs)
// addressValue = data_relocs->Relocate(*offset_ptr -
// addr_size, *this, addressValue);
} break;
case DW_EH_PE_uleb128:
addressValue = DE.GetULEB128(offset_ptr);
break;
case DW_EH_PE_udata2:
addressValue = DE.GetU16(offset_ptr);
break;
case DW_EH_PE_udata4:
addressValue = DE.GetU32(offset_ptr);
break;
case DW_EH_PE_udata8:
addressValue = DE.GetU64(offset_ptr);
break;
case DW_EH_PE_sleb128:
addressValue = DE.GetSLEB128(offset_ptr);
break;
case DW_EH_PE_sdata2:
addressValue = (int16_t)DE.GetU16(offset_ptr);
break;
case DW_EH_PE_sdata4:
addressValue = (int32_t)DE.GetU32(offset_ptr);
break;
case DW_EH_PE_sdata8:
addressValue = (int64_t)DE.GetU64(offset_ptr);
break;
default:
// Unhandled encoding type
assert(eh_ptr_enc);
break;
}
// Since we promote everything to 64 bit, we may need to sign extend
if (signExtendValue && addr_size < sizeof(baseAddress)) {
uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);
if (sign_bit & addressValue) {
uint64_t mask = ~sign_bit + 1;
addressValue |= mask;
}
}
return baseAddress + addressValue;
}
DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile,
SectionSP &section_sp,
lldb::RegisterKind reg_kind,
@ -223,9 +346,9 @@ DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
{
uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
cie_sp->personality_loc = m_cfi_data.GetGNUEHPointer(
&offset, arg_ptr_encoding, pc_rel_addr, LLDB_INVALID_ADDRESS,
LLDB_INVALID_ADDRESS);
cie_sp->personality_loc = GetGNUEHPointer(
m_cfi_data, &offset, arg_ptr_encoding, pc_rel_addr,
LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
}
break;
@ -361,14 +484,15 @@ void DWARFCallFrameInfo::GetFDEIndex() {
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(
&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
lldb::addr_t addr =
GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
text_addr, data_addr);
if (clear_address_zeroth_bit)
addr &= ~1ull;
lldb::addr_t length = m_cfi_data.GetGNUEHPointer(
&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr,
text_addr, data_addr);
lldb::addr_t length = GetGNUEHPointer(
m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
pc_rel_addr, text_addr, data_addr);
FDEEntryMap::Entry fde(addr, length, current_entry);
m_fde_index.Append(fde);
} else {
@ -434,11 +558,12 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(
&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr);
lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer(
&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr,
text_addr, data_addr);
lldb::addr_t range_base =
GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
text_addr, data_addr);
lldb::addr_t range_len = GetGNUEHPointer(
m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
pc_rel_addr, text_addr, data_addr);
AddressRange range(range_base, m_objfile.GetAddressByteSize(),
m_objfile.GetSectionList());
range.SetByteSize(range_len);
@ -449,8 +574,9 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) {
offset_t saved_offset = offset;
lsda_data_file_address = m_cfi_data.GetGNUEHPointer(
&offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr);
lsda_data_file_address =
GetGNUEHPointer(m_cfi_data, &offset, cie->lsda_addr_encoding,
pc_rel_addr, text_addr, data_addr);
if (offset - saved_offset != aug_data_len) {
// There is more in the augmentation region than we know how to process;
// don't read anything.

View File

@ -11,6 +11,7 @@
#include <utility>
#include <vector>
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
@ -1263,9 +1264,9 @@ bool GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
byte_size = 4;
break;
}
return data.Dump(s, byte_offset, format, byte_size, item_count, UINT32_MAX,
LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
return DumpDataExtractor(data, s, byte_offset, format, byte_size,
item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
bitfield_bit_size, bitfield_bit_offset, exe_scope);
}
return 0;
}

View File

@ -10,7 +10,7 @@
#include <sstream>
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
@ -1004,10 +1004,10 @@ bool JavaASTContext::DumpTypeValue(
size_t data_byte_size, uint32_t bitfield_bit_size,
uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) {
if (IsScalarType(type)) {
return data.Dump(s, data_offset, format, data_byte_size,
1, // count
UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
return DumpDataExtractor(data, s, data_offset, format, data_byte_size,
1, // count
UINT32_MAX, LLDB_INVALID_ADDRESS,
bitfield_bit_size, bitfield_bit_offset, exe_scope);
}
return false;
}

View File

@ -9,6 +9,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Symbol/OCamlASTContext.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamFile.h"
@ -621,9 +622,9 @@ bool OCamlASTContext::DumpTypeValue(
}
if (IsScalarType(type)) {
return data.Dump(s, byte_offset, format, byte_size, 1, SIZE_MAX,
LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
return DumpDataExtractor(data, s, byte_offset, format, byte_size, 1,
SIZE_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
bitfield_bit_offset, exe_scope);
}
return false;