aboutsummaryrefslogtreecommitdiff
path: root/frontend/3ds/sys/mman.h
blob: e295b8937394b36377ab20382ca9d6cb593cdc26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#ifndef MMAN_H
#define MMAN_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <malloc.h>

#include "3ds_utils.h"

#define PROT_READ       0b001
#define PROT_WRITE      0b010
#define PROT_EXEC       0b100
#define MAP_PRIVATE     2
#define MAP_FIXED       0x10
#define MAP_ANONYMOUS   0x20

#define MAP_FAILED      ((void *)-1)

static void* dynarec_cache = NULL;
static void* dynarec_cache_mapping = NULL;

static inline void* mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
   (void)fd;
   (void)offset;

   void* addr_out;

   if((prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) &&
      (flags == (MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS)))
   {
      if(__ctr_svchax)
      {
         /* this hack works only for pcsx_rearmed */
         uint32_t currentHandle;

         if(!dynarec_cache)
            dynarec_cache = memalign(0x1000, len);

         svcDuplicateHandle(&currentHandle, 0xFFFF8001);
         svcControlProcessMemory(currentHandle, addr, dynarec_cache,
                                 len, MEMOP_MAP, prot);
         svcCloseHandle(currentHandle);
         dynarec_cache_mapping = addr;
         return addr;
      }
      else
      {
         printf("tried to mmap RWX pages without svcControlProcessMemory access !\n");
         return MAP_FAILED;
      }

   }

   addr_out = malloc(len);
   if(!addr_out)
      return MAP_FAILED;

   return addr_out;
}

static inline int mprotect(void *addr, size_t len, int prot)
{
   if(__ctr_svchax)
   {
      uint32_t currentHandle;
      svcDuplicateHandle(&currentHandle, 0xFFFF8001);
      svcControlProcessMemory(currentHandle, addr, NULL,
                              len, MEMOP_PROT, prot);
      svcCloseHandle(currentHandle);
      return 0;
   }

   printf("mprotect called without svcControlProcessMemory access !\n");
   return -1;
}

static inline int munmap(void *addr, size_t len)
{
   if((addr == dynarec_cache_mapping) && __ctr_svchax)
   {
      uint32_t currentHandle;
      svcDuplicateHandle(&currentHandle, 0xFFFF8001);
      svcControlProcessMemory(currentHandle,
                              dynarec_cache, dynarec_cache_mapping,
                              len, MEMOP_UNMAP, 0b111);
      svcCloseHandle(currentHandle);
      dynarec_cache_mapping = NULL;

   }
   else
      free(addr);

   return 0;
}

#ifdef __cplusplus
};
#endif

#endif // MMAN_H