/*
 * See the dyninst/COPYRIGHT file for copyright information.
 * 
 * We provide the Paradyn Tools (below described as "Paradyn")
 * on an AS IS basis, and do not warrant its validity or performance.
 * We reserve the right to update, modify, or discontinue this
 * software at any time.  We shall have no obligation to supply such
 * updates or modifications or any other form of support to you.
 * 
 * By your use of Paradyn, you understand and agree that we (or any
 * other person or entity with proprietary rights in Paradyn) are
 * under no obligation to provide either maintenance services,
 * update services, notices of latent defects, or correction of
 * defects for Paradyn.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "common/h/Types.h"
#include "mmapalloc.h"
#include <sys/mman.h>
#include <string.h>

static const unsigned int linux_x86_64_mmap_flags_position = 26;
static const unsigned int linux_x86_64_mmap_size_position = 43;
static const unsigned int linux_x86_64_mmap_addr_position = 49;
static const unsigned int linux_x86_64_mmap_start_position = 4;
static const unsigned char linux_x86_64_call_mmap[] = {
   0x90, 0x90, 0x90, 0x90,                         //nop,nop,nop,nop
   0x48, 0x8d, 0x64, 0x24, 0x80,                   //lea    -128(%rsp),%rsp
   0x49, 0xc7, 0xc0, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0,%r8
   0x49, 0xc7, 0xc1, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0,%r9
   0x49, 0xc7, 0xc2, 0x22, 0x00, 0x00, 0x00,       //mov    $0x22,%r10
   0x48, 0xc7, 0xc2, 0x07, 0x00, 0x00, 0x00,       //mov    $0x7,%rdx
   0x48, 0x31, 0xf6,                               //xor    %rsi,%rsi
   0x48, 0xc7, 0xc6, 0x00, 0x00, 0x00, 0x00,       //mov    $<size>,%rsi
   0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $<addr>,%rdi
   0x00, 0x00, 0x00,                               //
   0x48, 0xc7, 0xc0, 0x09, 0x00, 0x00, 0x00,       //mov    $0x9,%rax
   0x0f, 0x05,                                     //syscall 
   0x48, 0x8d, 0xa4, 0x24, 0x80, 0x00, 0x00, 0x00, //lea    128(%rsp),%rsp
   0xcc,                                           //Trap
   0x90                                            //nop
};
static const unsigned int linux_x86_64_call_mmap_size = sizeof(linux_x86_64_call_mmap);

static const unsigned int linux_x86_64_munmap_size_position = 15;
static const unsigned int linux_x86_64_munmap_addr_position = 21;
static const unsigned int linux_x86_64_munmap_start_position = 4;
static const unsigned char linux_x86_64_call_munmap[] = {
   0x90, 0x90, 0x90, 0x90,                         //nop,nop,nop,nop
   0x48, 0x8d, 0x64, 0x24, 0x80,                   //lea    -128(%rsp),%rsp
   0x48, 0x31, 0xf6,                               //xor    %rsi,%rsi
   0x48, 0xc7, 0xc6, 0x00, 0x00, 0x00, 0x00,       //mov    $<size>,%rsi
   0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $<addr>,%rdi
   0x00, 0x00, 0x00,                               //
   0x48, 0xc7, 0xc0, 0x0b, 0x00, 0x00, 0x00,       //mov    $0xb,%rax
   0x0f, 0x05,                                     //syscall 
   0x48, 0x8d, 0xa4, 0x24, 0x80, 0x00, 0x00, 0x00, //lea    128(%rsp),%rsp
   0xcc,                                           //Trap
   0x90                                            //nop
};
static const unsigned int linux_x86_64_call_munmap_size = sizeof(linux_x86_64_call_munmap);

static const unsigned int linux_x86_mmap_flags_position = 20;
static const unsigned int linux_x86_mmap_size_position = 10;
static const unsigned int linux_x86_mmap_addr_position = 5;
static const unsigned int linux_x86_mmap_start_position = 4;
static const unsigned char linux_x86_call_mmap[] = {
   0x90, 0x90, 0x90, 0x90,                //nop; nop; nop; nop
   0xbb, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ebx  (addr)
   0xb9, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ecx  (size)
   0xba, 0x07, 0x00, 0x00, 0x00,          //mov    $0x7,%edx  (perms)
   0xbe, 0x22, 0x00, 0x00, 0x00,          //mov    $0x22,%esi (flags)
   0xbf, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%edi  (fd)
   0xbd, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ebp  (offset)
   0xb8, 0xc0, 0x00, 0x00, 0x00,          //mov    $0xc0,%eax (syscall)
   0xcd, 0x80,                            //int    $0x80
   0xcc,                                  //Trap
   0x90                                   //nop
};
static const unsigned int linux_x86_call_mmap_size = sizeof(linux_x86_call_mmap);

static const unsigned int linux_x86_munmap_size_position = 10;
static const unsigned int linux_x86_munmap_addr_position = 5;
static const unsigned int linux_x86_munmap_start_position = 4;
static const unsigned char linux_x86_call_munmap[] = {
   0x90, 0x90, 0x90, 0x90,                //nop; nop; nop; nop
   0xbb, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ebx  (addr)
   0xb9, 0x00, 0x00, 0x00, 0x00,          //mov    $0x0,%ecx  (size)
   0xb8, 0xc0, 0x00, 0x00, 0x00,          //mov    $0x5b,%eax (syscall)
   0xcd, 0x80,                            //int    $0x80
   0xcc,                                  //Trap
   0x90                                   //nop
};
static const unsigned int linux_x86_call_munmap_size = sizeof(linux_x86_call_munmap);

static const unsigned int linux_ppc32_mmap_flags_hi_position = 34;
static const unsigned int linux_ppc32_mmap_flags_lo_position = 38;
static const unsigned int linux_ppc32_mmap_size_hi_position = 18;
static const unsigned int linux_ppc32_mmap_size_lo_position = 22;
static const unsigned int linux_ppc32_mmap_addr_hi_position = 10;
static const unsigned int linux_ppc32_mmap_addr_lo_position = 14;
static const unsigned int linux_ppc32_mmap_start_position = 4;
static const unsigned char linux_ppc32_call_mmap[] = {
   0x60, 0x00, 0x00, 0x00,            // nop
   0x38, 0x00, 0x00, 0x5a,            // li      r0,<syscall>
   0x3c, 0x60, 0x00, 0x00,            // lis     r3,<addr_hi>
   0x60, 0x63, 0x00, 0x00,            // ori     r3,r3,<addr_lo>
   0x3c, 0x80, 0x00, 0x00,            // lis     r4,<size_hi>
   0x60, 0x84, 0x00, 0x00,            // ori     r4,r4,<size_lo>
   0x3c, 0xa0, 0x00, 0x00,            // lis     r5,<perms_hi>
   0x60, 0xa5, 0x00, 0x07,            // ori     r5,r5,<perms_lo>
   0x3c, 0xc0, 0x00, 0x00,            // lis     r6,<flags_hi>
   0x60, 0xc6, 0x00, 0x00,            // ori     r6,r6,<flags_lo>
   0x3c, 0xe0, 0xff, 0xff,            // lis     r7,<fd_hi>
   0x60, 0xe7, 0xff, 0xff,            // ori     r7,r7,<fd_lo>
   0x3d, 0x00, 0x00, 0x00,            // lis     r8,<offset>
   0x44, 0x00, 0x00, 0x02,            // sc
   0x7d, 0x82, 0x10, 0x08,            // trap
   0x60, 0x00, 0x00, 0x00             // nop
};
static const unsigned int linux_ppc32_call_mmap_size = sizeof(linux_ppc32_call_mmap);

static const unsigned int linux_ppc32_munmap_size_hi_position = 18;
static const unsigned int linux_ppc32_munmap_size_lo_position = 22;
static const unsigned int linux_ppc32_munmap_addr_hi_position = 10;
static const unsigned int linux_ppc32_munmap_addr_lo_position = 14;
static const unsigned int linux_ppc32_munmap_start_position = 4;
static const unsigned char linux_ppc32_call_munmap[] = {
   0x60, 0x60, 0x60, 0x60,              // nop
   0x38, 0x00, 0x00, 0x5b,              // li      r0,<syscall>
   0x3c, 0x60, 0x00, 0x00,              // lis     r3,<addr_hi>
   0x60, 0x63, 0x00, 0x00,              // ori     r3,r3,<addr_lo>
   0x3c, 0x80, 0x00, 0x00,              // lis     r4,<size_hi>
   0x60, 0x84, 0x00, 0x00,              // ori     r4,r4,<size_lo>
   0x44, 0x00, 0x00, 0x02,              // sc
   0x7d, 0x82, 0x10, 0x08,              // trap
   0x60, 0x00, 0x00, 0x00               // nop
};
static const unsigned int linux_ppc32_call_munmap_size = sizeof(linux_ppc32_call_munmap);

static const unsigned int linux_ppc64_mmap_flags_highest_position = 70;
static const unsigned int linux_ppc64_mmap_flags_higher_position = 74;
static const unsigned int linux_ppc64_mmap_flags_hi_position = 82;
static const unsigned int linux_ppc64_mmap_flags_lo_position = 86;
static const unsigned int linux_ppc64_mmap_size_highest_position = 30;
static const unsigned int linux_ppc64_mmap_size_higher_position = 34;
static const unsigned int linux_ppc64_mmap_size_hi_position = 42;
static const unsigned int linux_ppc64_mmap_size_lo_position = 46;
static const unsigned int linux_ppc64_mmap_addr_highest_position = 10;
static const unsigned int linux_ppc64_mmap_addr_higher_position = 14;
static const unsigned int linux_ppc64_mmap_addr_hi_position = 22;
static const unsigned int linux_ppc64_mmap_addr_lo_position = 26;
static const unsigned int linux_ppc64_mmap_start_position = 4;
static const unsigned char linux_ppc64_call_mmap[] = {
   0x60, 0x00, 0x00, 0x00,              // nop
   0x38, 0x00, 0x00, 0x5a,              // li      r0,<syscall>
   0x3c, 0x60, 0x00, 0x00,              // lis     r3,<addr_highest>
   0x60, 0x63, 0x00, 0x00,              // ori     r3,r3,<addr_higher>
   0x78, 0x63, 0x07, 0xc6,              // rldicr  r3,r3,0x32,0x31,
   0x64, 0x63, 0x00, 0x00,              // oris    r3,r3,<addr_hi>
   0x60, 0x63, 0x00, 0x00,              // ori     r3,r3,<addr_lo>
   0x3c, 0x80, 0x00, 0x00,              // lis     r4,<size_highest>
   0x60, 0x84, 0x00, 0x00,              // ori     r4,r4,<size_higher>
   0x78, 0x84, 0x07, 0xc6,              // rldicr  r4,r4,0x32,0x31,
   0x64, 0x84, 0x00, 0x00,              // oris    r4,r4,<size_hi>
   0x60, 0x84, 0x00, 0x00,              // ori     r4,r4,<size_lo>
   0x3c, 0xa0, 0x00, 0x00,              // lis     r5,<perms_highest>
   0x60, 0xa5, 0x00, 0x00,              // ori     r5,r5,<perms_higher>
   0x78, 0xa5, 0x07, 0xc6,              // rldicr  r5,r5,0x32,0x31,
   0x64, 0xa5, 0x00, 0x00,              // oris    r5,r5,<perms_hi>
   0x60, 0xa5, 0x00, 0x07,              // ori     r5,r5,<perms_lo>
   0x3c, 0xc0, 0x00, 0x00,              // lis     r6,<flags_highest>
   0x60, 0xc6, 0x00, 0x00,              // ori     r6,r6,<flags_higher>
   0x78, 0xc6, 0x07, 0xc6,              // rldicr  r6,r6,0x32,0x31,
   0x64, 0xc6, 0x00, 0x00,              // oris    r6,r6,<flags_hi>
   0x60, 0xc6, 0x00, 0x00,              // ori     r6,r6,<flags_lo>
   0x3c, 0xe0, 0x00, 0x00,              // lis     r7,<fd=-1>
   0x7c, 0xe7, 0x3b, 0xb8,              // nand    r7,r7,r7
   0x3d, 0x00, 0x00, 0x00,              // lis     r8,<offset>
   0x44, 0x00, 0x00, 0x02,              // sc      
   0x7d, 0x82, 0x10, 0x08,              // trap
   0x60, 0x00, 0x00, 0x00               // nop
};
static const unsigned int linux_ppc64_call_mmap_size = sizeof(linux_ppc64_call_mmap);

static const unsigned int linux_ppc64_munmap_size_highest_position = 30;
static const unsigned int linux_ppc64_munmap_size_higher_position = 34;
static const unsigned int linux_ppc64_munmap_size_hi_position = 42;
static const unsigned int linux_ppc64_munmap_size_lo_position = 46;
static const unsigned int linux_ppc64_munmap_addr_highest_position = 10;
static const unsigned int linux_ppc64_munmap_addr_higher_position = 14;
static const unsigned int linux_ppc64_munmap_addr_hi_position = 22;
static const unsigned int linux_ppc64_munmap_addr_lo_position = 26;
static const unsigned int linux_ppc64_munmap_start_position = 4;
static const unsigned char linux_ppc64_call_munmap[] = {
   0x60, 0x00, 0x00, 0x00,              // nop
   0x38, 0x00, 0x00, 0x5b,              // li      r0,<syscall>
   0x3c, 0x60, 0x00, 0x00,              // lis     r3,<addr_highest>
   0x60, 0x63, 0x00, 0x00,              // ori     r3,r3,<addr_higher>
   0x78, 0x63, 0x07, 0xc6,              // rldicr  r3,r3,0x32,0x31,
   0x64, 0x63, 0x00, 0x00,              // oris    r3,r3,<addr_hi>
   0x60, 0x63, 0x00, 0x00,              // ori     r3,r3,<addr_lo>
   0x3c, 0x80, 0x00, 0x00,              // lis     r4,<size_highest>
   0x60, 0x84, 0x00, 0x00,              // ori     r4,r4,<size_higher>
   0x78, 0x84, 0x07, 0xc6,              // rldicr  r4,r4,0x32,0x31,
   0x64, 0x84, 0x00, 0x00,              // oris    r4,r4,<size_hi>
   0x60, 0x84, 0x00, 0x00,              // ori     r4,r4,<size_lo>
   0x44, 0x00, 0x00, 0x02,              // sc      
   0x7d, 0x82, 0x10, 0x08,              // trap
   0x60, 0x00, 0x00, 0x00               // nop
};
static const unsigned int linux_ppc64_call_munmap_size = sizeof(linux_ppc64_call_munmap);

static const unsigned int freebsd_x86_64_mmap_flags_position = 21;
static const unsigned int freebsd_x86_64_mmap_size_position = 34;
static const unsigned int freebsd_x86_64_mmap_addr_position = 44;
static const unsigned int freebsd_x86_64_mmap_start_position = 4;
static const unsigned char freebsd_x86_64_call_mmap[] = {
   0x90, 0x90, 0x90, 0x90,                         //nop sled
   0x49, 0xc7, 0xc1, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0,%r9 (offset)
   0x49, 0xc7, 0xc0, 0xff, 0xff, 0xff, 0xff,       //mov    $0xffffffffffffffff,%r8 (fd)
   0x49, 0xc7, 0xc2, 0x12, 0x10, 0x00, 0x00,       //mov    $0x1012,%r10 (flags)
   0x48, 0xc7, 0xc2, 0x07, 0x00, 0x00, 0x00,       //mov    $0x7,%rdx (perms)
   0x48, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rsi (size)
   0x00, 0x00, 0x00,                               //
   0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rdi (addr)
   0x00, 0x00, 0x00,                               //
   0xb8, 0xdd, 0x01, 0x00, 0x00,                   //mov    $0x1dd,%eax (SYS_mmap)
   0x0f, 0x05,                                     //syscall
   0xcc,                                           //trap
   0x90                                            //nop
};
static const unsigned int freebsd_x86_64_call_mmap_size = sizeof(freebsd_x86_64_call_mmap);

static const unsigned int freebsd_x86_64_munmap_size_position = 6;
static const unsigned int freebsd_x86_64_munmap_addr_position = 16;
static const unsigned int freebsd_x86_64_munmap_start_position = 4;
static const unsigned char freebsd_x86_64_call_munmap[] = {
   0x90, 0x90, 0x90, 0x90,                         //nop sled
   0x48, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rsi
   0x00, 0x00, 0x00,                               //
   0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00,       //mov    $0x0000000000000000,%rdi
   0x00, 0x00, 0x00,                               //
   0xb8, 0x49, 0x00, 0x00, 0x00,                   //mov    $0x49,%eax
   0x0f, 0x05,                                     //syscall
   0xcc,                                           //trap
   0x90                                            //nop
};
static const unsigned int freebsd_x86_64_call_munmap_size = sizeof(freebsd_x86_64_call_munmap);

static const unsigned int freebsd_x86_mmap_flags_position = 9;
static const unsigned int freebsd_x86_mmap_size_position = 16;
static const unsigned int freebsd_x86_mmap_addr_position = 21;
static const unsigned int freebsd_x86_mmap_start_position = 4;
static const unsigned char freebsd_x86_call_mmap[] = {
   0x90, 0x90, 0x90, 0x90,                         //nop sled
   0x6a, 0x00,                                     //push   $0x0 (offset)
   0x6a, 0xff,                                     //push   $0xffffffff (fd)
   0x68, 0x12, 0x10, 0x00, 0x00,                   //push   $0x1012 (flags)
   0x6a, 0x07,                                     //push   $0x7 (perms)
   0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (size)
   0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (addr)
   0xb8, 0xdd, 0x01, 0x00, 0x00,                   //mov    $0x1dd,%eax (SYS_mmap)
   0x50,                                           //push   %eax (required by calling convention)
   0xcd, 0x80,                                     //int    $0x80
   0x8d, 0x64, 0x24, 0x1c,                         //lea    0x1c(%esp),%esp
   0xcc,                                           //trap
   0x90                                            //nop
};
static const unsigned int freebsd_x86_call_mmap_size = sizeof(freebsd_x86_call_mmap);

static const unsigned int freebsd_x86_munmap_size_position = 5;
static const unsigned int freebsd_x86_munmap_addr_position = 10;
static const unsigned int freebsd_x86_munmap_start_position = 4;
static const unsigned char freebsd_x86_call_munmap[] = {
   0x90, 0x90, 0x90, 0x90,                         //nop sled
   0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (size)    
   0x68, 0x00, 0x00, 0x00, 0x00,                   //push   $0x0 (addr)
   0xb8, 0x49, 0x00, 0x00, 0x00,                   //mov    $0x49,%eax (SYS_munmap)
   0x50,                                           //push   %eax (required by calling convention)
   0xcd, 0x80,                                     //int    $0x80
   0x8d, 0x64, 0x24, 0x0c,                         //lea    0xc(%esp),%esp 
   0xcc,                                           //trap
   0x90                                            //nop
};
static const unsigned int freebsd_x86_call_munmap_size = sizeof(freebsd_x86_call_munmap);

mmap_alloc_process::mmap_alloc_process(Dyninst::PID p, std::string e, std::vector<std::string> a, 
                                       std::vector<std::string> envp, std::map<int,int> f) :
   int_process(p, e, a, envp, f)
{
}

mmap_alloc_process::mmap_alloc_process(Dyninst::PID pid_, int_process *p) : 
   int_process(pid_, p)
{
}

mmap_alloc_process::~mmap_alloc_process()
{
}

// For compatibility 
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif

bool mmap_alloc_process::plat_collectAllocationResult(int_thread *thr, reg_response::ptr resp)
{
   switch (getTargetArch())
   {
      case Arch_x86_64: {
         bool result = thr->getRegister(x86_64::rax, resp);
         assert(result);
         break;
      }
      case Arch_x86: {
         bool result = thr->getRegister(x86::eax, resp);
         assert(result);
         break;
      }
      case Arch_ppc32: {
         bool result = thr->getRegister(ppc32::r3, resp);
         assert(result);
         break;
      }
      case Arch_ppc64: {
         bool result = thr->getRegister(ppc64::r3, resp);
         assert(result);
         break;
      }
      default:
         assert(0);
         break;
   }
   return true;
} 

bool mmap_alloc_process::plat_createAllocationSnippet(Dyninst::Address addr, bool use_addr, unsigned long size, 
                                                      void* &buffer, unsigned long &buffer_size, 
                                                      unsigned long &start_offset)
{
   int flags = MAP_ANONYMOUS | MAP_PRIVATE;
   if (use_addr) 
      flags |= MAP_FIXED;
   else
      addr = 0x0;

   if (getTargetArch() == Arch_x86_64 || getTargetArch() == Arch_x86) {
       const void *buf_tmp = NULL;
       unsigned addr_size = 0;
       unsigned addr_pos = 0;
       unsigned flags_pos = 0;
       unsigned size_pos = 0;

       bool use_linux = (getOS() == Dyninst::Linux);
       bool use_bsd = (getOS() == Dyninst::FreeBSD);
       bool use_64 = (getTargetArch() == Arch_x86_64);
       
       if (use_linux && use_64) {
          buf_tmp = linux_x86_64_call_mmap;
          buffer_size = linux_x86_64_call_mmap_size;
          start_offset = linux_x86_64_mmap_start_position;
          addr_pos = linux_x86_64_mmap_addr_position;
          flags_pos = linux_x86_64_mmap_flags_position;
          size_pos = linux_x86_64_mmap_size_position;
          addr_size = 8;
       }
       else if (use_bsd && use_64) {
          buf_tmp = freebsd_x86_64_call_mmap;
          buffer_size = freebsd_x86_64_call_mmap_size;
          start_offset = freebsd_x86_64_mmap_start_position;
          addr_pos = freebsd_x86_64_mmap_addr_position;
          flags_pos = freebsd_x86_64_mmap_flags_position;
          size_pos = freebsd_x86_64_mmap_size_position;
          addr_size = 8;
       }
       else if (use_linux && !use_64) {
          buf_tmp = linux_x86_call_mmap;
          buffer_size = linux_x86_call_mmap_size;
          start_offset = linux_x86_mmap_start_position;
          addr_pos = linux_x86_mmap_addr_position;
          flags_pos = linux_x86_mmap_flags_position;
          size_pos = linux_x86_mmap_size_position;
          addr_size = 4;
       } 
       else if (use_bsd && !use_64) {
          buf_tmp = freebsd_x86_call_mmap;
          buffer_size = freebsd_x86_call_mmap_size;
          start_offset = freebsd_x86_mmap_start_position;
          addr_pos = freebsd_x86_mmap_addr_position;
          flags_pos = freebsd_x86_mmap_flags_position;
          size_pos = freebsd_x86_mmap_size_position;
          addr_size = 4;
       }
       else {
          assert(0); //Fill in the entry in mmapalloc.h for this system
       }
       
       buffer = malloc(buffer_size);
       memcpy(buffer, buf_tmp, buffer_size);

       //Assuming endianess of debugger and debugee match.
       *((unsigned int *) (((char *) buffer)+size_pos)) = size;
       *((unsigned int *) (((char *) buffer)+flags_pos)) = flags;
       if (addr_size == 8)
          *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
       else if (addr_size == 4)
          *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
       else 
          assert(0);
   }
   else if (getTargetArch() == Arch_ppc32) {
      unsigned int flags_hi_position;
      unsigned int flags_lo_position;
      unsigned int size_hi_position;
      unsigned int size_lo_position;
      unsigned int addr_hi_position;
      unsigned int addr_lo_position;
      const void *buf_tmp;

      //BlueGene can share the linux allocation snippet.
      bool use_linux = (getOS() == Linux || getOS() == BlueGeneP || getOS() == BlueGeneL);

      if (use_linux) {
         flags_hi_position = linux_ppc32_mmap_flags_hi_position;
         flags_lo_position = linux_ppc32_mmap_flags_lo_position;
         size_hi_position = linux_ppc32_mmap_size_hi_position;
         size_lo_position = linux_ppc32_mmap_size_lo_position;
         addr_hi_position = linux_ppc32_mmap_addr_hi_position;
         addr_lo_position = linux_ppc32_mmap_addr_lo_position;
         start_offset = linux_ppc32_mmap_start_position;
         buffer_size = linux_ppc32_call_mmap_size;
         buf_tmp = linux_ppc32_call_mmap;
      }
      else {
         assert(0); //Fill in the entry in mmapalloc.h for this system
      }

      buffer = malloc(buffer_size);
      memcpy(buffer, buf_tmp, buffer_size);
      
      // Assuming endianess of debugger and debuggee match
      *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
      *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
      *((uint16_t *) (((char *) buffer)+flags_hi_position)) = (uint16_t)(flags >> 16);
      *((uint16_t *) (((char *) buffer)+flags_lo_position)) = (uint16_t)flags;
      *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
      *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
   }
   else if (getTargetArch() == Arch_ppc64) {
      unsigned int flags_highest_position;
      unsigned int flags_higher_position;
      unsigned int flags_hi_position;
      unsigned int flags_lo_position;
      unsigned int size_highest_position;
      unsigned int size_higher_position;
      unsigned int size_hi_position;
      unsigned int size_lo_position;
      unsigned int addr_highest_position;
      unsigned int addr_higher_position;
      unsigned int addr_hi_position;
      unsigned int addr_lo_position;
      const void *buf_tmp;

      //BlueGene can share the linux allocation snippet.
      bool use_linux = (getOS() == Linux || getOS() == BlueGeneQ);

      if (use_linux) {
         flags_highest_position = linux_ppc64_mmap_flags_highest_position;
         flags_higher_position = linux_ppc64_mmap_flags_higher_position;
         flags_hi_position = linux_ppc64_mmap_flags_hi_position;
         flags_lo_position = linux_ppc64_mmap_flags_lo_position;
         size_highest_position = linux_ppc64_mmap_size_highest_position;
         size_higher_position = linux_ppc64_mmap_size_higher_position;
         size_hi_position = linux_ppc64_mmap_size_hi_position;
         size_lo_position = linux_ppc64_mmap_size_lo_position;
         addr_highest_position = linux_ppc64_mmap_addr_highest_position;
         addr_higher_position = linux_ppc64_mmap_addr_higher_position;
         addr_hi_position = linux_ppc64_mmap_addr_hi_position;
         addr_lo_position = linux_ppc64_mmap_addr_lo_position;
         start_offset = linux_ppc64_mmap_start_position;
         buffer_size = linux_ppc64_call_mmap_size;
         buf_tmp = linux_ppc64_call_mmap;
      }
      else {
         assert(0); //Fill in the entry in mmapalloc.h for this system
      }
      buffer = malloc(buffer_size);
      memcpy(buffer, buf_tmp, buffer_size);


       // Assuming endianess of debugger and debuggee match
       *((uint16_t *) (((char *) buffer)+size_highest_position)) = (uint16_t)((uint64_t)size >> 48);
       *((uint16_t *) (((char *) buffer)+size_higher_position)) = (uint16_t)((uint64_t)size >> 32);
       *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
       *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
       *((uint16_t *) (((char *) buffer)+flags_highest_position)) = (uint16_t)((uint64_t)flags >> 48);
       *((uint16_t *) (((char *) buffer)+flags_higher_position)) = (uint16_t)((uint64_t)flags >> 32);
       *((uint16_t *) (((char *) buffer)+flags_hi_position)) = (uint16_t)(flags >> 16);
       *((uint16_t *) (((char *) buffer)+flags_lo_position)) = (uint16_t)flags;
       *((uint16_t *) (((char *) buffer)+addr_highest_position)) = (uint16_t)((uint64_t)addr >> 48);
       *((uint16_t *) (((char *) buffer)+addr_higher_position)) = (uint16_t)((uint64_t)addr >> 32);
       *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
       *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
   }else{
       assert(0);
   }

   return true;
}

bool mmap_alloc_process::plat_createDeallocationSnippet(Dyninst::Address addr, 
                                                        unsigned long size, void* &buffer, 
                                                        unsigned long &buffer_size, 
                                                        unsigned long &start_offset)
{
   if (getTargetArch() == Arch_x86_64 || getTargetArch() == Arch_x86) {
       const void *buf_tmp = NULL;
       unsigned addr_size = 0;
       unsigned addr_pos = 0;
       unsigned size_pos = 0;

       bool use_linux = (getOS() == Dyninst::Linux);
       bool use_bsd = (getOS() == Dyninst::FreeBSD);
       bool use_64 = (getTargetArch() == Arch_x86_64);

       if (use_linux && use_64) {
          buf_tmp = linux_x86_64_call_munmap;
          buffer_size = linux_x86_64_call_munmap_size;
          start_offset = linux_x86_64_munmap_start_position;
          addr_pos = linux_x86_64_munmap_addr_position;
          size_pos = linux_x86_64_munmap_size_position;
          addr_size = 8;
       }
       else if (use_bsd && use_64) {
          buf_tmp = freebsd_x86_64_call_munmap;
          buffer_size = freebsd_x86_64_call_munmap_size;
          start_offset = freebsd_x86_64_munmap_start_position;
          addr_pos = freebsd_x86_64_munmap_addr_position;
          size_pos = freebsd_x86_64_munmap_size_position;
          addr_size = 8;
       }
       else if (use_linux && !use_64) {
          buf_tmp = linux_x86_call_munmap;
          buffer_size = linux_x86_call_munmap_size;
          start_offset = linux_x86_munmap_start_position;
          addr_pos = linux_x86_munmap_addr_position;
          size_pos = linux_x86_munmap_size_position;
          addr_size = 4;
       } 
       else if (use_bsd && !use_64) {
          buf_tmp = freebsd_x86_call_munmap;
          buffer_size = freebsd_x86_call_munmap_size;
          start_offset = freebsd_x86_munmap_start_position;
          addr_pos = freebsd_x86_munmap_addr_position;
          size_pos = freebsd_x86_munmap_size_position;
          addr_size = 4;
       }
       else {
          assert(0);
       }
       
       buffer = malloc(buffer_size);
       memcpy(buffer, buf_tmp, buffer_size);

       //Assuming endianess of debugger and debugee match.
       *((unsigned int *) (((char *) buffer)+size_pos)) = size;
       if (addr_size == 8)
          *((unsigned long *) (((char *) buffer)+addr_pos)) = addr;
       else if (addr_size == 4)
          *((unsigned *) (((char *) buffer)+addr_pos)) = (unsigned) addr;
       else 
          assert(0);
   }
   else if (getTargetArch() == Arch_ppc32) {
      unsigned int size_hi_position;
      unsigned int size_lo_position;
      unsigned int addr_hi_position;
      unsigned int addr_lo_position;
      const void *buf_tmp = NULL;

      bool use_linux = (getOS() == Linux || getOS() == BlueGeneP || getOS() == BlueGeneL);
      if (use_linux) {
         buf_tmp = linux_ppc32_call_munmap;
         size_hi_position = linux_ppc32_munmap_size_hi_position;
         size_lo_position = linux_ppc32_munmap_size_lo_position;
         addr_hi_position = linux_ppc32_munmap_addr_hi_position;
         addr_lo_position = linux_ppc32_munmap_addr_lo_position;
         buffer_size = linux_ppc32_call_munmap_size;
         start_offset = linux_ppc32_munmap_start_position;
      }
      else {
         assert(0);
      }

       buffer = malloc(buffer_size);
       memcpy(buffer, buf_tmp, buffer_size);

       // Assuming endianess of debugger and debuggee match
       *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
       *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
       *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
       *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
   }
   else if( getTargetArch() == Arch_ppc64 ) {
      unsigned int size_highest_position;
      unsigned int size_higher_position;
      unsigned int size_hi_position;
      unsigned int size_lo_position;
      unsigned int addr_highest_position;
      unsigned int addr_higher_position;
      unsigned int addr_hi_position;
      unsigned int addr_lo_position;
      const void *buf_tmp = NULL;

      bool use_linux = (getOS() == Linux || getOS() == BlueGeneQ);
      if (use_linux) {
         buf_tmp = linux_ppc64_call_munmap;
         size_highest_position = linux_ppc64_munmap_size_highest_position;
         size_higher_position = linux_ppc64_munmap_size_higher_position;
         size_hi_position = linux_ppc64_munmap_size_hi_position;
         size_lo_position = linux_ppc64_munmap_size_lo_position;
         addr_highest_position = linux_ppc64_munmap_addr_highest_position;
         addr_higher_position = linux_ppc64_munmap_addr_higher_position;
         addr_hi_position = linux_ppc64_munmap_addr_hi_position;
         addr_lo_position = linux_ppc64_munmap_addr_lo_position;
         buffer_size = linux_ppc64_call_munmap_size;
         start_offset = linux_ppc64_munmap_start_position;
      }
      else {
         assert(0);
      }

      buffer = malloc(buffer_size);
      memcpy(buffer, buf_tmp, buffer_size);
      
      // Assuming endianess of debugger and debuggee match
      *((uint16_t *) (((char *) buffer)+size_highest_position)) = (uint16_t)((uint64_t)size >> 48);
      *((uint16_t *) (((char *) buffer)+size_higher_position)) = (uint16_t)((uint64_t)size >> 32);
      *((uint16_t *) (((char *) buffer)+size_hi_position)) = (uint16_t)(size >> 16);
      *((uint16_t *) (((char *) buffer)+size_lo_position)) = (uint16_t)size;
      *((uint16_t *) (((char *) buffer)+addr_highest_position)) = (uint16_t)((uint64_t)addr >> 48);
      *((uint16_t *) (((char *) buffer)+addr_higher_position)) = (uint16_t)((uint64_t)addr >> 32);
      *((uint16_t *) (((char *) buffer)+addr_hi_position)) = (uint16_t)(addr >> 16);
      *((uint16_t *) (((char *) buffer)+addr_lo_position)) = (uint16_t)addr;
   }
   else {
      assert(0);
   }

   return true;
}
