DebugUtils.cxx
Go to the documentation of this file.
1 
2 #include "CoreUtils/DebugUtils.h"
3 
4 // C/C++ standard libraries
5 #include <sstream>
6 
7 
8 //-----------------------------------------------------------------------------
9 //--- gar::debug::CallInfo_t
10 //---
12 
13  //----------------------------------------------------------------------------
14 #if (__linux__)
15  constexpr auto boo = std::string::npos;
16  range_t libraryStr { boo, boo };
17  range_t addressStr { boo, boo };
18  range_t functionStr { boo, boo };
19  range_t offsetStr { boo, boo };
20  setAll(s, addressStr, libraryStr, functionStr, offsetStr);
21 
22  // expected format:
23  // libraryName(mangledSymbol+offset) [hexAddress]
24  // (+offset optional)
25 
26  size_t i = s.find('(');
27  if (i == boo) return false;
28  libraryStr.first = 0;
29  while (true) {
30  // at all time, if we find a '(', we start over
31  // since a '(' can only be after the library name
32 
33  libraryStr = { 0U, i };
34  addressStr = { boo, boo };
35  functionStr = { boo, boo };
36  offsetStr = { boo, boo };
37 
38  functionStr.first = ++i;
39 
40  i = s.find_first_of("(+-)", i);
41  if (i == boo) return false;
42  switch (s[i]) {
43  case '(': continue;
44  case '+': case '-':
45  functionStr.second = i;
46  if (s[i] == '+') ++i;
47  offsetStr.first = i;
48  i = s.find_first_of("()", ++i);
49  if (i == boo) return false;
50  switch (s[i]) {
51  case '(': continue;
52  case ')':
53  offsetStr.second = i;
54  break;
55  } // switch (inner)
56  break;
57  case ')':
58  functionStr.second = i;
59  break;
60  } // switch (outer)
61 
62  // finish with the address
63  i = s.find_first_of("([", ++i);
64  if (i == boo) break;
65  if (s[i] == '(') continue;
66  addressStr.first = ++i;
67 
68  i = s.find_first_of("(]", i);
69  if (s[i] == '(') continue;
70  addressStr.second = i;
71 
72  break;
73  } // while (for ever)
74 
75  setAll(s, addressStr, libraryStr, functionStr, offsetStr);
76  return true;
77 
78  //----------------------------------------------------------------------------
79 #elif (__APPLE__)
80  // expected format:
81  // N libraryName address mangledFunction + offset
82  // "+ offset" is considered optional
83  original = s;
84  while (true) {
85  std::istringstream sstr(s);
86  int n;
87  char plus;
88  sstr
89  >> n
90  >> libraryName
91  >> std::hex >> address >> std::dec
93 
94  // optional offset
95  if (sstr.fail()) break; // an error somewhere: bail out
96  sstr >> plus;
97  if (sstr.fail()) offset = 0;
98  else {
99  if (plus != '+') break;
100  sstr >> offset;
101  if (sstr.fail()) break;
102  }
103 
105  return true;
106  } // while
107  address = nullptr;
108  libraryName.clear();
109  mangledFunctionName.clear();
110  functionName.clear();
111  offset = 0;
112  return false;
113  //----------------------------------------------------------------------------
114 #else
115 # error("I am not on Linux nor on OSX. Hard to believe.")
116 #endif
117 } // gar::debug::CallInfo_t::ParseString()
118 
119 
120 
122  std::string const& s,
123  range_t addressStr, range_t libraryStr,
124  range_t functionStr, range_t offsetStr
125  )
126 {
127  original = s;
128 
129  libraryName = extract(s, libraryStr);
130 
131  mangledFunctionName = extract(s, functionStr);
133 
134  if (!emptyRange(addressStr)) {
135  std::istringstream sstr(extract(s, addressStr));
136  sstr >> address;
137  }
138 
139  if (emptyRange(offsetStr)) offset = 0;
140  else {
141  auto offsetRange = offsetStr;
142  if (!emptyRange(offsetRange)) {
143  bool neg = (s[offsetRange.first] == '-');
144  std::istringstream sstr;
145  if (neg || (s[offsetRange.first] == '+')) ++offsetRange.first;
146  if (s.substr(offsetRange.first, 2) == "0x") {
147  offsetRange.first += 2;
148  sstr.setf(std::ios::hex);
149  }
150  sstr.str(extract(s, offsetRange));
151  sstr >> offset;
152  if (neg) offset = -offset;
153  }
154  } // if offset ... else
155 
156 } // gar::debug::CallInfo_t::setAll()
157 
158 //-----------------------------------------------------------------------------
void * address
function address
Definition: DebugUtils.h:96
bool ParseString(std::string const &s)
Returns whether the translation was complete (offset is optional!)
Definition: DebugUtils.cxx:11
std::string libraryName
parsed library name
Definition: DebugUtils.h:93
void demangleFunction()
Runs the demangler and stores the result.
Definition: DebugUtils.h:109
std::string string
Definition: nybbler.cc:12
std::pair< size_t, size_t > range_t
Definition: DebugUtils.h:63
std::ptrdiff_t offset
instruction pointer offset
Definition: DebugUtils.h:97
QTextStream & hex(QTextStream &s)
std::string original
string from the backtrace, unparsed
Definition: DebugUtils.h:92
static bool emptyRange(range_t const &r)
Returns whether the range is empty or invalid.
Definition: DebugUtils.h:102
std::string functionName
parsed function name, demangled
Definition: DebugUtils.h:94
std::string mangledFunctionName
parsed function name, unprocessed
Definition: DebugUtils.h:95
std::void_t< T > n
void setAll(std::string const &s, range_t addressStr, range_t libraryStr, range_t functionStr, range_t offsetStr)
Fills the information from an original string and parsed ranges.
Definition: DebugUtils.cxx:121
QTextStream & dec(QTextStream &s)
if(!yymsg) yymsg
static QCString * s
Definition: config.cpp:1042
static std::string extract(std::string const &s, range_t const &r)
Translates a range into a string.
Definition: DebugUtils.h:105