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�������������������������������<----��PRE(sys_door,�DOOR_RETURN)<br> 229PRE(sys_door,�DOOR_CALL)��---><br> 230�������������������������������---->��POST(sys_door,�DOOR_RETURN)<br> 231�������������������������������������������---->�server_procedure()<br> 232�������������������������������������������<----<br> 233�������������������������������<----��PRE(sys_door,�DOOR_RETURN)<br> 234POST(sys_door,�DOOR_CALL)�<---<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"><<�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�>></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