1) Cmake support for PPC64LE builds
[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_size;
598         unsigned int addr_pos, size_pos, flags_pos;
599
600         bool use_linux = ( getOS() == Linux );
601
602         if (use_linux) {
603            start_offset             = linux_aarch64_mmap_start_position;
604            buffer_size              = linux_aarch64_call_mmap_size;
605            buf_tmp                  = linux_aarch64_call_mmap;
606            addr_pos                 = linux_aarch64_mmap_addr_position;
607            size_pos                 = linux_aarch64_mmap_size_position;
608            flags_pos                = linux_aarch64_mmap_flags_position;
609            addr_size = 8;
610         }
611         else {
612            assert(0); //Fill in the entry in mmapalloc.h for this system
613         }
614         buffer = malloc(buffer_size);
615         memcpy(buffer, buf_tmp, buffer_size);
616
617         // To avoid the matter of endianness, I decided to operate on byte.
618         pthrd_printf("ARM-info: create alloc snippet...\n");
619 #define BYTE_ASSGN(POS, VAL) \
620             (*(((char *) buffer) + POS + 1)) |= ((VAL>>11)&0x1f);\
621             (*(((char *) buffer) + POS + 2)) |= ((VAL>> 3)&0xff);\
622             (*(((char *) buffer) + POS + 3)) |= ((VAL<< 5)&0xf0);
623
624         BYTE_ASSGN(addr_pos,    (uint16_t)(addr)     )
625         BYTE_ASSGN(addr_pos+4,  (uint16_t)(addr>>16) )
626         BYTE_ASSGN(addr_pos+8,  (uint16_t)(addr>>32) )
627         BYTE_ASSGN(addr_pos+12, (uint16_t)(addr>>48) )
628
629         BYTE_ASSGN(size_pos,    (uint16_t)(size) )
630         BYTE_ASSGN(size_pos+4,  (uint16_t)(size>>16) )
631         BYTE_ASSGN(size_pos+8,  (uint16_t)(size>>32) )
632         BYTE_ASSGN(size_pos+12, (uint16_t)(size>>48) )
633
634         BYTE_ASSGN(flags_pos,    (uint16_t)(flags) )
635         BYTE_ASSGN(flags_pos+4,  (uint16_t)(flags>>16) )
636         //BYTE_ASSGN(flags_pos+8,  (uint16_t)(flags>>32) )
637         //BYTE_ASSGN(flags_pos+12, (uint16_t)(flags>>48) )
638
639         //according to experiments, aarch64 is little-endian
640         //the byte order with a word should be re-arranged
641 #define SWAP4BYTE(POS) \
642             ((char *)buffer)[POS+3]^= ((char*)buffer)[POS]; \
643             ((char *)buffer)[POS]  ^= ((char*)buffer)[POS+3]; \
644             ((char *)buffer)[POS+3]^= ((char*)buffer)[POS]; \
645             ((char *)buffer)[POS+2]^= ((char*)buffer)[POS+1]; \
646             ((char *)buffer)[POS+1]^= ((char*)buffer)[POS+2]; \
647             ((char *)buffer)[POS+2]^= ((char*)buffer)[POS+1];
648
649         for(unsigned int i=0; i < buffer_size ; i+=4){
650             SWAP4BYTE(i)
651         }
652
653 //debug
654 #if 1
655         pthrd_printf("ARM-info: dump alloc snippet...\n");
656         pthrd_printf("addr %ld, 0x%lx\n", addr, addr);
657         pthrd_printf("size %ld, 0x%lx\n", size, size);
658         pthrd_printf("flags 0x%x:\n", flags);
659
660         for(unsigned int i = 0; i< buffer_size ; i+=4){
661             pthrd_printf("0x%8x\n", *((unsigned int *)(((char *)buffer)+i)) );
662         }
663
664 #endif
665
666     }else{
667         assert(0);
668     }
669
670     return true;
671 }
672
673 bool mmap_alloc_process::plat_createDeallocationSnippet(Dyninst::Address addr,
674                                                         unsigned long size, void* &buffer,
675                                                         unsigned long &buffer_size,
676                                                         unsigned long &start_offset)
677 {
678    if (getTargetArch() == Arch_x86_64 || getTargetArch() == Arch_x86) {
679        const void *buf_tmp = NULL;
680        unsigned addr_size = 0;
681        unsigned addr_pos = 0;
682        unsigned size_pos = 0;
683
684        bool use_linux = (getOS() == Dyninst::Linux);
685        bool use_bsd = (getOS() == Dyninst::FreeBSD);
686        bool use_64 = (getTargetArch() == Arch_x86_64);
687
688        if (use_linux && use_64) {
689           buf_tmp = linux_x86_64_call_munmap;
690           buffer_size = linux_x86_64_call_munmap_size;
691           start_offset = linux_x86_64_munmap_start_position;
692           addr_pos = linux_x86_64_munmap_addr_position;
693           size_pos = linux_x86_64_munmap_size_position;
694           addr_size = 8;
695        }
696        else if (use_bsd && use_64) {
697           buf_tmp = freebsd_x86_64_call_munmap;
698           buffer_size = freebsd_x86_64_call_munmap_size;
699           start_offset = freebsd_x86_64_munmap_start_position;
700           addr_pos = freebsd_x86_64_munmap_addr_position;
701           size_pos = freebsd_x86_64_munmap_size_position;
702           addr_size = 8;
703        }
704        else if (use_linux && !use_64) {
705           buf_tmp = linux_x86_call_munmap;
706           buffer_size = linux_x86_call_munmap_size;
707           start_offset = linux_x86_munmap_start_position;
708           addr_pos = linux_x86_munmap_addr_position;
709           size_pos = linux_x86_munmap_size_position;
710           addr_size = 4;
711        }
712        else if (use_bsd && !use_64) {
713           buf_tmp = freebsd_x86_call_munmap;
714           buffer_size = freebsd_x86_call_munmap_size;
715           start_offset = freebsd_x86_munmap_start_position;
716           addr_pos = freebsd_x86_munmap_addr_position;
717           size_pos = freebsd_x86_munmap_size_position;
718           addr_size = 4;
719        }
720        else {
721           assert(0);
722        }
723
724        buffer = malloc(buffer_size);
725        memcpy(buffer, buf_tmp, buffer_size);
726
727        //Assuming endianess of debugger and debugee match.
728        *((unsigned int *) (((char *) buffer)+size_pos)) = size;
729        if (addr_size == 8)
730           *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
731        else if (addr_size == 4)
732           *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
733        else
734           assert(0);
735    }
736    else if (getTargetArch() == Arch_ppc32) {
737       unsigned int size_hi_position;
738       unsigned int size_lo_position;
739       unsigned int addr_hi_position;
740       unsigned int addr_lo_position;
741       const void *buf_tmp = NULL;
742
743       bool use_linux = (getOS() == Linux || getOS() == BlueGeneP || getOS() == BlueGeneL);
744       if (use_linux) {
745          buf_tmp = linux_ppc32_call_munmap;
746          size_hi_position = linux_ppc32_munmap_size_hi_position;
747          size_lo_position = linux_ppc32_munmap_size_lo_position;
748          addr_hi_position = linux_ppc32_munmap_addr_hi_position;
749          addr_lo_position = linux_ppc32_munmap_addr_lo_position;
750          buffer_size = linux_ppc32_call_munmap_size;
751          start_offset = linux_ppc32_munmap_start_position;
752       }
753       else {
754          assert(0);
755       }
756
757        buffer = malloc(buffer_size);
758        memcpy(buffer, buf_tmp, buffer_size);
759
760        // Assuming endianess of debugger and debuggee match
761        *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
762        *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
763        *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
764        *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
765    }
766    else if( getTargetArch() == Arch_ppc64 ) {
767       unsigned int size_highest_position;
768       unsigned int size_higher_position;
769       unsigned int size_hi_position;
770       unsigned int size_lo_position;
771       unsigned int addr_highest_position;
772       unsigned int addr_higher_position;
773       unsigned int addr_hi_position;
774       unsigned int addr_lo_position;
775       const void *buf_tmp = NULL;
776
777       bool use_linux = (getOS() == Linux || getOS() == BlueGeneQ);
778       if (use_linux) {
779          buf_tmp = linux_ppc64_call_munmap;
780          size_highest_position = linux_ppc64_munmap_size_highest_position;
781          size_higher_position = linux_ppc64_munmap_size_higher_position;
782          size_hi_position = linux_ppc64_munmap_size_hi_position;
783          size_lo_position = linux_ppc64_munmap_size_lo_position;
784          addr_highest_position = linux_ppc64_munmap_addr_highest_position;
785          addr_higher_position = linux_ppc64_munmap_addr_higher_position;
786          addr_hi_position = linux_ppc64_munmap_addr_hi_position;
787          addr_lo_position = linux_ppc64_munmap_addr_lo_position;
788          buffer_size = linux_ppc64_call_munmap_size;
789          start_offset = linux_ppc64_munmap_start_position;
790       }
791       else {
792          assert(0);
793       }
794
795       buffer = malloc(buffer_size);
796       memcpy(buffer, buf_tmp, buffer_size);
797
798       uint32_t *pwords = (uint32_t *)buffer;
799
800       // MJMTODO - Assumes endianess of debugger and debuggee match
801       pwords[size_highest_position] |= (uint32_t)(((uint64_t)size >> 48) & 0x0000ffff);
802       pwords[size_higher_position]  |= (uint32_t)(((uint64_t)size >> 32) & 0x0000ffff);
803       pwords[size_hi_position]      |= (uint32_t)(((uint64_t)size >> 16) & 0x0000ffff);
804       pwords[size_lo_position]      |= (uint32_t)((uint64_t)size & 0x0000ffff);
805       pwords[addr_highest_position] |= (uint32_t)(((uint64_t)addr >> 48) & 0x0000ffff);
806       pwords[addr_higher_position]  |= (uint32_t)(((uint64_t)addr >> 32) & 0x0000ffff);
807       pwords[addr_hi_position]      |= (uint32_t)(((uint64_t)addr >> 16) & 0x0000ffff);
808       pwords[addr_lo_position]      |= (uint32_t)((uint64_t)addr & 0x0000ffff);
809    }
810    else if( getTargetArch() == Arch_aarch64 ) {
811         const void *buf_tmp = NULL;
812         unsigned int addr_size;
813         unsigned int addr_pos;
814         unsigned int size_pos;
815
816         bool use_linux = (getOS() == Linux );
817         if (use_linux) {
818             buf_tmp             = linux_aarch64_call_munmap;
819             buffer_size         = linux_aarch64_call_munmap_size;
820             start_offset        = linux_aarch64_munmap_start_position;
821             addr_pos            = linux_aarch64_munmap_addr_position;
822             size_pos            = linux_aarch64_munmap_size_position;
823             addr_size           = 8;
824         }
825         else {
826            assert(0);
827         }
828
829         buffer = malloc(buffer_size);
830         memcpy(buffer, buf_tmp, buffer_size);
831
832         pthrd_printf("ARM-info: create de-alloc snippet...\n");
833
834         BYTE_ASSGN(addr_pos,    (uint16_t)(addr)     )
835         BYTE_ASSGN(addr_pos+4,  (uint16_t)(addr>>16) )
836         BYTE_ASSGN(addr_pos+8,  (uint16_t)(addr>>32) )
837         BYTE_ASSGN(addr_pos+12, (uint16_t)(addr>>48) )
838
839         BYTE_ASSGN(size_pos,    (uint16_t)(size) )
840         BYTE_ASSGN(size_pos+4,  (uint16_t)(size>>16) )
841         BYTE_ASSGN(size_pos+8,  (uint16_t)(size>>32) )
842         BYTE_ASSGN(size_pos+12, (uint16_t)(size>>48) )
843
844         //swap 4bytes
845         for(unsigned int i=0; i<buffer_size; i+=4){
846             SWAP4BYTE(i)
847         }
848
849         // Assuming endianess of debugger and debuggee match
850         assert(addr_size == 8);
851    }
852    else {
853       assert(0);
854    }
855
856    return true;
857 }