1 /**
2  * This module exposes functionality for inspecting and manipulating memory.
3  *
4  * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
5  *            All rights reserved.
6  * License:
7  *  This software is provided 'as-is', without any express or implied
8  *  warranty. In no event will the authors be held liable for any damages
9  *  arising from the use of this software.
10  *
11  *  Permission is granted to anyone to use this software for any purpose,
12  *  including commercial applications, and to alter it and redistribute it
13  *  freely, in both source and binary form, subject to the following
14  *  restrictions:
15  *
16  *  o  The origin of this software must not be misrepresented; you must not
17  *     claim that you wrote the original software. If you use this software
18  *     in a product, an acknowledgment in the product documentation would be
19  *     appreciated but is not required.
20  *  o  Altered source versions must be plainly marked as such, and must not
21  *     be misrepresented as being the original software.
22  *  o  This notice may not be removed or altered from any source
23  *     distribution.
24  * Authors:   Walter Bright, Sean Kelly
25  */
26 module rt.compiler.dmd.rt.memory;
27 
28 
29 private
30 {
31     version( linux )
32     {
33         version = SimpleLibcStackEnd;
34 
35         version( SimpleLibcStackEnd )
36         {
37             extern (C) extern void* __libc_stack_end;
38         }
39     }
40     version( OSX )
41     {
42         extern (C)
43         {
44             extern void* __osx_stack_end;    // set by D startup code
45         }
46     }
47     version( freebsd )
48     {
49         extern (C)
50         {
51             extern void* __libc_stack_end;
52         }
53     }
54 
55 }
56 
57 
58 /**
59  *
60  */
61 extern (C) void* rt_stackBottom()
62 {
63     version( Win32 )
64     {
65         asm
66         {
67             naked;
68             mov EAX,FS:4;
69             ret;
70         }
71     }
72     else version( linux )
73     {
74         version( SimpleLibcStackEnd ) {
75             return __libc_stack_end;
76         } else {
77             // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
78                 static void** libc_stack_end;
79 
80                 if( libc_stack_end == libc_stack_end.init )
81                 {
82                     void* handle = dlopen( null, RTLD_NOW );
83                     libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
84                     dlclose( handle );
85                 }
86                 return *libc_stack_end;
87         }
88     } else version( darwin ) {
89         return __osx_stack_end;
90     } else version( freebsd ) {
91         return __libc_stack_end;
92     } else {
93         static assert( false, "Operating system not supported." );
94     }
95 }
96 
97 
98 /**
99  *
100  */
101 extern (C) void* rt_stackTop()
102 {
103     version( D_InlineAsm_X86 )
104     {
105         asm
106         {
107             naked;
108             mov EAX, ESP;
109             ret;
110         }
111     }
112     else version( D_InlineAsm_X86_64 )
113     {
114         asm
115         {
116             naked;
117             mov RAX, RSP;
118             ret;
119         }
120     }
121     else
122     {
123             static assert( false, "Architecture not supported." );
124     }
125 }
126 
127 
128 private
129 {
130     version( Win32 )
131     {
132         extern (C)
133         {
134             extern int _xi_a;   // &_xi_a just happens to be start of data segment
135             extern int _edata;  // &_edata is start of BSS segment
136             extern int _end;    // &_end is past end of BSS
137         }
138     }
139     else version( linux )
140     {
141         extern (C)
142         {
143             extern int _data;
144             extern int __data_start;
145             extern int _end;
146             extern int _data_start__;
147             extern int _data_end__;
148             extern int _bss_start__;
149             extern int _bss_end__;
150             extern int __fini_array_end;
151         }
152 
153             alias __data_start  Data_Start;
154             alias _end          Data_End;
155     }
156 
157     alias void delegate( void*, void* ) scanFn;
158 
159     version (FreeBSD)
160     {
161         extern (C)
162         {
163         extern char etext;
164         extern int _end;
165         }
166     }
167 
168     version (Solaris)
169     {
170         extern (C)
171         {
172             extern char etext;
173             extern int _end;
174         }
175     }
176 }
177 
178 /**
179  *
180  */
181 extern (C) void rt_scanStaticData( scanFn scan )
182 {
183     version( Win32 )
184     {
185         scan( &_xi_a, &_end );
186     }
187     else version( linux )
188     {
189         scan( &__data_start, &_end );
190     }
191     else version( darwin ){
192         // already ranges already added through osxgc.c functions
193     }
194     else version (FreeBSD)
195     {
196         scan( &etext, &_end );
197     }
198     else version (Solaris)
199     {
200         scan( &etext, &_end );
201     }
202     else
203     {
204         static assert( false, "Operating system not supported." );
205     }
206 }