Merge pull request #298 from teco-kit/master
[dyninst.git] / dynC_API / doc / 1-DynC.tex
1 \section{DynC API}
2 \subsection{Motivation}
3 Dyninst is a powerful instrumentation tool, but specifying instrumentation code
4 (known as an Abstract Syntax Tree) in the \code{BPatch\_snippet} language can be
5 cumbersome. DynC API answers these concerns, enabling a programmer to easily and
6 quickly build \code{BPatch\_snippets} using a simple C-like language. Other
7 advantages to specifying \code{BPatch\_snippets} using dynC include cleaner,
8 more readable mutator code, automatic variable handling, and runtime-compiled
9 snippets.
10
11 As a motivating example, the following implements a function tracer that
12 notifies the user when entering and exiting functions, and keeps track of the
13 number of times each function is called.
14
15 \subsubsection{Dyninst API}
16
17 When creating a function tracer using the Dyninst API, the programmer must
18 perform many discrete lookups and create many \code{BPatch\_snippet objects},
19 which are then combined and inserted into the mutatee.
20
21 \noindent Look up \code{printf}:
22
23 \lstset{language=[GNU]C++,basicstyle=\fontfamily{fvm}\selectfont\small}
24 \lstset{numbers=left, numberstyle=\tiny, stepnumber=5, numbersep=5pt}
25 \lstset{showstringspaces=false}
26 \begin{lstlisting}
27   std::vector<BPatch_function *> *printf_func;
28   appImage->findFunction("printf", printf_func);
29   BPatch_function *BPF_printf = printf_func[0];
30 \end{lstlisting}
31
32 \noindent Create each \code{printf} pattern:
33 \begin{lstlisting}
34   BPatch_constExpr entryPattern("Entering %s, called %d times.\n");
35   BPatch_constExpr exitPattern("Exiting %s.\n");
36 \end{lstlisting}
37
38 \noindent \textbf{For each function, do the following:}
39
40 Create snippet vectors:
41 \begin{lstlisting}
42      std::vector<BPatch_snippet *> entrySnippetVect;
43      std::vector<BPatch_snippet *> exitSnippetVect;
44 \end{lstlisting}
45
46 Create the \code{intCounter} global variable:
47 \begin{lstlisting}
48      appProc->malloc(appImage->findType("int"), std::string("intCounter"));
49 \end{lstlisting}
50
51 Get the name of the function:
52 \begin{lstlisting}
53      char fName[128];
54      BPatch_constExpr funcName(functions[i]->getName(fName, 128));
55 \end{lstlisting}
56
57 Build the entry \code{printf}:
58 \begin{lstlisting}
59      std::vector<BPatch_snippet *> entryArgs;
60      entryArgs.push_back(entryPattern);
61      entryArgs.push_back(funcName);
62      entryArgs.push_back(intCounter);
63 \end{lstlisting}
64
65 Build the exit \code{printf}:
66 \begin{lstlisting}
67      std::vector<BPatch_snippet *> exitArgs;
68      exitArgs.push_back(exitPattern);
69      exitArgs.push_back(funcName);
70 \end{lstlisting}
71
72 Add \code{printf} to the snippet:
73 \begin{lstlisting}
74      entrySnippetVect.push_back(BPatch_functionCallExpr(*printf_func, entryArgs));
75      exitSnippetVect.push_back(BPatch_functionCallExpr(*printf_func, exitArgs));
76 \end{lstlisting}
77
78 Increment the counter:
79 \begin{lstlisting}
80      BPatch_arithExpr addOne(BPatch_assign, *intCounter, 
81             BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(1)));
82 \end{lstlisting}
83
84 Add increment to the entry snippet:
85 \begin{lstlisting}
86      entrySnippetVect.push_back(&addOne);
87 \end{lstlisting}
88
89 Insert the snippets:
90 \begin{lstlisting}
91      appProc->insertSnippet(*entrySnippetVect, functions[i]->findPoint(BPatch_entry));
92      appProc->insertSnippet(*exitSnippetVect, functions[i]->findPoint(BPatch_exit));
93 \end{lstlisting}
94
95 \begin{center} 
96 %\rule{6.5in}{1pt}
97 \end{center}
98
99 \begin{comment}
100   // find points
101   std::vector<BPatch_point *> *entryPoints = functions[i]->findPoint(BPatch_entry);
102   std::vector<BPatch_point *> *exitPoints = functions[i]->findPoint(BPatch_exit);
103
104   // insert snippets
105   appProc->insertSnippet(BPatch_sequence(entrySnippetVect), entryPoints);
106   appProc->insertSnippet(BPatch_sequence(exitSnippetVect), exitPoints);
107 }
108
109   // run mutatee
110   appProc->continueExecution();
111 \end{comment}
112
113 \pagebreak
114
115
116 \subsubsection{DynC API}
117
118 A function tracer is much easier to build in DynC API, especially if reading dynC code from file. Storing dynC code in external files not only cleans up mutator code, but also allows the programmer to modify snippets without recompiling.
119
120 \vspace{0.5cm}
121
122 %\begin{center} 
123 %\rule{6.5in}{1pt}
124 %\end{center}
125
126 \noindent In this example, the files \code{myEntryDynC.txt} and \code{myExitDynC.txt} contain dynC code:
127
128 %\lstset{frame=single}
129 \begin{lstlisting}
130   // myEntryDynC.txt
131   static int intCounter;
132   printf("Entering %s, called %d times.\n", dyninst`function_name, intCounter++);
133 \end{lstlisting}
134
135 \begin{lstlisting}
136   // myExitDynC.txt
137   printf("Leaving %s.\n", dyninst`function_name);
138 \end{lstlisting}
139
140 %\lstset{frame=none}
141
142 \noindent The code to read, build, and insert the snippets would look something like the following:
143
144 \noindent First open files:
145 \begin{lstlisting}
146   FILE *entryFile = fopen("myEntryDynC.txt", "r");
147   FILE *exitFile = fopen("myExitDynC.txt", "r");
148 \end{lstlisting}
149
150 \noindent Next call DynC API with each function's entry and exit points:
151 \begin{lstlisting}
152   BPatch_snippet *entrySnippet = 
153        dynC_API::createSnippet(entryFile, entryPoint, "entrySnippet");
154   BPatch_snippet *exitSnippet = 
155        dynC_API::createSnippet(exitFile, exitPoint, "exitSnippet");
156 \end{lstlisting}
157
158 \noindent Finally insert the snippets at each function's entry and exit points:
159 \begin{lstlisting}
160   appProc->insertSnippet(*entrySnippet, entryPoint);
161   appProc->insertSnippet(*exitSnippet, exitPoint);
162 \end{lstlisting}
163
164 \begin{comment}
165 \begin{lstlisting}
166 /*** Create Snippet ***/
167 // build entryString
168 std::stringstream entryString;
169 entryString << "static int intCounter;" << endl;
170 entryString << "inf`printf(\"Entering %s, which has been called %d times.\\n\"";
171 entryString << ",dyninst`function_name, intCounter);";
172
173 // call to DynC API
174 BPatch_snippet *entrySnippet = 
175        dynC_API::createSnippet(entryString.str().c_str(), entryPoint, "entrySnippet");
176
177 // build exitString
178 std::stringstream exitString;
179 exitString << "inf`printf(\"Exiting %s.\\n\", dyninst`function_name);";
180
181 // call to DynC API
182 BPatch_snippet *exitSnippet = 
183        dynC_API::createSnippet(exitString.str().c_str(), app, "exitSnippet");
184 /*** Finish Snippet ***/
185
186 // find all entry and exit points
187 std::vector<BPatch_point *> * entry_points = (*functions)[0]->findPoint(BPatch_entry);
188 std::vector<BPatch_point *> * exit_points = (*functions)[0]->findPoint(BPatch_exit);
189
190 for(unsigned int i = 1; i < functions->size(); i++){
191   entry_points->push_back((*(*functions)[i]->findPoint(BPatch_entry))[0]);
192   exit_points->push_back((*(*functions)[i]->findPoint(BPatch_exit))[0]);
193 }
194
195 // insert Snippets
196 appProc->insertSnippet(*entrySnippet, entry_points);
197 appProc->insertSnippet(*exitSnippet, exit_points);
198   
199 //run mutatee
200 appProc->continueExecution();
201
202 \end{lstlisting}
203 \end{comment}
204
205 %\begin{center} 
206 %\noindent \rule{6.5in}{1pt}
207 %\end{center}
208
209 \subsection{Calling DynC API}
210 All DynC functions reside in the \code{dynC\_API} namespace. The primary DynC API function is:
211 \begin{lstlisting}
212    BPatch_Snippet *createSnippet(<dynC code>, <location>, char * name);
213 \end{lstlisting}
214 where \code{<dynC code>} can be either a constant c-style string or a file
215 descriptor and \code{<location>} can take the form of a \code{BPatch\_point} or
216 a \code{BPatch\_addressSpace}. There is also an optional parameter to name a
217 snippet. A snippet name makes code and error reporting much easier to read, and
218 allows for the grouping of snippets (see section \ref{sec:varExplain}). If a
219 snippet name is not specified, the default name \code{Snippet\_[<\#>]} is used.
220 \\
221
222 \begin{centering}
223
224 \begin{table}[!th]
225 \begin{tabular}{|l|p{11cm}|}
226 \hline
227 \code{<dynC code>} & Description\\
228 \hline
229 \code{std::string str} & A C++ string containing dynC code.\\
230 \hline
231 \code{const char *s} & A null terminated string containing dynC code\\
232 \hline 
233 \code{FILE *f} & A standard C file descriptor. Facilitates reading dynC code from file.\\
234 \hline
235
236 \end{tabular}
237 \caption{\code{createSnippet(...)} input options: dynC code}
238 \end{table}
239
240 \begin{table}[!th]
241 \begin{tabular}{|l|p{8cm}|}
242 \hline
243 \code{<location>} & Description\\
244 \hline
245 \code{BPatch\_point \&point} & Creates a snippet specific to a single point.\\
246 \hline
247 \code{BPatch\_addressSpace \&addSpace} & Creates a more flexible snippet
248 specific to an address space. See Section \ref{sec:nopoint}.\\
249 \hline
250 \end{tabular}
251 \caption{\code{createSnippet(...)} input options: location}
252 \end{table}
253
254 \end{centering}
255
256 The location parameter is the point or address space in which the snippet will be inserted. Inserting a snippet created for one location into another can cause undefined behavior.
257
258 \subsection{Creating Snippets Without Point Information}
259 \label{sec:nopoint}
260
261 Creating a snippet without point information (i.e., calling
262 \code{createSnippet(...)} with a \code{BPatch\_addressSpace}) results in a far
263 more flexible snippet that may be inserted at any point in the specified address
264 space. There are, however, a few restrictions on the types of operations that
265 may be performed by a flexible snippet. No local variables may be accessed,
266 including parameters and return values. Mutatee variables must be accessed
267 through the \code{global} domain.
268