Update Examples in dataflowAPI (#700)
[dyninst.git] / proccontrol / src / mmapalloc.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  *
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  *
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "common/src/Types.h"
32 #include "mmapalloc.h"
33 #include <sys/mman.h>
34 #include <string.h>
35
36 static const unsigned int linux_x86_64_mmap_flags_position = 26;
37 static const unsigned int linux_x86_64_mmap_size_position = 43;
38 static const unsigned int linux_x86_64_mmap_addr_position = 49;
39 static const unsigned int linux_x86_64_mmap_start_position = 4;
40 static const unsigned char linux_x86_64_call_mmap[] = {
41    0x90, 0x90, 0x90, 0x90,                         //nop,nop,nop,nop
42    0x48, 0x8d, 0x64, 0x24, 0x80,                   //lea    -128(%rsp),%rsp
43    0x49, 0xc7, 0xc0, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0,%r8
44    0x49, 0xc7, 0xc1, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0,%r9
45    0x49, 0xc7, 0xc2, 0x22, 0x00, 0x00, 0x00,       //mov    $0x22,%r10
46    0x48, 0xc7, 0xc2, 0x07, 0x00, 0x00, 0x00,       //mov    $0x7,%rdx
47    0x48, 0x31, 0xf6,                               //xor    %rsi,%rsi
48    0x48, 0xc7, 0xc6, 0x00, 0x00, 0x00, 0x00,       //mov    $<size>,%rsi
49    0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $<addr>,%rdi
50    0x00, 0x00, 0x00,                               //
51    0x48, 0xc7, 0xc0, 0x09, 0x00, 0x00, 0x00,       //mov    $0x9,%rax
52    0x0f, 0x05,                                     //syscall
53    0x48, 0x8d, 0xa4, 0x24, 0x80, 0x00, 0x00, 0x00, //lea    128(%rsp),%rsp
54    0xcc,                                           //Trap
55    0x90                                            //nop
56 };
57 static const unsigned int linux_x86_64_call_mmap_size = sizeof(linux_x86_64_call_mmap);
58
59 static const unsigned int linux_x86_64_munmap_size_position = 15;
60 static const unsigned int linux_x86_64_munmap_addr_position = 21;
61 static const unsigned int linux_x86_64_munmap_start_position = 4;
62 static const unsigned char linux_x86_64_call_munmap[] = {
63    0x90, 0x90, 0x90, 0x90,                         //nop,nop,nop,nop
64    0x48, 0x8d, 0x64, 0x24, 0x80,                   //lea    -128(%rsp),%rsp
65    0x48, 0x31, 0xf6,                               //xor    %rsi,%rsi
66    0x48, 0xc7, 0xc6, 0x00, 0x00, 0x00, 0x00,       //mov    $<size>,%rsi
67    0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $<addr>,%rdi
68    0x00, 0x00, 0x00,                               //
69    0x48, 0xc7, 0xc0, 0x0b, 0x00, 0x00, 0x00,       //mov    $0xb,%rax
70    0x0f, 0x05,                                     //syscall
71    0x48, 0x8d, 0xa4, 0x24, 0x80, 0x00, 0x00, 0x00, //lea    128(%rsp),%rsp
72    0xcc,                                           //Trap
73    0x90                                            //nop
74 };
75 static const unsigned int linux_x86_64_call_munmap_size = sizeof(linux_x86_64_call_munmap);
76
77 static const unsigned int linux_x86_mmap_flags_position = 20;
78 static const unsigned int linux_x86_mmap_size_position = 10;
79 static const unsigned int linux_x86_mmap_addr_position = 5;
80 static const unsigned int linux_x86_mmap_start_position = 4;
81 static const unsigned char linux_x86_call_mmap[] = {
82    0x90, 0x90, 0x90, 0x90,                //nop; nop; nop; nop
83    0xbb, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ebx  (addr)
84    0xb9, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ecx  (size)
85    0xba, 0x07, 0x00, 0x00, 0x00,          //mov    $0x7,%edx  (perms)
86    0xbe, 0x22, 0x00, 0x00, 0x00,          //mov    $0x22,%esi (flags)
87    0xbf, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%edi  (fd)
88    0xbd, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ebp  (offset)
89    0xb8, 0xc0, 0x00, 0x00, 0x00,          //mov    $0xc0,%eax (syscall)
90    0xcd, 0x80,                            //int    $0x80
91    0xcc,                                  //Trap
92    0x90                                   //nop
93 };
94 static const unsigned int linux_x86_call_mmap_size = sizeof(linux_x86_call_mmap);
95
96 static const unsigned int linux_x86_munmap_size_position = 10;
97 static const unsigned int linux_x86_munmap_addr_position = 5;
98 static const unsigned int linux_x86_munmap_start_position = 4;
99 static const unsigned char linux_x86_call_munmap[] = {
100    0x90, 0x90, 0x90, 0x90,                //nop; nop; nop; nop
101    0xbb, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ebx  (addr)
102    0xb9, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ecx  (size)
103    0xb8, 0xc0, 0x00, 0x00, 0x00,          //mov    $0x5b,%eax (syscall)
104    0xcd, 0x80,                            //int    $0x80
105    0xcc,                                  //Trap
106    0x90                                   //nop
107 };
108 static const unsigned int linux_x86_call_munmap_size = sizeof(linux_x86_call_munmap);
109
110 static const unsigned int linux_ppc32_mmap_flags_hi_position = 34;
111 static const unsigned int linux_ppc32_mmap_flags_lo_position = 38;
112 static const unsigned int linux_ppc32_mmap_size_hi_position = 18;
113 static const unsigned int linux_ppc32_mmap_size_lo_position = 22;
114 static const unsigned int linux_ppc32_mmap_addr_hi_position = 10;
115 static const unsigned int linux_ppc32_mmap_addr_lo_position = 14;
116 static const unsigned int linux_ppc32_mmap_start_position = 4;
117 static const unsigned char linux_ppc32_call_mmap[] = {
118    0x60, 0x00, 0x00, 0x00,            // nop
119    0x38, 0x00, 0x00, 0x5a,            // li      r0,<syscall>
120    0x3c, 0x60, 0x00, 0x00,            // lis     r3,<addr_hi>
121    0x60, 0x63, 0x00, 0x00,            // ori     r3,r3,<addr_lo>
122    0x3c, 0x80, 0x00, 0x00,            // lis     r4,<size_hi>
123    0x60, 0x84, 0x00, 0x00,            // ori     r4,r4,<size_lo>
124    0x3c, 0xa0, 0x00, 0x00,            // lis     r5,<perms_hi>
125    0x60, 0xa5, 0x00, 0x07,            // ori     r5,r5,<perms_lo>
126    0x3c, 0xc0, 0x00, 0x00,            // lis     r6,<flags_hi>
127    0x60, 0xc6, 0x00, 0x00,            // ori     r6,r6,<flags_lo>
128    0x3c, 0xe0, 0xff, 0xff,            // lis     r7,<fd_hi>
129    0x60, 0xe7, 0xff, 0xff,            // ori     r7,r7,<fd_lo>
130    0x3d, 0x00, 0x00, 0x00,            // lis     r8,<offset>
131    0x44, 0x00, 0x00, 0x02,            // sc
132    0x7d, 0x82, 0x10, 0x08,            // trap
133    0x60, 0x00, 0x00, 0x00             // nop
134 };
135 static const unsigned int linux_ppc32_call_mmap_size = sizeof(linux_ppc32_call_mmap);
136
137 static const unsigned int linux_ppc32_munmap_size_hi_position = 18;
138 static const unsigned int linux_ppc32_munmap_size_lo_position = 22;
139 static const unsigned int linux_ppc32_munmap_addr_hi_position = 10;
140 static const unsigned int linux_ppc32_munmap_addr_lo_position = 14;
141 static const unsigned int linux_ppc32_munmap_start_position = 4;
142 static const unsigned char linux_ppc32_call_munmap[] = {
143    0x60, 0x60, 0x60, 0x60,              // nop
144    0x38, 0x00, 0x00, 0x5b,              // li      r0,<syscall>
145    0x3c, 0x60, 0x00, 0x00,              // lis     r3,<addr_hi>
146    0x60, 0x63, 0x00, 0x00,              // ori     r3,r3,<addr_lo>
147    0x3c, 0x80, 0x00, 0x00,              // lis     r4,<size_hi>
148    0x60, 0x84, 0x00, 0x00,              // ori     r4,r4,<size_lo>
149    0x44, 0x00, 0x00, 0x02,              // sc
150    0x7d, 0x82, 0x10, 0x08,              // trap
151    0x60, 0x00, 0x00, 0x00               // nop
152 };
153 static const unsigned int linux_ppc32_call_munmap_size = sizeof(linux_ppc32_call_munmap);
154
155 static const unsigned int linux_ppc64_mmap_start_position = 4;
156 static const unsigned int linux_ppc64_mmap_addr_highest_position =    2;
157 static const unsigned int linux_ppc64_mmap_addr_higher_position =     3;
158 static const unsigned int linux_ppc64_mmap_addr_hi_position =         5;
159 static const unsigned int linux_ppc64_mmap_addr_lo_position =         6;
160 static const unsigned int linux_ppc64_mmap_size_highest_position =    7;
161 static const unsigned int linux_ppc64_mmap_size_higher_position =     8;
162 static const unsigned int linux_ppc64_mmap_size_hi_position =        10;
163 static const unsigned int linux_ppc64_mmap_size_lo_position =        11;
164 static const unsigned int linux_ppc64_mmap_flags_highest_position =  17;
165 static const unsigned int linux_ppc64_mmap_flags_higher_position =   18;
166 static const unsigned int linux_ppc64_mmap_flags_hi_position =       20;
167 static const unsigned int linux_ppc64_mmap_flags_lo_position =       21;
168 static const uint32_t linux_ppc64_call_mmap[] = {
169    /*  0 */ 0x60000000,              // nop
170    /*  1 */ 0x3800005a,              // li      r0,<syscall>
171    /*  2 */ 0x3c600000,              // lis     r3,<addr_highest>
172    /*  3 */ 0x60630000,              // ori     r3,r3,<addr_higher>
173    /*  4 */ 0x786307c6,              // rldicr  r3,r3,0x32,0x31,
174    /*  5 */ 0x64630000,              // oris    r3,r3,<addr_hi>
175    /*  6 */ 0x60630000,              // ori     r3,r3,<addr_lo>
176    /*  7 */ 0x3c800000,              // lis     r4,<size_highest>
177    /*  8 */ 0x60840000,              // ori     r4,r4,<size_higher>
178    /*  9 */ 0x788407c6,              // rldicr  r4,r4,0x32,0x31,
179    /* 10 */ 0x64840000,              // oris    r4,r4,<size_hi>
180    /* 11 */ 0x60840000,              // ori     r4,r4,<size_lo>
181    /* 12 */ 0x3ca00000,              // lis     r5,<perms_highest>
182    /* 13 */ 0x60a50000,              // ori     r5,r5,<perms_higher>
183    /* 14 */ 0x78a507c6,              // rldicr  r5,r5,0x32,0x31,
184    /* 15 */ 0x64a50000,              // oris    r5,r5,<perms_hi>
185    /* 16 */ 0x60a50007,              // ori     r5,r5,<perms_lo>
186    /* 17 */ 0x3cc00000,              // lis     r6,<flags_highest>
187    /* 18 */ 0x60c60000,              // ori     r6,r6,<flags_higher>
188    /* 19 */ 0x78c607c6,              // rldicr  r6,r6,0x32,0x31,
189    /* 20 */ 0x64c60000,              // oris    r6,r6,<flags_hi>
190    /* 21 */ 0x60c60000,              // ori     r6,r6,<flags_lo>
191    /* 22 */ 0x3ce00000,              // lis     r7,<fd=-1>
192    /* 23 */ 0x7ce73bb8,              // nand    r7,r7,r7
193    /* 24 */ 0x3d000000,              // lis     r8,<offset>
194    /* 25 */ 0x44000002,              // sc
195    /* 26 */ 0x7d821008,              // trap
196    /* 27 */ 0x60000000               // nop
197 };
198 static const unsigned int linux_ppc64_call_mmap_size = sizeof(linux_ppc64_call_mmap);
199
200 static const unsigned int linux_ppc64_munmap_start_position = 4;
201 static const unsigned int linux_ppc64_munmap_addr_highest_position =  2;
202 static const unsigned int linux_ppc64_munmap_addr_higher_position =   3;
203 static const unsigned int linux_ppc64_munmap_addr_hi_position =       5;
204 static const unsigned int linux_ppc64_munmap_addr_lo_position =       6;
205 static const unsigned int linux_ppc64_munmap_size_highest_position =  7;
206 static const unsigned int linux_ppc64_munmap_size_higher_position =   8;
207 static const unsigned int linux_ppc64_munmap_size_hi_position =      10;
208 static const unsigned int linux_ppc64_munmap_size_lo_position =      11;
209 static const uint32_t linux_ppc64_call_munmap[] = {
210    /*  0 */ 0x60000000,              // nop
211    /*  1 */ 0x3800005b,              // li      r0,<syscall>
212    /*  2 */ 0x3c600000,              // lis     r3,<addr_highest>
213    /*  3 */ 0x60630000,              // ori     r3,r3,<addr_higher>
214    /*  4 */ 0x786307c6,              // rldicr  r3,r3,0x32,0x31,
215    /*  5 */ 0x64630000,              // oris    r3,r3,<addr_hi>
216    /*  6 */ 0x60630000,              // ori     r3,r3,<addr_lo>
217    /*  7 */ 0x3c800000,              // lis     r4,<size_highest>
218    /*  8 */ 0x60840000,              // ori     r4,r4,<size_higher>
219    /*  9 */ 0x788407c6,              // rldicr  r4,r4,0x32,0x31,
220    /* 10 */ 0x64840000,              // oris    r4,r4,<size_hi>
221    /* 11 */ 0x60840000,              // ori     r4,r4,<size_lo>
222    /* 12 */ 0x44000002,              // sc
223    /* 13 */ 0x7d821008,              // trap
224    /* 14 */ 0x60000000               // nop
225 };
226 static const unsigned int linux_ppc64_call_munmap_size = sizeof(linux_ppc64_call_munmap);
227
228 //aarch64
229 //mov
230 //31-21 | 20 - 5 | 4 - 0
231 //      | imm    | reg
232 static const unsigned int linux_aarch64_mmap_start_position = 4;
233 static const unsigned int linux_aarch64_mmap_addr_position =  8;
234 static const unsigned int linux_aarch64_mmap_size_position =  linux_aarch64_mmap_addr_position +16;
235 static const unsigned int linux_aarch64_mmap_flags_position = linux_aarch64_mmap_size_position + 16;
236 static const unsigned char linux_aarch64_call_mmap[] = {
237     // _NR_mmap 1058
238     0xd5, 0x03, 0x20, 0x1f,         // nop              ;mmap(void *addr, size_t size, int _prot,
239                                     //                  ;   int _flags, int _fd, _off_t offset)
240     //0xd2, 0x80, 0x84, 0x48,       // mov x8, #d1058   ;pass sys call number
241     0xd2, 0x80, 0x1b, 0xc8,         // mov x8, #222   ;pass sys call number,
242                                     //222 is correct, 1058 can lead to invalid return val
243
244     0xd2, 0x80, 0x00, 0x00,         // mov  x0, #0           ;<addr>
245     0xf2, 0xa0, 0x00, 0x00,         // movk x0, #0, lsl #16     ;<addr>
246     0xf2, 0xc0, 0x00, 0x00,         // movk x0, #0, lsl #32     ;<addr>
247     0xf2, 0xe0, 0x00, 0x00,         // movk x0, #0, lsl #48     ;<addr>
248
249     0xd2, 0x80, 0x00, 0x01,         // mov  x1, #0               ;<size>
250     0xf2, 0xa0, 0x00, 0x01,         // movk x1, #0, lsl #16      ;<size>
251     0xf2, 0xc0, 0x00, 0x01,         // movk x1, #0, lsl #32      ;<size>
252     0xf2, 0xe0, 0x00, 0x01,         // movk x1, #0, lsl #48      ;<size>
253
254     0xd2, 0x80, 0x00, 0x03,         // mov x3, #0x00            ;<flags>
255     0xf2, 0xa0, 0x00, 0x03,         // movk x3, #0x00, lsl #16      ;<flags>
256     //0xf2, 0xc0, 0x00, 0x03,         // movk x3, #0x00, lsl #32      ;<flags>
257     //0xf2, 0xe0, 0x00, 0x03,         // movk x3, #0x00, lsl #48      ;<flags>
258
259     0xd2, 0x80, 0x00, 0xe2,             // mov x2, #0x7     ;<prot>
260     0xd2, 0x80, 0x00, 0x04,             // mov x4  #0       ;fd
261     0xd2, 0x80, 0x00, 0x05,             // mov x5, #0       ;offset
262
263     0xd4, 0x00, 0x00, 0x01,             // svc #0           ;system call
264     0xd4, 0x20, 0x00, 0x00,             // brk #0           ;trap?
265     0xd5, 0x03, 0x20, 0x1f              // nop
266 };
267 static const unsigned int linux_aarch64_call_mmap_size = sizeof(linux_aarch64_call_mmap);
268
269 static const unsigned int linux_aarch64_munmap_start_position = 4;
270 static const unsigned int linux_aarch64_munmap_addr_position =  8;
271 static const unsigned int linux_aarch64_munmap_size_position = linux_aarch64_munmap_addr_position + 16;
272 static const unsigned char linux_aarch64_call_munmap[] = {
273     0xd5, 0x03, 0x20, 0x1f,             // nop              ;munmap(void *addr, int size)
274     0xd2, 0x80, 0x1a, 0xe8,         // mov x8, #d215    ;pass sys call number
275
276     0xd2, 0x80, 0x00, 0x00,         // mov x0, #0       ;&addr
277     0xf2, 0xa0, 0x00, 0x00,         // mov x0, #0, lsl #16     ;<addr>
278     0xf2, 0xc0, 0x00, 0x00,         // mov x0, #0, lsl #32     ;<addr>
279     0xf2, 0xe0, 0x00, 0x00,         // mov x0, #0, lsl #48     ;<addr>
280
281     0xd2, 0x80, 0x00, 0x01,         // mov x1, #0               ;size
282     0xf2, 0xa0, 0x00, 0x01,         // mov x1, #0, lsl #16      ;<size>
283     0xf2, 0xc0, 0x00, 0x01,         // mov x1, #0, lsl #32      ;<size>
284     0xf2, 0xe0, 0x00, 0x01,         // mov x1, #0, lsl #48      ;<size>
285
286     0xd4, 0x00, 0x00, 0x01,             // svc #0
287     0xd4, 0x20, 0x00, 0x00,             // brk #0
288     0xd5, 0x03, 0x20, 0x1f              // nop
289 };
290 static const unsigned int linux_aarch64_call_munmap_size = sizeof(linux_aarch64_call_munmap);
291
292 static const unsigned int freebsd_x86_64_mmap_flags_position = 21;
293 static const unsigned int freebsd_x86_64_mmap_size_position = 34;
294 static const unsigned int freebsd_x86_64_mmap_addr_position = 44;
295 static const unsigned int freebsd_x86_64_mmap_start_position = 4;
296 static const unsigned char freebsd_x86_64_call_mmap[] = {
297    0x90, 0x90, 0x90, 0x90,                         //nop sled
298    0x49, 0xc7, 0xc1, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0,%r9 (offset)
299    0x49, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff,       //mov    $0xffffffffffffffff,%r8 (fd)
300    0x49, 0xc7, 0xc2, 0x12, 0x10, 0x00, 0x00,       //mov    $0x1012,%r10 (flags)
301    0x48, 0xc7, 0xc2, 0x07, 0x00, 0x00, 0x00,       //mov    $0x7,%rdx (perms)
302    0x48, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rsi (size)
303    0x00, 0x00, 0x00,                               //
304    0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rdi (addr)
305    0x00, 0x00, 0x00,                               //
306    0xb8, 0xdd, 0x01, 0x00, 0x00,                   //mov    $0x1dd,%eax (SYS_mmap)
307    0x0f, 0x05,                                     //syscall
308    0xcc,                                           //trap
309    0x90                                            //nop
310 };
311 static const unsigned int freebsd_x86_64_call_mmap_size = sizeof(freebsd_x86_64_call_mmap);
312
313 static const unsigned int freebsd_x86_64_munmap_size_position = 6;
314 static const unsigned int freebsd_x86_64_munmap_addr_position = 16;
315 static const unsigned int freebsd_x86_64_munmap_start_position = 4;
316 static const unsigned char freebsd_x86_64_call_munmap[] = {
317    0x90, 0x90, 0x90, 0x90,                         //nop sled
318    0x48, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rsi
319    0x00, 0x00, 0x00,                               //
320    0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rdi
321    0x00, 0x00, 0x00,                               //
322    0xb8, 0x49, 0x00, 0x00, 0x00,                   //mov    $0x49,%eax
323    0x0f, 0x05,                                     //syscall
324    0xcc,                                           //trap
325    0x90                                            //nop
326 };
327 static const unsigned int freebsd_x86_64_call_munmap_size = sizeof(freebsd_x86_64_call_munmap);
328
329 static const unsigned int freebsd_x86_mmap_flags_position = 9;
330 static const unsigned int freebsd_x86_mmap_size_position = 16;
331 static const unsigned int freebsd_x86_mmap_addr_position = 21;
332 static const unsigned int freebsd_x86_mmap_start_position = 4;
333 static const unsigned char freebsd_x86_call_mmap[] = {
334    0x90, 0x90, 0x90, 0x90,                         //nop sled
335    0x6a, 0x00,                                     //push   $0x0 (offset)
336    0x6a, 0xff,                                     //push   $0xffffffff (fd)
337    0x68, 0x12, 0x10, 0x00, 0x00,                   //push   $0x1012 (flags)
338    0x6a, 0x07,                                     //push   $0x7 (perms)
339    0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (size)
340    0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (addr)
341    0xb8, 0xdd, 0x01, 0x00, 0x00,                   //mov    $0x1dd,%eax (SYS_mmap)
342    0x50,                                           //push   %eax (required by calling convention)
343    0xcd, 0x80,                                     //int    $0x80
344    0x8d, 0x64, 0x24, 0x1c,                         //lea    0x1c(%esp),%esp
345    0xcc,                                           //trap
346    0x90                                            //nop
347 };
348 static const unsigned int freebsd_x86_call_mmap_size = sizeof(freebsd_x86_call_mmap);
349
350 static const unsigned int freebsd_x86_munmap_size_position = 5;
351 static const unsigned int freebsd_x86_munmap_addr_position = 10;
352 static const unsigned int freebsd_x86_munmap_start_position = 4;
353 static const unsigned char freebsd_x86_call_munmap[] = {
354    0x90, 0x90, 0x90, 0x90,                         //nop sled
355    0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (size)
356    0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (addr)
357    0xb8, 0x49, 0x00, 0x00, 0x00,                   //mov    $0x49,%eax (SYS_munmap)
358    0x50,                                           //push   %eax (required by calling convention)
359    0xcd, 0x80,                                     //int    $0x80
360    0x8d, 0x64, 0x24, 0x0c,                         //lea    0xc(%esp),%esp
361    0xcc,                                           //trap
362    0x90                                            //nop
363 };
364 static const unsigned int freebsd_x86_call_munmap_size = sizeof(freebsd_x86_call_munmap);
365
366 mmap_alloc_process::mmap_alloc_process(Dyninst::PID p, std::string e, std::vector<std::string> a,
367                                        std::vector<std::string> envp, std::map<int,int> f) :
368    int_process(p, e, a, envp, f)
369 {
370 }
371
372 mmap_alloc_process::mmap_alloc_process(Dyninst::PID pid_, int_process *p) :
373    int_process(pid_, p)
374 {
375 }
376
377 mmap_alloc_process::~mmap_alloc_process()
378 {
379 }
380
381 // For compatibility
382 #ifndef MAP_ANONYMOUS
383 #define MAP_ANONYMOUS MAP_ANON
384 #endif
385
386 bool mmap_alloc_process::plat_collectAllocationResult(int_thread *thr, reg_response::ptr resp)
387 {
388     switch (getTargetArch())
389     {
390         case Arch_x86_64: {
391             bool result = thr->getRegister(x86_64::rax, resp);
392             assert(result);
393             if(!result) return false;
394             break;
395         }
396         case Arch_x86: {
397             bool result = thr->getRegister(x86::eax, resp);
398             assert(result);
399             if(!result) return false;
400             break;
401         }
402         case Arch_ppc32: {
403             bool result = thr->getRegister(ppc32::r3, resp);
404             assert(result);
405             if(!result) return false;
406             break;
407         }
408         case Arch_ppc64: {
409             bool result = thr->getRegister(ppc64::r3, resp);
410             assert(result);
411                 if(!result) return false;
412             break;
413         }
414         case Arch_aarch64: {
415             bool result = thr->getRegister(aarch64::x0, resp);
416             assert(result);
417                     if(!result) return false;
418             break;
419         }
420         default:
421             assert(0);
422             break;
423     }
424     return true;
425 }
426
427 bool mmap_alloc_process::plat_createAllocationSnippet(Dyninst::Address addr, bool use_addr, unsigned long size,
428                                                       void* &buffer, unsigned long &buffer_size,
429                                                       unsigned long &start_offset)
430 {
431     int flags = MAP_ANONYMOUS | MAP_PRIVATE;
432     if (use_addr)
433         flags |= MAP_FIXED;
434     else
435         addr = 0x0;
436
437     if (getTargetArch() == Arch_x86_64 || getTargetArch() == Arch_x86) {
438         const void *buf_tmp = NULL;
439         unsigned addr_size = 0;
440         unsigned addr_pos = 0;
441         unsigned flags_pos = 0;
442         unsigned size_pos = 0;
443
444         bool use_linux = (getOS() == Dyninst::Linux);
445         bool use_bsd = (getOS() == Dyninst::FreeBSD);
446         bool use_64 = (getTargetArch() == Arch_x86_64);
447
448         if (use_linux && use_64) {
449            buf_tmp = linux_x86_64_call_mmap;
450            buffer_size = linux_x86_64_call_mmap_size;
451            start_offset = linux_x86_64_mmap_start_position;
452            addr_pos = linux_x86_64_mmap_addr_position;
453            flags_pos = linux_x86_64_mmap_flags_position;
454            size_pos = linux_x86_64_mmap_size_position;
455            addr_size = 8;
456         }
457         else if (use_bsd && use_64) {
458            buf_tmp = freebsd_x86_64_call_mmap;
459            buffer_size = freebsd_x86_64_call_mmap_size;
460            start_offset = freebsd_x86_64_mmap_start_position;
461            addr_pos = freebsd_x86_64_mmap_addr_position;
462            flags_pos = freebsd_x86_64_mmap_flags_position;
463            size_pos = freebsd_x86_64_mmap_size_position;
464            addr_size = 8;
465         }
466         else if (use_linux && !use_64) {
467            buf_tmp = linux_x86_call_mmap;
468            buffer_size = linux_x86_call_mmap_size;
469            start_offset = linux_x86_mmap_start_position;
470            addr_pos = linux_x86_mmap_addr_position;
471            flags_pos = linux_x86_mmap_flags_position;
472            size_pos = linux_x86_mmap_size_position;
473            addr_size = 4;
474         }
475         else if (use_bsd && !use_64) {
476            buf_tmp = freebsd_x86_call_mmap;
477            buffer_size = freebsd_x86_call_mmap_size;
478            start_offset = freebsd_x86_mmap_start_position;
479            addr_pos = freebsd_x86_mmap_addr_position;
480            flags_pos = freebsd_x86_mmap_flags_position;
481            size_pos = freebsd_x86_mmap_size_position;
482            addr_size = 4;
483         }
484         else {
485            assert(0); //Fill in the entry in mmapalloc.h for this system
486         }
487
488         buffer = malloc(buffer_size);
489         memcpy(buffer, buf_tmp, buffer_size);
490
491         //Assuming endianess of debugger and debugee match.
492         *((unsigned int *) (((char *) buffer)+size_pos)) = size;
493         *((unsigned int *) (((char *) buffer)+flags_pos)) = flags;
494         if (addr_size == 8)
495             *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
496         else if (addr_size == 4)
497             *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
498         else
499             assert(0);
500    }
501     else  if (getTargetArch() == Arch_ppc32) {
502         unsigned int flags_hi_position;
503         unsigned int flags_lo_position;
504         unsigned int size_hi_position;
505         unsigned int size_lo_position;
506         unsigned int addr_hi_position;
507         unsigned int addr_lo_position;
508         const void *buf_tmp;
509
510         //BlueGene can share the linux allocation snippet.
511         bool use_linux = (getOS() == Linux || getOS() == BlueGeneP || getOS() == BlueGeneL);
512
513         if (use_linux) {
514            flags_hi_position = linux_ppc32_mmap_flags_hi_position;
515            flags_lo_position = linux_ppc32_mmap_flags_lo_position;
516            size_hi_position = linux_ppc32_mmap_size_hi_position;
517            size_lo_position = linux_ppc32_mmap_size_lo_position;
518            addr_hi_position = linux_ppc32_mmap_addr_hi_position;
519            addr_lo_position = linux_ppc32_mmap_addr_lo_position;
520            start_offset = linux_ppc32_mmap_start_position;
521            buffer_size = linux_ppc32_call_mmap_size;
522            buf_tmp = linux_ppc32_call_mmap;
523         }
524         else {
525            assert(0); //Fill in the entry in mmapalloc.h for this system
526         }
527
528         buffer = malloc(buffer_size);
529         memcpy(buffer, buf_tmp, buffer_size);
530
531         // Assuming endianess of debugger and debuggee match
532         *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
533         *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
534         *((uint16_t *) (((char *) buffer)+flags_hi_position)) = (uint16_t)(flags >> 16);
535         *((uint16_t *) (((char *) buffer)+flags_lo_position)) = (uint16_t)flags;
536         *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
537         *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
538    }
539    else if (getTargetArch() == Arch_ppc64) {
540       unsigned int flags_highest_position;
541       unsigned int flags_higher_position;
542       unsigned int flags_hi_position;
543       unsigned int flags_lo_position;
544       unsigned int size_highest_position;
545       unsigned int size_higher_position;
546       unsigned int size_hi_position;
547       unsigned int size_lo_position;
548       unsigned int addr_highest_position;
549       unsigned int addr_higher_position;
550       unsigned int addr_hi_position;
551       unsigned int addr_lo_position;
552       const void *buf_tmp;
553
554       //BlueGene can share the linux allocation snippet.
555       bool use_linux = (getOS() == Linux || getOS() == BlueGeneQ);
556
557       if (use_linux) {
558          flags_highest_position = linux_ppc64_mmap_flags_highest_position;
559          flags_higher_position = linux_ppc64_mmap_flags_higher_position;
560          flags_hi_position = linux_ppc64_mmap_flags_hi_position;
561          flags_lo_position = linux_ppc64_mmap_flags_lo_position;
562          size_highest_position = linux_ppc64_mmap_size_highest_position;
563          size_higher_position = linux_ppc64_mmap_size_higher_position;
564          size_hi_position = linux_ppc64_mmap_size_hi_position;
565          size_lo_position = linux_ppc64_mmap_size_lo_position;
566          addr_highest_position = linux_ppc64_mmap_addr_highest_position;
567          addr_higher_position = linux_ppc64_mmap_addr_higher_position;
568          addr_hi_position = linux_ppc64_mmap_addr_hi_position;
569          addr_lo_position = linux_ppc64_mmap_addr_lo_position;
570          start_offset = linux_ppc64_mmap_start_position;
571          buffer_size = linux_ppc64_call_mmap_size;
572          buf_tmp = linux_ppc64_call_mmap;
573       }
574       else {
575          assert(0); //Fill in the entry in mmapalloc.h for this system
576       }
577       buffer = malloc(buffer_size);
578       memcpy(buffer, buf_tmp, buffer_size);
579
580       uint32_t *pwords = (uint32_t *)buffer;
581
582       // MJMTODO - Assumes endianess of debugger and debuggee match
583       pwords[size_highest_position]  |= (uint32_t)(((uint64_t)size >> 48) & 0x0000ffff);
584       pwords[size_higher_position]   |= (uint32_t)(((uint64_t)size >> 32) & 0x0000ffff);
585       pwords[size_hi_position]       |= (uint32_t)(((uint64_t)size >> 16) & 0x0000ffff);
586       pwords[size_lo_position]       |= (uint32_t)((uint64_t)size & 0x0000ffff);
587       pwords[flags_highest_position] |= (uint32_t)(((uint64_t)flags >> 48) & 0x0000ffff);
588       pwords[flags_higher_position]  |= (uint32_t)(((uint64_t)flags >> 32) & 0x0000ffff);
589       pwords[flags_hi_position]      |= (uint32_t)(((uint64_t)flags >> 16) & 0x0000ffff);
590       pwords[flags_lo_position]      |= (uint32_t)((uint64_t)flags & 0x0000ffff);
591       pwords[addr_highest_position]  |= (uint32_t)(((uint64_t)addr >> 48) & 0x0000ffff);
592       pwords[addr_higher_position]   |= (uint32_t)(((uint64_t)addr >> 32) & 0x0000ffff);
593       pwords[addr_hi_position]       |= (uint32_t)(((uint64_t)addr >> 16) & 0x0000ffff);
594       pwords[addr_lo_position]       |= (uint32_t)((uint64_t)addr & 0x0000ffff);
595     } else if( getTargetArch() == Arch_aarch64 ){
596         const void *buf_tmp;
597         unsigned int addr_pos, size_pos, flags_pos;
598
599         bool use_linux = ( getOS() == Linux );
600
601         if (use_linux) {
602            start_offset             = linux_aarch64_mmap_start_position;
603            buffer_size              = linux_aarch64_call_mmap_size;
604            buf_tmp                  = linux_aarch64_call_mmap;
605            addr_pos                 = linux_aarch64_mmap_addr_position;
606            size_pos                 = linux_aarch64_mmap_size_position;
607            flags_pos                = linux_aarch64_mmap_flags_position;
608         }
609         else {
610            assert(0); //Fill in the entry in mmapalloc.h for this system
611         }
612         buffer = malloc(buffer_size);
613         memcpy(buffer, buf_tmp, buffer_size);
614
615         // To avoid the matter of endianness, I decided to operate on byte.
616         pthrd_printf("ARM-info: create alloc snippet...\n");
617 #define BYTE_ASSGN(POS, VAL) \
618             (*(((char *) buffer) + POS + 1)) |= ((VAL>>11)&0x1f);\
619             (*(((char *) buffer) + POS + 2)) |= ((VAL>> 3)&0xff);\
620             (*(((char *) buffer) + POS + 3)) |= ((VAL<< 5)&0xf0);
621
622         BYTE_ASSGN(addr_pos,    (uint16_t)(addr)     )
623         BYTE_ASSGN(addr_pos+4,  (uint16_t)(addr>>16) )
624         BYTE_ASSGN(addr_pos+8,  (uint16_t)(addr>>32) )
625         BYTE_ASSGN(addr_pos+12, (uint16_t)(addr>>48) )
626
627         BYTE_ASSGN(size_pos,    (uint16_t)(size) )
628         BYTE_ASSGN(size_pos+4,  (uint16_t)(size>>16) )
629         BYTE_ASSGN(size_pos+8,  (uint16_t)(size>>32) )
630         BYTE_ASSGN(size_pos+12, (uint16_t)(size>>48) )
631
632         BYTE_ASSGN(flags_pos,    (uint16_t)(flags) )
633         BYTE_ASSGN(flags_pos+4,  (uint16_t)(flags>>16) )
634         //BYTE_ASSGN(flags_pos+8,  (uint16_t)(flags>>32) )
635         //BYTE_ASSGN(flags_pos+12, (uint16_t)(flags>>48) )
636
637         //according to experiments, aarch64 is little-endian
638         //the byte order with a word should be re-arranged
639 #define SWAP4BYTE(POS) \
640             ((char *)buffer)[POS+3]^= ((char*)buffer)[POS]; \
641             ((char *)buffer)[POS]  ^= ((char*)buffer)[POS+3]; \
642             ((char *)buffer)[POS+3]^= ((char*)buffer)[POS]; \
643             ((char *)buffer)[POS+2]^= ((char*)buffer)[POS+1]; \
644             ((char *)buffer)[POS+1]^= ((char*)buffer)[POS+2]; \
645             ((char *)buffer)[POS+2]^= ((char*)buffer)[POS+1];
646
647         for(unsigned int i=0; i < buffer_size ; i+=4){
648             SWAP4BYTE(i)
649         }
650
651 //debug
652 #if 1
653         pthrd_printf("ARM-info: dump alloc snippet...\n");
654         pthrd_printf("addr %ld, 0x%lx\n", addr, addr);
655         pthrd_printf("size %ld, 0x%lx\n", size, size);
656         pthrd_printf("flags 0x%x:\n", flags);
657
658         for(unsigned int i = 0; i< buffer_size ; i+=4){
659             pthrd_printf("0x%8x\n", *((unsigned int *)(((char *)buffer)+i)) );
660         }
661
662 #endif
663
664     }else{
665         assert(0);
666     }
667
668     return true;
669 }
670
671 bool mmap_alloc_process::plat_createDeallocationSnippet(Dyninst::Address addr,
672                                                         unsigned long size, void* &buffer,
673                                                         unsigned long &buffer_size,
674                                                         unsigned long &start_offset)
675 {
676    if (getTargetArch() == Arch_x86_64 || getTargetArch() == Arch_x86) {
677        const void *buf_tmp = NULL;
678        unsigned addr_size = 0;
679        unsigned addr_pos = 0;
680        unsigned size_pos = 0;
681
682        bool use_linux = (getOS() == Dyninst::Linux);
683        bool use_bsd = (getOS() == Dyninst::FreeBSD);
684        bool use_64 = (getTargetArch() == Arch_x86_64);
685
686        if (use_linux && use_64) {
687           buf_tmp = linux_x86_64_call_munmap;
688           buffer_size = linux_x86_64_call_munmap_size;
689           start_offset = linux_x86_64_munmap_start_position;
690           addr_pos = linux_x86_64_munmap_addr_position;
691           size_pos = linux_x86_64_munmap_size_position;
692           addr_size = 8;
693        }
694        else if (use_bsd && use_64) {
695           buf_tmp = freebsd_x86_64_call_munmap;
696           buffer_size = freebsd_x86_64_call_munmap_size;
697           start_offset = freebsd_x86_64_munmap_start_position;
698           addr_pos = freebsd_x86_64_munmap_addr_position;
699           size_pos = freebsd_x86_64_munmap_size_position;
700           addr_size = 8;
701        }
702        else if (use_linux && !use_64) {
703           buf_tmp = linux_x86_call_munmap;
704           buffer_size = linux_x86_call_munmap_size;
705           start_offset = linux_x86_munmap_start_position;
706           addr_pos = linux_x86_munmap_addr_position;
707           size_pos = linux_x86_munmap_size_position;
708           addr_size = 4;
709        }
710        else if (use_bsd && !use_64) {
711           buf_tmp = freebsd_x86_call_munmap;
712           buffer_size = freebsd_x86_call_munmap_size;
713           start_offset = freebsd_x86_munmap_start_position;
714           addr_pos = freebsd_x86_munmap_addr_position;
715           size_pos = freebsd_x86_munmap_size_position;
716           addr_size = 4;
717        }
718        else {
719           assert(0);
720        }
721
722        buffer = malloc(buffer_size);
723        memcpy(buffer, buf_tmp, buffer_size);
724
725        //Assuming endianess of debugger and debugee match.
726        *((unsigned int *) (((char *) buffer)+size_pos)) = size;
727        if (addr_size == 8)
728           *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
729        else if (addr_size == 4)
730           *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
731        else
732           assert(0);
733    }
734    else if (getTargetArch() == Arch_ppc32) {
735       unsigned int size_hi_position;
736       unsigned int size_lo_position;
737       unsigned int addr_hi_position;
738       unsigned int addr_lo_position;
739       const void *buf_tmp = NULL;
740
741       bool use_linux = (getOS() == Linux || getOS() == BlueGeneP || getOS() == BlueGeneL);
742       if (use_linux) {
743          buf_tmp = linux_ppc32_call_munmap;
744          size_hi_position = linux_ppc32_munmap_size_hi_position;
745          size_lo_position = linux_ppc32_munmap_size_lo_position;
746          addr_hi_position = linux_ppc32_munmap_addr_hi_position;
747          addr_lo_position = linux_ppc32_munmap_addr_lo_position;
748          buffer_size = linux_ppc32_call_munmap_size;
749          start_offset = linux_ppc32_munmap_start_position;
750       }
751       else {
752          assert(0);
753       }
754
755        buffer = malloc(buffer_size);
756        memcpy(buffer, buf_tmp, buffer_size);
757
758        // Assuming endianess of debugger and debuggee match
759        *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
760        *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
761        *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
762        *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
763    }
764    else if( getTargetArch() == Arch_ppc64 ) {
765       unsigned int size_highest_position;
766       unsigned int size_higher_position;
767       unsigned int size_hi_position;
768       unsigned int size_lo_position;
769       unsigned int addr_highest_position;
770       unsigned int addr_higher_position;
771       unsigned int addr_hi_position;
772       unsigned int addr_lo_position;
773       const void *buf_tmp = NULL;
774
775       bool use_linux = (getOS() == Linux || getOS() == BlueGeneQ);
776       if (use_linux) {
777          buf_tmp = linux_ppc64_call_munmap;
778          size_highest_position = linux_ppc64_munmap_size_highest_position;
779          size_higher_position = linux_ppc64_munmap_size_higher_position;
780          size_hi_position = linux_ppc64_munmap_size_hi_position;
781          size_lo_position = linux_ppc64_munmap_size_lo_position;
782          addr_highest_position = linux_ppc64_munmap_addr_highest_position;
783          addr_higher_position = linux_ppc64_munmap_addr_higher_position;
784          addr_hi_position = linux_ppc64_munmap_addr_hi_position;
785          addr_lo_position = linux_ppc64_munmap_addr_lo_position;
786          buffer_size = linux_ppc64_call_munmap_size;
787          start_offset = linux_ppc64_munmap_start_position;
788       }
789       else {
790          assert(0);
791       }
792
793       buffer = malloc(buffer_size);
794       memcpy(buffer, buf_tmp, buffer_size);
795
796       uint32_t *pwords = (uint32_t *)buffer;
797
798       // MJMTODO - Assumes endianess of debugger and debuggee match
799       pwords[size_highest_position] |= (uint32_t)(((uint64_t)size >> 48) & 0x0000ffff);
800       pwords[size_higher_position]  |= (uint32_t)(((uint64_t)size >> 32) & 0x0000ffff);
801       pwords[size_hi_position]      |= (uint32_t)(((uint64_t)size >> 16) & 0x0000ffff);
802       pwords[size_lo_position]      |= (uint32_t)((uint64_t)size & 0x0000ffff);
803       pwords[addr_highest_position] |= (uint32_t)(((uint64_t)addr >> 48) & 0x0000ffff);
804       pwords[addr_higher_position]  |= (uint32_t)(((uint64_t)addr >> 32) & 0x0000ffff);
805       pwords[addr_hi_position]      |= (uint32_t)(((uint64_t)addr >> 16) & 0x0000ffff);
806       pwords[addr_lo_position]      |= (uint32_t)((uint64_t)addr & 0x0000ffff);
807    }
808    else if( getTargetArch() == Arch_aarch64 ) {
809         const void *buf_tmp = NULL;
810         unsigned int addr_size;
811         unsigned int addr_pos;
812         unsigned int size_pos;
813
814         bool use_linux = (getOS() == Linux );
815         if (use_linux) {
816             buf_tmp             = linux_aarch64_call_munmap;
817             buffer_size         = linux_aarch64_call_munmap_size;
818             start_offset        = linux_aarch64_munmap_start_position;
819             addr_pos            = linux_aarch64_munmap_addr_position;
820             size_pos            = linux_aarch64_munmap_size_position;
821             addr_size           = 8;
822         }
823         else {
824            assert(0);
825         }
826
827         buffer = malloc(buffer_size);
828         memcpy(buffer, buf_tmp, buffer_size);
829
830         pthrd_printf("ARM-info: create de-alloc snippet...\n");
831
832         BYTE_ASSGN(addr_pos,    (uint16_t)(addr)     )
833         BYTE_ASSGN(addr_pos+4,  (uint16_t)(addr>>16) )
834         BYTE_ASSGN(addr_pos+8,  (uint16_t)(addr>>32) )
835         BYTE_ASSGN(addr_pos+12, (uint16_t)(addr>>48) )
836
837         BYTE_ASSGN(size_pos,    (uint16_t)(size) )
838         BYTE_ASSGN(size_pos+4,  (uint16_t)(size>>16) )
839         BYTE_ASSGN(size_pos+8,  (uint16_t)(size>>32) )
840         BYTE_ASSGN(size_pos+12, (uint16_t)(size>>48) )
841
842         //swap 4bytes
843         for(unsigned int i=0; i<buffer_size; i+=4){
844             SWAP4BYTE(i)
845         }
846
847         // Assuming endianess of debugger and debuggee match
848         assert(addr_size == 8);
849    }
850    else {
851       assert(0);
852    }
853
854    return true;
855 }