LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
DebugUtils.cxx
Go to the documentation of this file.
2 
3 // C/C++ standard libraries
4 #include <istream>
5 #include <sstream>
6 
7 //-----------------------------------------------------------------------------
8 //--- lar::debug::CallInfo_t
9 //---
10 bool lar::debug::CallInfo_t::ParseString(std::string const& s)
11 {
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 '+':
45  case '-':
46  functionStr.second = i;
47  if (s[i] == '+') ++i;
48  offsetStr.first = i;
49  i = s.find_first_of("()", ++i);
50  if (i == boo) return false;
51  switch (s[i]) {
52  case '(': continue;
53  case ')': offsetStr.second = i; break;
54  } // switch (inner)
55  break;
56  case ')': functionStr.second = i; break;
57  } // switch (outer)
58 
59  // finish with the address
60  i = s.find_first_of("([", ++i);
61  if (i == boo) break;
62  if (s[i] == '(') continue;
63  addressStr.first = ++i;
64 
65  i = s.find_first_of("(]", i);
66  if (s[i] == '(') continue;
67  addressStr.second = i;
68 
69  break;
70  } // while (for ever)
71 
72  setAll(s, addressStr, libraryStr, functionStr, offsetStr);
73  return true;
74 
75  //----------------------------------------------------------------------------
76 #elif (__APPLE__)
77  // expected format:
78  // N libraryName address mangledFunction + offset
79  // "+ offset" is considered optional
80  original = s;
81  while (true) {
82  std::istringstream sstr(s);
83  int n;
84  char plus;
85  sstr >> n >> libraryName >> std::hex >> address >> std::dec >> mangledFunctionName;
86 
87  // optional offset
88  if (sstr.fail()) break; // an error somewhere: bail out
89  sstr >> plus;
90  if (sstr.fail())
91  offset = 0;
92  else {
93  if (plus != '+') break;
94  sstr >> offset;
95  if (sstr.fail()) break;
96  }
97 
99  return true;
100  } // while
101  address = nullptr;
102  libraryName.clear();
103  mangledFunctionName.clear();
104  functionName.clear();
105  offset = 0;
106  return false;
107  //----------------------------------------------------------------------------
108 #else
109 #error("I am not on Linux nor on OSX. Hard to believe.")
110 #endif
111 } // lar::debug::CallInfo_t::ParseString()
112 
113 void lar::debug::CallInfo_t::setAll(std::string const& s,
114  range_t addressStr,
115  range_t libraryStr,
116  range_t functionStr,
117  range_t offsetStr)
118 {
119  original = s;
120 
121  libraryName = extract(s, libraryStr);
122 
123  mangledFunctionName = extract(s, functionStr);
125 
126  if (!emptyRange(addressStr)) {
127  std::istringstream sstr(extract(s, addressStr));
128  sstr >> address;
129  }
130 
131  if (emptyRange(offsetStr))
132  offset = 0;
133  else {
134  auto offsetRange = offsetStr;
135  if (!emptyRange(offsetRange)) {
136  bool neg = (s[offsetRange.first] == '-');
137  std::istringstream sstr;
138  if (neg || (s[offsetRange.first] == '+')) ++offsetRange.first;
139  if (s.substr(offsetRange.first, 2) == "0x") {
140  offsetRange.first += 2;
141  sstr.setf(std::ios::hex);
142  }
143  sstr.str(extract(s, offsetRange));
144  sstr >> offset;
145  if (neg) offset = -offset;
146  }
147  } // if offset ... else
148 
149 } // lar::debug::CallInfo_t::setAll()
150 
151 //-----------------------------------------------------------------------------
std::string original
String from the backtrace, unparsed.
Definition: DebugUtils.h:90
static std::string extract(std::string const &s, range_t const &r)
Translates a range into a string.
Definition: DebugUtils.h:102
std::string functionName
Parsed function name, demangled.
Definition: DebugUtils.h:92
std::string libraryName
Parsed library name.
Definition: DebugUtils.h:91
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:113
void * address
Function address.
Definition: DebugUtils.h:94
void demangleFunction()
Runs the demangler and stores the result.
Definition: DebugUtils.h:108
if(nlines<=0)
bool ParseString(std::string const &s)
Returns whether the translation was complete (offset is optional!).
Definition: DebugUtils.cxx:10
std::pair< size_t, size_t > range_t
Definition: DebugUtils.h:62
static bool emptyRange(range_t const &r)
Returns whether the range is empty or invalid.
Definition: DebugUtils.h:99
Functions to help debugging by instrumenting code.
std::string mangledFunctionName
Parsed function name, unprocessed.
Definition: DebugUtils.h:93
Char_t n[5]
std::ptrdiff_t offset
Instruction pointer offset.
Definition: DebugUtils.h:95