From 6ee0d135e6abfd21c6fd3ba8c5da1133b10a69d3 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sat, 17 Sep 2016 19:22:56 +0200 Subject: [PATCH] Handle pointer-to-member function values that are virtual functions. A pointer-to-member function can hold a pointer to a virtual member function. Parse such a value. --- kdbg/gdbdriver.cpp | 65 +++++++++++++++++++++++++++++++++++++++---- kdbg/testprogs/multibrkpt.cpp | 9 ++++++ kdbg/testprogs/testfile.cpp | 5 +++- 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/kdbg/gdbdriver.cpp b/kdbg/gdbdriver.cpp index e4234c6..cdd5009 100644 --- a/kdbg/gdbdriver.cpp +++ b/kdbg/gdbdriver.cpp @@ -1171,13 +1171,53 @@ static void skipNestedWithString(const char*& s, char opening, char closing) s = p; } -inline void skipName(const char*& p) +static void skipName(const char*& p) { // allow : (for enumeration values) and $ and . (for _vtbl.) while (isalnum(*p) || *p == '_' || *p == ':' || *p == '$' || *p == '.') p++; } +static void skipFunctionName(const char*& p) +{ + while (*p) + { + if (*p == '<') { + // skip template parameter list + skipNestedAngles(p); + } else if (*p == '(') { + // this skips "(anonymous namespace)" as well as the formal + // parameter list of the containing function if this is a member + // of a nested class + skipNestedWithString(p, '(', ')'); + } else if (isalnum(*p) || *p == '_' || *p == ':') { + const char* start = p; + skipName(p); + // check for operator + if (p-start >= 8 && + strncmp(p-8, "operator", 8) == 0 && + // do not mistake this as the tail of some identifier + (p-start == 8 || !(isalnum(p[-9]) || p[-9] == '_'))) + { + // skip forward until we find the opening parenthesis + // this catches both operator()(...) as well as + // type conversion operators, e.g. + // operator char const*() const + // operator void(*)() + while (*p && *p != '(') + p++; + } + } else if (strncmp(p, " const", 6) == 0 && + // must not mistake "const" as the beginning of + // a subequent identifier + !isalnum(p[6]) && p[6] != '_') { + p += 6; + } else { + break; + } + } +} + static bool parseName(const char*& s, QString& name, VarTree::NameKind& kind) { kind = VarTree::NKplain; @@ -1283,6 +1323,8 @@ repeat: // (E *) 0xbffff450 // red // &parseP (HTMLClueV *, char *) + // &virtual table offset 0, this adjustment 140737488346016 + // &virtual Dl::operator char const*() const // Variable "x" is not available. // The value of variable 'x' is distributed... // -nan(0xfffff081defa0) @@ -1373,12 +1415,23 @@ repeat: checkMultiPart = p[1] == '\''; skipString(p); } else if (*p == '&') { - // function pointer p++; - skipName(p); - skipSpace(p); - if (*p == '(') { - skipNested(p, '(', ')'); + if (strncmp(p, "virtual ", 8) == 0) { + p += 8; + if (strncmp(p, "table offset ", 13) == 0) { + p += 13; + skipDecimal(p); + checkMultiPart = true; + } else { + skipFunctionName(p); + } + } else { + // function pointer + skipName(p); + skipSpace(p); + if (*p == '(') { + skipNested(p, '(', ')'); + } } } else if (strncmp(p, "Variable \"", 10) == 0) { // Variable "x" is not available. diff --git a/kdbg/testprogs/multibrkpt.cpp b/kdbg/testprogs/multibrkpt.cpp index d2d15ba..7a71885 100644 --- a/kdbg/testprogs/multibrkpt.cpp +++ b/kdbg/testprogs/multibrkpt.cpp @@ -14,6 +14,9 @@ struct Templated void PrintV() { cout << __func__ << " val=" << val << endl; } + virtual void PrintName(int,int) const { + cout << __func__ << endl; + } }; struct MostDerived : Templated, Templated @@ -28,6 +31,9 @@ struct MostDerived : Templated, Templated Templated::PrintV(); Templated::PrintV(); } + virtual void PrintName(int,int) const { + cout << __func__ << endl; + } }; int main() @@ -38,10 +44,13 @@ int main() void (Templated::*pmf1)(); void (Templated::*pmf2)(); void (MostDerived::*pmf3)(); + void (MostDerived::*pmf4)(int,int) const; pmf1 = static_cast::*)()>(&MostDerived::PrintV); // the following has a non-trivial "this adjustment" pmf2 = static_cast::*)()>(&MostDerived::PrintV); pmf3 = &Templated::PrintV; + pmf4 = &Templated::PrintName; bothobj.PrintV(); + (bothobj.*pmf4)(2, -5); } diff --git a/kdbg/testprogs/testfile.cpp b/kdbg/testprogs/testfile.cpp index 18b9ab5..e747c37 100644 --- a/kdbg/testprogs/testfile.cpp +++ b/kdbg/testprogs/testfile.cpp @@ -38,9 +38,10 @@ public: Dl(int r); virtual int f(int x); int operator()(const QString& x, int& y) const; - operator const char*() { return 0; } + virtual operator const char*() const { return 0; } operator PtrFunc*(); void takeACStr(const char* cstr); + double m; }; namespace A { @@ -185,6 +186,8 @@ int main(int argc, char* argv[]) int n = 83; d1(strref, n); PtrFunc* ppf = d1; + const char* (Dl::*pmf)() const = &Dl::operator const char*; + double (Dl::*pmv) = &Dl::m; d1.takeACStr(globarstr); } -- 2.11.4.GIT