Skip to content
Snippets Groups Projects
Commit 7baf7b24 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger[New CDB]: Pass formatting parameters.

Pass around formatting parameters as structure.
Prototypically implement formatting of char *-Pointers
as UTF8.
Transfer registers and modules only if dock window is visible.
parent 691aa41e
No related branches found
No related tags found
No related merge requests found
...@@ -104,11 +104,14 @@ static const CommandDescription commandDescriptions[] = { ...@@ -104,11 +104,14 @@ static const CommandDescription commandDescriptions[] = {
"iname1-list: Comma-separated list of inames"}, "iname1-list: Comma-separated list of inames"},
{"locals", {"locals",
"Prints local variables of symbol group in GDBMI or debug format", "Prints local variables of symbol group in GDBMI or debug format",
"[-t token] [-h] [-d] [-e expand-list] [-u uninitialized-list]\n<frame-number> [iname]\n" "[-t token] [T formats] [-I formats] [-c] [-h] [-d] [-e expand-list] [-u uninitialized-list]\n<frame-number> [iname]\n"
"-h human-readable ouput\n" "-h human-readable ouput\n"
"-d debug output\n" "-d debug output\n"
"-c complex dumpers\n"
"-e expand-list Comma-separated list of inames to be expanded beforehand\n" "-e expand-list Comma-separated list of inames to be expanded beforehand\n"
"-u uninitialized-list Comma-separated list of uninitialized inames"}, "-u uninitialized-list Comma-separated list of uninitialized inames\n"
"-I formatmap map of 'hex-encoded-iname=typecode'\n"
"-T formatmap map of 'hex-encoded-type-name=typecode'"},
{"dumplocal", "Dumps local variable using simple dumpers (testing command).", {"dumplocal", "Dumps local variable using simple dumpers (testing command).",
"[-t token] <frame-number> <iname>"}, "[-t token] <frame-number> <iname>"},
{"typecast","Performs a type cast on an unexpanded iname of symbol group.", {"typecast","Performs a type cast on an unexpanded iname of symbol group.",
...@@ -270,12 +273,11 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int * ...@@ -270,12 +273,11 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int *
{ {
// Parse the command // Parse the command
unsigned debugOutput = 0; unsigned debugOutput = 0;
bool humanReadableGdbmi = false;
std::string iname; std::string iname;
StringList tokens = commandTokens<StringList>(args, token); StringList tokens = commandTokens<StringList>(args, token);
StringVector expandedInames; StringVector expandedInames;
StringVector uninitializedInames; StringVector uninitializedInames;
DumpParameters parameters;
// Parse away options // Parse away options
while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') { while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
const char option = tokens.front().at(1); const char option = tokens.front().at(1);
...@@ -285,7 +287,10 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int * ...@@ -285,7 +287,10 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int *
debugOutput++; debugOutput++;
break; break;
case 'h': case 'h':
humanReadableGdbmi = true; parameters.dumpFlags |= DumpParameters::DumpHumanReadable;
break;
case 'c':
parameters.dumpFlags |= DumpParameters::DumpComplexDumpers;
break; break;
case 'u': case 'u':
if (tokens.empty()) { if (tokens.empty()) {
...@@ -303,8 +308,25 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int * ...@@ -303,8 +308,25 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int *
split(tokens.front(), ',', std::back_inserter(expandedInames)); split(tokens.front(), ',', std::back_inserter(expandedInames));
tokens.pop_front(); tokens.pop_front();
break; break;
} case 'T': // typeformats: 'hex'ed name = formatnumber,...'
} if (tokens.empty()) {
*errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
return std::string();
}
parameters.typeFormats = DumpParameters::decodeFormatArgument(tokens.front());
tokens.pop_front();
break;
case 'I': // individual formats: 'hex'ed name = formatnumber,...'
if (tokens.empty()) {
*errorMessage = singleLineUsage(commandDescriptions[CmdLocals]);
return std::string();
}
parameters.individualFormats = DumpParameters::decodeFormatArgument(tokens.front());
tokens.pop_front();
break;
} // case option
} // for options
// Frame and iname // Frame and iname
unsigned frame; unsigned frame;
if (tokens.empty() || !integerFromString(tokens.front(), &frame)) { if (tokens.empty() || !integerFromString(tokens.front(), &frame)) {
...@@ -329,8 +351,8 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int * ...@@ -329,8 +351,8 @@ static std::string commmandLocals(ExtensionCommandContext &exc,PCSTR args, int *
const SymbolGroupValueContext dumpContext(exc.dataSpaces()); const SymbolGroupValueContext dumpContext(exc.dataSpaces());
return iname.empty() ? return iname.empty() ?
symGroup->dump(dumpContext, humanReadableGdbmi) : symGroup->dump(dumpContext, parameters) :
symGroup->dump(iname, dumpContext, humanReadableGdbmi, errorMessage); symGroup->dump(iname, dumpContext, parameters, errorMessage);
} }
extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args) extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)
......
...@@ -185,6 +185,55 @@ std::wstring stringToWString(const std::string &w) ...@@ -185,6 +185,55 @@ std::wstring stringToWString(const std::string &w)
return rc; return rc;
} }
// Convert an ASCII hex digit to its value 'A'->10
inline unsigned hexDigit(char c)
{
if (c <= '9')
return c - '0';
if (c <= 'F')
return c - 'A' + 10;
return c - 'a' + 10;
}
// Convert an ASCII hex digit to its value 'A'->10
inline char toHexDigit(unsigned v)
{
if (v < 10)
return char(v) + '0';
return char(v - 10) + 'a';
}
// String from hex "414A" -> "AJ".
std::string stringFromHex(const char *p, const char *end)
{
if (p == end)
return std::string();
std::string rc;
rc.reserve((end - p) / 2);
for ( ; p < end; p++) {
unsigned c = 16 * hexDigit(*p);
c += hexDigit(*++p);
rc.push_back(char(c));
}
return rc;
}
std::wstring dataToHexW(const unsigned char *p, const unsigned char *end)
{
if (p == end)
return std::wstring();
std::wstring rc;
rc.reserve(2 * (end - p));
for ( ; p < end ; p++) {
const unsigned c = *p;
rc.push_back(toHexDigit(c / 16));
rc.push_back(toHexDigit(c &0xF));
}
return rc;
}
// Format a map as a GDBMI hash {key="value",..} // Format a map as a GDBMI hash {key="value",..}
void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &m) void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &m)
{ {
......
...@@ -86,6 +86,18 @@ bool integerFromString(const std::string &s, Integer *v) ...@@ -86,6 +86,18 @@ bool integerFromString(const std::string &s, Integer *v)
return !str.fail(); return !str.fail();
} }
// Read an integer from a wstring as '10' or '0xA'
template <class Integer>
bool integerFromWString(const std::wstring &s, Integer *v)
{
const bool isHex = s.compare(0, 2, L"0x") == 0;
std::wistringstream str(isHex ? s.substr(2, s.size() - 2) : s);
if (isHex)
str >> std::hex;
str >> *v;
return !str.fail();
}
void replace(std::wstring &s, wchar_t before, wchar_t after); void replace(std::wstring &s, wchar_t before, wchar_t after);
// Stream a string onto a char stream doing backslash & octal escaping // Stream a string onto a char stream doing backslash & octal escaping
...@@ -128,6 +140,10 @@ std::string wStringToGdbmiString(const std::wstring &w); ...@@ -128,6 +140,10 @@ std::string wStringToGdbmiString(const std::wstring &w);
std::string wStringToString(const std::wstring &w); std::string wStringToString(const std::wstring &w);
std::wstring stringToWString(const std::string &w); std::wstring stringToWString(const std::string &w);
// String from hex "414A" -> "AJ".
std::string stringFromHex(const char *begin, const char *end);
std::wstring dataToHexW(const unsigned char *begin, const unsigned char *end);
// Format a map as a GDBMI hash {key="value",..} // Format a map as a GDBMI hash {key="value",..}
void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &); void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &);
......
...@@ -76,6 +76,128 @@ std::ostream &operator<<(std::ostream &str, const DEBUG_SYMBOL_PARAMETERS &param ...@@ -76,6 +76,128 @@ std::ostream &operator<<(std::ostream &str, const DEBUG_SYMBOL_PARAMETERS &param
return str; return str;
} }
// --------------- DumpParameters
DumpParameters::DumpParameters() : dumpFlags(0)
{
}
// typeformats: decode hex-encoded name, value pairs:
// '414A=2,...' -> map of "AB:2".
DumpParameters::FormatMap DumpParameters::decodeFormatArgument(const std::string &f)
{
FormatMap rc;
const std::string::size_type size = f.size();
// Split 'hexname=4,'
for (std::string::size_type pos = 0; pos < size ; ) {
// Cut out key
const std::string::size_type equalsPos = f.find('=', pos);
if (equalsPos == std::string::npos)
return rc;
const std::string name = stringFromHex(f.c_str() + pos, f.c_str() + equalsPos);
// Search for number
const std::string::size_type numberPos = equalsPos + 1;
std::string::size_type nextPos = f.find(',', numberPos);
if (nextPos == std::string::npos)
nextPos = size;
int format;
if (!integerFromString(f.substr(numberPos, nextPos - numberPos), &format))
return rc;
rc.insert(FormatMap::value_type(name, format));
pos = nextPos + 1;
}
return rc;
}
int DumpParameters::format(const std::string &type, const std::string &iname) const
{
if (!individualFormats.empty()) {
const FormatMap::const_iterator iit = individualFormats.find(iname);
if (iit != individualFormats.end())
return iit->second;
}
if (!typeFormats.empty()) {
const FormatMap::const_iterator tit = typeFormats.find(type);
if (tit != typeFormats.end())
return tit->second;
}
return -1;
}
enum PointerFormats // Watch data pointer format requests
{
FormatRawPointer = 0,
FormatLatin1String = 1,
FormatUtf8String = 2,
FormatUtf16String = 3,
FormatUcs4String = 4
};
enum DumpEncoding // WatchData encoding of GDBMI values
{
DumpEncodingAscii = 0,
DumpEncodingBase64 = 1,
DumpEncodingBase64_Utf16 = 2,
DumpEncodingBase64_Ucs4 = 3,
DumpEncodingHex_Latin1 = 6,
DumpEncodingHex_Utf161 = 7,
DumpEncodingHex_Ucs4_LittleEndian = 8,
DumpEncodingHex_Utf8_LittleEndian = 9,
DumpEncodingHex_Ucs4_BigEndian = 10,
DumpEncodingHex_Utf16_BigEndian = 11,
DumpEncodingHex_Utf16_LittleEndian = 12
};
bool DumpParameters::recode(const std::string &type,
const std::string &iname,
const SymbolGroupValueContext &ctx,
std::wstring *value, int *encoding) const
{
// We basically handle char formats for 'char *', '0x834478 "hallo.."'
// Determine address and length from the pointer value output,
// read the raw memory and recode if that is possible.
const int newFormat = format(type, iname);
if (newFormat < 2)
return false;
if (value->compare(0, 2, L"0x"))
return false;
const std::wstring::size_type quote1 = value->find(L'"', 2);
if (quote1 == std::wstring::npos)
return false;
const std::wstring::size_type quote2 = value->find(L'"', quote1 + 1);
if (quote2 == std::wstring::npos)
return false;
const std::wstring::size_type length = quote2 - quote1 - 1;
if (!length)
return false;
ULONG64 address = 0;
if (!integerFromWString(value->substr(0, quote1 - 1), &address) || !address)
return false;
// Allocate real length + 4 bytes ('\0') for largest format.
// '\0' is not listed in the CDB output.
const std::wstring::size_type allocLength = length + 4;
unsigned char *buffer = new unsigned char[allocLength];
std::fill(buffer, buffer + allocLength, 0);
ULONG obtained = 0;
if (FAILED(ctx.dataspaces->ReadVirtual(address, buffer, ULONG(length), &obtained))) {
delete [] buffer;
return false;
}
// Recode raw memory
switch (newFormat) {
case FormatUtf8String:
*value = dataToHexW(buffer, buffer + length + 1); // UTF8 + 0
*encoding = DumpEncodingHex_Utf8_LittleEndian;
break;
case FormatUtf16String:
break;
case FormatUcs4String:
break;
}
delete [] buffer;
return true;
}
// ------------- SymbolGroup
SymbolGroup::SymbolGroup(IDebugSymbolGroup2 *sg, SymbolGroup::SymbolGroup(IDebugSymbolGroup2 *sg,
const SymbolParameterVector &vec, const SymbolParameterVector &vec,
ULONG threadId, ULONG threadId,
...@@ -579,7 +701,9 @@ static inline void indentStream(std::ostream &str, unsigned depth) ...@@ -579,7 +701,9 @@ static inline void indentStream(std::ostream &str, unsigned depth)
str << " "; str << " ";
} }
void SymbolGroupNode::dump(std::ostream &str, const SymbolGroupValueContext &ctx) void SymbolGroupNode::dump(std::ostream &str,
const DumpParameters &p,
const SymbolGroupValueContext &ctx)
{ {
const std::string iname = fullIName(); const std::string iname = fullIName();
const std::string t = type(); const std::string t = type();
...@@ -595,16 +719,22 @@ void SymbolGroupNode::dump(std::ostream &str, const SymbolGroupValueContext &ctx ...@@ -595,16 +719,22 @@ void SymbolGroupNode::dump(std::ostream &str, const SymbolGroupValueContext &ctx
bool valueEditable = !uninitialized; bool valueEditable = !uninitialized;
bool valueEnabled = !uninitialized; bool valueEnabled = !uninitialized;
const std::wstring value = displayValue(ctx); // Shall it be recoded?
// ASCII or base64? std::wstring value = displayValue(ctx);
if (isSevenBitClean(value.c_str(), value.size())) { int encoding = 0;
str << ",valueencoded=\"0\",value=\"" << gdbmiWStringFormat(value) << '"'; if (p.recode(t, iname, ctx, &value, &encoding)) {
} else { str << ",valueencoded=\"" << encoding
str << ",valueencoded=\"2\",value=\""; << "\",value=\"" << gdbmiWStringFormat(value) <<'"';
base64Encode(str, reinterpret_cast<const unsigned char *>(value.c_str()), value.size() * sizeof(wchar_t)); } else { // As is: ASCII or base64?
str << '"'; if (isSevenBitClean(value.c_str(), value.size())) {
str << ",valueencoded=\"" << DumpEncodingAscii << "\",value=\""
<< gdbmiWStringFormat(value) << '"';
} else {
str << ",valueencoded=\"" << DumpEncodingBase64_Utf16 << "\",value=\"";
base64Encode(str, reinterpret_cast<const unsigned char *>(value.c_str()), value.size() * sizeof(wchar_t));
str << '"';
}
} }
// Children: Dump all known or subelements (guess). // Children: Dump all known or subelements (guess).
const VectorIndexType childCountGuess = uninitialized ? 0 : const VectorIndexType childCountGuess = uninitialized ? 0 :
(m_children.empty() ? m_parameters.SubElements : m_children.size()); (m_children.empty() ? m_parameters.SubElements : m_children.size());
...@@ -792,11 +922,12 @@ static inline std::string msgNotFound(const std::string &nodeName) ...@@ -792,11 +922,12 @@ static inline std::string msgNotFound(const std::string &nodeName)
return str.str(); return str.str();
} }
std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx, bool humanReadable) const std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx,
const DumpParameters &p) const
{ {
std::ostringstream str; std::ostringstream str;
DumpSymbolGroupNodeVisitor visitor(str, ctx, humanReadable); DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
if (humanReadable) if (p.humanReadable())
str << '\n'; str << '\n';
str << '['; str << '[';
accept(visitor); accept(visitor);
...@@ -805,7 +936,10 @@ std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx, bool humanRead ...@@ -805,7 +936,10 @@ std::string SymbolGroup::dump(const SymbolGroupValueContext &ctx, bool humanRead
} }
// Dump a node, potentially expand // Dump a node, potentially expand
std::string SymbolGroup::dump(const std::string &iname, const SymbolGroupValueContext &ctx, bool humanReadable, std::string *errorMessage) std::string SymbolGroup::dump(const std::string &iname,
const SymbolGroupValueContext &ctx,
const DumpParameters &p,
std::string *errorMessage)
{ {
SymbolGroupNode *const node = find(iname); SymbolGroupNode *const node = find(iname);
if (node == 0) { if (node == 0) {
...@@ -819,9 +953,9 @@ std::string SymbolGroup::dump(const std::string &iname, const SymbolGroupValueCo ...@@ -819,9 +953,9 @@ std::string SymbolGroup::dump(const std::string &iname, const SymbolGroupValueCo
return false; return false;
} }
std::ostringstream str; std::ostringstream str;
if (humanReadable) if (p.humanReadable())
str << '\n'; str << '\n';
DumpSymbolGroupNodeVisitor visitor(str, ctx, humanReadable); DumpSymbolGroupNodeVisitor visitor(str, ctx, p);
str << '['; str << '[';
node->accept(visitor, 0, 0); node->accept(visitor, 0, 0);
str << ']'; str << ']';
...@@ -1056,8 +1190,9 @@ SymbolGroupNodeVisitor::VisitResult ...@@ -1056,8 +1190,9 @@ SymbolGroupNodeVisitor::VisitResult
// --------------------- DumpSymbolGroupNodeVisitor // --------------------- DumpSymbolGroupNodeVisitor
DumpSymbolGroupNodeVisitor::DumpSymbolGroupNodeVisitor(std::ostream &os, DumpSymbolGroupNodeVisitor::DumpSymbolGroupNodeVisitor(std::ostream &os,
const SymbolGroupValueContext &context, const SymbolGroupValueContext &context,
bool humanReadable) : const DumpParameters &parameters) :
m_os(os), m_humanReadable(humanReadable),m_context(context), m_visitChildren(false) m_os(os), m_context(context), m_parameters(parameters),
m_visitChildren(false)
{ {
} }
...@@ -1073,18 +1208,18 @@ SymbolGroupNodeVisitor::VisitResult ...@@ -1073,18 +1208,18 @@ SymbolGroupNodeVisitor::VisitResult
// Do not recurse into children unless the node was expanded by the watch model // Do not recurse into children unless the node was expanded by the watch model
if (child) if (child)
m_os << ','; // Separator in parents list m_os << ','; // Separator in parents list
if (m_humanReadable) { if (m_parameters.humanReadable()) {
m_os << '\n'; m_os << '\n';
indentStream(m_os, depth * 2); indentStream(m_os, depth * 2);
} }
m_os << '{'; m_os << '{';
node->dump(m_os, m_context); node->dump(m_os, m_parameters, m_context);
if (m_visitChildren) { // open children array if (m_visitChildren) { // open children array
m_os << ",children=["; m_os << ",children=[";
} else { // No children, close array. } else { // No children, close array.
m_os << '}'; m_os << '}';
} }
if (m_humanReadable) if (m_parameters.humanReadable())
m_os << '\n'; m_os << '\n';
return m_visitChildren ? VisitContinue : VisitSkipChildren; return m_visitChildren ? VisitContinue : VisitSkipChildren;
} }
...@@ -1092,6 +1227,6 @@ SymbolGroupNodeVisitor::VisitResult ...@@ -1092,6 +1227,6 @@ SymbolGroupNodeVisitor::VisitResult
void DumpSymbolGroupNodeVisitor::childrenVisited(const SymbolGroupNode *, unsigned) void DumpSymbolGroupNodeVisitor::childrenVisited(const SymbolGroupNode *, unsigned)
{ {
m_os << "]}"; // Close children array and self m_os << "]}"; // Close children array and self
if (m_humanReadable) if (m_parameters.humanReadable())
m_os << '\n'; m_os << '\n';
} }
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include <iosfwd> #include <iosfwd>
std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p); std::ostream &operator<<(std::ostream &, const DEBUG_SYMBOL_PARAMETERS&p);
...@@ -42,6 +43,31 @@ class SymbolGroupNodeVisitor; ...@@ -42,6 +43,31 @@ class SymbolGroupNodeVisitor;
class SymbolGroup; class SymbolGroup;
struct SymbolGroupValueContext; struct SymbolGroupValueContext;
// All parameters for dumping in one struct.
struct DumpParameters
{
typedef std::map<std::string, int> FormatMap; // type or iname to format
enum DumpFlags
{
DumpHumanReadable = 0x1,
DumpComplexDumpers = 0x2
};
DumpParameters();
bool humanReadable() const { return dumpFlags & DumpHumanReadable; }
// Helper to decode format option arguments.
static FormatMap decodeFormatArgument(const std::string &f);
bool recode(const std::string &type, const std::string &iname,
const SymbolGroupValueContext &ctx,
std::wstring *value, int *encoding) const;
int format(const std::string &type, const std::string &iname) const;
unsigned dumpFlags;
FormatMap typeFormats;
FormatMap individualFormats;
};
// Thin wrapper around a symbol group entry. Provides accessors for fixed-up // Thin wrapper around a symbol group entry. Provides accessors for fixed-up
// symbol group value and a dumping facility triggered by dump()/displayValue() // symbol group value and a dumping facility triggered by dump()/displayValue()
// calling dumpSimpleType() based on SymbolGroupValue expressions. These values // calling dumpSimpleType() based on SymbolGroupValue expressions. These values
...@@ -70,6 +96,7 @@ public: ...@@ -70,6 +96,7 @@ public:
ExpandedByDumper = 0x10, ExpandedByDumper = 0x10,
AdditionalSymbol = 0x20 // Introduced by addSymbol, should not be visible AdditionalSymbol = 0x20 // Introduced by addSymbol, should not be visible
}; };
typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector; typedef std::vector<DEBUG_SYMBOL_PARAMETERS> SymbolParameterVector;
typedef std::vector<SymbolGroupNode *> SymbolGroupNodePtrVector; typedef std::vector<SymbolGroupNode *> SymbolGroupNodePtrVector;
typedef SymbolGroupNodePtrVector::iterator SymbolGroupNodePtrVectorIterator; typedef SymbolGroupNodePtrVector::iterator SymbolGroupNodePtrVectorIterator;
...@@ -102,7 +129,7 @@ public: ...@@ -102,7 +129,7 @@ public:
SymbolGroup *symbolGroup() const { return m_symbolGroup; } SymbolGroup *symbolGroup() const { return m_symbolGroup; }
// I/O: Gdbmi dump for Visitors // I/O: Gdbmi dump for Visitors
void dump(std::ostream &str, const SymbolGroupValueContext &ctx); void dump(std::ostream &str, const DumpParameters &p, const SymbolGroupValueContext &ctx);
// I/O: debug for Visitors // I/O: debug for Visitors
void debug(std::ostream &os, unsigned verbosity, unsigned depth) const; void debug(std::ostream &os, unsigned verbosity, unsigned depth) const;
...@@ -202,10 +229,11 @@ public: ...@@ -202,10 +229,11 @@ public:
~SymbolGroup(); ~SymbolGroup();
// Dump all // Dump all
std::string dump(const SymbolGroupValueContext &ctx, bool humanReadable = false) const; std::string dump(const SymbolGroupValueContext &ctx,
const DumpParameters &p = DumpParameters()) const;
// Expand node and dump // Expand node and dump
std::string dump(const std::string &iname, const SymbolGroupValueContext &ctx, std::string dump(const std::string &iname, const SymbolGroupValueContext &ctx,
bool humanReadable, std::string *errorMessage); const DumpParameters &p, std::string *errorMessage);
std::string debug(const std::string &iname = std::string(), unsigned verbosity = 0) const; std::string debug(const std::string &iname = std::string(), unsigned verbosity = 0) const;
unsigned frame() const { return m_frame; } unsigned frame() const { return m_frame; }
...@@ -274,15 +302,15 @@ class DumpSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor { ...@@ -274,15 +302,15 @@ class DumpSymbolGroupNodeVisitor : public SymbolGroupNodeVisitor {
public: public:
explicit DumpSymbolGroupNodeVisitor(std::ostream &os, explicit DumpSymbolGroupNodeVisitor(std::ostream &os,
const SymbolGroupValueContext &context, const SymbolGroupValueContext &context,
bool humanReadable); const DumpParameters &parameters = DumpParameters());
private: private:
virtual VisitResult visit(SymbolGroupNode *node, unsigned child, unsigned depth); virtual VisitResult visit(SymbolGroupNode *node, unsigned child, unsigned depth);
virtual void childrenVisited(const SymbolGroupNode * node, unsigned depth); virtual void childrenVisited(const SymbolGroupNode * node, unsigned depth);
std::ostream &m_os; std::ostream &m_os;
const bool m_humanReadable;
const SymbolGroupValueContext &m_context; const SymbolGroupValueContext &m_context;
const DumpParameters &m_parameters;
bool m_visitChildren; bool m_visitChildren;
}; };
......
...@@ -653,13 +653,26 @@ void CdbEngine::updateWatchData(const Debugger::Internal::WatchData &dataIn, ...@@ -653,13 +653,26 @@ void CdbEngine::updateWatchData(const Debugger::Internal::WatchData &dataIn,
updateLocalVariable(dataIn.iname); updateLocalVariable(dataIn.iname);
} }
void CdbEngine::addLocalsOptions(ByteArrayInputStream &str) const
{
if (debuggerCore()->boolSetting(UseDebuggingHelpers))
str << blankSeparator << "-c";
const QByteArray typeFormats = watchHandler()->typeFormatRequests();
if (!typeFormats.isEmpty())
str << blankSeparator << "-T " << typeFormats;
const QByteArray individualFormats = watchHandler()->individualFormatRequests();
if (!individualFormats.isEmpty())
str << blankSeparator << "-I " << individualFormats;
}
void CdbEngine::updateLocalVariable(const QByteArray &iname) void CdbEngine::updateLocalVariable(const QByteArray &iname)
{ {
const int stackFrame = stackHandler()->currentIndex(); const int stackFrame = stackHandler()->currentIndex();
if (stackFrame >= 0) { if (stackFrame >= 0) {
QByteArray localsArguments; QByteArray localsArguments;
ByteArrayInputStream str(localsArguments); ByteArrayInputStream str(localsArguments);
str << stackFrame << ' ' << iname; addLocalsOptions(str);
str << blankSeparator << stackFrame << ' ' << iname;
postExtensionCommand("locals", localsArguments, 0, &CdbEngine::handleLocals); postExtensionCommand("locals", localsArguments, 0, &CdbEngine::handleLocals);
} else { } else {
qWarning("Internal error; no stack frame in updateLocalVariable"); qWarning("Internal error; no stack frame in updateLocalVariable");
...@@ -973,6 +986,7 @@ void CdbEngine::activateFrame(int index) ...@@ -973,6 +986,7 @@ void CdbEngine::activateFrame(int index)
str << e; str << e;
} }
} }
addLocalsOptions(str);
// Uninitialized variables if desired // Uninitialized variables if desired
if (debuggerCore()->boolSetting(UseCodeModel)) { if (debuggerCore()->boolSetting(UseCodeModel)) {
QStringList uninitializedVariables; QStringList uninitializedVariables;
...@@ -1299,8 +1313,10 @@ void CdbEngine::handleSessionIdle(const QByteArray &message) ...@@ -1299,8 +1313,10 @@ void CdbEngine::handleSessionIdle(const QByteArray &message)
notifyInferiorSpontaneousStop(); notifyInferiorSpontaneousStop();
} }
// Start sequence to get all relevant data. Hack: Avoid module reload? // Start sequence to get all relevant data. Hack: Avoid module reload?
unsigned sequence = CommandListStack|CommandListRegisters|CommandListThreads; unsigned sequence = CommandListStack;
if (modulesHandler()->modules().size() == 0) if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_REGISTER)))
sequence |= CommandListRegisters;
if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_MODULES)))
sequence |= CommandListModules; sequence |= CommandListModules;
postCommandSequence(sequence); postCommandSequence(sequence);
// Report stop reason (GDBMI) // Report stop reason (GDBMI)
......
...@@ -45,6 +45,7 @@ class DisassemblerViewAgent; ...@@ -45,6 +45,7 @@ class DisassemblerViewAgent;
struct CdbBuiltinCommand; struct CdbBuiltinCommand;
struct CdbExtensionCommand; struct CdbExtensionCommand;
struct CdbOptions; struct CdbOptions;
class ByteArrayInputStream;
class CdbEngine : public Debugger::DebuggerEngine class CdbEngine : public Debugger::DebuggerEngine
{ {
...@@ -174,6 +175,7 @@ private: ...@@ -174,6 +175,7 @@ private:
QString normalizeFileName(const QString &f); QString normalizeFileName(const QString &f);
void updateLocalVariable(const QByteArray &iname); void updateLocalVariable(const QByteArray &iname);
int elapsedLogTime() const; int elapsedLogTime() const;
void addLocalsOptions(ByteArrayInputStream &s) const;
const QByteArray m_creatorExtPrefix; const QByteArray m_creatorExtPrefix;
const QByteArray m_tokenPrefix; const QByteArray m_tokenPrefix;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment