blob: f79d67cd771476bc8d72062e43b39f4eb9e3352c [file] [log] [blame]
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00001/*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +00005 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
Roland McGrathe1e584b2003-06-02 19:18:58 +00006 * Copyright (c) 2000 PocketPenguins Inc. Linux for Hitachi SuperH
7 * port by Greg Banks <gbanks@pocketpenguins.com>
Elliott Hughesb7556142018-02-20 17:03:16 -08008 * Copyright (c) 1999-2018 The strace developers.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +00009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000032 */
33
34#include "defs.h"
Elliott Hughesb7556142018-02-20 17:03:16 -080035#include <linux/mman.h>
Wichert Akkerman2e2553a1999-05-09 00:29:58 +000036#include <sys/mman.h>
Denys Vlasenko1ba85432013-02-19 11:28:20 +010037
Dmitry V. Levinea1fea62015-03-31 19:45:08 +000038unsigned long
39get_pagesize(void)
Dmitry V. Levinc76a3632013-03-05 14:58:24 +000040{
41 static unsigned long pagesize;
42
43 if (!pagesize)
44 pagesize = sysconf(_SC_PAGESIZE);
45 return pagesize;
46}
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000047
Dmitry V. Levina0bd3742015-04-07 01:36:50 +000048SYS_FUNC(brk)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000049{
Dmitry V. Levin85813ce2015-07-19 23:37:40 +000050 printaddr(tcp->u_arg[0]);
51
52 return RVAL_DECODED | RVAL_HEX;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000053}
54
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000055#include "xlat/mmap_prot.h"
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +000056#include "xlat/mmap_flags.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000057
Elliott Hughesb7556142018-02-20 17:03:16 -080058#ifndef MAP_HUGE_SHIFT
59# define MAP_HUGE_SHIFT 26
60#endif
61
62#ifndef MAP_HUGE_MASK
63# define MAP_HUGE_MASK 0x3f
64#endif
65
66static void
67print_mmap_flags(kernel_ulong_t flags)
68{
69 printxval64(mmap_flags, flags & MAP_TYPE, "MAP_???");
70 flags &= ~MAP_TYPE;
71
72 const unsigned int mask = MAP_HUGE_MASK << MAP_HUGE_SHIFT;
73 const unsigned int hugetlb_value = flags & mask;
74
75 flags &= ~mask;
Elliott Hughes28e98bc2018-06-14 16:59:04 -070076 if (flags) {
77 tprints("|");
78 printflags64(mmap_flags, flags, NULL);
79 }
Elliott Hughesb7556142018-02-20 17:03:16 -080080
81 if (hugetlb_value)
82 tprintf("|%u<<MAP_HUGE_SHIFT",
83 hugetlb_value >> MAP_HUGE_SHIFT);
84}
85
Dmitry V. Levin85813ce2015-07-19 23:37:40 +000086static void
Elliott Hughesd35df492017-02-15 15:19:05 -080087print_mmap(struct tcb *tcp, kernel_ulong_t *u_arg, unsigned long long offset)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +000088{
Elliott Hughesd35df492017-02-15 15:19:05 -080089 const kernel_ulong_t addr = u_arg[0];
90 const kernel_ulong_t len = u_arg[1];
91 const kernel_ulong_t prot = u_arg[2];
92 const kernel_ulong_t flags = u_arg[3];
Dmitry V. Levin3ae86902016-04-01 15:31:23 +000093 const int fd = u_arg[4];
94
95 printaddr(addr);
Elliott Hughesd35df492017-02-15 15:19:05 -080096 tprintf(", %" PRI_klu ", ", len);
97 printflags64(mmap_prot, prot, "PROT_???");
Dmitry V. Levin85813ce2015-07-19 23:37:40 +000098 tprints(", ");
Elliott Hughesb7556142018-02-20 17:03:16 -080099 print_mmap_flags(flags);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000100 tprints(", ");
Dmitry V. Levin3ae86902016-04-01 15:31:23 +0000101 printfd(tcp, fd);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000102 tprintf(", %#llx", offset);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000103}
104
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100105/* Syscall name<->function correspondence is messed up on many arches.
106 * For example:
107 * i386 has __NR_mmap == 90, and it is "old mmap", and
108 * also it has __NR_mmap2 == 192, which is a "new mmap with page offsets".
109 * But x86_64 has just one __NR_mmap == 9, a "new mmap with byte offsets".
110 * Confused? Me too!
111 */
112
Elliott Hughesb7556142018-02-20 17:03:16 -0800113#if HAVE_ARCH_OLD_MMAP
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100114/* Params are pointed to by u_arg[0], offset is in bytes */
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000115SYS_FUNC(old_mmap)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000116{
Elliott Hughesb7556142018-02-20 17:03:16 -0800117 kernel_ulong_t *args =
118 fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
119
120 if (args)
121 print_mmap(tcp, args, args[5]);
122 else
123 printaddr(tcp->u_arg[0]);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000124
125 return RVAL_DECODED | RVAL_HEX;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000126}
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000127
Elliott Hughesb7556142018-02-20 17:03:16 -0800128# if HAVE_ARCH_OLD_MMAP_PGOFF
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100129/* Params are pointed to by u_arg[0], offset is in pages */
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000130SYS_FUNC(old_mmap_pgoff)
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100131{
Elliott Hughesb7556142018-02-20 17:03:16 -0800132 kernel_ulong_t *args =
133 fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
134
135 if (args) {
136 unsigned long long offset;
137
138 offset = args[5];
139 offset *= get_pagesize();
140
141 print_mmap(tcp, args, offset);
142 } else {
143 printaddr(tcp->u_arg[0]);
144 }
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000145
146 return RVAL_DECODED | RVAL_HEX;
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100147}
Elliott Hughesb7556142018-02-20 17:03:16 -0800148# endif /* HAVE_ARCH_OLD_MMAP_PGOFF */
149#endif /* HAVE_ARCH_OLD_MMAP */
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100150
151/* Params are passed directly, offset is in bytes */
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000152SYS_FUNC(mmap)
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000153{
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100154 /* Example of kernel-side handling of this variety of mmap:
155 * arch/x86/kernel/sys_x86_64.c::SYSCALL_DEFINE6(mmap, ...) calls
156 * sys_mmap_pgoff(..., off >> PAGE_SHIFT); i.e. off is in bytes,
157 * since the above code converts off to pages.
158 */
Elliott Hughesd35df492017-02-15 15:19:05 -0800159 print_mmap(tcp, tcp->u_arg, tcp->u_arg[5]);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000160
161 return RVAL_DECODED | RVAL_HEX;
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100162}
163
164/* Params are passed directly, offset is in pages */
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000165SYS_FUNC(mmap_pgoff)
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100166{
167 /* Try test/mmap_offset_decode.c */
168 unsigned long long offset;
Elliott Hughesd35df492017-02-15 15:19:05 -0800169 offset = tcp->u_arg[5];
Dmitry V. Levinc76a3632013-03-05 14:58:24 +0000170 offset *= get_pagesize();
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000171 print_mmap(tcp, tcp->u_arg, offset);
172
173 return RVAL_DECODED | RVAL_HEX;
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100174}
175
176/* Params are passed directly, offset is in 4k units */
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000177SYS_FUNC(mmap_4koff)
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100178{
179 unsigned long long offset;
Elliott Hughesd35df492017-02-15 15:19:05 -0800180 offset = tcp->u_arg[5];
Denys Vlasenko1ba85432013-02-19 11:28:20 +0100181 offset <<= 12;
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000182 print_mmap(tcp, tcp->u_arg, offset);
183
184 return RVAL_DECODED | RVAL_HEX;
Wichert Akkerman4dc8a2a1999-12-23 14:20:14 +0000185}
186
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000187SYS_FUNC(munmap)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000188{
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000189 printaddr(tcp->u_arg[0]);
Elliott Hughesd35df492017-02-15 15:19:05 -0800190 tprintf(", %" PRI_klu, tcp->u_arg[1]);
191
192 return RVAL_DECODED;
193}
194
195static int
196do_mprotect(struct tcb *tcp, bool has_pkey)
197{
198 printaddr(tcp->u_arg[0]);
199 tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
200 printflags64(mmap_prot, tcp->u_arg[2], "PROT_???");
201
202 if (has_pkey)
203 tprintf(", %d", (int) tcp->u_arg[3]);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000204
205 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000206}
207
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000208SYS_FUNC(mprotect)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000209{
Elliott Hughesd35df492017-02-15 15:19:05 -0800210 return do_mprotect(tcp, false);
211}
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000212
Elliott Hughesd35df492017-02-15 15:19:05 -0800213SYS_FUNC(pkey_mprotect)
214{
215 return do_mprotect(tcp, true);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000216}
217
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000218#include "xlat/mremap_flags.h"
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000219
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000220SYS_FUNC(mremap)
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000221{
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000222 printaddr(tcp->u_arg[0]);
Elliott Hughesd35df492017-02-15 15:19:05 -0800223 tprintf(", %" PRI_klu ", %" PRI_klu ", ", tcp->u_arg[1], tcp->u_arg[2]);
224 printflags64(mremap_flags, tcp->u_arg[3], "MREMAP_???");
Dmitry V. Levinfdc45592009-12-24 23:34:58 +0000225#ifdef MREMAP_FIXED
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000226 if ((tcp->u_arg[3] & (MREMAP_MAYMOVE | MREMAP_FIXED)) ==
227 (MREMAP_MAYMOVE | MREMAP_FIXED)) {
228 tprints(", ");
229 printaddr(tcp->u_arg[4]);
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000230 }
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000231#endif
232 return RVAL_DECODED | RVAL_HEX;
Wichert Akkerman2e2553a1999-05-09 00:29:58 +0000233}
234
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000235#include "xlat/madvise_cmds.h"
Wichert Akkermanc7926982000-04-10 22:22:31 +0000236
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000237SYS_FUNC(madvise)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000238{
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000239 printaddr(tcp->u_arg[0]);
Elliott Hughesd35df492017-02-15 15:19:05 -0800240 tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000241 printxval(madvise_cmds, tcp->u_arg[2], "MADV_???");
242
243 return RVAL_DECODED;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000244}
245
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000246#include "xlat/mlockall_flags.h"
Wichert Akkermanc7926982000-04-10 22:22:31 +0000247
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000248SYS_FUNC(mlockall)
Wichert Akkermanc7926982000-04-10 22:22:31 +0000249{
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000250 printflags(mlockall_flags, tcp->u_arg[0], "MCL_???");
251
252 return RVAL_DECODED;
Wichert Akkermanc7926982000-04-10 22:22:31 +0000253}
254
Dmitry V. Levin0ed617b2014-04-25 23:30:54 +0000255#include "xlat/mctl_sync.h"
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000256
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000257SYS_FUNC(msync)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000258{
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000259 /* addr */
260 printaddr(tcp->u_arg[0]);
261 /* len */
Elliott Hughesd35df492017-02-15 15:19:05 -0800262 tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000263 /* flags */
264 printflags(mctl_sync, tcp->u_arg[2], "MS_???");
265
266 return RVAL_DECODED;
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000267}
268
Dmitry V. Levin0d0a50a2015-11-15 02:35:57 +0000269#include "xlat/mlock_flags.h"
270
271SYS_FUNC(mlock2)
272{
273 printaddr(tcp->u_arg[0]);
Elliott Hughesd35df492017-02-15 15:19:05 -0800274 tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
Dmitry V. Levin0d0a50a2015-11-15 02:35:57 +0000275 printflags(mlock_flags, tcp->u_arg[2], "MLOCK_???");
276
277 return RVAL_DECODED;
278}
279
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000280SYS_FUNC(mincore)
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000281{
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000282 if (entering(tcp)) {
Dmitry V. Levin2c389f62015-07-19 23:25:56 +0000283 printaddr(tcp->u_arg[0]);
Elliott Hughesd35df492017-02-15 15:19:05 -0800284 tprintf(", %" PRI_klu ", ", tcp->u_arg[1]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000285 } else {
Dmitry V. Levindfea1da2016-01-29 01:51:54 +0000286 const unsigned long page_size = get_pagesize();
287 const unsigned long page_mask = page_size - 1;
288 unsigned long len = tcp->u_arg[1];
289 unsigned char *vec = NULL;
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200290
Dmitry V. Levindfea1da2016-01-29 01:51:54 +0000291 len = len / page_size + (len & page_mask ? 1 : 0);
Dmitry V. Levin2c389f62015-07-19 23:25:56 +0000292 if (syserror(tcp) || !verbose(tcp) ||
293 !tcp->u_arg[2] || !(vec = malloc(len)) ||
294 umoven(tcp, tcp->u_arg[2], len, vec) < 0)
295 printaddr(tcp->u_arg[2]);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000296 else {
Dmitry V. Levindfea1da2016-01-29 01:51:54 +0000297 unsigned long i;
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200298 tprints("[");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000299 for (i = 0; i < len; i++) {
Elliott Hughesd35df492017-02-15 15:19:05 -0800300 if (i)
301 tprints(", ");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000302 if (abbrev(tcp) && i >= max_strlen) {
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200303 tprints("...");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000304 break;
305 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200306 tprints((vec[i] & 1) ? "1" : "0");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000307 }
Denys Vlasenko60fe8c12011-09-01 10:00:28 +0200308 tprints("]");
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000309 }
Denys Vlasenko1d46ba52011-08-31 14:00:02 +0200310 free(vec);
Wichert Akkerman76baf7c1999-02-19 00:21:36 +0000311 }
312 return 0;
313}
314
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000315SYS_FUNC(remap_file_pages)
Roland McGrath72c5b7b2003-03-05 04:08:00 +0000316{
Elliott Hughesd35df492017-02-15 15:19:05 -0800317 const kernel_ulong_t addr = tcp->u_arg[0];
318 const kernel_ulong_t size = tcp->u_arg[1];
319 const kernel_ulong_t prot = tcp->u_arg[2];
320 const kernel_ulong_t pgoff = tcp->u_arg[3];
321 const kernel_ulong_t flags = tcp->u_arg[4];
Dmitry V. Levin3ae86902016-04-01 15:31:23 +0000322
323 printaddr(addr);
Elliott Hughesd35df492017-02-15 15:19:05 -0800324 tprintf(", %" PRI_klu ", ", size);
325 printflags64(mmap_prot, prot, "PROT_???");
326 tprintf(", %" PRI_klu ", ", pgoff);
Elliott Hughesb7556142018-02-20 17:03:16 -0800327 print_mmap_flags(flags);
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000328
329 return RVAL_DECODED;
Roland McGrath72c5b7b2003-03-05 04:08:00 +0000330}
Roland McGrathb10a3352004-10-07 18:53:12 +0000331
Denys Vlasenko84703742012-02-25 02:38:52 +0100332#if defined(POWERPC)
Dmitry V. Levin0f04b9d2016-05-07 23:00:52 +0000333static bool
334print_protmap_entry(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
335{
Elliott Hughesdc75b012017-07-05 13:54:44 -0700336 tprintf("%#08x", *(unsigned int *) elem_buf);
Dmitry V. Levin0f04b9d2016-05-07 23:00:52 +0000337
338 return true;
339}
340
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000341SYS_FUNC(subpage_prot)
Roland McGrath4a6f6522008-08-25 03:09:16 +0000342{
Elliott Hughesd35df492017-02-15 15:19:05 -0800343 kernel_ulong_t addr = tcp->u_arg[0];
344 kernel_ulong_t len = tcp->u_arg[1];
345 kernel_ulong_t nmemb = len >> 16;
346 kernel_ulong_t map = tcp->u_arg[2];
Roland McGrath4a6f6522008-08-25 03:09:16 +0000347
Dmitry V. Levin0f04b9d2016-05-07 23:00:52 +0000348 printaddr(addr);
Elliott Hughesd35df492017-02-15 15:19:05 -0800349 tprintf(", %" PRI_klu ", ", len);
Dmitry V. Levin0f04b9d2016-05-07 23:00:52 +0000350
351 unsigned int entry;
352 print_array(tcp, map, nmemb, &entry, sizeof(entry),
353 umoven_or_printaddr, print_protmap_entry, 0);
Roland McGrath4a6f6522008-08-25 03:09:16 +0000354
Dmitry V. Levin85813ce2015-07-19 23:37:40 +0000355 return RVAL_DECODED;
Roland McGrath4a6f6522008-08-25 03:09:16 +0000356}
357#endif