1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <stdio.h>
28 #include <stdio_ext.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <strings.h>
34 #include <dirent.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/int_fmtio.h>
38 #include <libproc.h>
39
40 typedef struct look_arg {
41 int pflags;
42 const char *lwps;
43 int count;
44 } look_arg_t;
45
46 static int look(char *);
47 static int lwplook(look_arg_t *, const lwpstatus_t *, const lwpsinfo_t *);
48 static char *prflags(int);
49 static char *prwhy(int);
50 static char *prwhat(int, int);
51 static void dumpregs(const prgregset_t, int);
52 #if defined(__sparc) && defined(_ILP32)
53 static void dumpregs_v8p(const prgregset_t, const prxregset_t *, int);
54 #endif
55
56 static char *command;
57 static struct ps_prochandle *Pr;
58
59 static int is64; /* Is current process 64-bit? */
60 static int rflag; /* Show registers? */
61
62 #define LWPFLAGS \
63 (PR_STOPPED|PR_ISTOP|PR_DSTOP|PR_ASLEEP|PR_PCINVAL|PR_STEP \
64 |PR_AGENT|PR_DETACH|PR_DAEMON)
65
66 #define PROCFLAGS \
67 (PR_ISSYS|PR_VFORKP|PR_ORPHAN|PR_NOSIGCHLD|PR_WAITPID \
68 |PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_MSFORK|PR_PTRACE)
69
70 #define ALLFLAGS (LWPFLAGS|PROCFLAGS)
71
72 int
main(int argc,char ** argv)73 main(int argc, char **argv)
74 {
75 int rc = 0;
76 int errflg = 0;
77 int opt;
78 struct rlimit rlim;
79
80 if ((command = strrchr(argv[0], '/')) != NULL)
81 command++;
82 else
83 command = argv[0];
84
85 /* options */
86 while ((opt = getopt(argc, argv, "r")) != EOF) {
87 switch (opt) {
88 case 'r': /* show registers */
89 rflag = 1;
90 break;
91 default:
92 errflg = 1;
93 break;
94 }
95 }
96
97 argc -= optind;
98 argv += optind;
99
100 if (errflg || argc <= 0) {
101 (void) fprintf(stderr,
102 "usage:\t%s [-r] { pid | core }[/lwps] ...\n", command);
103 (void) fprintf(stderr, " (report process status flags)\n");
104 (void) fprintf(stderr, " -r : report registers\n");
105 return (2);
106 }
107
108 /*
109 * Make sure we'll have enough file descriptors to handle a target
110 * that has many many mappings.
111 */
112 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
113 rlim.rlim_cur = rlim.rlim_max;
114 (void) setrlimit(RLIMIT_NOFILE, &rlim);
115 (void) enable_extended_FILE_stdio(-1, -1);
116 }
117
118 while (argc-- > 0)
119 rc += look(*argv++);
120
121 return (rc);
122 }
123
124 static int
look(char * arg)125 look(char *arg)
126 {
127 int gcode;
128 int gcode2;
129 pstatus_t pstatus;
130 psinfo_t psinfo;
131 int flags;
132 sigset_t sigmask;
133 fltset_t fltmask;
134 sysset_t entryset;
135 sysset_t exitset;
136 uint32_t sigtrace, sigtrace1, sigtrace2, fltbits;
137 uint32_t sigpend, sigpend1, sigpend2;
138 uint32_t *bits;
139 char buf[PRSIGBUFSZ];
140 look_arg_t lookarg;
141
142 if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_ANY,
143 PGRAB_RETAIN | PGRAB_FORCE | PGRAB_RDONLY | PGRAB_NOSTOP, &gcode,
144 &lookarg.lwps)) == NULL) {
145 if (gcode == G_NOPROC &&
146 proc_arg_psinfo(arg, PR_ARG_PIDS, &psinfo, &gcode2) > 0 &&
147 psinfo.pr_nlwp == 0) {
148 (void) printf("%d:\t<defunct>\n\n", (int)psinfo.pr_pid);
149 return (0);
150 }
151 (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
152 command, arg, Pgrab_error(gcode));
153 return (1);
154 }
155
156 (void) memcpy(&pstatus, Pstatus(Pr), sizeof (pstatus_t));
157 (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
158 proc_unctrl_psinfo(&psinfo);
159
160 if (psinfo.pr_nlwp == 0) {
161 (void) printf("%d:\t<defunct>\n\n", (int)psinfo.pr_pid);
162 Prelease(Pr, PRELEASE_RETAIN);
163 return (0);
164 }
165
166 is64 = (pstatus.pr_dmodel == PR_MODEL_LP64);
167
168 sigmask = pstatus.pr_sigtrace;
169 fltmask = pstatus.pr_flttrace;
170 entryset = pstatus.pr_sysentry;
171 exitset = pstatus.pr_sysexit;
172
173 if (Pstate(Pr) == PS_DEAD) {
174 (void) printf("core '%s' of %d:\t%.70s\n",
175 arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
176 } else {
177 (void) printf("%d:\t%.70s\n",
178 (int)psinfo.pr_pid, psinfo.pr_psargs);
179 }
180
181 (void) printf("\tdata model = %s", is64? "_LP64" : "_ILP32");
182 if ((flags = (pstatus.pr_flags & PROCFLAGS)) != 0)
183 (void) printf(" flags = %s", prflags(flags));
184 (void) printf("\n");
185
186 fltbits = *((uint32_t *)&fltmask);
187 if (fltbits)
188 (void) printf("\tflttrace = 0x%.8x\n", fltbits);
189
190 #if (MAXSIG > 2 * 32) && (MAXSIG <= 3 * 32) /* assumption */
191 sigtrace = *((uint32_t *)&sigmask);
192 sigtrace1 = *((uint32_t *)&sigmask + 1);
193 sigtrace2 = *((uint32_t *)&sigmask + 2);
194 #else
195 #error "fix me: MAXSIG out of bounds"
196 #endif
197 if (sigtrace | sigtrace1 | sigtrace2)
198 (void) printf("\tsigtrace = 0x%.8x 0x%.8x 0x%.8x\n\t %s\n",
199 sigtrace, sigtrace1, sigtrace2,
200 proc_sigset2str(&sigmask, "|", 1, buf, sizeof (buf)));
201
202 bits = ((uint32_t *)&entryset);
203 if (bits[0] | bits[1] | bits[2] | bits[3] |
204 bits[4] | bits[5] | bits[6] | bits[7])
205 (void) printf(
206 "\tentryset = "
207 "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
208 "\t "
209 "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
210 bits[0], bits[1], bits[2], bits[3],
211 bits[4], bits[5], bits[6], bits[7]);
212
213 bits = ((uint32_t *)&exitset);
214 if (bits[0] | bits[1] | bits[2] | bits[3] |
215 bits[4] | bits[5] | bits[6] | bits[7])
216 (void) printf(
217 "\texitset = "
218 "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n"
219 "\t "
220 "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
221 bits[0], bits[1], bits[2], bits[3],
222 bits[4], bits[5], bits[6], bits[7]);
223
224 #if (MAXSIG > 2 * 32) && (MAXSIG <= 3 * 32) /* assumption */
225 sigpend = *((uint32_t *)&pstatus.pr_sigpend);
226 sigpend1 = *((uint32_t *)&pstatus.pr_sigpend + 1);
227 sigpend2 = *((uint32_t *)&pstatus.pr_sigpend + 2);
228 #else
229 #error "fix me: MAXSIG out of bounds"
230 #endif
231 if (sigpend | sigpend1 | sigpend2)
232 (void) printf("\tsigpend = 0x%.8x,0x%.8x,0x%.8x\n",
233 sigpend, sigpend1, sigpend2);
234
235 lookarg.pflags = pstatus.pr_flags;
236 lookarg.count = 0;
237 (void) Plwp_iter_all(Pr, (proc_lwp_all_f *)lwplook, &lookarg);
238
239 if (lookarg.count == 0)
240 (void) printf("No matching lwps found");
241
242 (void) printf("\n");
243 Prelease(Pr, PRELEASE_RETAIN);
244
245 return (0);
246 }
247
248 static int
lwplook_zombie(const lwpsinfo_t * pip)249 lwplook_zombie(const lwpsinfo_t *pip)
250 {
251 (void) printf(" /%d:\t<defunct>\n", (int)pip->pr_lwpid);
252 return (0);
253 }
254
255 static int
lwplook(look_arg_t * arg,const lwpstatus_t * psp,const lwpsinfo_t * pip)256 lwplook(look_arg_t *arg, const lwpstatus_t *psp, const lwpsinfo_t *pip)
257 {
258 int flags;
259 uint32_t sighold, sighold1, sighold2;
260 uint32_t sigpend, sigpend1, sigpend2;
261 int cursig;
262 char buf[32];
263
264 if (!proc_lwp_in_set(arg->lwps, pip->pr_lwpid))
265 return (0);
266
267 arg->count++;
268
269 if (psp == NULL)
270 return (lwplook_zombie(pip));
271
272 /*
273 * PR_PCINVAL is just noise if the lwp is not stopped.
274 * Don't bother reporting it unless the lwp is stopped.
275 */
276 flags = psp->pr_flags & LWPFLAGS;
277 if (!(flags & PR_STOPPED))
278 flags &= ~PR_PCINVAL;
279
280 (void) printf(" /%d:\tflags = %s", (int)psp->pr_lwpid, prflags(flags));
281 if ((flags & PR_ASLEEP) || (psp->pr_syscall &&
282 !(arg->pflags & PR_ISSYS))) {
283 if (flags & PR_ASLEEP) {
284 if ((flags & ~PR_ASLEEP) != 0)
285 (void) printf("|");
286 (void) printf("ASLEEP");
287 }
288 if (psp->pr_syscall && !(arg->pflags & PR_ISSYS)) {
289 uint_t i;
290
291 (void) printf(" %s(",
292 proc_sysname(psp->pr_syscall, buf, sizeof (buf)));
293 for (i = 0; i < psp->pr_nsysarg; i++) {
294 if (i != 0)
295 (void) printf(",");
296 (void) printf("0x%lx", psp->pr_sysarg[i]);
297 }
298 (void) printf(")");
299 }
300 }
301 (void) printf("\n");
302
303 if (flags & PR_STOPPED) {
304 (void) printf("\twhy = %s", prwhy(psp->pr_why));
305 if (psp->pr_why != PR_REQUESTED &&
306 psp->pr_why != PR_SUSPENDED)
307 (void) printf(" what = %s",
308 prwhat(psp->pr_why, psp->pr_what));
309 (void) printf("\n");
310 }
311
312 #if (MAXSIG > 2 * 32) && (MAXSIG <= 3 * 32) /* assumption */
313 sighold = *((uint32_t *)&psp->pr_lwphold);
314 sighold1 = *((uint32_t *)&psp->pr_lwphold + 1);
315 sighold2 = *((uint32_t *)&psp->pr_lwphold + 2);
316 sigpend = *((uint32_t *)&psp->pr_lwppend);
317 sigpend1 = *((uint32_t *)&psp->pr_lwppend + 1);
318 sigpend2 = *((uint32_t *)&psp->pr_lwppend + 2);
319 #else
320 #error "fix me: MAXSIG out of bounds"
321 #endif
322 cursig = psp->pr_cursig;
323
324 if (sighold | sighold1 | sighold2)
325 (void) printf("\tsigmask = 0x%.8x,0x%.8x,0x%.8x\n",
326 sighold, sighold1, sighold2);
327 if (sigpend | sigpend1 | sigpend2)
328 (void) printf("\tlwppend = 0x%.8x,0x%.8x,0x%.8x\n",
329 sigpend, sigpend1, sigpend2);
330 if (cursig)
331 (void) printf("\tcursig = %s\n",
332 proc_signame(cursig, buf, sizeof (buf)));
333
334 if (rflag) {
335 if (Pstate(Pr) == PS_DEAD || (arg->pflags & PR_STOPPED)) {
336 #if defined(__sparc) && defined(_ILP32)
337 /*
338 * If we're SPARC/32-bit, see if we can get extra
339 * register state for this lwp. If it's a v8plus
340 * program, print the 64-bit register values.
341 */
342 prxregset_t prx;
343
344 if (Plwp_getxregs(Pr, psp->pr_lwpid, &prx) == 0 &&
345 prx.pr_type == XR_TYPE_V8P)
346 dumpregs_v8p(psp->pr_reg, &prx, is64);
347 else
348 #endif /* __sparc && _ILP32 */
349 dumpregs(psp->pr_reg, is64);
350 } else
351 (void) printf("\tNot stopped, can't show registers\n");
352 }
353
354 return (0);
355 }
356
357 static char *
prflags(int arg)358 prflags(int arg)
359 {
360 static char code_buf[200];
361 char *str = code_buf;
362
363 if (arg == 0)
364 return ("0");
365
366 if (arg & ~ALLFLAGS)
367 (void) sprintf(str, "0x%x", arg & ~ALLFLAGS);
368 else
369 *str = '\0';
370
371 /*
372 * Display the semi-permanent lwp flags first.
373 */
374 if (arg & PR_DAEMON) /* daemons are always detached so */
375 (void) strcat(str, "|DAEMON");
376 else if (arg & PR_DETACH) /* report detach only if non-daemon */
377 (void) strcat(str, "|DETACH");
378
379 if (arg & PR_STOPPED)
380 (void) strcat(str, "|STOPPED");
381 if (arg & PR_ISTOP)
382 (void) strcat(str, "|ISTOP");
383 if (arg & PR_DSTOP)
384 (void) strcat(str, "|DSTOP");
385 #if 0 /* displayed elsewhere */
386 if (arg & PR_ASLEEP)
387 (void) strcat(str, "|ASLEEP");
388 #endif
389 if (arg & PR_PCINVAL)
390 (void) strcat(str, "|PCINVAL");
391 if (arg & PR_STEP)
392 (void) strcat(str, "|STEP");
393 if (arg & PR_AGENT)
394 (void) strcat(str, "|AGENT");
395 if (arg & PR_ISSYS)
396 (void) strcat(str, "|ISSYS");
397 if (arg & PR_VFORKP)
398 (void) strcat(str, "|VFORKP");
399 if (arg & PR_ORPHAN)
400 (void) strcat(str, "|ORPHAN");
401 if (arg & PR_NOSIGCHLD)
402 (void) strcat(str, "|NOSIGCHLD");
403 if (arg & PR_WAITPID)
404 (void) strcat(str, "|WAITPID");
405 if (arg & PR_FORK)
406 (void) strcat(str, "|FORK");
407 if (arg & PR_RLC)
408 (void) strcat(str, "|RLC");
409 if (arg & PR_KLC)
410 (void) strcat(str, "|KLC");
411 if (arg & PR_ASYNC)
412 (void) strcat(str, "|ASYNC");
413 if (arg & PR_BPTADJ)
414 (void) strcat(str, "|BPTADJ");
415 if (arg & PR_MSACCT)
416 (void) strcat(str, "|MSACCT");
417 if (arg & PR_MSFORK)
418 (void) strcat(str, "|MSFORK");
419 if (arg & PR_PTRACE)
420 (void) strcat(str, "|PTRACE");
421
422 if (*str == '|')
423 str++;
424
425 return (str);
426 }
427
428 static char *
prwhy(int why)429 prwhy(int why)
430 {
431 static char buf[20];
432 char *str;
433
434 switch (why) {
435 case PR_REQUESTED:
436 str = "PR_REQUESTED";
437 break;
438 case PR_SIGNALLED:
439 str = "PR_SIGNALLED";
440 break;
441 case PR_SYSENTRY:
442 str = "PR_SYSENTRY";
443 break;
444 case PR_SYSEXIT:
445 str = "PR_SYSEXIT";
446 break;
447 case PR_JOBCONTROL:
448 str = "PR_JOBCONTROL";
449 break;
450 case PR_FAULTED:
451 str = "PR_FAULTED";
452 break;
453 case PR_SUSPENDED:
454 str = "PR_SUSPENDED";
455 break;
456 default:
457 str = buf;
458 (void) sprintf(str, "%d", why);
459 break;
460 }
461
462 return (str);
463 }
464
465 static char *
prwhat(int why,int what)466 prwhat(int why, int what)
467 {
468 static char buf[32];
469 char *str;
470
471 switch (why) {
472 case PR_SIGNALLED:
473 case PR_JOBCONTROL:
474 str = proc_signame(what, buf, sizeof (buf));
475 break;
476 case PR_SYSENTRY:
477 case PR_SYSEXIT:
478 str = proc_sysname(what, buf, sizeof (buf));
479 break;
480 case PR_FAULTED:
481 str = proc_fltname(what, buf, sizeof (buf));
482 break;
483 default:
484 (void) sprintf(str = buf, "%d", what);
485 break;
486 }
487
488 return (str);
489 }
490
491 #if defined(__sparc)
492 static const char * const regname[NPRGREG] = {
493 " %g0", " %g1", " %g2", " %g3", " %g4", " %g5", " %g6", " %g7",
494 " %o0", " %o1", " %o2", " %o3", " %o4", " %o5", " %sp", " %o7",
495 " %l0", " %l1", " %l2", " %l3", " %l4", " %l5", " %l6", " %l7",
496 " %i0", " %i1", " %i2", " %i3", " %i4", " %i5", " %fp", " %i7",
497 #ifdef __sparcv9
498 "%ccr", " %pc", "%npc", " %y", "%asi", "%fprs"
499 #else
500 "%psr", " %pc", "%npc", " %y", "%wim", "%tbr"
501 #endif
502 };
503 #endif /* __sparc */
504
505 #if defined(__amd64)
506 static const char * const regname[NPRGREG] = {
507 "%r15", "%r14", "%r13", "%r12", "%r11", "%r10", " %r9", " %r8",
508 "%rdi", "%rsi", "%rbp", "%rbx", "%rdx", "%rcx", "%rax", "%trapno",
509 "%err", "%rip", " %cs", "%rfl", "%rsp", " %ss", " %fs", " %gs",
510 " %es", " %ds", "%fsbase", "%gsbase"
511 };
512
513 static const char * const regname32[NPRGREG32] = {
514 " %gs", " %fs", " %es", " %ds", "%edi", "%esi", "%ebp", "%esp",
515 "%ebx", "%edx", "%ecx", "%eax", "%trapno", "%err", "%eip", " %cs",
516 "%efl", "%uesp", " %ss"
517 };
518
519 /* XX64 Do we want to expose this through libproc */
520 void
prgregset_n_to_32(const prgreg_t * src,prgreg32_t * dst)521 prgregset_n_to_32(const prgreg_t *src, prgreg32_t *dst)
522 {
523 bzero(dst, NPRGREG32 * sizeof (prgreg32_t));
524 dst[GS] = src[REG_GS];
525 dst[FS] = src[REG_FS];
526 dst[DS] = src[REG_DS];
527 dst[ES] = src[REG_ES];
528 dst[EDI] = src[REG_RDI];
529 dst[ESI] = src[REG_RSI];
530 dst[EBP] = src[REG_RBP];
531 dst[EBX] = src[REG_RBX];
532 dst[EDX] = src[REG_RDX];
533 dst[ECX] = src[REG_RCX];
534 dst[EAX] = src[REG_RAX];
535 dst[TRAPNO] = src[REG_TRAPNO];
536 dst[ERR] = src[REG_ERR];
537 dst[EIP] = src[REG_RIP];
538 dst[CS] = src[REG_CS];
539 dst[EFL] = src[REG_RFL];
540 dst[UESP] = src[REG_RSP];
541 dst[SS] = src[REG_SS];
542 }
543
544 #elif defined(__i386)
545 static const char * const regname[NPRGREG] = {
546 " %gs", " %fs", " %es", " %ds", "%edi", "%esi", "%ebp", "%esp",
547 "%ebx", "%edx", "%ecx", "%eax", "%trapno", "%err", "%eip", " %cs",
548 "%efl", "%uesp", " %ss"
549 };
550 #endif /* __i386 */
551
552 #if defined(__amd64) && defined(_LP64)
553 static void
dumpregs32(const prgregset_t reg)554 dumpregs32(const prgregset_t reg)
555 {
556 prgregset32_t reg32;
557 int i;
558
559 prgregset_n_to_32(reg, reg32);
560
561 for (i = 0; i < NPRGREG32; i++) {
562 (void) printf(" %s = 0x%.8X",
563 regname32[i], reg32[i]);
564 if ((i+1) % 4 == 0)
565 (void) putchar('\n');
566 }
567 if (i % 4 != 0)
568 (void) putchar('\n');
569 }
570 #endif
571
572 static void
dumpregs(const prgregset_t reg,int is64)573 dumpregs(const prgregset_t reg, int is64)
574 {
575 int width = is64? 16 : 8;
576 int cols = is64? 2 : 4;
577 int i;
578
579 #if defined(__amd64) && defined(_LP64)
580 if (!is64) {
581 dumpregs32(reg);
582 return;
583 }
584 #endif
585
586 for (i = 0; i < NPRGREG; i++) {
587 (void) printf(" %s = 0x%.*lX",
588 regname[i], width, (long)reg[i]);
589 if ((i+1) % cols == 0)
590 (void) putchar('\n');
591 }
592 if (i % cols != 0)
593 (void) putchar('\n');
594 }
595
596 #if defined(__sparc) && defined(_ILP32)
597 static void
dumpregs_v8p(const prgregset_t reg,const prxregset_t * xreg,int is64)598 dumpregs_v8p(const prgregset_t reg, const prxregset_t *xreg, int is64)
599 {
600 static const uint32_t zero[8] = { 0 };
601 int gr, xr, cols = 2;
602 uint64_t xval;
603
604 if (memcmp(xreg->pr_un.pr_v8p.pr_xg, zero, sizeof (zero)) == 0 &&
605 memcmp(xreg->pr_un.pr_v8p.pr_xo, zero, sizeof (zero)) == 0) {
606 dumpregs(reg, is64);
607 return;
608 }
609
610 for (gr = R_G0, xr = XR_G0; gr <= R_G7; gr++, xr++) {
611 xval = (uint64_t)xreg->pr_un.pr_v8p.pr_xg[xr] << 32 |
612 (uint64_t)(uint32_t)reg[gr];
613 (void) printf(" %s = 0x%.16" PRIX64, regname[gr], xval);
614 if ((gr + 1) % cols == 0)
615 (void) putchar('\n');
616 }
617
618 for (gr = R_O0, xr = XR_O0; gr <= R_O7; gr++, xr++) {
619 xval = (uint64_t)xreg->pr_un.pr_v8p.pr_xo[xr] << 32 |
620 (uint64_t)(uint32_t)reg[gr];
621 (void) printf(" %s = 0x%.16" PRIX64, regname[gr], xval);
622 if ((gr + 1) % cols == 0)
623 (void) putchar('\n');
624 }
625
626 for (gr = R_L0; gr < NPRGREG; gr++) {
627 (void) printf(" %s = 0x%.8lX",
628 regname[gr], (long)reg[gr]);
629 if ((gr + 1) % cols == 0)
630 (void) putchar('\n');
631 }
632
633 if (gr % cols != 0)
634 (void) putchar('\n');
635 }
636 #endif /* __sparc && _ILP32 */
637