Skip to content

Commit 585bc60

Browse files
committed
xml-parser: read PID and cmd-line captured by valgrind
1 parent 03a45de commit 585bc60

File tree

2 files changed

+104
-6
lines changed

2 files changed

+104
-6
lines changed

src/defect.hh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ struct DefEvent {
5555
int verbosityLevel = 0;
5656

5757
DefEvent() { }
58+
59+
explicit DefEvent(const std::string &event):
60+
event(event)
61+
{
62+
}
5863
};
5964

6065
inline bool cmpEvents(bool *pResult, const DefEvent &a, const DefEvent &b)
@@ -92,7 +97,7 @@ struct Defect {
9297

9398
Defect() { }
9499

95-
explicit Defect(const std::string checker):
100+
explicit Defect(const std::string &checker):
96101
checker(checker)
97102
{
98103
}

src/xml-parser.cc

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323

2424
#include <boost/property_tree/xml_parser.hpp>
2525

26+
// executable of the dynamic linker (used as ELF interpreter)
27+
#ifndef LD_LINUX_SO
28+
# define LD_LINUX_SO "/lib64/ld-linux-x86-64.so.2"
29+
#endif
30+
2631
/// tree decoder for valgrind XML output
2732
class ValgrindTreeDecoder: public AbstractTreeDecoder {
2833
public:
@@ -36,12 +41,101 @@ class ValgrindTreeDecoder: public AbstractTreeDecoder {
3641
Defect defPrototype = Defect("VALGRIND_WARNING");
3742
};
3843

44+
/// hide explicit invocation of dynamic linker from command-line args
45+
bool /* continue */ skipLdArgs(
46+
std::string *pExe,
47+
pt::ptree::const_iterator *pIt,
48+
const pt::ptree::const_iterator itEnd)
49+
{
50+
if (*pExe != LD_LINUX_SO)
51+
return /* continue */ true;
52+
53+
for (bool skipArg = false; *pIt != itEnd; ++(*pIt)) {
54+
if (skipArg) {
55+
skipArg = false;
56+
continue;
57+
}
58+
59+
const std::string argVal = (*pIt)->second.get_value<std::string>();
60+
if (argVal == "--preload")
61+
goto skip_arg;
62+
63+
if (argVal == "--argv0")
64+
goto skip_arg;
65+
66+
// record path of the real binary being executed
67+
*pExe = argVal;
68+
++(*pIt);
69+
return /* continue */ (itEnd != *pIt);
70+
71+
skip_arg:
72+
skipArg = true;
73+
}
74+
75+
return /* break */ false;
76+
}
77+
78+
/// read command-line of the executed program
79+
void readExeArgs(
80+
std::string *pExe,
81+
std::string *pArgs,
82+
const pt::ptree *root)
83+
{
84+
const pt::ptree *argsNode;
85+
if (!findChildOf(&argsNode, *root, "args"))
86+
return;
87+
88+
const pt::ptree *argvNode;
89+
if (!findChildOf(&argvNode, *argsNode, "argv"))
90+
return;
91+
92+
// read name of executable
93+
*pExe = valueOf<std::string>(*argvNode, "exe", *pExe);
94+
95+
// read command-line args
96+
pt::ptree::const_iterator it;
97+
for (it = argvNode->begin(); argvNode->end() != it; ++it) {
98+
if (it->first != "arg")
99+
// skip this node
100+
continue;
101+
102+
if (!skipLdArgs(pExe, &it, argvNode->end()))
103+
break;
104+
105+
*pArgs += " ";
106+
*pArgs += it->second.get_value<std::string>();
107+
}
108+
}
109+
39110
void ValgrindTreeDecoder::readRoot(
40-
const pt::ptree **pDefList,
41-
const pt::ptree *root)
111+
const pt::ptree **pDefList,
112+
const pt::ptree *root)
42113
{
43-
// TODO: read path to the binary and command-line args
114+
// valgrind reports will be at the same level in the XML tree
44115
*pDefList = root;
116+
117+
const int pid = valueOf<int>(*root, "pid", 0);
118+
if (!pid)
119+
// insufficient data
120+
return;
121+
122+
// read command-line
123+
std::string exe = "<unknown>";
124+
std::string args;
125+
readExeArgs(&exe, &args, root);
126+
127+
// create a note event in the defect prototype
128+
this->defPrototype.events.push_back(DefEvent("note"));
129+
DefEvent &noteEvt = this->defPrototype.events.back();
130+
noteEvt.fileName = exe;
131+
132+
// record PID and command-line args
133+
std::ostringstream str;
134+
str << "while executing process " << pid;
135+
if (!args.empty())
136+
str << " with arguments:" << args;
137+
noteEvt.msg = str.str();
138+
noteEvt.verbosityLevel = /* note */ 1;
45139
}
46140

47141
bool ValgrindTreeDecoder::readNode(Defect *pDef, pt::ptree::const_iterator defIter)
@@ -57,9 +151,8 @@ bool ValgrindTreeDecoder::readNode(Defect *pDef, pt::ptree::const_iterator defIt
57151

58152
// initialize the key event
59153
def.keyEventIdx = def.events.size();
60-
def.events.push_back(DefEvent());
154+
def.events.push_back(DefEvent("warning"));
61155
DefEvent &keyEvent = def.events.back();
62-
keyEvent.event = "warning";
63156

64157
// read "kind" of the report
65158
const pt::ptree &defNode = defIter->second;

0 commit comments

Comments
 (0)