• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
4<title>5.�README_MISSING_SYSCALL_OR_IOCTL</title>
5<link rel="stylesheet" type="text/css" href="vg_basic.css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="index.html" title="Valgrind Documentation">
8<link rel="up" href="dist.html" title="Valgrind Distribution Documents">
9<link rel="prev" href="dist.readme.html" title="4.�README">
10<link rel="next" href="dist.readme-developers.html" title="6.�README_DEVELOPERS">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<div><table class="nav" width="100%" cellspacing="3" cellpadding="3" border="0" summary="Navigation header"><tr>
14<td width="22px" align="center" valign="middle"><a accesskey="p" href="dist.readme.html"><img src="images/prev.png" width="18" height="21" border="0" alt="Prev"></a></td>
15<td width="25px" align="center" valign="middle"><a accesskey="u" href="dist.html"><img src="images/up.png" width="21" height="18" border="0" alt="Up"></a></td>
16<td width="31px" align="center" valign="middle"><a accesskey="h" href="index.html"><img src="images/home.png" width="27" height="20" border="0" alt="Up"></a></td>
17<th align="center" valign="middle">Valgrind Distribution Documents</th>
18<td width="22px" align="center" valign="middle"><a accesskey="n" href="dist.readme-developers.html"><img src="images/next.png" width="18" height="21" border="0" alt="Next"></a></td>
19</tr></table></div>
20<div class="chapter">
21<div class="titlepage"><div><div><h1 class="title">
22<a name="dist.readme-missing"></a>5.�README_MISSING_SYSCALL_OR_IOCTL</h1></div></div></div>
23<div class="literallayout"><p><br>
24������<br>
25Dealing�with�missing�system�call�or�ioctl�wrappers�in�Valgrind<br>
26~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
27You're�probably�reading�this�because�Valgrind�bombed�out�whilst<br>
28running�your�program,�and�advised�you�to�read�this�file.��The�good<br>
29news�is�that,�in�general,�it's�easy�to�write�the�missing�syscall�or<br>
30ioctl�wrappers�you�need,�so�that�you�can�continue�your�debugging.��If<br>
31you�send�the�resulting�patches�to�me,�then�you'll�be�doing�a�favour�to<br>
32all�future�Valgrind�users�too.<br>
33<br>
34Note�that�an�"ioctl"�is�just�a�special�kind�of�system�call,�really;�so<br>
35there's�not�a�lot�of�need�to�distinguish�them�(at�least�conceptually)<br>
36in�the�discussion�that�follows.<br>
37<br>
38All�this�machinery�is�in�coregrind/m_syswrap.<br>
39<br>
40<br>
41What�are�syscall/ioctl�wrappers?��What�do�they�do?<br>
42~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
43Valgrind�does�what�it�does,�in�part,�by�keeping�track�of�everything�your<br>
44program�does.��When�a�system�call�happens,�for�example�a�request�to�read<br>
45part�of�a�file,�control�passes�to�the�Linux�kernel,�which�fulfills�the<br>
46request,�and�returns�control�to�your�program.��The�problem�is�that�the<br>
47kernel�will�often�change�the�status�of�some�part�of�your�program's�memory<br>
48as�a�result,�and�tools�(instrumentation�plug-ins)�may�need�to�know�about<br>
49this.<br>
50<br>
51Syscall�and�ioctl�wrappers�have�two�jobs:�<br>
52<br>
531.�Tell�a�tool�what's�about�to�happen,�before�the�syscall�takes�place.��A<br>
54���tool�could�perform�checks�beforehand,�eg.�if�memory�about�to�be�written<br>
55���is�actually�writeable.��This�part�is�useful,�but�not�strictly<br>
56���essential.<br>
57<br>
582.�Tell�a�tool�what�just�happened,�after�a�syscall�takes�place.��This�is<br>
59���so�it�can�update�its�view�of�the�program's�state,�eg.�that�memory�has<br>
60���just�been�written�to.��This�step�is�essential.<br>
61<br>
62The�"happenings"�mostly�involve�reading/writing�of�memory.<br>
63<br>
64So,�let's�look�at�an�example�of�a�wrapper�for�a�system�call�which<br>
65should�be�familiar�to�many�Unix�programmers.<br>
66<br>
67<br>
68The�syscall�wrapper�for�time()<br>
69~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
70The�wrapper�for�the�time�system�call�looks�like�this:<br>
71<br>
72��PRE(sys_time)<br>
73��{<br>
74�����/*�time_t�time(time_t�*t);�*/<br>
75�����PRINT("sys_time�(�%p�)",ARG1);<br>
76�����PRE_REG_READ1(long,�"time",�int�*,�t);<br>
77�����if�(ARG1�!=�0)�{<br>
78��������PRE_MEM_WRITE(�"time(t)",�ARG1,�sizeof(vki_time_t)�);<br>
79�����}<br>
80��}<br>
81<br>
82��POST(sys_time)<br>
83��{��<br>
84�����if�(ARG1�!=�0)�{<br>
85��������POST_MEM_WRITE(�ARG1,�sizeof(vki_time_t)�);<br>
86�����}<br>
87��}<br>
88<br>
89The�first�thing�we�do�happens�before�the�syscall�occurs,�in�the�PRE()�function.<br>
90The�PRE()�function�typically�starts�with�invoking�to�the�PRINT()�macro.�This<br>
91PRINT()�macro�implements�support�for�the�--trace-syscalls�command�line�option.<br>
92Next,�the�tool�is�told�the�return�type�of�the�syscall,�that�the�syscall�has<br>
93one�argument,�the�type�of�the�syscall�argument�and�that�the�argument�is�being<br>
94read�from�a�register:<br>
95<br>
96�����PRE_REG_READ1(long,�"time",�int�*,�t);<br>
97<br>
98Next,�if�a�non-NULL�buffer�is�passed�in�as�the�argument,�tell�the�tool�that�the<br>
99buffer�is�about�to�be�written�to:<br>
100<br>
101�����if�(ARG1�!=�0)�{<br>
102��������PRE_MEM_WRITE(�"time",�ARG1,�sizeof(vki_time_t)�);<br>
103�����}<br>
104<br>
105Finally,�the�really�important�bit,�after�the�syscall�occurs,�in�the�POST()<br>
106function:��if,�and�only�if,�the�system�call�was�successful,�tell�the�tool�that<br>
107the�memory�was�written:<br>
108<br>
109�����if�(ARG1�!=�0)�{<br>
110��������POST_MEM_WRITE(�ARG1,�sizeof(vki_time_t)�);<br>
111�����}<br>
112<br>
113The�POST()�function�won't�be�called�if�the�syscall�failed,�so�you<br>
114don't�need�to�worry�about�checking�that�in�the�POST()�function.<br>
115(Note:�this�is�sometimes�a�bug;�some�syscalls�do�return�results�when<br>
116they�"fail"�-�for�example,�nanosleep�returns�the�amount�of�unslept<br>
117time�if�interrupted.�TODO:�add�another�per-syscall�flag�for�this<br>
118case.)<br>
119<br>
120Note�that�we�use�the�type�'vki_time_t'.��This�is�a�copy�of�the�kernel<br>
121type,�with�'vki_'�prefixed.��Our�copies�of�such�types�are�kept�in�the<br>
122appropriate�vki*.h�file(s).��We�don't�include�kernel�headers�or�glibc�headers<br>
123directly.<br>
124<br>
125<br>
126Writing�your�own�syscall�wrappers�(see�below�for�ioctl�wrappers)<br>
127~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
128If�Valgrind�tells�you�that�system�call�NNN�is�unimplemented,�do�the�<br>
129following:<br>
130<br>
1311.��Find�out�the�name�of�the�system�call:<br>
132<br>
133�������grep�NNN�/usr/include/asm/unistd*.h<br>
134<br>
135����This�should�tell�you�something�like��__NR_mysyscallname.<br>
136����Copy�this�entry�to�include/vki/vki-scnums-$(VG_PLATFORM).h.<br>
137<br>
138<br>
1392.��Do�'man�2�mysyscallname'�to�get�some�idea�of�what�the�syscall<br>
140����does.��Note�that�the�actual�kernel�interface�can�differ�from�this,<br>
141����so�you�might�also�want�to�check�a�version�of�the�Linux�kernel<br>
142����source.<br>
143<br>
144����NOTE:�any�syscall�which�has�something�to�do�with�signals�or<br>
145����threads�is�probably�"special",�and�needs�more�careful�handling.<br>
146����Post�something�to�valgrind-developers�if�you�aren't�sure.<br>
147<br>
148<br>
1493.��Add�a�case�to�the�already-huge�collection�of�wrappers�in�<br>
150����the�coregrind/m_syswrap/syswrap-*.c�files.�<br>
151����For�each�in-memory�parameter�which�is�read�or�written�by<br>
152����the�syscall,�do�one�of<br>
153����<br>
154������PRE_MEM_READ(�...�)<br>
155������PRE_MEM_RASCIIZ(�...�)�<br>
156������PRE_MEM_WRITE(�...�)�<br>
157������<br>
158����for��that�parameter.��Then�do�the�syscall.��Then,�if�the�syscall<br>
159����succeeds,�issue�suitable�POST_MEM_WRITE(�...�)�calls.<br>
160����(There's�no�need�for�POST_MEM_READ�calls.)<br>
161<br>
162����Also,�add�it�to�the�syscall_table[]�array;�use�one�of�GENX_,�GENXY<br>
163����LINX_,�LINXY,�PLAX_,�PLAXY.<br>
164����GEN*�for�generic�syscalls�(in�syswrap-generic.c),�LIN*�for�linux<br>
165����specific�ones�(in�syswrap-linux.c)�and�PLA*�for�the�platform<br>
166����dependent�ones�(in�syswrap-$(PLATFORM)-linux.c).<br>
167����The�*XY�variant�if�it�requires�a�PRE()�and�POST()�function,�and<br>
168����the�*X_�variant�if�it�only�requires�a�PRE()<br>
169����function.��<br>
170����<br>
171����If�you�find�this�difficult,�read�the�wrappers�for�other�syscalls<br>
172����for�ideas.��A�good�tip�is�to�look�for�the�wrapper�for�a�syscall<br>
173����which�has�a�similar�behaviour�to�yours,�and�use�it�as�a�<br>
174����starting�point.<br>
175<br>
176����If�you�need�structure�definitions�and/or�constants�for�your�syscall,<br>
177����copy�them�from�the�kernel�headers�into�include/vki.h�and�co.,�with<br>
178����the�appropriate�vki_*/VKI_*�name�mangling.��Don't�#include�any<br>
179����kernel�headers.��And�certainly�don't�#include�any�glibc�headers.<br>
180<br>
181����Test�it.<br>
182<br>
183����Note�that�a�common�error�is�to�call�POST_MEM_WRITE(�...�)<br>
184����with�0�(NULL)�as�the�first�(address)�argument.��This�usually�means<br>
185����your�logic�is�slightly�inadequate.��It's�a�sufficiently�common�bug<br>
186����that�there's�a�built-in�check�for�it,�and�you'll�get�a�"probably<br>
187����sanity�check�failure"�for�the�syscall�wrapper�you�just�made,�if�this<br>
188����is�the�case.<br>
189<br>
190<br>
1914.��Once�happy,�send�us�the�patch.��Pretty�please.<br>
192<br>
193<br>
194<br>
195<br>
196Writing�your�own�ioctl�wrappers<br>
197~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
198<br>
199Is�pretty�much�the�same�as�writing�syscall�wrappers,�except�that�all<br>
200the�action�happens�within�PRE(ioctl)�and�POST(ioctl).<br>
201<br>
202There's�a�default�case,�sometimes�it�isn't�correct�and�you�have�to�write�a<br>
203more�specific�case�to�get�the�right�behaviour.<br>
204<br>
205As�above,�please�create�a�bug�report�and�attach�the�patch�as�described<br>
206on�http://www.valgrind.org.<br>
207<br>
208<br>
209Writing�your�own�door�call�wrappers�(Solaris�only)<br>
210~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br>
211<br>
212Unlike�syscalls�or�ioctls,�door�calls�transfer�data�between�two�userspace<br>
213programs,�albeit�through�a�kernel�interface.�Programs�may�use�completely<br>
214proprietary�semantics�in�the�data�buffers�passed�between�them.<br>
215Therefore�it�may�not�be�possible�to�capture�these�semantics�within<br>
216a�Valgrind�door�call�or�door�return�wrapper.<br>
217<br>
218Nevertheless,�for�system�or�well-known�door�services�it�would�be�beneficial<br>
219to�have�a�door�call�and�a�door�return�wrapper.�Writing�such�wrapper�is�pretty<br>
220much�the�same�as�writing�ioctl�wrappers.�Please�take�a�few�moments�to�study<br>
221the�following�picture�depicting�how�a�door�client�and�a�door�server�interact<br>
222through�the�kernel�interface�in�a�typical�scenario:<br>
223<br>
224<br>
225door�client�thread����������kernel�������door�server�thread<br>
226invokes�door_call()���������������������invokes�door_return()<br>
227-------------------------------------------------------------------<br>
228�������������������������������&lt;----��PRE(sys_door,�DOOR_RETURN)<br>
229PRE(sys_door,�DOOR_CALL)��---&gt;<br>
230�������������������������������----&gt;��POST(sys_door,�DOOR_RETURN)<br>
231�������������������������������������������----&gt;�server_procedure()<br>
232�������������������������������������������&lt;----<br>
233�������������������������������&lt;----��PRE(sys_door,�DOOR_RETURN)<br>
234POST(sys_door,�DOOR_CALL)�&lt;---<br>
235<br>
236The�first�PRE(sys_door,�DOOR_RETURN)�is�invoked�with�data_ptr=NULL<br>
237and�data_size=0.�That's�because�it�has�not�received�any�data�from<br>
238a�door�call,�yet.<br>
239<br>
240Semantics�are�described�by�the�following�functions<br>
241in�coregring/m_syswrap/syswrap-solaris.c�module:<br>
242o�For�a�door�call�wrapper�the�following�attributes�of�'params'�argument:<br>
243��-�data_ptr�(and�associated�data_size)�as�input�buffer�(request);<br>
244������described�in�door_call_pre_mem_params_data()<br>
245��-�rbuf�(and�associated�rsize)�as�output�buffer�(response);<br>
246������described�in�door_call_post_mem_params_rbuf()<br>
247o�For�a�door�return�wrapper�the�following�parameters:<br>
248��-�data_ptr�(and�associated�data_size)�as�input�buffer�(request);<br>
249������described�in�door_return_post_mem_data()<br>
250��-�data_ptr�(and�associated�data_size)�as�output�buffer�(response);<br>
251������described�in�door_return_pre_mem_data()<br>
252<br>
253There's�a�default�case�which�may�not�be�correct�and�you�have�to�write�a<br>
254more�specific�case�to�get�the�right�behaviour.�Unless�Valgrind's�option<br>
255'--sim-hints=lax-doors'�is�specified,�the�default�case�also�spits�a�warning.<br>
256<br>
257As�above,�please�create�a�bug�report�and�attach�the�patch�as�described<br>
258on�http://www.valgrind.org.<br>
259<br>
260����</p></div>
261</div>
262<div>
263<br><table class="nav" width="100%" cellspacing="3" cellpadding="2" border="0" summary="Navigation footer">
264<tr>
265<td rowspan="2" width="40%" align="left">
266<a accesskey="p" href="dist.readme.html">&lt;&lt;�4.�README</a>�</td>
267<td width="20%" align="center"><a accesskey="u" href="dist.html">Up</a></td>
268<td rowspan="2" width="40%" align="right">�<a accesskey="n" href="dist.readme-developers.html">6.�README_DEVELOPERS�&gt;&gt;</a>
269</td>
270</tr>
271<tr><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td></tr>
272</table>
273</div>
274</body>
275</html>
276