New C Runtime.
[repair.git] / Repair / RepairCompiler / MCC / Runtime / stack.c
1 /*
2 Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
4 Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
5 Copyright (c) 1999-2001 by Hewlett-Packard. All rights reserved.
6
7 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8 OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
9
10 Permission is hereby granted to use or copy this program
11 for any purpose,  provided the above notices are retained on all copies.
12 Permission to modify the code and to distribute modified code is granted,
13 provided the above notices are retained, and a notice that the code was
14 modified is included with the above copyright notice.
15  */
16
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <unistd.h>
24
25 #define ptr_t void *
26 #pragma weak __libc_stack_end
27 extern ptr_t __libc_stack_end;
28 #define word unsigned int
29 # define STAT_SKIP 27   /* Number of fields preceding startstack        */
30                         /* field in /proc/self/stat                     */
31 #define ABORT printf
32
33   ptr_t GC_linux_stack_base(void)
34   {
35     /* We read the stack base value from /proc/self/stat.  We do this   */
36     /* using direct I/O system calls in order to avoid calling malloc   */
37     /* in case REDIRECT_MALLOC is defined.                              */
38 #   define STAT_BUF_SIZE 4096
39 #   define STAT_READ read
40           /* Should probably call the real read, if read is wrapped.    */
41     char stat_buf[STAT_BUF_SIZE];
42     int f;
43     char c;
44     word result = 0;
45     size_t i, buf_offset = 0;
46
47     /* First try the easy way.  This should work for glibc 2.2  */
48       if (0 != &__libc_stack_end) {
49 #       ifdef IA64
50           /* Some versions of glibc set the address 16 bytes too        */
51           /* low while the initialization code is running.              */
52           if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) {
53             return __libc_stack_end + 0x10;
54           } /* Otherwise it's not safe to add 16 bytes and we fall      */
55             /* back to using /proc.                                     */
56 #       else
57           return __libc_stack_end;
58 #       endif
59       }
60     f = open("/proc/self/stat", O_RDONLY);
61     if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) {
62         ABORT("Couldn't read /proc/self/stat");
63     }
64     c = stat_buf[buf_offset++];
65     /* Skip the required number of fields.  This number is hopefully    */
66     /* constant across all Linux implementations.                       */
67       for (i = 0; i < STAT_SKIP; ++i) {
68         while (isspace(c)) c = stat_buf[buf_offset++];
69         while (!isspace(c)) c = stat_buf[buf_offset++];
70       }
71     while (isspace(c)) c = stat_buf[buf_offset++];
72     while (isdigit(c)) {
73       result *= 10;
74       result += c - '0';
75       c = stat_buf[buf_offset++];
76     }
77     close(f);
78     if (result < 0x10000000) ABORT("Absurd stack bottom value");
79     return (ptr_t)result;
80   }