Whamcloud - gitweb
Branch b1_8
[fs/lustre-release.git] / lnet / libcfs / darwin / darwin-utils.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lnet/libcfs/darwin/darwin-utils.c
37  *
38  * Darwin porting library
39  * Make things easy to port
40  *
41  * Author: Phil Schwan <phil@clusterfs.com>
42  */
43 #define DEBUG_SUBSYSTEM S_LNET
44
45 #include <mach/mach_types.h>
46 #include <string.h>
47 #include <sys/errno.h>
48 #include <sys/types.h>
49 #include <sys/fcntl.h>
50 #include <lnet/types.h>
51
52 #include <libcfs/kp30.h>
53
54 #ifndef isspace
55 inline int
56 isspace(char c)
57 {
58         return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
59 }
60 #endif
61
62 char * strpbrk(const char * cs,const char * ct)
63 {
64         const char *sc1,*sc2;
65         
66         for( sc1 = cs; *sc1 != '\0'; ++sc1) {
67                 for( sc2 = ct; *sc2 != '\0'; ++sc2) {
68                         if (*sc1 == *sc2)
69                                 return (char *) sc1;
70                 }
71         }
72         return NULL;
73 }
74
75 char * strsep(char **s, const char *ct)
76 {
77         char *sbegin = *s, *end;
78         
79         if (sbegin == NULL)
80                 return NULL;
81         end = strpbrk(sbegin, ct);
82         if (end != NULL)
83                 *end++ = '\0';
84         *s = end;
85
86         return sbegin;
87 }
88
89 size_t strnlen(const char * s, size_t count)
90 {
91         const char *sc;
92
93         for (sc = s; count-- && *sc != '\0'; ++sc)
94                 /* nothing */;
95         return sc - s;
96 }
97
98 char *
99 strstr(const char *in, const char *str)
100 {
101         char c;
102         size_t len;
103         
104         c = *str++;
105         if (!c)
106                 return (char *) in;     // Trivial empty string case
107         len = strlen(str);
108         do {
109                 char sc;
110                 do {
111                         sc = *in++;
112                         if (!sc)
113                                 return (char *) 0;
114                 } while (sc != c);
115         } while (strncmp(in, str, len) != 0);
116         return (char *) (in - 1);
117 }
118
119 char *
120 strrchr(const char *p, int ch)
121 {
122         const char *end = p + strlen(p);
123         do {
124                 if (*end == (char)ch)
125                         return (char *)end;
126         } while (--end >= p);
127         return NULL;
128 }
129
130 char *
131 ul2dstr(unsigned long address, char *buf, int len)
132 {
133         char *pos = buf + len - 1;
134
135         if (len <= 0 || !buf)
136                 return NULL;
137         *pos = 0;
138         while (address) {
139                 if (!--len) break;
140                 *--pos = address % 10 + '0';
141                 address /= 10;
142         }
143         return pos;
144 }
145
146 /*
147  * miscellaneous libcfs stuff
148  */
149
150 /*
151  * Convert server error code to client format.
152  * Linux errno.h.
153  */
154
155 /* obtained by
156  *
157  *     cc /usr/include/asm/errno.h -E -dM | grep '#define E' | sort -n -k3,3
158  *
159  */
160 enum linux_errnos {
161         LINUX_EPERM              = 1,
162         LINUX_ENOENT             = 2,
163         LINUX_ESRCH              = 3,
164         LINUX_EINTR              = 4,
165         LINUX_EIO                = 5,
166         LINUX_ENXIO              = 6,
167         LINUX_E2BIG              = 7,
168         LINUX_ENOEXEC            = 8,
169         LINUX_EBADF              = 9,
170         LINUX_ECHILD             = 10,
171         LINUX_EAGAIN             = 11,
172         LINUX_ENOMEM             = 12,
173         LINUX_EACCES             = 13,
174         LINUX_EFAULT             = 14,
175         LINUX_ENOTBLK            = 15,
176         LINUX_EBUSY              = 16,
177         LINUX_EEXIST             = 17,
178         LINUX_EXDEV              = 18,
179         LINUX_ENODEV             = 19,
180         LINUX_ENOTDIR            = 20,
181         LINUX_EISDIR             = 21,
182         LINUX_EINVAL             = 22,
183         LINUX_ENFILE             = 23,
184         LINUX_EMFILE             = 24,
185         LINUX_ENOTTY             = 25,
186         LINUX_ETXTBSY            = 26,
187         LINUX_EFBIG              = 27,
188         LINUX_ENOSPC             = 28,
189         LINUX_ESPIPE             = 29,
190         LINUX_EROFS              = 30,
191         LINUX_EMLINK             = 31,
192         LINUX_EPIPE              = 32,
193         LINUX_EDOM               = 33,
194         LINUX_ERANGE             = 34,
195         LINUX_EDEADLK            = 35,
196         LINUX_ENAMETOOLONG       = 36,
197         LINUX_ENOLCK             = 37,
198         LINUX_ENOSYS             = 38,
199         LINUX_ENOTEMPTY          = 39,
200         LINUX_ELOOP              = 40,
201         LINUX_ENOMSG             = 42,
202         LINUX_EIDRM              = 43,
203         LINUX_ECHRNG             = 44,
204         LINUX_EL2NSYNC           = 45,
205         LINUX_EL3HLT             = 46,
206         LINUX_EL3RST             = 47,
207         LINUX_ELNRNG             = 48,
208         LINUX_EUNATCH            = 49,
209         LINUX_ENOCSI             = 50,
210         LINUX_EL2HLT             = 51,
211         LINUX_EBADE              = 52,
212         LINUX_EBADR              = 53,
213         LINUX_EXFULL             = 54,
214         LINUX_ENOANO             = 55,
215         LINUX_EBADRQC            = 56,
216         LINUX_EBADSLT            = 57,
217         LINUX_EBFONT             = 59,
218         LINUX_ENOSTR             = 60,
219         LINUX_ENODATA            = 61,
220         LINUX_ETIME              = 62,
221         LINUX_ENOSR              = 63,
222         LINUX_ENONET             = 64,
223         LINUX_ENOPKG             = 65,
224         LINUX_EREMOTE            = 66,
225         LINUX_ENOLINK            = 67,
226         LINUX_EADV               = 68,
227         LINUX_ESRMNT             = 69,
228         LINUX_ECOMM              = 70,
229         LINUX_EPROTO             = 71,
230         LINUX_EMULTIHOP          = 72,
231         LINUX_EDOTDOT            = 73,
232         LINUX_EBADMSG            = 74,
233         LINUX_EOVERFLOW          = 75,
234         LINUX_ENOTUNIQ           = 76,
235         LINUX_EBADFD             = 77,
236         LINUX_EREMCHG            = 78,
237         LINUX_ELIBACC            = 79,
238         LINUX_ELIBBAD            = 80,
239         LINUX_ELIBSCN            = 81,
240         LINUX_ELIBMAX            = 82,
241         LINUX_ELIBEXEC           = 83,
242         LINUX_EILSEQ             = 84,
243         LINUX_ERESTART           = 85,
244         LINUX_ESTRPIPE           = 86,
245         LINUX_EUSERS             = 87,
246         LINUX_ENOTSOCK           = 88,
247         LINUX_EDESTADDRREQ       = 89,
248         LINUX_EMSGSIZE           = 90,
249         LINUX_EPROTOTYPE         = 91,
250         LINUX_ENOPROTOOPT        = 92,
251         LINUX_EPROTONOSUPPORT    = 93,
252         LINUX_ESOCKTNOSUPPORT    = 94,
253         LINUX_EOPNOTSUPP         = 95,
254         LINUX_EPFNOSUPPORT       = 96,
255         LINUX_EAFNOSUPPORT       = 97,
256         LINUX_EADDRINUSE         = 98,
257         LINUX_EADDRNOTAVAIL      = 99,
258         LINUX_ENETDOWN           = 100,
259         LINUX_ENETUNREACH        = 101,
260         LINUX_ENETRESET          = 102,
261         LINUX_ECONNABORTED       = 103,
262         LINUX_ECONNRESET         = 104,
263         LINUX_ENOBUFS            = 105,
264         LINUX_EISCONN            = 106,
265         LINUX_ENOTCONN           = 107,
266         LINUX_ESHUTDOWN          = 108,
267         LINUX_ETOOMANYREFS       = 109,
268         LINUX_ETIMEDOUT          = 110,
269         LINUX_ECONNREFUSED       = 111,
270         LINUX_EHOSTDOWN          = 112,
271         LINUX_EHOSTUNREACH       = 113,
272         LINUX_EALREADY           = 114,
273         LINUX_EINPROGRESS        = 115,
274         LINUX_ESTALE             = 116,
275         LINUX_EUCLEAN            = 117,
276         LINUX_ENOTNAM            = 118,
277         LINUX_ENAVAIL            = 119,
278         LINUX_EISNAM             = 120,
279         LINUX_EREMOTEIO          = 121,
280         LINUX_EDQUOT             = 122,
281         LINUX_ENOMEDIUM          = 123,
282         LINUX_EMEDIUMTYPE        = 124,
283
284         /*
285          * we don't need these, but for completeness..
286          */
287         LINUX_EDEADLOCK          = LINUX_EDEADLK,
288         LINUX_EWOULDBLOCK        = LINUX_EAGAIN
289 };
290
291 int convert_server_error(__u64 ecode)
292 {
293         int sign;
294         int code;
295
296         static int errno_xlate[] = {
297                 /* success is always success */
298                 [0]                     = 0,
299                 [LINUX_EPERM]           = EPERM,
300                 [LINUX_ENOENT]          = ENOENT,
301                 [LINUX_ESRCH]           = ESRCH,
302                 [LINUX_EINTR]           = EINTR,
303                 [LINUX_EIO]             = EIO,
304                 [LINUX_ENXIO]           = ENXIO,
305                 [LINUX_E2BIG]           = E2BIG,
306                 [LINUX_ENOEXEC]         = ENOEXEC,
307                 [LINUX_EBADF]           = EBADF,
308                 [LINUX_ECHILD]          = ECHILD,
309                 [LINUX_EAGAIN]          = EAGAIN,
310                 [LINUX_ENOMEM]          = ENOMEM,
311                 [LINUX_EACCES]          = EACCES,
312                 [LINUX_EFAULT]          = EFAULT,
313                 [LINUX_ENOTBLK]         = ENOTBLK,
314                 [LINUX_EBUSY]           = EBUSY,
315                 [LINUX_EEXIST]          = EEXIST,
316                 [LINUX_EXDEV]           = EXDEV,
317                 [LINUX_ENODEV]          = ENODEV,
318                 [LINUX_ENOTDIR]         = ENOTDIR,
319                 [LINUX_EISDIR]          = EISDIR,
320                 [LINUX_EINVAL]          = EINVAL,
321                 [LINUX_ENFILE]          = ENFILE,
322                 [LINUX_EMFILE]          = EMFILE,
323                 [LINUX_ENOTTY]          = ENOTTY,
324                 [LINUX_ETXTBSY]         = ETXTBSY,
325                 [LINUX_EFBIG]           = EFBIG,
326                 [LINUX_ENOSPC]          = ENOSPC,
327                 [LINUX_ESPIPE]          = ESPIPE,
328                 [LINUX_EROFS]           = EROFS,
329                 [LINUX_EMLINK]          = EMLINK,
330                 [LINUX_EPIPE]           = EPIPE,
331                 [LINUX_EDOM]            = EDOM,
332                 [LINUX_ERANGE]          = ERANGE,
333                 [LINUX_EDEADLK]         = EDEADLK,
334                 [LINUX_ENAMETOOLONG]    = ENAMETOOLONG,
335                 [LINUX_ENOLCK]          = ENOLCK,
336                 [LINUX_ENOSYS]          = ENOSYS,
337                 [LINUX_ENOTEMPTY]       = ENOTEMPTY,
338                 [LINUX_ELOOP]           = ELOOP,
339                 [LINUX_ENOMSG]          = ENOMSG,
340                 [LINUX_EIDRM]           = EIDRM,
341                 [LINUX_ECHRNG]          = EINVAL /* ECHRNG */,
342                 [LINUX_EL2NSYNC]        = EINVAL /* EL2NSYNC */,
343                 [LINUX_EL3HLT]          = EINVAL /* EL3HLT */,
344                 [LINUX_EL3RST]          = EINVAL /* EL3RST */,
345                 [LINUX_ELNRNG]          = EINVAL /* ELNRNG */,
346                 [LINUX_EUNATCH]         = EINVAL /* EUNATCH */,
347                 [LINUX_ENOCSI]          = EINVAL /* ENOCSI */,
348                 [LINUX_EL2HLT]          = EINVAL /* EL2HLT */,
349                 [LINUX_EBADE]           = EINVAL /* EBADE */,
350                 [LINUX_EBADR]           = EBADRPC,
351                 [LINUX_EXFULL]          = EINVAL /* EXFULL */,
352                 [LINUX_ENOANO]          = EINVAL /* ENOANO */,
353                 [LINUX_EBADRQC]         = EINVAL /* EBADRQC */,
354                 [LINUX_EBADSLT]         = EINVAL /* EBADSLT */,
355                 [LINUX_EBFONT]          = EINVAL /* EBFONT */,
356                 [LINUX_ENOSTR]          = EINVAL /* ENOSTR */,
357                 [LINUX_ENODATA]         = EINVAL /* ENODATA */,
358                 [LINUX_ETIME]           = EINVAL /* ETIME */,
359                 [LINUX_ENOSR]           = EINVAL /* ENOSR */,
360                 [LINUX_ENONET]          = EINVAL /* ENONET */,
361                 [LINUX_ENOPKG]          = EINVAL /* ENOPKG */,
362                 [LINUX_EREMOTE]         = EREMOTE,
363                 [LINUX_ENOLINK]         = EINVAL /* ENOLINK */,
364                 [LINUX_EADV]            = EINVAL /* EADV */,
365                 [LINUX_ESRMNT]          = EINVAL /* ESRMNT */,
366                 [LINUX_ECOMM]           = EINVAL /* ECOMM */,
367                 [LINUX_EPROTO]          = EPROTOTYPE,
368                 [LINUX_EMULTIHOP]       = EINVAL /* EMULTIHOP */,
369                 [LINUX_EDOTDOT]         = EINVAL /* EDOTDOT */,
370                 [LINUX_EBADMSG]         = EINVAL /* EBADMSG */,
371                 [LINUX_EOVERFLOW]       = EOVERFLOW,
372                 [LINUX_ENOTUNIQ]        = EINVAL /* ENOTUNIQ */,
373                 [LINUX_EBADFD]          = EINVAL /* EBADFD */,
374                 [LINUX_EREMCHG]         = EINVAL /* EREMCHG */,
375                 [LINUX_ELIBACC]         = EINVAL /* ELIBACC */,
376                 [LINUX_ELIBBAD]         = EINVAL /* ELIBBAD */,
377                 [LINUX_ELIBSCN]         = EINVAL /* ELIBSCN */,
378                 [LINUX_ELIBMAX]         = EINVAL /* ELIBMAX */,
379                 [LINUX_ELIBEXEC]        = EINVAL /* ELIBEXEC */,
380                 [LINUX_EILSEQ]          = EILSEQ,
381                 [LINUX_ERESTART]        = EINVAL /* because ERESTART is
382                                                   * negative in XNU */,
383                 [LINUX_ESTRPIPE]        = EINVAL /* ESTRPIPE */,
384                 [LINUX_EUSERS]          = EUSERS,
385                 [LINUX_ENOTSOCK]        = ENOTSOCK,
386                 [LINUX_EDESTADDRREQ]    = EDESTADDRREQ,
387                 [LINUX_EMSGSIZE]        = EMSGSIZE,
388                 [LINUX_EPROTOTYPE]      = EPROTOTYPE,
389                 [LINUX_ENOPROTOOPT]     = ENOPROTOOPT,
390                 [LINUX_EPROTONOSUPPORT] = EPROTONOSUPPORT,
391                 [LINUX_ESOCKTNOSUPPORT] = ESOCKTNOSUPPORT,
392                 [LINUX_EOPNOTSUPP]      = EOPNOTSUPP,
393                 [LINUX_EPFNOSUPPORT]    = EPFNOSUPPORT,
394                 [LINUX_EAFNOSUPPORT]    = EAFNOSUPPORT,
395                 [LINUX_EADDRINUSE]      = EADDRINUSE,
396                 [LINUX_EADDRNOTAVAIL]   = EADDRNOTAVAIL,
397                 [LINUX_ENETDOWN]        = ENETDOWN,
398                 [LINUX_ENETUNREACH]     = ENETUNREACH,
399                 [LINUX_ENETRESET]       = ENETRESET,
400                 [LINUX_ECONNABORTED]    = ECONNABORTED,
401                 [LINUX_ECONNRESET]      = ECONNRESET,
402                 [LINUX_ENOBUFS]         = ENOBUFS,
403                 [LINUX_EISCONN]         = EISCONN,
404                 [LINUX_ENOTCONN]        = ENOTCONN,
405                 [LINUX_ESHUTDOWN]       = ESHUTDOWN,
406                 [LINUX_ETOOMANYREFS]    = ETOOMANYREFS,
407                 [LINUX_ETIMEDOUT]       = ETIMEDOUT,
408                 [LINUX_ECONNREFUSED]    = ECONNREFUSED,
409                 [LINUX_EHOSTDOWN]       = EHOSTDOWN,
410                 [LINUX_EHOSTUNREACH]    = EHOSTUNREACH,
411                 [LINUX_EALREADY]        = EALREADY,
412                 [LINUX_EINPROGRESS]     = EINPROGRESS,
413                 [LINUX_ESTALE]          = ESTALE,
414                 [LINUX_EUCLEAN]         = EINVAL /* EUCLEAN */,
415                 [LINUX_ENOTNAM]         = EINVAL /* ENOTNAM */,
416                 [LINUX_ENAVAIL]         = EINVAL /* ENAVAIL */,
417                 [LINUX_EISNAM]          = EINVAL /* EISNAM */,
418                 [LINUX_EREMOTEIO]       = EINVAL /* EREMOTEIO */,
419                 [LINUX_EDQUOT]          = EDQUOT,
420                 [LINUX_ENOMEDIUM]       = EINVAL /* ENOMEDIUM */,
421                 [LINUX_EMEDIUMTYPE]     = EINVAL /* EMEDIUMTYPE */,
422         };
423         code = (int)ecode;
424         if (code >= 0) {
425                 sign = +1;
426         } else {
427                 sign = -1;
428                 code = -code;
429         }
430         if (code < (sizeof errno_xlate) / (sizeof errno_xlate[0])) {
431                 code = errno_xlate[code];
432                 LASSERT(code >= 0);
433         }
434         return sign * code;
435 }
436
437 enum {
438         LINUX_O_RDONLY   =           00,
439         LINUX_O_WRONLY   =           01,
440         LINUX_O_RDWR     =           02,
441         LINUX_O_CREAT    =         0100,
442         LINUX_O_EXCL     =         0200,
443         LINUX_O_NOCTTY   =         0400,
444         LINUX_O_TRUNC    =        01000,
445         LINUX_O_APPEND   =        02000,
446         LINUX_O_NONBLOCK =        04000,
447         LINUX_O_NDELAY   =             LINUX_O_NONBLOCK,
448         LINUX_O_SYNC     =       010000,
449         LINUX_O_FSYNC    =             LINUX_O_SYNC,
450         LINUX_O_ASYNC    =       020000,
451         LINUX_O_DIRECT   =       040000,
452         LINUX_O_NOFOLLOW =      0400000
453 };
454
455 static inline void obit_convert(int *cflag, int *sflag,
456                                 unsigned cmask, unsigned smask)
457 {
458         if (*cflag & cmask != 0) {
459                 *sflag |= smask;
460                 *cflag &= ~cmask;
461         }
462 }
463
464 /*
465  * convert <fcntl.h> flag from XNU client to Linux _i386_ server.
466  */
467 int convert_client_oflag(int cflag, int *result)
468 {
469         int sflag = 0;
470
471         cflag = 0;
472         obit_convert(&cflag, &sflag, O_RDONLY,   LINUX_O_RDONLY);
473         obit_convert(&cflag, &sflag, O_WRONLY,   LINUX_O_WRONLY);
474         obit_convert(&cflag, &sflag, O_RDWR,     LINUX_O_RDWR);
475         obit_convert(&cflag, &sflag, O_NONBLOCK, LINUX_O_NONBLOCK);
476         obit_convert(&cflag, &sflag, O_APPEND,   LINUX_O_APPEND);
477         obit_convert(&cflag, &sflag, O_ASYNC,    LINUX_O_ASYNC);
478         obit_convert(&cflag, &sflag, O_FSYNC,    LINUX_O_FSYNC);
479         obit_convert(&cflag, &sflag, O_NOFOLLOW, LINUX_O_NOFOLLOW);
480         obit_convert(&cflag, &sflag, O_CREAT,    LINUX_O_CREAT);
481         obit_convert(&cflag, &sflag, O_TRUNC,    LINUX_O_TRUNC);
482         obit_convert(&cflag, &sflag, O_EXCL,     LINUX_O_EXCL);
483         obit_convert(&cflag, &sflag, O_CREAT,    LINUX_O_CREAT);
484         obit_convert(&cflag, &sflag, O_NDELAY,   LINUX_O_NDELAY);
485         obit_convert(&cflag, &sflag, O_NOCTTY,   LINUX_O_NOCTTY);
486         /*
487          * Some more obscure BSD flags have no Linux counterparts:
488          *
489          * O_SHLOCK     0x0010
490          * O_EXLOCK     0x0020
491          * O_EVTONLY    0x8000
492          * O_POPUP      0x80000000
493          * O_ALERT      0x20000000
494          */
495         if (cflag == 0) {
496                 *result = sflag;
497                 return 0;
498         } else
499                 return -EINVAL;
500 }
501
502 #ifdef __DARWIN8__
503 #else /* !__DARWIN8__ */
504 extern int unix_syscall();
505 extern int unix_syscall_return();
506
507 extern int ktrsysret();
508 extern int ktrace();
509
510 extern int ast_taken();
511 extern int ast_check();
512
513 extern int trap();
514 extern int syscall_trace();
515
516 static int is_addr_in_range(void *addr, void *start, void *end)
517 {
518         return start <= addr && addr <= end;
519 }
520
521 extern void cfs_thread_agent (void);
522
523 static int is_last_frame(void *addr)
524 {
525         if (addr == NULL)
526                 return 1;
527         else if (is_addr_in_range(addr, unix_syscall, unix_syscall_return))
528                 return 1;
529         else if (is_addr_in_range(addr, ktrsysret, ktrace))
530                 return 1;
531         else if (is_addr_in_range(addr, ast_taken, ast_check))
532                 return 1;
533         else if (is_addr_in_range(addr, trap, syscall_trace))
534                 return 1;
535         else if (is_addr_in_range(addr, cfs_thread_agent, cfs_kernel_thread))
536                 return 1;
537         else
538                 return 0;
539 }
540
541 static void *get_frame(int i)
542 {
543         void *result;
544
545 #define CASE(i) case (i): result = __builtin_return_address(i); break
546         switch (i + 1) {
547                 CASE(1);
548                 CASE(2);
549                 CASE(3);
550                 CASE(4);
551                 CASE(5);
552                 CASE(6);
553                 CASE(7);
554                 CASE(8);
555                 CASE(9);
556                 CASE(10);
557                 CASE(11);
558                 CASE(12);
559                 CASE(13);
560                 CASE(14);
561                 CASE(15);
562                 CASE(16);
563                 CASE(17);
564                 CASE(18);
565                 CASE(19);
566                 CASE(20);
567         default:
568                 panic("impossible frame number: %d\n", i);
569                 result = NULL;
570         }
571         return result;
572 }
573
574 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
575 {
576         int i;
577
578         memset(trace, 0, sizeof *trace);
579         for (i = 0; i < sizeof_array(trace->frame); ++ i) {
580                 void *addr;
581
582                 addr = get_frame(i);
583                 trace->frame[i] = addr;
584                 if (is_last_frame(addr))
585                         break;
586         }
587 }
588
589 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
590 {
591         if (0 <= frame_no && frame_no < sizeof_array(trace->frame))
592                 return trace->frame[frame_no];
593         else
594                 return NULL;
595 }
596 #endif /* !__DARWIN8__ */