23
23
24
24
#include < boost/property_tree/xml_parser.hpp>
25
25
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
+
26
31
// / tree decoder for valgrind XML output
27
32
class ValgrindTreeDecoder : public AbstractTreeDecoder {
28
33
public:
@@ -36,12 +41,101 @@ class ValgrindTreeDecoder: public AbstractTreeDecoder {
36
41
Defect defPrototype = Defect(" VALGRIND_WARNING" );
37
42
};
38
43
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
+
39
110
void ValgrindTreeDecoder::readRoot (
40
- const pt::ptree **pDefList,
41
- const pt::ptree *root)
111
+ const pt::ptree **pDefList,
112
+ const pt::ptree *root)
42
113
{
43
- // TODO: read path to the binary and command-line args
114
+ // valgrind reports will be at the same level in the XML tree
44
115
*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 ¬eEvt = 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 ;
45
139
}
46
140
47
141
bool ValgrindTreeDecoder::readNode (Defect *pDef, pt::ptree::const_iterator defIter)
@@ -57,9 +151,8 @@ bool ValgrindTreeDecoder::readNode(Defect *pDef, pt::ptree::const_iterator defIt
57
151
58
152
// initialize the key event
59
153
def.keyEventIdx = def.events .size ();
60
- def.events .push_back (DefEvent ());
154
+ def.events .push_back (DefEvent (" warning " ));
61
155
DefEvent &keyEvent = def.events .back ();
62
- keyEvent.event = " warning" ;
63
156
64
157
// read "kind" of the report
65
158
const pt::ptree &defNode = defIter->second ;
0 commit comments