├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── failures
├── execv
│ ├── Makefile
│ └── source
│ │ └── main.c
└── shm_open
│ ├── Makefile
│ └── source
│ └── main.c
├── freebsd
├── dirent
│ ├── Makefile
│ └── source
│ │ └── main.c
├── kernel_stacks
│ ├── Makefile
│ ├── include
│ │ └── uthash.h
│ └── source
│ │ └── main.c
└── write_access
│ ├── Makefile
│ └── source
│ └── main.c
├── kernel
├── cache
│ ├── Makefile
│ └── source
│ │ └── main.c
├── function_hook
│ ├── Makefile
│ └── source
│ │ └── main.c
├── resolve
│ ├── Makefile
│ └── source
│ │ └── main.c
├── server_hello_world
│ ├── Makefile
│ └── source
│ │ └── main.c
└── system_call_hook
│ ├── Makefile
│ └── source
│ └── main.c
├── libless
├── for_a_while
│ ├── Makefile
│ └── source
│ │ └── main.c
├── return
│ ├── Makefile
│ └── source
│ │ └── main.c
└── stress
│ ├── Makefile
│ └── source
│ └── main.c
├── posix
├── pthread
│ ├── Makefile
│ └── source
│ │ └── main.c
├── pthread_errno
│ ├── Makefile
│ └── source
│ │ └── main.c
├── sigsegv_handling
│ ├── Makefile
│ └── source
│ │ └── main.c
├── sigsegv_pthread_handling
│ ├── Makefile
│ └── source
│ │ └── main.c
└── stdio_redirect
│ ├── Makefile
│ └── source
│ └── main.c
├── ps4sdk
├── kernel_execute
│ ├── Makefile
│ ├── include
│ │ └── kmain.h
│ └── source
│ │ ├── kmain.c
│ │ └── main.c
├── protected_memory
│ ├── Makefile
│ └── source
│ │ └── main.c
├── shared_memory
│ ├── Makefile
│ └── source
│ │ └── main.c
└── system_call_hook
│ ├── Makefile
│ ├── include
│ └── kmain.h
│ └── source
│ ├── kmain.c
│ └── main.c
└── sce
├── modules
├── Makefile
└── source
│ └── main.c
└── resolve
├── Makefile
└── source
└── main.c
/.gitignore:
--------------------------------------------------------------------------------
1 | **/build/
2 | **/bin/
3 | scratch
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .DEFAULT_GOAL := all
2 |
3 | Dirs := $(wildcard */*/)
4 | Targets := all clean
5 |
6 | DirTargets := $(foreach t,$(Targets),$(addsuffix $t,$(Dirs)))
7 |
8 | .PHONY : $(Targets) $(DirTargets)
9 |
10 | $(Targets) : % : $(addsuffix %,$(Dirs))
11 |
12 | $(DirTargets) :
13 | $(MAKE) -C $(@D) $(@F:.%=%)
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ps4sdk-examples
2 | Examples, showcases and prove-of-concepts which show something realized with ps4sdk (not necessarily unique to the PS4)
3 |
4 | ## Examples
5 | * `libless` - These do not use any library functions (not even the sdk) and are good for initial tests or when something breaks
6 | * `posix` - These solely use posix and standard C APIs and should run under any such system
7 | * `freebsd` - These are pure freebsd examples (and should work there too)
8 | * `sce` - These showcase SCE functions
9 | * `ps4sdk` - These are user space programs which use the sdks own (common) capabilities
10 | * `kernel` - These are showing something we can do in the kernel using the sdk
11 | * `failures` - These are corner-cases, which noteworthyly do not work (but could be expected to by somebody)
12 |
13 | ## Noteworthy
14 | * `freebsd/dirent` displays the fs and can be run after you use another elf to escalate your privileges
15 | * `ps4sdk/kernel_execute` shows how to enter the kernel from user space on your own (it's likely less
16 | convenient and useful then a kernel payload, but has its use-case).
17 | * `ps4sdk/system_call_hook` shows how to temporarily hook from user space. Be aware, that when your program
18 | exits, your resources (all functions and data) will be freed too. **Be sure to unlink** any of these user space resources
19 | from the kernel before you exit main. A kernel payload that never ends (sleep on a mutex) is more likely to be useful and stable
20 | for any long term or persistent (module like) modifications. See `kernel/system_call` for comparison.
21 | * `kernel/system_call_hook`, `kernel/function_hook` print the same descriptor all the time. That's not a bug,
22 | it's what actually happens. Press the options button to see changes. To influence the return values, use a post
23 | hook and alter args->returns->rax (etc.). Try the function index (rindex) hook (on 5055), close the browser,
24 | connect and restart the browser.
25 |
26 | ## Important
27 | The exploit may not always enter the kernel on the first try. If you browser crashes,
28 | simply try again. It's likely to work. This will be tuned in the future as much as possible.
29 | Especially after you crashed your kernel, this behaviour is very common (down right normal) because the
30 | initial resource allocation differs.
31 |
--------------------------------------------------------------------------------
/failures/execv/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/failures/execv/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 |
7 | char *sceKernelGetRandomizedPath()
8 | {
9 | char path[16];
10 | int length = 11;
11 | char *r;
12 | // on 1.75 using path alone will null out (override) the first 4 bytes
13 | // thus, return probably a two value struct with val1 = null
14 | syscall(602, 0, path + 4, &length);
15 | r = malloc(12);
16 | r[0] = '/';
17 | strcpy(r, path + 4);
18 | return r;
19 | }
20 |
21 | int main(int argc, char **argv)
22 | {
23 | char path[1024];
24 | char *args[2];
25 | int r;
26 |
27 | strcpy(path, "/");
28 | strcat(path, sceKernelGetRandomizedPath());
29 | // the current procress seems to be able to exec itself
30 | // nothing else ...
31 | // so the runtime seems to be restricted this way
32 | strcat(path, "/common/lib/WebProcess.self");
33 |
34 | args[0] = path;
35 | args[1] = NULL; // Invalid args ...
36 |
37 | r = execv(args[0], args);
38 | printf("execv(%s) = %i\n", args[0], r);
39 |
40 | return EXIT_SUCCESS;
41 | }
42 |
--------------------------------------------------------------------------------
/failures/shm_open/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/failures/shm_open/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #ifndef MAP_TYPE
9 | #define MAP_TYPE 0x0f
10 | #endif
11 |
12 | int main(int argc, char **argv)
13 | {
14 | long pz;
15 | int h, h2;
16 | char *w, *e;
17 | int i;
18 |
19 | pz = sysconf(_SC_PAGESIZE);
20 | h = shm_open("/jmploop", O_CREAT|O_TRUNC|O_RDWR, 0755);
21 | h2 = dup(h); // could have mattered ;)
22 | ftruncate(h, pz);
23 |
24 | #ifdef __PS4__ // neither works on the ps4
25 | w = mmap(NULL, pz, PROT_READ | PROT_WRITE, MAP_SHARED, h, 0);
26 | e = mmap(NULL, pz, PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_TYPE, h2, 0);
27 | #else
28 | w = mmap(NULL, pz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, h, 0);
29 | e = mmap(NULL, pz, PROT_READ | PROT_EXEC, MAP_FILE | MAP_SHARED, h2, 0);
30 | #endif
31 |
32 | close(h);
33 | close(h2);
34 |
35 | for(i = 0; i < pz; i += 2)
36 | {
37 | w[i] = 0xeb;
38 | w[i + 1] = 0xfe;
39 | }
40 | w[0] = 0xeb;
41 | w[1] = 0xfc;
42 |
43 | void (*run)(void) = (void (*)(void))(e + 8);
44 | run();
45 |
46 | shm_unlink("/jmploop");
47 |
48 | return EXIT_SUCCESS;
49 | }
50 |
--------------------------------------------------------------------------------
/freebsd/dirent/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/freebsd/dirent/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #ifdef __PS4__
16 | #include
17 |
18 | __typeof__(__stdoutp) __stdoutp;
19 | __typeof__(__stdoutp) *__stdoutp_address;
20 | __typeof__(__mb_sb_limit) __mb_sb_limit;
21 | __typeof__(__mb_sb_limit) *__mb_sb_limit_address;
22 | __typeof__(_CurrentRuneLocale) _CurrentRuneLocale;
23 | __typeof__(_CurrentRuneLocale) *_CurrentRuneLocale_address;
24 | #endif
25 |
26 | #define DirectoryBufferSize 1024 * 1024
27 | #define TemporaryNameSize 4096
28 |
29 | int printDirectoryTree_(const char *name, int depth)
30 | {
31 | int dir, count;
32 | char *buffer;
33 | char *temporaryName;
34 | struct dirent *entry;
35 | int position;
36 | struct stat sb;
37 |
38 | dir = open(name, O_RDONLY | O_DIRECTORY);
39 | if(dir == -1)
40 | goto e1;
41 |
42 | buffer = malloc(DirectoryBufferSize);
43 | if(buffer == NULL)
44 | goto e2;
45 |
46 | temporaryName = malloc(TemporaryNameSize);
47 | if(temporaryName == NULL)
48 | goto e3;
49 |
50 | count = getdents(dir, buffer, DirectoryBufferSize);
51 | if(count <= 0)
52 | goto e4;
53 |
54 | entry = (struct dirent *)buffer;
55 | if(entry == NULL || entry->d_reclen == 0)
56 | goto e4;
57 |
58 | for(position = 0; position < count;)
59 | {
60 | entry = (struct dirent *)(buffer + position);
61 |
62 | if(entry->d_reclen == 0)
63 | break;
64 |
65 | if(strncmp(entry->d_name, ".", entry->d_namlen) == 0 || strncmp(entry->d_name, "..", entry->d_namlen) == 0)
66 | {
67 | position += entry->d_reclen;
68 | continue;
69 | }
70 |
71 | strcpy(temporaryName, name);
72 | {
73 | size_t l = strlen(name);
74 | if(l > 0 && name[l - 1] != '/')
75 | strcat(temporaryName, "/");
76 | }
77 | strcat(temporaryName, entry->d_name);
78 | printf("%s", temporaryName);
79 | if(stat(temporaryName, &sb) >= 0)
80 | {
81 | printf(" [size: %"PRIdMAX" mode: ", (intmax_t)sb.st_size);
82 | printf((S_ISDIR(sb.st_mode)) ? "d" : "-");
83 | printf((sb.st_mode & S_IRUSR) ? "r" : "-");
84 | printf((sb.st_mode & S_IWUSR) ? "w" : "-");
85 | printf((sb.st_mode & S_IXUSR) ? "x" : "-");
86 | printf((sb.st_mode & S_IRGRP) ? "r" : "-");
87 | printf((sb.st_mode & S_IWGRP) ? "w" : "-");
88 | printf((sb.st_mode & S_IXGRP) ? "x" : "-");
89 | printf((sb.st_mode & S_IROTH) ? "r" : "-");
90 | printf((sb.st_mode & S_IWOTH) ? "w" : "-");
91 | printf((sb.st_mode & S_IXOTH) ? "x" : "-");
92 | printf("]");
93 | }
94 | printf("\n");
95 |
96 | if(entry->d_type == DT_UNKNOWN)
97 | {
98 | position += entry->d_reclen;
99 | continue;
100 | }
101 |
102 | if(entry->d_type == DT_DIR && entry->d_fileno != 0)
103 | printDirectoryTree_(temporaryName, depth + 1);
104 |
105 | fflush(stdout);
106 |
107 | position += entry->d_reclen;
108 | }
109 |
110 | free(temporaryName);
111 | free(buffer);
112 | close(dir);
113 |
114 | return 0;
115 |
116 | e4:
117 | free(temporaryName);
118 | e3:
119 | free(buffer);
120 | e2:
121 | close(dir);
122 | e1:
123 |
124 | return -1;
125 | }
126 |
127 | int printDirectoryTree(const char *name)
128 | {
129 | struct stat sb;
130 |
131 | printf("%s", name);
132 | if(stat(name, &sb) >= 0)
133 | {
134 | printf(" [size: %"PRIdMAX" mode: ", (intmax_t)sb.st_size);
135 | printf((S_ISDIR(sb.st_mode)) ? "d" : "-");
136 | printf((sb.st_mode & S_IRUSR) ? "r" : "-");
137 | printf((sb.st_mode & S_IWUSR) ? "w" : "-");
138 | printf((sb.st_mode & S_IXUSR) ? "x" : "-");
139 | printf((sb.st_mode & S_IRGRP) ? "r" : "-");
140 | printf((sb.st_mode & S_IWGRP) ? "w" : "-");
141 | printf((sb.st_mode & S_IXGRP) ? "x" : "-");
142 | printf((sb.st_mode & S_IROTH) ? "r" : "-");
143 | printf((sb.st_mode & S_IWOTH) ? "w" : "-");
144 | printf((sb.st_mode & S_IXOTH) ? "x" : "-");
145 | printf("]");
146 | }
147 | printf("\n");
148 | return printDirectoryTree_(name, 0);
149 | }
150 |
151 | int main(int argc, char **argv)
152 | {
153 | #ifdef __PS4__
154 | int libc = sceKernelLoadStartModule("libSceLibcInternal.sprx", 0, NULL, 0, 0, 0);
155 | sceKernelDlsym(libc, "__stdoutp", (void **)&__stdoutp_address);
156 | __stdoutp = *__stdoutp_address;
157 | sceKernelDlsym(libc, "__mb_sb_limit", (void **)&__mb_sb_limit_address);
158 | __mb_sb_limit = *__mb_sb_limit_address;
159 | sceKernelDlsym(libc, "_CurrentRuneLocale", (void **)&_CurrentRuneLocale_address);
160 | _CurrentRuneLocale = *_CurrentRuneLocale_address;
161 | #endif
162 |
163 | printDirectoryTree("/");
164 | fflush(stdout);
165 |
166 | return EXIT_SUCCESS;
167 | }
168 |
--------------------------------------------------------------------------------
/freebsd/kernel_stacks/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/freebsd/kernel_stacks/include/uthash.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | #ifndef UTHASH_H
25 | #define UTHASH_H
26 |
27 | #include /* memcmp,strlen */
28 | #include /* ptrdiff_t */
29 | #include /* exit() */
30 |
31 | /* These macros use decltype or the earlier __typeof GNU extension.
32 | As decltype is only available in newer compilers (VS2010 or gcc 4.3+
33 | when compiling c++ source) this code uses whatever method is needed
34 | or, for VS2008 where neither is available, uses casting workarounds. */
35 | #if defined(_MSC_VER) /* MS compiler */
36 | #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
37 | #define DECLTYPE(x) (decltype(x))
38 | #else /* VS2008 or older (or VS2010 in C mode) */
39 | #define NO_DECLTYPE
40 | #define DECLTYPE(x)
41 | #endif
42 | #elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
43 | #define NO_DECLTYPE
44 | #define DECLTYPE(x)
45 | #else /* GNU, Sun and other compilers */
46 | #define DECLTYPE(x) (__typeof(x))
47 | #endif
48 |
49 | #ifdef NO_DECLTYPE
50 | #define DECLTYPE_ASSIGN(dst,src) \
51 | do { \
52 | char **_da_dst = (char**)(&(dst)); \
53 | *_da_dst = (char*)(src); \
54 | } while(0)
55 | #else
56 | #define DECLTYPE_ASSIGN(dst,src) \
57 | do { \
58 | (dst) = DECLTYPE(dst)(src); \
59 | } while(0)
60 | #endif
61 |
62 | /* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
63 | #if defined(_WIN32)
64 | #if defined(_MSC_VER) && _MSC_VER >= 1600
65 | #include
66 | #elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
67 | #include
68 | #else
69 | typedef unsigned int uint32_t;
70 | typedef unsigned char uint8_t;
71 | #endif
72 | #elif defined(__GNUC__) && !defined(__VXWORKS__)
73 | #include
74 | #else
75 | typedef unsigned int uint32_t;
76 | typedef unsigned char uint8_t;
77 | #endif
78 |
79 | #define UTHASH_VERSION 1.9.9
80 |
81 | #ifndef uthash_fatal
82 | #define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
83 | #endif
84 | #ifndef uthash_malloc
85 | #define uthash_malloc(sz) malloc(sz) /* malloc fcn */
86 | #endif
87 | #ifndef uthash_free
88 | #define uthash_free(ptr,sz) free(ptr) /* free fcn */
89 | #endif
90 |
91 | #ifndef uthash_noexpand_fyi
92 | #define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
93 | #endif
94 | #ifndef uthash_expand_fyi
95 | #define uthash_expand_fyi(tbl) /* can be defined to log expands */
96 | #endif
97 |
98 | /* initial number of buckets */
99 | #define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */
100 | #define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */
101 | #define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */
102 |
103 | /* calculate the element whose hash handle address is hhe */
104 | #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
105 |
106 | #define HASH_FIND(hh,head,keyptr,keylen,out) \
107 | do { \
108 | out=NULL; \
109 | if (head != NULL) { \
110 | unsigned _hf_bkt,_hf_hashv; \
111 | HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
112 | if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv) != 0) { \
113 | HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
114 | keyptr,keylen,out); \
115 | } \
116 | } \
117 | } while (0)
118 |
119 | #ifdef HASH_BLOOM
120 | #define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)
121 | #define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)
122 | #define HASH_BLOOM_MAKE(tbl) \
123 | do { \
124 | (tbl)->bloom_nbits = HASH_BLOOM; \
125 | (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
126 | if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
127 | memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
128 | (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
129 | } while (0)
130 |
131 | #define HASH_BLOOM_FREE(tbl) \
132 | do { \
133 | uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
134 | } while (0)
135 |
136 | #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
137 | #define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
138 |
139 | #define HASH_BLOOM_ADD(tbl,hashv) \
140 | HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))
141 |
142 | #define HASH_BLOOM_TEST(tbl,hashv) \
143 | HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))
144 |
145 | #else
146 | #define HASH_BLOOM_MAKE(tbl)
147 | #define HASH_BLOOM_FREE(tbl)
148 | #define HASH_BLOOM_ADD(tbl,hashv)
149 | #define HASH_BLOOM_TEST(tbl,hashv) (1)
150 | #define HASH_BLOOM_BYTELEN 0U
151 | #endif
152 |
153 | #define HASH_MAKE_TABLE(hh,head) \
154 | do { \
155 | (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
156 | sizeof(UT_hash_table)); \
157 | if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
158 | memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
159 | (head)->hh.tbl->tail = &((head)->hh); \
160 | (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
161 | (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
162 | (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
163 | (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
164 | HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
165 | if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
166 | memset((head)->hh.tbl->buckets, 0, \
167 | HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
168 | HASH_BLOOM_MAKE((head)->hh.tbl); \
169 | (head)->hh.tbl->signature = HASH_SIGNATURE; \
170 | } while(0)
171 |
172 | #define HASH_ADD(hh,head,fieldname,keylen_in,add) \
173 | HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
174 |
175 | #define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
176 | do { \
177 | replaced=NULL; \
178 | HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
179 | if (replaced!=NULL) { \
180 | HASH_DELETE(hh,head,replaced); \
181 | } \
182 | HASH_ADD(hh,head,fieldname,keylen_in,add); \
183 | } while(0)
184 |
185 | #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
186 | do { \
187 | unsigned _ha_bkt; \
188 | (add)->hh.next = NULL; \
189 | (add)->hh.key = (char*)(keyptr); \
190 | (add)->hh.keylen = (unsigned)(keylen_in); \
191 | if (!(head)) { \
192 | head = (add); \
193 | (head)->hh.prev = NULL; \
194 | HASH_MAKE_TABLE(hh,head); \
195 | } else { \
196 | (head)->hh.tbl->tail->next = (add); \
197 | (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
198 | (head)->hh.tbl->tail = &((add)->hh); \
199 | } \
200 | (head)->hh.tbl->num_items++; \
201 | (add)->hh.tbl = (head)->hh.tbl; \
202 | HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
203 | (add)->hh.hashv, _ha_bkt); \
204 | HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
205 | HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
206 | HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
207 | HASH_FSCK(hh,head); \
208 | } while(0)
209 |
210 | #define HASH_TO_BKT( hashv, num_bkts, bkt ) \
211 | do { \
212 | bkt = ((hashv) & ((num_bkts) - 1U)); \
213 | } while(0)
214 |
215 | /* delete "delptr" from the hash table.
216 | * "the usual" patch-up process for the app-order doubly-linked-list.
217 | * The use of _hd_hh_del below deserves special explanation.
218 | * These used to be expressed using (delptr) but that led to a bug
219 | * if someone used the same symbol for the head and deletee, like
220 | * HASH_DELETE(hh,users,users);
221 | * We want that to work, but by changing the head (users) below
222 | * we were forfeiting our ability to further refer to the deletee (users)
223 | * in the patch-up process. Solution: use scratch space to
224 | * copy the deletee pointer, then the latter references are via that
225 | * scratch pointer rather than through the repointed (users) symbol.
226 | */
227 | #define HASH_DELETE(hh,head,delptr) \
228 | do { \
229 | struct UT_hash_handle *_hd_hh_del; \
230 | if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
231 | uthash_free((head)->hh.tbl->buckets, \
232 | (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
233 | HASH_BLOOM_FREE((head)->hh.tbl); \
234 | uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
235 | head = NULL; \
236 | } else { \
237 | unsigned _hd_bkt; \
238 | _hd_hh_del = &((delptr)->hh); \
239 | if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
240 | (head)->hh.tbl->tail = \
241 | (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
242 | (head)->hh.tbl->hho); \
243 | } \
244 | if ((delptr)->hh.prev != NULL) { \
245 | ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
246 | (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
247 | } else { \
248 | DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
249 | } \
250 | if (_hd_hh_del->next != NULL) { \
251 | ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
252 | (head)->hh.tbl->hho))->prev = \
253 | _hd_hh_del->prev; \
254 | } \
255 | HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
256 | HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
257 | (head)->hh.tbl->num_items--; \
258 | } \
259 | HASH_FSCK(hh,head); \
260 | } while (0)
261 |
262 |
263 | /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
264 | #define HASH_FIND_STR(head,findstr,out) \
265 | HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out)
266 | #define HASH_ADD_STR(head,strfield,add) \
267 | HASH_ADD(hh,head,strfield[0],(unsigned int)strlen(add->strfield),add)
268 | #define HASH_REPLACE_STR(head,strfield,add,replaced) \
269 | HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced)
270 | #define HASH_FIND_INT(head,findint,out) \
271 | HASH_FIND(hh,head,findint,sizeof(int),out)
272 | #define HASH_ADD_INT(head,intfield,add) \
273 | HASH_ADD(hh,head,intfield,sizeof(int),add)
274 | #define HASH_REPLACE_INT(head,intfield,add,replaced) \
275 | HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
276 | #define HASH_FIND_PTR(head,findptr,out) \
277 | HASH_FIND(hh,head,findptr,sizeof(void *),out)
278 | #define HASH_ADD_PTR(head,ptrfield,add) \
279 | HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
280 | #define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \
281 | HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
282 | #define HASH_DEL(head,delptr) \
283 | HASH_DELETE(hh,head,delptr)
284 |
285 | /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
286 | * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
287 | */
288 | #ifdef HASH_DEBUG
289 | #define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
290 | #define HASH_FSCK(hh,head) \
291 | do { \
292 | struct UT_hash_handle *_thh; \
293 | if (head) { \
294 | unsigned _bkt_i; \
295 | unsigned _count; \
296 | char *_prev; \
297 | _count = 0; \
298 | for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
299 | unsigned _bkt_count = 0; \
300 | _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
301 | _prev = NULL; \
302 | while (_thh) { \
303 | if (_prev != (char*)(_thh->hh_prev)) { \
304 | HASH_OOPS("invalid hh_prev %p, actual %p\n", \
305 | _thh->hh_prev, _prev ); \
306 | } \
307 | _bkt_count++; \
308 | _prev = (char*)(_thh); \
309 | _thh = _thh->hh_next; \
310 | } \
311 | _count += _bkt_count; \
312 | if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
313 | HASH_OOPS("invalid bucket count %u, actual %u\n", \
314 | (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
315 | } \
316 | } \
317 | if (_count != (head)->hh.tbl->num_items) { \
318 | HASH_OOPS("invalid hh item count %u, actual %u\n", \
319 | (head)->hh.tbl->num_items, _count ); \
320 | } \
321 | /* traverse hh in app order; check next/prev integrity, count */ \
322 | _count = 0; \
323 | _prev = NULL; \
324 | _thh = &(head)->hh; \
325 | while (_thh) { \
326 | _count++; \
327 | if (_prev !=(char*)(_thh->prev)) { \
328 | HASH_OOPS("invalid prev %p, actual %p\n", \
329 | _thh->prev, _prev ); \
330 | } \
331 | _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
332 | _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
333 | (head)->hh.tbl->hho) : NULL ); \
334 | } \
335 | if (_count != (head)->hh.tbl->num_items) { \
336 | HASH_OOPS("invalid app item count %u, actual %u\n", \
337 | (head)->hh.tbl->num_items, _count ); \
338 | } \
339 | } \
340 | } while (0)
341 | #else
342 | #define HASH_FSCK(hh,head)
343 | #endif
344 |
345 | /* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
346 | * the descriptor to which this macro is defined for tuning the hash function.
347 | * The app can #include to get the prototype for write(2). */
348 | #ifdef HASH_EMIT_KEYS
349 | #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
350 | do { \
351 | unsigned _klen = fieldlen; \
352 | write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
353 | write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \
354 | } while (0)
355 | #else
356 | #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
357 | #endif
358 |
359 | /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
360 | #ifdef HASH_FUNCTION
361 | #define HASH_FCN HASH_FUNCTION
362 | #else
363 | #define HASH_FCN HASH_JEN
364 | #endif
365 |
366 | /* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
367 | #define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
368 | do { \
369 | unsigned _hb_keylen=(unsigned)keylen; \
370 | const unsigned char *_hb_key=(const unsigned char*)(key); \
371 | (hashv) = 0; \
372 | while (_hb_keylen-- != 0U) { \
373 | (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \
374 | } \
375 | bkt = (hashv) & (num_bkts-1U); \
376 | } while (0)
377 |
378 |
379 | /* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
380 | * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
381 | #define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
382 | do { \
383 | unsigned _sx_i; \
384 | const unsigned char *_hs_key=(const unsigned char*)(key); \
385 | hashv = 0; \
386 | for(_sx_i=0; _sx_i < keylen; _sx_i++) { \
387 | hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
388 | } \
389 | bkt = hashv & (num_bkts-1U); \
390 | } while (0)
391 | /* FNV-1a variation */
392 | #define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
393 | do { \
394 | unsigned _fn_i; \
395 | const unsigned char *_hf_key=(const unsigned char*)(key); \
396 | hashv = 2166136261U; \
397 | for(_fn_i=0; _fn_i < keylen; _fn_i++) { \
398 | hashv = hashv ^ _hf_key[_fn_i]; \
399 | hashv = hashv * 16777619U; \
400 | } \
401 | bkt = hashv & (num_bkts-1U); \
402 | } while(0)
403 |
404 | #define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
405 | do { \
406 | unsigned _ho_i; \
407 | const unsigned char *_ho_key=(const unsigned char*)(key); \
408 | hashv = 0; \
409 | for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
410 | hashv += _ho_key[_ho_i]; \
411 | hashv += (hashv << 10); \
412 | hashv ^= (hashv >> 6); \
413 | } \
414 | hashv += (hashv << 3); \
415 | hashv ^= (hashv >> 11); \
416 | hashv += (hashv << 15); \
417 | bkt = hashv & (num_bkts-1U); \
418 | } while(0)
419 |
420 | #define HASH_JEN_MIX(a,b,c) \
421 | do { \
422 | a -= b; a -= c; a ^= ( c >> 13 ); \
423 | b -= c; b -= a; b ^= ( a << 8 ); \
424 | c -= a; c -= b; c ^= ( b >> 13 ); \
425 | a -= b; a -= c; a ^= ( c >> 12 ); \
426 | b -= c; b -= a; b ^= ( a << 16 ); \
427 | c -= a; c -= b; c ^= ( b >> 5 ); \
428 | a -= b; a -= c; a ^= ( c >> 3 ); \
429 | b -= c; b -= a; b ^= ( a << 10 ); \
430 | c -= a; c -= b; c ^= ( b >> 15 ); \
431 | } while (0)
432 |
433 | #define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
434 | do { \
435 | unsigned _hj_i,_hj_j,_hj_k; \
436 | unsigned const char *_hj_key=(unsigned const char*)(key); \
437 | hashv = 0xfeedbeefu; \
438 | _hj_i = _hj_j = 0x9e3779b9u; \
439 | _hj_k = (unsigned)(keylen); \
440 | while (_hj_k >= 12U) { \
441 | _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
442 | + ( (unsigned)_hj_key[2] << 16 ) \
443 | + ( (unsigned)_hj_key[3] << 24 ) ); \
444 | _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
445 | + ( (unsigned)_hj_key[6] << 16 ) \
446 | + ( (unsigned)_hj_key[7] << 24 ) ); \
447 | hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
448 | + ( (unsigned)_hj_key[10] << 16 ) \
449 | + ( (unsigned)_hj_key[11] << 24 ) ); \
450 | \
451 | HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
452 | \
453 | _hj_key += 12; \
454 | _hj_k -= 12U; \
455 | } \
456 | hashv += (unsigned)(keylen); \
457 | switch ( _hj_k ) { \
458 | case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \
459 | case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \
460 | case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \
461 | case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \
462 | case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \
463 | case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \
464 | case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \
465 | case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
466 | case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
467 | case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
468 | case 1: _hj_i += _hj_key[0]; \
469 | } \
470 | HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
471 | bkt = hashv & (num_bkts-1U); \
472 | } while(0)
473 |
474 | /* The Paul Hsieh hash function */
475 | #undef get16bits
476 | #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
477 | || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
478 | #define get16bits(d) (*((const uint16_t *) (d)))
479 | #endif
480 |
481 | #if !defined (get16bits)
482 | #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
483 | +(uint32_t)(((const uint8_t *)(d))[0]) )
484 | #endif
485 | #define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
486 | do { \
487 | unsigned const char *_sfh_key=(unsigned const char*)(key); \
488 | uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \
489 | \
490 | unsigned _sfh_rem = _sfh_len & 3U; \
491 | _sfh_len >>= 2; \
492 | hashv = 0xcafebabeu; \
493 | \
494 | /* Main loop */ \
495 | for (;_sfh_len > 0U; _sfh_len--) { \
496 | hashv += get16bits (_sfh_key); \
497 | _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \
498 | hashv = (hashv << 16) ^ _sfh_tmp; \
499 | _sfh_key += 2U*sizeof (uint16_t); \
500 | hashv += hashv >> 11; \
501 | } \
502 | \
503 | /* Handle end cases */ \
504 | switch (_sfh_rem) { \
505 | case 3: hashv += get16bits (_sfh_key); \
506 | hashv ^= hashv << 16; \
507 | hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \
508 | hashv += hashv >> 11; \
509 | break; \
510 | case 2: hashv += get16bits (_sfh_key); \
511 | hashv ^= hashv << 11; \
512 | hashv += hashv >> 17; \
513 | break; \
514 | case 1: hashv += *_sfh_key; \
515 | hashv ^= hashv << 10; \
516 | hashv += hashv >> 1; \
517 | } \
518 | \
519 | /* Force "avalanching" of final 127 bits */ \
520 | hashv ^= hashv << 3; \
521 | hashv += hashv >> 5; \
522 | hashv ^= hashv << 4; \
523 | hashv += hashv >> 17; \
524 | hashv ^= hashv << 25; \
525 | hashv += hashv >> 6; \
526 | bkt = hashv & (num_bkts-1U); \
527 | } while(0)
528 |
529 | #ifdef HASH_USING_NO_STRICT_ALIASING
530 | /* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
531 | * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
532 | * MurmurHash uses the faster approach only on CPU's where we know it's safe.
533 | *
534 | * Note the preprocessor built-in defines can be emitted using:
535 | *
536 | * gcc -m64 -dM -E - < /dev/null (on gcc)
537 | * cc -## a.c (where a.c is a simple test file) (Sun Studio)
538 | */
539 | #if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
540 | #define MUR_GETBLOCK(p,i) p[i]
541 | #else /* non intel */
542 | #define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)
543 | #define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)
544 | #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
545 | #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
546 | #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
547 | #if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
548 | #define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
549 | #define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
550 | #define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
551 | #else /* assume little endian non-intel */
552 | #define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
553 | #define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
554 | #define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
555 | #endif
556 | #define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
557 | (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
558 | (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
559 | MUR_ONE_THREE(p))))
560 | #endif
561 | #define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
562 | #define MUR_FMIX(_h) \
563 | do { \
564 | _h ^= _h >> 16; \
565 | _h *= 0x85ebca6bu; \
566 | _h ^= _h >> 13; \
567 | _h *= 0xc2b2ae35u; \
568 | _h ^= _h >> 16; \
569 | } while(0)
570 |
571 | #define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
572 | do { \
573 | const uint8_t *_mur_data = (const uint8_t*)(key); \
574 | const int _mur_nblocks = (int)(keylen) / 4; \
575 | uint32_t _mur_h1 = 0xf88D5353u; \
576 | uint32_t _mur_c1 = 0xcc9e2d51u; \
577 | uint32_t _mur_c2 = 0x1b873593u; \
578 | uint32_t _mur_k1 = 0; \
579 | const uint8_t *_mur_tail; \
580 | const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \
581 | int _mur_i; \
582 | for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \
583 | _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
584 | _mur_k1 *= _mur_c1; \
585 | _mur_k1 = MUR_ROTL32(_mur_k1,15); \
586 | _mur_k1 *= _mur_c2; \
587 | \
588 | _mur_h1 ^= _mur_k1; \
589 | _mur_h1 = MUR_ROTL32(_mur_h1,13); \
590 | _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \
591 | } \
592 | _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \
593 | _mur_k1=0; \
594 | switch((keylen) & 3U) { \
595 | case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \
596 | case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \
597 | case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \
598 | _mur_k1 *= _mur_c1; \
599 | _mur_k1 = MUR_ROTL32(_mur_k1,15); \
600 | _mur_k1 *= _mur_c2; \
601 | _mur_h1 ^= _mur_k1; \
602 | } \
603 | _mur_h1 ^= (uint32_t)(keylen); \
604 | MUR_FMIX(_mur_h1); \
605 | hashv = _mur_h1; \
606 | bkt = hashv & (num_bkts-1U); \
607 | } while(0)
608 | #endif /* HASH_USING_NO_STRICT_ALIASING */
609 |
610 | /* key comparison function; return 0 if keys equal */
611 | #define HASH_KEYCMP(a,b,len) memcmp(a,b,(unsigned long)(len))
612 |
613 | /* iterate over items in a known bucket to find desired item */
614 | #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
615 | do { \
616 | if (head.hh_head != NULL) { DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); } \
617 | else { out=NULL; } \
618 | while (out != NULL) { \
619 | if ((out)->hh.keylen == (keylen_in)) { \
620 | if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) { break; } \
621 | } \
622 | if ((out)->hh.hh_next != NULL) { DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); } \
623 | else { out = NULL; } \
624 | } \
625 | } while(0)
626 |
627 | /* add an item to a bucket */
628 | #define HASH_ADD_TO_BKT(head,addhh) \
629 | do { \
630 | head.count++; \
631 | (addhh)->hh_next = head.hh_head; \
632 | (addhh)->hh_prev = NULL; \
633 | if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \
634 | (head).hh_head=addhh; \
635 | if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \
636 | && ((addhh)->tbl->noexpand != 1U)) { \
637 | HASH_EXPAND_BUCKETS((addhh)->tbl); \
638 | } \
639 | } while(0)
640 |
641 | /* remove an item from a given bucket */
642 | #define HASH_DEL_IN_BKT(hh,head,hh_del) \
643 | (head).count--; \
644 | if ((head).hh_head == hh_del) { \
645 | (head).hh_head = hh_del->hh_next; \
646 | } \
647 | if (hh_del->hh_prev) { \
648 | hh_del->hh_prev->hh_next = hh_del->hh_next; \
649 | } \
650 | if (hh_del->hh_next) { \
651 | hh_del->hh_next->hh_prev = hh_del->hh_prev; \
652 | }
653 |
654 | /* Bucket expansion has the effect of doubling the number of buckets
655 | * and redistributing the items into the new buckets. Ideally the
656 | * items will distribute more or less evenly into the new buckets
657 | * (the extent to which this is true is a measure of the quality of
658 | * the hash function as it applies to the key domain).
659 | *
660 | * With the items distributed into more buckets, the chain length
661 | * (item count) in each bucket is reduced. Thus by expanding buckets
662 | * the hash keeps a bound on the chain length. This bounded chain
663 | * length is the essence of how a hash provides constant time lookup.
664 | *
665 | * The calculation of tbl->ideal_chain_maxlen below deserves some
666 | * explanation. First, keep in mind that we're calculating the ideal
667 | * maximum chain length based on the *new* (doubled) bucket count.
668 | * In fractions this is just n/b (n=number of items,b=new num buckets).
669 | * Since the ideal chain length is an integer, we want to calculate
670 | * ceil(n/b). We don't depend on floating point arithmetic in this
671 | * hash, so to calculate ceil(n/b) with integers we could write
672 | *
673 | * ceil(n/b) = (n/b) + ((n%b)?1:0)
674 | *
675 | * and in fact a previous version of this hash did just that.
676 | * But now we have improved things a bit by recognizing that b is
677 | * always a power of two. We keep its base 2 log handy (call it lb),
678 | * so now we can write this with a bit shift and logical AND:
679 | *
680 | * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
681 | *
682 | */
683 | #define HASH_EXPAND_BUCKETS(tbl) \
684 | do { \
685 | unsigned _he_bkt; \
686 | unsigned _he_bkt_i; \
687 | struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
688 | UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
689 | _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
690 | 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
691 | if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
692 | memset(_he_new_buckets, 0, \
693 | 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
694 | tbl->ideal_chain_maxlen = \
695 | (tbl->num_items >> (tbl->log2_num_buckets+1U)) + \
696 | (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
697 | tbl->nonideal_items = 0; \
698 | for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
699 | { \
700 | _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
701 | while (_he_thh != NULL) { \
702 | _he_hh_nxt = _he_thh->hh_next; \
703 | HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \
704 | _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
705 | if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
706 | tbl->nonideal_items++; \
707 | _he_newbkt->expand_mult = _he_newbkt->count / \
708 | tbl->ideal_chain_maxlen; \
709 | } \
710 | _he_thh->hh_prev = NULL; \
711 | _he_thh->hh_next = _he_newbkt->hh_head; \
712 | if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \
713 | _he_thh; } \
714 | _he_newbkt->hh_head = _he_thh; \
715 | _he_thh = _he_hh_nxt; \
716 | } \
717 | } \
718 | uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
719 | tbl->num_buckets *= 2U; \
720 | tbl->log2_num_buckets++; \
721 | tbl->buckets = _he_new_buckets; \
722 | tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
723 | (tbl->ineff_expands+1U) : 0U; \
724 | if (tbl->ineff_expands > 1U) { \
725 | tbl->noexpand=1; \
726 | uthash_noexpand_fyi(tbl); \
727 | } \
728 | uthash_expand_fyi(tbl); \
729 | } while(0)
730 |
731 |
732 | /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
733 | /* Note that HASH_SORT assumes the hash handle name to be hh.
734 | * HASH_SRT was added to allow the hash handle name to be passed in. */
735 | #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
736 | #define HASH_SRT(hh,head,cmpfcn) \
737 | do { \
738 | unsigned _hs_i; \
739 | unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
740 | struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
741 | if (head != NULL) { \
742 | _hs_insize = 1; \
743 | _hs_looping = 1; \
744 | _hs_list = &((head)->hh); \
745 | while (_hs_looping != 0U) { \
746 | _hs_p = _hs_list; \
747 | _hs_list = NULL; \
748 | _hs_tail = NULL; \
749 | _hs_nmerges = 0; \
750 | while (_hs_p != NULL) { \
751 | _hs_nmerges++; \
752 | _hs_q = _hs_p; \
753 | _hs_psize = 0; \
754 | for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
755 | _hs_psize++; \
756 | _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \
757 | ((void*)((char*)(_hs_q->next) + \
758 | (head)->hh.tbl->hho)) : NULL); \
759 | if (! (_hs_q) ) { break; } \
760 | } \
761 | _hs_qsize = _hs_insize; \
762 | while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\
763 | if (_hs_psize == 0U) { \
764 | _hs_e = _hs_q; \
765 | _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \
766 | ((void*)((char*)(_hs_q->next) + \
767 | (head)->hh.tbl->hho)) : NULL); \
768 | _hs_qsize--; \
769 | } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \
770 | _hs_e = _hs_p; \
771 | if (_hs_p != NULL){ \
772 | _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \
773 | ((void*)((char*)(_hs_p->next) + \
774 | (head)->hh.tbl->hho)) : NULL); \
775 | } \
776 | _hs_psize--; \
777 | } else if (( \
778 | cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
779 | DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
780 | ) <= 0) { \
781 | _hs_e = _hs_p; \
782 | if (_hs_p != NULL){ \
783 | _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \
784 | ((void*)((char*)(_hs_p->next) + \
785 | (head)->hh.tbl->hho)) : NULL); \
786 | } \
787 | _hs_psize--; \
788 | } else { \
789 | _hs_e = _hs_q; \
790 | _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \
791 | ((void*)((char*)(_hs_q->next) + \
792 | (head)->hh.tbl->hho)) : NULL); \
793 | _hs_qsize--; \
794 | } \
795 | if ( _hs_tail != NULL ) { \
796 | _hs_tail->next = ((_hs_e != NULL) ? \
797 | ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
798 | } else { \
799 | _hs_list = _hs_e; \
800 | } \
801 | if (_hs_e != NULL) { \
802 | _hs_e->prev = ((_hs_tail != NULL) ? \
803 | ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
804 | } \
805 | _hs_tail = _hs_e; \
806 | } \
807 | _hs_p = _hs_q; \
808 | } \
809 | if (_hs_tail != NULL){ \
810 | _hs_tail->next = NULL; \
811 | } \
812 | if ( _hs_nmerges <= 1U ) { \
813 | _hs_looping=0; \
814 | (head)->hh.tbl->tail = _hs_tail; \
815 | DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
816 | } \
817 | _hs_insize *= 2U; \
818 | } \
819 | HASH_FSCK(hh,head); \
820 | } \
821 | } while (0)
822 |
823 | /* This function selects items from one hash into another hash.
824 | * The end result is that the selected items have dual presence
825 | * in both hashes. There is no copy of the items made; rather
826 | * they are added into the new hash through a secondary hash
827 | * hash handle that must be present in the structure. */
828 | #define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
829 | do { \
830 | unsigned _src_bkt, _dst_bkt; \
831 | void *_last_elt=NULL, *_elt; \
832 | UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
833 | ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
834 | if (src != NULL) { \
835 | for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
836 | for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
837 | _src_hh != NULL; \
838 | _src_hh = _src_hh->hh_next) { \
839 | _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
840 | if (cond(_elt)) { \
841 | _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
842 | _dst_hh->key = _src_hh->key; \
843 | _dst_hh->keylen = _src_hh->keylen; \
844 | _dst_hh->hashv = _src_hh->hashv; \
845 | _dst_hh->prev = _last_elt; \
846 | _dst_hh->next = NULL; \
847 | if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \
848 | if (dst == NULL) { \
849 | DECLTYPE_ASSIGN(dst,_elt); \
850 | HASH_MAKE_TABLE(hh_dst,dst); \
851 | } else { \
852 | _dst_hh->tbl = (dst)->hh_dst.tbl; \
853 | } \
854 | HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
855 | HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
856 | (dst)->hh_dst.tbl->num_items++; \
857 | _last_elt = _elt; \
858 | _last_elt_hh = _dst_hh; \
859 | } \
860 | } \
861 | } \
862 | } \
863 | HASH_FSCK(hh_dst,dst); \
864 | } while (0)
865 |
866 | #define HASH_CLEAR(hh,head) \
867 | do { \
868 | if (head != NULL) { \
869 | uthash_free((head)->hh.tbl->buckets, \
870 | (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
871 | HASH_BLOOM_FREE((head)->hh.tbl); \
872 | uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
873 | (head)=NULL; \
874 | } \
875 | } while(0)
876 |
877 | #define HASH_OVERHEAD(hh,head) \
878 | ((head != NULL) ? ( \
879 | (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
880 | ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
881 | sizeof(UT_hash_table) + \
882 | (HASH_BLOOM_BYTELEN))) : 0U)
883 |
884 | #ifdef NO_DECLTYPE
885 | #define HASH_ITER(hh,head,el,tmp) \
886 | for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \
887 | (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL)))
888 | #else
889 | #define HASH_ITER(hh,head,el,tmp) \
890 | for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \
891 | (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL)))
892 | #endif
893 |
894 | /* obtain a count of items in the hash */
895 | #define HASH_COUNT(head) HASH_CNT(hh,head)
896 | #define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U)
897 |
898 | typedef struct UT_hash_bucket {
899 | struct UT_hash_handle *hh_head;
900 | unsigned count;
901 |
902 | /* expand_mult is normally set to 0. In this situation, the max chain length
903 | * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
904 | * the bucket's chain exceeds this length, bucket expansion is triggered).
905 | * However, setting expand_mult to a non-zero value delays bucket expansion
906 | * (that would be triggered by additions to this particular bucket)
907 | * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
908 | * (The multiplier is simply expand_mult+1). The whole idea of this
909 | * multiplier is to reduce bucket expansions, since they are expensive, in
910 | * situations where we know that a particular bucket tends to be overused.
911 | * It is better to let its chain length grow to a longer yet-still-bounded
912 | * value, than to do an O(n) bucket expansion too often.
913 | */
914 | unsigned expand_mult;
915 |
916 | } UT_hash_bucket;
917 |
918 | /* random signature used only to find hash tables in external analysis */
919 | #define HASH_SIGNATURE 0xa0111fe1u
920 | #define HASH_BLOOM_SIGNATURE 0xb12220f2u
921 |
922 | typedef struct UT_hash_table {
923 | UT_hash_bucket *buckets;
924 | unsigned num_buckets, log2_num_buckets;
925 | unsigned num_items;
926 | struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
927 | ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
928 |
929 | /* in an ideal situation (all buckets used equally), no bucket would have
930 | * more than ceil(#items/#buckets) items. that's the ideal chain length. */
931 | unsigned ideal_chain_maxlen;
932 |
933 | /* nonideal_items is the number of items in the hash whose chain position
934 | * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
935 | * hash distribution; reaching them in a chain traversal takes >ideal steps */
936 | unsigned nonideal_items;
937 |
938 | /* ineffective expands occur when a bucket doubling was performed, but
939 | * afterward, more than half the items in the hash had nonideal chain
940 | * positions. If this happens on two consecutive expansions we inhibit any
941 | * further expansion, as it's not helping; this happens when the hash
942 | * function isn't a good fit for the key domain. When expansion is inhibited
943 | * the hash will still work, albeit no longer in constant time. */
944 | unsigned ineff_expands, noexpand;
945 |
946 | uint32_t signature; /* used only to find hash tables in external analysis */
947 | #ifdef HASH_BLOOM
948 | uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
949 | uint8_t *bloom_bv;
950 | uint8_t bloom_nbits;
951 | #endif
952 |
953 | } UT_hash_table;
954 |
955 | typedef struct UT_hash_handle {
956 | struct UT_hash_table *tbl;
957 | void *prev; /* prev element in app order */
958 | void *next; /* next element in app order */
959 | struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
960 | struct UT_hash_handle *hh_next; /* next hh in bucket order */
961 | void *key; /* ptr to enclosing struct's key */
962 | unsigned keylen; /* enclosing struct's key len */
963 | unsigned hashv; /* result of hash-fcn(key) */
964 | } UT_hash_handle;
965 |
966 | #endif /* UTHASH_H */
967 |
--------------------------------------------------------------------------------
/freebsd/kernel_stacks/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 | //#include
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "uthash.h"
21 |
22 | #ifdef __PS4__
23 | #include
24 |
25 | __typeof__(__stdoutp) __stdoutp;
26 | __typeof__(__stdoutp) *__stdoutp_address;
27 | __typeof__(__mb_sb_limit) __mb_sb_limit;
28 | __typeof__(__mb_sb_limit) *__mb_sb_limit_address;
29 | __typeof__(_CurrentRuneLocale) _CurrentRuneLocale;
30 | __typeof__(_CurrentRuneLocale) *_CurrentRuneLocale_address;
31 |
32 | #endif
33 |
34 | typedef struct KernelFunction
35 | {
36 | uintmax_t id; // address
37 | int number; // seen first at
38 | char found[700]; // seen at
39 | char name[256]; // name
40 | UT_hash_handle hh;
41 | }
42 | KernelFunction;
43 |
44 | /*
45 | static sigjmp_buf jmpbuf;
46 |
47 | void sighandler(int sig)
48 | {
49 | siglongjmp(jmpbuf, 1);
50 | }
51 | */
52 |
53 | int printBytes(char *str, size_t size)
54 | {
55 | int i;
56 | if(str == NULL)
57 | return -1;
58 | for(i = 0; i < size; ++i)
59 | printf("%02X", (unsigned char)str[i]);
60 | printf("\n");
61 | return 0;
62 | }
63 |
64 | int printPrintableBytes(char *str, size_t size)
65 | {
66 | int i;
67 | if(str == NULL)
68 | return -1;
69 | for(i = 0; i < size; ++i)
70 | if(isprint(str[i]))
71 | printf("%c", str[i]);
72 | else
73 | printf(" ");
74 | printf("\n");
75 | return 0;
76 | }
77 |
78 | void *loopSyscall(void *arg)
79 | {
80 | int *syscallNumber = (int *)arg;
81 | while(*syscallNumber >= 0)
82 | syscall(*syscallNumber, 0, 0, 0, 0, 0);
83 | return NULL;
84 | }
85 |
86 | void *loopSyscall_rand(void *arg)
87 | {
88 | int *syscallNumber = (int *)arg;
89 | while(*syscallNumber >= 0) // rand aint thread safe ... who gives
90 | syscall(*syscallNumber, rand(), rand(), rand(), rand(), rand());
91 | return NULL;
92 | }
93 |
94 | void hashKernelFunctionAdd(KernelFunction **kernelFunctions, int address, char *name, int number)
95 | {
96 | KernelFunction *s;
97 |
98 | HASH_FIND_INT(*kernelFunctions, &address, s);
99 | if (s == NULL)
100 | {
101 | s = (KernelFunction *)calloc(sizeof(KernelFunction), 1);
102 | s->id = address;
103 | s->number = number;
104 | strcpy(s->name, name);
105 | HASH_ADD_INT(*kernelFunctions, id, s);
106 | }
107 | s->found[number] = 1;
108 | }
109 |
110 | void hashKernelFunctionPrint(KernelFunction **kernelFunctions)
111 | {
112 | KernelFunction *s, *t;
113 | int i;
114 |
115 | HASH_ITER(hh, *kernelFunctions, s, t)
116 | {
117 | printf("0x%"PRIxMAX" %s %i [", s->id, s->name, s->number);
118 | for(i = 0; i < 700; ++i)
119 | if(s->found[i] == 1)
120 | printf("%i ", i);
121 | printf("]\n");
122 | fflush(stdout);
123 | HASH_DEL(*kernelFunctions, s);
124 | free(s);
125 | }
126 | }
127 |
128 | void hashKernelFunctionsFromStackTrace(KernelFunction **kernelFunctions, char *trace, int number)
129 | {
130 | int index;
131 | intmax_t address;
132 | intmax_t offset;
133 | char *name;
134 |
135 | char plusData[2048];
136 | char *line, *lineSave;
137 |
138 | //printf("%s", trace);
139 | //fflush(stdout);
140 |
141 | line = strtok_r(trace, "\n", &lineSave);
142 | while(line != NULL)
143 | {
144 | char *token, *tokenSave, *plus, *plusSave;
145 |
146 | token = strtok_r(line, " ", &tokenSave);
147 | sscanf(token, "#%i ", &index);
148 | token = strtok_r(NULL, " ", &tokenSave);
149 | sscanf(token, "%"SCNxMAX" at ", &address);
150 | token = strtok_r(NULL, " ", &tokenSave);
151 | token = strtok_r(NULL, " ", &tokenSave);
152 | sscanf(token, "%s", plusData);
153 |
154 | name = strtok_r(plusData, "+", &plusSave);
155 | plus = strtok_r(NULL, "+", &plusSave);
156 | sscanf(plus, "%"SCNxMAX, &offset);
157 |
158 | line = strtok_r(NULL, "\n", &lineSave);
159 |
160 | //printf("%"PRIxMAX" %s\n", address - offset, name);
161 | //fflush(stdout);
162 | hashKernelFunctionAdd(kernelFunctions, address - offset, name, number);
163 | }
164 | }
165 |
166 | int main(int argc, char **argv)
167 | {
168 | //struct sigaction action;
169 | pthread_t threads[16];
170 | struct kinfo_kstack *stacks;
171 | size_t stackCount;
172 | int name[4];
173 | volatile int syscallNumber, i, j, k, l;
174 | char block[700];
175 |
176 | memset(block, 0, 700);
177 | block[0] = 1; // SIGSYS, change args
178 | block[1] = 1;
179 | block[8] = 1; // "old"
180 | block[11] = 0; // "old" but doesn't crash?
181 | block[18] = 1; // "freebsd4"
182 | block[19] = 1; // "old"
183 | block[38] = 1; // unchecked but "old"
184 | block[40] = 1; // unchecked but "old"
185 | block[44] = 1; // unchecked but "old"
186 | block[46] = 1; // "old"
187 | block[48] = 1; // unchecked but "old"
188 | block[52] = 1; // unchecked but "old"
189 | block[62] = 1; // unchecked but "old"
190 | block[63] = 1; // unchecked but "old"
191 | block[64] = 1; // unchecked but "old"
192 | block[67] = 1; // unchecked but "old"
193 | block[68] = 1; // unchecked but "old"
194 | block[71] = 1; // unchecked but "old"
195 | block[76] = 1; // unchecked but "old"
196 | block[77] = 1; // unchecked but "old"
197 | block[84] = 1; // "old"
198 | block[87] = 1; // unchecked but "old"
199 | block[88] = 1; // unchecked but "old"
200 | block[93] = 1; // blocks - change args ... ?
201 | block[99] = 1; // unchecked but "old"
202 | block[101] = 1; // unchecked but "old"
203 | block[102] = 1; // unchecked but "old"
204 | block[103] = 1; // unchecked but "old"
205 | block[107] = 1; // unchecked but "old"
206 | block[108] = 1; // unchecked but "old"
207 | block[109] = 1; // unchecked but "old"
208 | block[110] = 1; // unchecked but "old"
209 | block[111] = 1; // unchecked but "old"
210 | block[112] = 1; // unchecked but "old"
211 | block[113] = 1; // unchecked but "old"
212 | block[114] = 1; // unchecked but "old"
213 | block[115] = 1; // unchecked but "old"
214 | block[125] = 1; // unchecked but "old"
215 | block[129] = 1; // unchecked but "old"
216 | block[130] = 1; // unchecked but "old"
217 | block[139] = 1; // unchecked but "old"
218 | block[141] = 1; // unchecked but "old"
219 | block[142] = 1; // unchecked but "old"
220 | block[143] = 1; // unchecked but "old"
221 | block[144] = 1; // unchecked but "old"
222 | block[145] = 1; // unchecked but "old"
223 | block[146] = 1; // unchecked but "old"
224 | block[149] = 1; // unchecked but "old"
225 | block[150] = 1; // unchecked but "old"
226 | block[156] = 1; // unchecked but "old"
227 | block[157] = 1; // "freebsd4"
228 | block[158] = 1; // "freebsd4"
229 | block[162] = 1; // "freebsd4"
230 | block[163] = 1; // "freebsd4"
231 | block[164] = 1; // "freebsd4"
232 | block[198] = 1; // SIGSYS, change args
233 | block[297] = 1; // unchecked but "freebsd4"
234 | block[313] = 1; // unchecked but "old"
235 | block[322] = 1; // unchecked but "old"
236 | block[323] = 1; // unchecked but "old"
237 | block[336] = 1; // unchecked but "freebsd4"
238 | block[342] = 1; // unchecked but "freebsd4"
239 | block[344] = 1; // unchecked but "freebsd4"
240 | block[431] = 1; // blocks
241 | block[442] = 1; // blocks
242 | block[455] = 1;
243 | block[578] = 1; // kernel crash
244 | block[522] = 1; // when run from 0 to 617 - this one hangs ...
245 | block[579] = 1; // kernel crash
246 |
247 | srand(time(NULL));
248 |
249 | #ifdef __PS4__
250 | int libc = sceKernelLoadStartModule("libSceLibcInternal.sprx", 0, NULL, 0, 0, 0);
251 | sceKernelDlsym(libc, "__stdoutp", (void **)&__stdoutp_address);
252 | __stdoutp = *__stdoutp_address;
253 | sceKernelDlsym(libc, "__mb_sb_limit", (void **)&__mb_sb_limit_address);
254 | __mb_sb_limit = *__mb_sb_limit_address;
255 | sceKernelDlsym(libc, "_CurrentRuneLocale", (void **)&_CurrentRuneLocale_address);
256 | _CurrentRuneLocale = *_CurrentRuneLocale_address;
257 | #endif
258 |
259 | /*
260 | action.sa_handler = sighandler;
261 | action.sa_flags = 0;
262 | sigemptyset(&action.sa_mask);
263 | sigaction(SIGSYS, &action, NULL);
264 | sigaction(SIGSEGV, &action, NULL);
265 | sigaction(SIGILL, &action, NULL);
266 | */
267 |
268 | KernelFunction *kernelFunctions = NULL;
269 |
270 | name[0] = CTL_KERN;
271 | name[1] = KERN_PROC;
272 | name[2] = KERN_PROC_KSTACK;
273 | name[3] = getpid();
274 |
275 | for(k = 0; k <= 617; ++k)
276 | //for(k = 531; k <= 617; ++k)
277 | {
278 | /*
279 | if(sigsetjmp(jmpbuf, 1) != 0)
280 | {
281 | //printf("SIGSEGV, SIGILL or SIGSYS -> skipping %i\n", k);
282 | printf("<-error ");
283 | continue;
284 | }
285 | */
286 |
287 | printf("%i ", k);
288 |
289 | if(block[k] == 1)
290 | {
291 | printf("<-skip ");
292 | if(k % 16 == 0)
293 | printf("\n");
294 | continue;
295 | }
296 |
297 | if(k % 16 == 0)
298 | printf("\n");
299 |
300 | syscallNumber = k;
301 |
302 | for(l = 0; l < sizeof(threads) / sizeof(threads[0]); ++l)
303 | pthread_create(&threads[l], NULL, loopSyscall_rand, (void *)&syscallNumber);
304 |
305 | for(i = 0; i < 256; ++i)
306 | {
307 | if(sysctl(name, 4, NULL, &stackCount, NULL, 0) < 0)
308 | break;
309 |
310 | stacks = malloc(stackCount);
311 |
312 | if(sysctl(name, 4, stacks, &stackCount, NULL, 0) < 0)
313 | break;
314 |
315 | for(j = 0; j < stackCount / sizeof(stacks[0]); ++j)
316 | hashKernelFunctionsFromStackTrace(&kernelFunctions, stacks[j].kkst_trace, syscallNumber);
317 | //hashKernelFunctionsFromStackTrace(&kernelFunctions, stacks[0].kkst_trace, syscallNumber);
318 |
319 | free(stacks);
320 | }
321 |
322 | //hashKernelFunctionPrint(&kernelFunctions);
323 |
324 | syscallNumber = -1;
325 | for(l = 0; l < sizeof(threads) / sizeof(threads[0]); ++l)
326 | pthread_join(threads[l], NULL);
327 |
328 | //sleep(10);
329 | }
330 | printf("\n");
331 |
332 | hashKernelFunctionPrint(&kernelFunctions);
333 |
334 | return EXIT_SUCCESS;
335 | }
336 |
--------------------------------------------------------------------------------
/freebsd/write_access/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/freebsd/write_access/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #ifdef __PS4__
16 | #include
17 |
18 | __typeof__(__stdoutp) __stdoutp;
19 | __typeof__(__stdoutp) *__stdoutp_address;
20 | __typeof__(__mb_sb_limit) __mb_sb_limit;
21 | __typeof__(__mb_sb_limit) *__mb_sb_limit_address;
22 | __typeof__(_CurrentRuneLocale) _CurrentRuneLocale;
23 | __typeof__(_CurrentRuneLocale) *_CurrentRuneLocale_address;
24 | #endif
25 |
26 | /* !!! DANGER !!!
27 | Writes and deletes a ./test file into any subfolder of / to check access
28 | Only use it on a freebsd if you got no files named "test" that you care
29 | about ^_^
30 | */
31 |
32 | #define DirectoryBufferSize 1024 * 1024
33 | #define TemporaryNameSize 4096
34 |
35 | int printDirectoryTree_(const char *name, int depth)
36 | {
37 | int dir, count;
38 | char *buffer;
39 | char *temporaryName;
40 | struct dirent *entry;
41 | int position;
42 | struct stat sb;
43 |
44 | dir = open(name, O_RDONLY | O_DIRECTORY);
45 | if(dir == -1)
46 | goto e1;
47 |
48 | buffer = malloc(DirectoryBufferSize);
49 | if(buffer == NULL)
50 | goto e2;
51 |
52 | temporaryName = malloc(TemporaryNameSize);
53 | if(temporaryName == NULL)
54 | goto e3;
55 |
56 | count = getdents(dir, buffer, DirectoryBufferSize);
57 | if(count <= 0)
58 | goto e4;
59 |
60 | entry = (struct dirent *)buffer;
61 | if(entry == NULL || entry->d_reclen == 0)
62 | goto e4;
63 |
64 | for(position = 0; position < count;)
65 | {
66 | entry = (struct dirent *)(buffer + position);
67 |
68 | if(entry->d_reclen == 0)
69 | break;
70 |
71 | if(strncmp(entry->d_name, ".", entry->d_namlen) == 0 || strncmp(entry->d_name, "..", entry->d_namlen) == 0)
72 | {
73 | position += entry->d_reclen;
74 | continue;
75 | }
76 |
77 | strcpy(temporaryName, name);
78 | {
79 | size_t l = strlen(name);
80 | if(l > 0 && name[l - 1] != '/')
81 | strcat(temporaryName, "/");
82 | }
83 | strcat(temporaryName, entry->d_name);
84 | if(stat(temporaryName, &sb) >= 0)
85 | {
86 | if(S_ISDIR(sb.st_mode))
87 | {
88 | printf("%s", temporaryName);
89 | strcat(temporaryName, "/test");
90 | int t = open(temporaryName, O_RDWR);
91 | if(t >= 0)
92 | {
93 | printf(" RW");
94 |
95 | if(write(t, temporaryName, strlen(temporaryName)) < 0)
96 | printf(" E2");
97 | if(close(t) < 0)
98 | printf(" E3");
99 | if(unlink(temporaryName) < 0)
100 | printf(" E4");
101 | }
102 | else
103 | printf(" E1");
104 | printf("\n");
105 | strcpy(temporaryName, name);
106 | {
107 | size_t l = strlen(name);
108 | if(l > 0 && name[l - 1] != '/')
109 | strcat(temporaryName, "/");
110 | }
111 | strcat(temporaryName, entry->d_name);
112 | }
113 | }
114 |
115 | if(entry->d_type == DT_UNKNOWN)
116 | {
117 | position += entry->d_reclen;
118 | continue;
119 | }
120 |
121 | if(entry->d_type == DT_DIR && entry->d_fileno != 0)
122 | printDirectoryTree_(temporaryName, depth + 1);
123 |
124 | fflush(stdout);
125 |
126 | position += entry->d_reclen;
127 | }
128 |
129 | free(temporaryName);
130 | free(buffer);
131 | close(dir);
132 |
133 | return 0;
134 |
135 | e4:
136 | free(temporaryName);
137 | e3:
138 | free(buffer);
139 | e2:
140 | close(dir);
141 | e1:
142 |
143 | return -1;
144 | }
145 |
146 | int printDirectoryTree(const char *name)
147 | {
148 | printf("%s\n", name);
149 | return printDirectoryTree_(name, 0);
150 | }
151 |
152 | int main(int argc, char **argv)
153 | {
154 | #ifdef __PS4__
155 | int libc = sceKernelLoadStartModule("libSceLibcInternal.sprx", 0, NULL, 0, 0, 0);
156 | sceKernelDlsym(libc, "__stdoutp", (void **)&__stdoutp_address);
157 | __stdoutp = *__stdoutp_address;
158 | sceKernelDlsym(libc, "__mb_sb_limit", (void **)&__mb_sb_limit_address);
159 | __mb_sb_limit = *__mb_sb_limit_address;
160 | sceKernelDlsym(libc, "_CurrentRuneLocale", (void **)&_CurrentRuneLocale_address);
161 | _CurrentRuneLocale = *_CurrentRuneLocale_address;
162 | #endif
163 |
164 | printDirectoryTree("/");
165 | fflush(stdout);
166 |
167 | return EXIT_SUCCESS;
168 | }
169 |
--------------------------------------------------------------------------------
/kernel/cache/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/kernel/cache/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include
5 |
6 | #define SERVER_PORT 5088
7 |
8 | int main(int argc, char **argv)
9 | {
10 | Ps4KernelCache *c;
11 | void *m, *m2;
12 | int r;
13 |
14 | Ps4KernelThread *td;
15 | Ps4KernelSocket *client;
16 |
17 | if(ps4KernelIsInKernel() != PS4_OK)
18 | {
19 | printf("This is not a user space application.\n");
20 | return PS4_ERROR_IS_KERNEL_ELF;
21 | }
22 |
23 | ps4KernelThreadGetCurrent(&td);
24 | r = ps4KernelSocketTCPServerCreateAcceptThenDestroy(td, &client, SERVER_PORT);
25 |
26 | m = m2 = NULL;
27 | r = ps4KernelCacheCreate(&c);
28 | r = ps4KernelSocketPrint(td, client, "cache create: %p %i\n", c, r);
29 |
30 | r = ps4KernelCacheGet(c, "foo", &m2);
31 | r = ps4KernelSocketPrint(td, client, "cache get foo m2: %p %i\n", m2, r);
32 |
33 | m = (void *)42;
34 | r = ps4KernelCacheSet(c, "foo", m);
35 | r = ps4KernelSocketPrint(td, client, "cache set foo m: %p %i\n", m, r);
36 |
37 | r = ps4KernelCacheGet(c, "foo", &m2);
38 | r = ps4KernelSocketPrint(td, client, "cache get foo m2: %p %i\n", m2, r);
39 |
40 | r = ps4KernelCacheDelete(c, "foo");
41 | r = ps4KernelSocketPrint(td, client, "cache delete foo: %i\n", r);
42 |
43 | r = ps4KernelCacheDelete(c, "bar");
44 | r = ps4KernelSocketPrint(td, client, "cache delete bar: %i\n", r);
45 |
46 | m2 = NULL;
47 | r = ps4KernelCacheGet(c, "foo", &m2);
48 | r = ps4KernelSocketPrint(td, client, "cache get foo m2: %p %i\n", m2, r);
49 |
50 | r = ps4KernelCacheDestroy(c);
51 | r = ps4KernelSocketPrint(td, client, "cache destroy: %p %i\n", m2, r);
52 |
53 | // Global (rerun)
54 |
55 | m = NULL;
56 | r = ps4KernelCacheGlobalGet("ps4.test.foo", &m);
57 | r = ps4KernelSocketPrint(td, client, "m: %p %i\n", m, r);
58 |
59 | m = (void *)0x42;
60 | r = ps4KernelCacheGlobalSet("ps4.test.foo", m);
61 | r = ps4KernelSocketPrint(td, client, "m: %p %i\n", m, r);
62 |
63 | m = NULL;
64 | r = ps4KernelCacheGlobalGet("ps4.test.foo", &m);
65 | r = ps4KernelSocketPrint(td, client, "m: %p %i\n", m, r);
66 |
67 | //m = ps4KernelDlSym("sysctl_handle_64");
68 | //r = ps4KernelSocketPrint(td, client, "ps4KernelDlSym sysctl_handle_64: %p\n", m);
69 |
70 | // uses a sub-cache called ps4.kernel.symbol.lookup
71 | r = ps4KernelSymbolLookUp("sysctl_handle_64", &m);
72 | r = ps4KernelSocketPrint(td, client, "ps4KernelSymbolLookUp sysctl_handle_64: %p %i\n", m, r);
73 |
74 | m = NULL;
75 | r = ps4KernelCacheGlobalGet("ps4.kernel.symbol.lookup", &m);
76 | r = ps4KernelSocketPrint(td, client, "ps4.kernel.symbol.lookup: %p %i\n", m, r);
77 |
78 |
79 | r = ps4KernelSocketDestroy(client);
80 |
81 | return EXIT_SUCCESS;
82 | }
83 |
--------------------------------------------------------------------------------
/kernel/function_hook/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/kernel/function_hook/source/main.c:
--------------------------------------------------------------------------------
1 | #define _XOPEN_SOURCE 700
2 | #define __BSD_VISIBLE 1
3 | #define _KERNEL
4 | #define _STANDALONE
5 | #define _WANT_UCRED
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | //#include
12 | #include
13 |
14 | #include
15 | //#include
16 | #include
17 |
18 | #include
19 |
20 | #define SERVER_PORT 5088
21 |
22 | static Ps4KernelSocket *sock;
23 |
24 | int strnlenHook(const char *s, size_t n)
25 | {
26 | struct thread *td;
27 |
28 | ps4KernelThreadGetCurrent(&td);
29 | // !!! do not use format => strlen inf. loop => crash !!!
30 | ps4KernelSocketPrint(td, sock, s);
31 | ps4KernelSocketPrint(td, sock, "\n");
32 |
33 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
34 | }
35 |
36 | int snprintfHook(char *str, size_t size, const char *format, ...)
37 | {
38 | struct thread *td;
39 | va_list args;
40 |
41 | ps4KernelThreadGetCurrent(&td);
42 | //ps4KernelSocketPrint(td, sock, "%p %zu ", str, size);
43 | va_start(args, format);
44 | ps4KernelSocketPrintSizedWithArgumentList(td, sock, size, format, args);
45 | va_end(args);
46 | ps4KernelSocketPrint(td, sock, "\n");
47 |
48 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
49 | }
50 |
51 | int strncpyHook(char *dest, const char *src, size_t n)
52 | {
53 | struct thread *td;
54 |
55 | ps4KernelThreadGetCurrent(&td);
56 | ps4KernelSocketPrint(td, sock, "%s\n", src);
57 |
58 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
59 | }
60 |
61 | int printfHook(const char *format, ...)
62 | {
63 | struct thread *td;
64 | va_list args;
65 |
66 | ps4KernelThreadGetCurrent(&td);
67 | va_start(args, format);
68 | ps4KernelSocketPrintWithArgumentList(td, sock, format, args);
69 | va_end(args);
70 | ps4KernelSocketPrint(td, sock, "\n");
71 |
72 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
73 | }
74 |
75 | int kern_closeHook(struct thread *td, int fd)
76 | {
77 | Ps4KernelFunctionHookArgument *arg;
78 | // hidden-argument-jutsu - do this as the first call thou!
79 | // also allows you to interrupt via return and set a return via arg
80 | // maybe that should switch around ... ? -> issue
81 | ps4KernelThreadGetSecondaryReturn(td, (register_t *)&arg);
82 |
83 | ps4KernelSocketPrint(td, sock, "%p %p %i\n", td, arg->function, fd);
84 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
85 | }
86 |
87 | int indexHook(const char *s, int c)
88 | {
89 | struct thread *td;
90 |
91 | ps4KernelThreadGetCurrent(&td);
92 | ps4KernelSocketPrint(td, sock, "%s %i %c\n", s, c, c);
93 |
94 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
95 | }
96 |
97 | int genericHook(struct thread *td, Ps4KernelFunctionHookArgument *arg)
98 | {
99 | // The current type returns 0,1 for now.
100 | // This will be changed to the same control values observed in function hooks (need to do it in asm ...)
101 | ps4KernelSocketPrint(td, sock, "Type %p:\n", arg->hookTypeCurrent);
102 |
103 | ps4KernelSocketPrint(td, sock, "%p(%p, %p, %p, %p, %p, %p) %p\n\t => %p %p %p %p %p %p\n",
104 | arg->function,
105 | arg->arguments->rdi, arg->arguments->rsi, arg->arguments->rdx,
106 | arg->arguments->rcx, arg->arguments->r8, arg->arguments->r9,
107 | arg->arguments->rax,
108 | arg->returns->rax, arg->returns->rdx,
109 | arg->returns->xmm0.low, arg->returns->xmm0.high,
110 | arg->returns->xmm1.low, arg->returns->xmm1.high
111 | );
112 |
113 | return PS4_KERNEL_FUNCTION_HOOK_CONTROL_CONTINUE;
114 | }
115 |
116 | void socketPrintHook(struct thread *td, Ps4KernelSocket *s, Ps4KernelFunctionHook *h)
117 | {
118 | Ps4KernelFunctionHookArgument *arg = (Ps4KernelFunctionHookArgument *)h;
119 |
120 | ps4KernelSocketPrint(td, s,
121 | "hook[%p] =\n"
122 | "{\n"
123 | "\tfunction: %p,\n"
124 | "\thook: %p,\n"
125 | "\thookCurrent: (will be null *) %p,\n"
126 | "\thookCount: %p,\n"
127 | "\thookSize: %p,\n"
128 | "\tbridge: %p,\n"
129 | "\tbridgeCopiedSize: %p,\n"
130 | "\targuments[%p]: (will contain null *) \n"
131 | "\t{\n"
132 | "\t\trax: %p,\n"
133 | "\t\trdi: %p,\n"
134 | "\t\trsi: %p,\n"
135 | "\t\trdx: %p,\n"
136 | "\t\trcx: %p,\n"
137 | "\t\tr8: %p,\n"
138 | "\t\tr9: %p\n"
139 | "\t},\n"
140 | "\tlock: %p,\n"
141 | "\thookTypeCurrent: (will be null *) %p,\n"
142 | "\tentryCount: %p,\n"
143 | "\tcallCount: %p,\n"
144 | "\treturnTo: (will be null *) %p,\n"
145 | "\tr12: (will be null *) %p,\n"
146 | "\thandler: %p,\n"
147 | "\tprologue: %p,\n"
148 | "\thookType: %p,\n"
149 | "\treturns[%p]: (will contain null *) \n"
150 | "\t{\n"
151 | "\t\trax: %p,\n"
152 | "\t\trdx: %p,\n"
153 | "\t\txmm0: %p %p,\n"
154 | "\t\txmm1: %p %p\n"
155 | "\t}\n"
156 | "\tallocate: %p\n"
157 | "\tfree: %p\n"
158 | "\tmt: %p\n"
159 | "\tuserArgument: %p\n"
160 | "}\n"
161 | "* = This is will not show per-hook runtime values due to the lock-less design.\n",
162 | arg,
163 | arg->function,
164 | arg->hook,
165 | arg->hookCurrent,
166 | arg->hookCount,
167 | arg->hookSize,
168 | arg->bridge,
169 | arg->bridgeCopiedSize,
170 | arg->arguments,
171 | arg->arguments->rax,
172 | arg->arguments->rdi,
173 | arg->arguments->rsi,
174 | arg->arguments->rdx,
175 | arg->arguments->rcx,
176 | arg->arguments->r8,
177 | arg->arguments->r9,
178 | arg->lock,
179 | arg->hookTypeCurrent,
180 | arg->entryCount,
181 | arg->callCount,
182 | arg->returnTo,
183 | arg->r12,
184 | arg->handler,
185 | arg->prologue,
186 | arg->hookType,
187 | arg->returns,
188 | arg->returns->rax,
189 | arg->returns->rdx,
190 | arg->returns->xmm0.low, arg->returns->xmm0.high,
191 | arg->returns->xmm1.low, arg->returns->xmm1.high,
192 | arg->allocate,
193 | arg->free,
194 | arg->mt,
195 | arg->userArgument
196 | );
197 |
198 | for(int i = 0; i < arg->hookCount; ++i)
199 | ps4KernelSocketPrint(td, sock, "hook[%i]: %p %p\n", i, arg->hook[i], arg->hookType[i]);
200 | }
201 |
202 | #include
203 | #include
204 | #include
205 |
206 | int main(int argc, char **argv)
207 | {
208 | struct thread *td;
209 | struct socket *client;
210 | void *fn;
211 | Ps4KernelFunctionHook *h;
212 | int r;
213 |
214 | if(ps4KernelIsInKernel() != PS4_OK)
215 | {
216 | printf("This is not a user space application.\n");
217 | return PS4_ERROR_IS_KERNEL_ELF;
218 | }
219 |
220 | ps4KernelThreadGetCurrent(&td);
221 |
222 | r = ps4KernelSocketTCPServerCreateAcceptThenDestroy(td, &client, SERVER_PORT);
223 |
224 | sock = client;
225 |
226 | fn = ps4KernelDlSym("kern_close");
227 | r = ps4KernelSocketPrintHexDump(td, client, fn, 64);
228 | ps4KernelFunctionHook(fn, (void *)genericHook, PS4_KERNEL_FUNCTION_HOOK_TYPE_GENERIC_BOTH);
229 | ps4KernelFunctionPrehook(fn, (void *)kern_closeHook);
230 | r = ps4KernelSocketPrintHexDump(td, client, fn, 64);
231 | pause("hooked", 10000);
232 | ps4KernelFunctionGetHook(fn, &h);
233 | socketPrintHook(td, client, h);
234 | ps4KernelFunctionUnhook(fn);
235 | r = ps4KernelSocketPrintHexDump(td, client, fn, 64);
236 |
237 | r = ps4KernelSocketDestroy(client);
238 |
239 | return PS4_OK;
240 | }
241 |
--------------------------------------------------------------------------------
/kernel/resolve/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/kernel/resolve/source/main.c:
--------------------------------------------------------------------------------
1 | #define __BSD_VISIBLE 1
2 | #define _KERNEL
3 |
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include
11 |
12 | #define SERVER_PORT 5088
13 | #define NAME_SIZE 128
14 |
15 | int main(int argc, char **argv)
16 | {
17 | Ps4KernelThread *td;
18 | Ps4KernelSocket *client;
19 |
20 | char symbolName[NAME_SIZE];
21 | void *symbol;
22 | int match;
23 |
24 | ps4KernelThreadGetCurrent(&td);
25 |
26 | ps4KernelSocketTCPServerCreateAcceptThenDestroy(td, &client, SERVER_PORT);
27 |
28 | ps4KernelSocketPrint(td, client, "Input: \n");
29 | ps4KernelSocketPrint(td, client, "Output: \n");
30 | ps4KernelSocketPrint(td, client, "To exit input: \"exit!\"\n");
31 |
32 | while(1)
33 | {
34 | symbolName[0] = '\0';
35 | symbol = NULL;
36 |
37 | ps4KernelSocketScan(td, client, &match, "%s", symbolName);
38 | if(match < 1)
39 | break;
40 |
41 | if(strncmp(symbolName, "exit!", 4) == 0)
42 | break;
43 |
44 | symbol = ps4KernelDlSym(symbolName);
45 |
46 | if(ps4KernelSocketPrint(td, client, "%s %"PRIxPTR"\n", symbolName, (uintptr_t)symbol) != PS4_OK)
47 | break;
48 | }
49 |
50 | ps4KernelSocketPrint(td, client, "Done\n");
51 |
52 | ps4KernelSocketDestroy(client);
53 |
54 | return PS4_OK;
55 | }
56 |
--------------------------------------------------------------------------------
/kernel/server_hello_world/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/kernel/server_hello_world/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | #define SERVER_PORT 5088
11 |
12 | int kernel_main(int argc, char **argv);
13 | int user_main(int argc, char **argv);
14 |
15 | int main(int argc, char **argv) // adaptive main
16 | {
17 | if(ps4KernelIsInKernel() == PS4_OK)
18 | // send this elf to 5054, connect, see connection get closed
19 | // send this elf to 5055, close browser, connect, see connection get closed ^^
20 | return kernel_main(argc, argv);
21 | // send this elf to 5053, connect, see connection get closed
22 | return user_main(argc, argv);
23 | }
24 |
25 | int kernel_main(int argc, char **argv)
26 | {
27 | Ps4KernelThread *td;
28 | Ps4KernelSocket *client;
29 | int r;
30 |
31 | /*
32 | struct socket *server;
33 | struct sockaddr_in address;
34 |
35 | memset(&address, 0, sizeof(address));
36 | address.sin_len = sizeof(address);
37 | address.sin_family = AF_INET;
38 | address.sin_addr.s_addr = htonl(INADDR_ANY);
39 | address.sin_port = htons(SERVER_PORT);
40 | */
41 |
42 | ps4KernelThreadGetCurrent(&td);
43 |
44 | /*
45 | server = client = NULL;
46 | r = ps4KernelSocketTCPServerCreate(td, &server, SERVER_PORT, 10);
47 | r = ps4KernelSocketAccept(td, server, &client);
48 |
49 | r = ps4KernelSocketPrint(td, client, "foo\n");
50 |
51 | r = ps4KernelSocketDestroy(td, client);
52 | r = ps4KernelSocketDestroy(td, server);
53 | */
54 |
55 | r = ps4KernelSocketTCPServerCreateAcceptThenDestroy(td, &client, SERVER_PORT);
56 |
57 | r = ps4KernelSocketPrint(td, client, "Hello world from your ps4 kernel via ps4sdk. Kind regards and greetings to all who read this, hito <3\n{main:%p, argc:%i, argv[0]:%s}\n\n", main, argc, argv[0]);
58 |
59 | r = ps4KernelSocketDestroy(client);
60 |
61 | return PS4_OK;
62 | }
63 |
64 | int user_main(int argc, char **argv)
65 | {
66 | int client;
67 | FILE *cout;
68 | //FILE *cin;
69 | int r;
70 |
71 | r = ps4SocketTCPServerCreateAcceptThenDestroy(&client, SERVER_PORT);
72 | //ps4StreamOpenFileDuplicate(&cin, client, "rb");
73 | ps4StreamOpenFileDuplicate(&cout, client, "wb");
74 | close(client);
75 |
76 | // Change standard io buffering
77 | //setvbuf(cin, NULL, _IOLBF, 0);
78 | setvbuf(cout, NULL, _IONBF, 0);
79 | //setvbuf(cerr, NULL, _IONBF, 0);
80 |
81 | fprintf(cout, "Hello world from your ps4 user space via ps4sdk. Kind regards and greetings to all who read this, hito <3\n{main:%p, argc:%i, argv[0]:%s}\n\n", main, argc, argv[0]);
82 |
83 | fclose(cout);
84 | //fclose(cin);
85 |
86 | return PS4_OK;
87 | }
88 |
--------------------------------------------------------------------------------
/kernel/system_call_hook/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/kernel/system_call_hook/source/main.c:
--------------------------------------------------------------------------------
1 | #define _XOPEN_SOURCE 700
2 | #define __BSD_VISIBLE 1
3 | #define _KERNEL
4 | #define _STANDALONE
5 | #define _WANT_UCRED
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | //#include
12 | #include
13 |
14 | #include
15 | //#include
16 | #include
17 | #include
18 |
19 | #include
20 | #include
21 |
22 | #include
23 |
24 | #define SERVER_PORT 5088
25 |
26 | static Ps4KernelSocket *sock;
27 |
28 |
29 | int sysCloseHook(struct thread *td, struct close_args *uap)
30 | {
31 | Ps4KernelSystemCallHookArgument *arg;
32 | // magic - do this in the first line thou!
33 | // also allows you to interrupt via return and set a return via arg
34 | // maybe that should be switch around ... ? -> issue
35 | ps4KernelThreadGetSecondaryReturn(td, (register_t *)&arg);
36 |
37 | ps4KernelSocketPrint(td, sock, "pre: %p %p %i\n", arg->hookTypeCurrent, arg->number, uap->fd);
38 | return PS4_KERNEL_SYSTEM_CALL_HOOK_CONTROL_CONTINUE;
39 | }
40 |
41 | int sysCloseHookGeneric(struct thread *td, Ps4KernelSystemCallHookArgument *arg)
42 | {
43 | struct close_args *uap;
44 | uap = (struct close_args *)arg->uap;
45 |
46 | ps4KernelSocketPrint(td, sock, "generic: %p %p %i\n", arg->hookTypeCurrent, arg->number, uap->fd);
47 | return PS4_KERNEL_SYSTEM_CALL_HOOK_CONTROL_CONTINUE;
48 | }
49 |
50 | void socketPrintHook(Ps4KernelThread *td, Ps4KernelSocket *s, Ps4KernelSystemCallHook *h)
51 | {
52 | Ps4KernelSystemCallHookArgument *arg = (Ps4KernelSystemCallHookArgument *)h;
53 |
54 | ps4KernelSocketPrint(td, s,
55 | "hook[%p] =\n"
56 | "{\n"
57 | "\tclone: %p,\n"
58 | "\thandler: %p,\n"
59 | "\tprologue: %p,\n"
60 | "\thook: %p,\n"
61 | "\thookType: %p,\n"
62 | "\thookCount: %p,\n"
63 | "\thookSize: %p,\n"
64 | "\thookTypeCurrent: (will be null *) %p,\n"
65 | "\tlock: %p,\n"
66 | "\tentryCount: %p,\n"
67 | "\tcallCount: %p,\n"
68 | "\tsystemCalls: %p,\n"
69 | "\tnumber: %p,\n"
70 | "\toriginalCall: %p,\n"
71 | "\tthread: (will be null *) %p,\n"
72 | "\tuap: (will be null *) %p,\n"
73 | "\tsysret: (will be (32bit) null *) %p,\n"
74 | "\treturns[%p]:\n"
75 | "\t{\n"
76 | "\t\t0: (will be null *) %p,\n"
77 | "\t\t1: (will be null *) %p,\n"
78 | "\t}\n"
79 | "\tuserArgument: %p,\n"
80 | "\tallocate: %p,\n"
81 | "\tfree: %p,\n"
82 | "\tmt: %p\n"
83 | "}\n"
84 | "* = This is will not show per-hook runtime values due to the lock-less design.\n",
85 | arg,
86 | arg->clone,
87 | arg->handler,
88 | arg->prologue,
89 | arg->hook,
90 | arg->hookType,
91 | arg->hookCount,
92 | arg->hookSize,
93 | arg->hookTypeCurrent,
94 | arg->lock,
95 | arg->entryCount,
96 | arg->callCount,
97 | arg->systemCalls,
98 | arg->number,
99 | arg->originalCall,
100 | arg->thread,
101 | arg->uap,
102 | arg->sysret,
103 | arg->returns,
104 | arg->returns[0],
105 | arg->returns[1],
106 | arg->userArgument,
107 | arg->allocate,
108 | arg->free,
109 | arg->mt
110 | );
111 |
112 | for(int i = 0; i < arg->hookCount; ++i)
113 | ps4KernelSocketPrint(td, s, "hook[%i]: %p %p\n", i, arg->hook[i], arg->hookType[i]);
114 | }
115 |
116 | int main(int argc, char **argv)
117 | {
118 | struct thread *td;
119 | struct socket *client;
120 | int number;
121 | Ps4KernelSystemCallHook *h;
122 | struct sysent *sy;
123 | int r;
124 |
125 | ps4ExpressionReturnOnError(ps4KernelSymbolLookUp("sysent", (void **)&sy));
126 |
127 | if(ps4KernelIsInKernel() != PS4_OK)
128 | {
129 | printf("This is not a user space application.\n");
130 | return PS4_ERROR_IS_KERNEL_ELF;
131 | }
132 |
133 | ps4KernelThreadGetCurrent(&td);
134 |
135 | r = ps4KernelSocketTCPServerCreateAcceptThenDestroy(td, &client, SERVER_PORT);
136 |
137 | sock = client;
138 |
139 | // press "options" to see menue handles getting closed
140 | number = SYS_close;
141 | r = ps4KernelSocketPrintHexDump(td, client, &sy[number], sizeof(struct sysent));
142 |
143 | ps4KernelSystemCallHookCreate(&h, number);
144 | r = ps4KernelSocketPrintHexDump(td, client, &sy[number], sizeof(struct sysent));
145 | ps4KernelSystemCallHookAdd(h, (void *)sysCloseHookGeneric, PS4_KERNEL_SYSTEM_CALL_HOOK_TYPE_GENERIC_BOTH);
146 | ps4KernelSystemCallHookAdd(h, (void *)sysCloseHook, PS4_KERNEL_SYSTEM_CALL_HOOK_TYPE_PRE);
147 | pause("hooked", 10000);
148 | socketPrintHook(td, client, h);
149 | ps4KernelSystemCallHookDestroy(h);
150 | r = ps4KernelSocketPrintHexDump(td, client, &sy[number], sizeof(struct sysent));
151 |
152 | r = ps4KernelSocketDestroy(client);
153 |
154 | return PS4_OK;
155 | }
156 |
--------------------------------------------------------------------------------
/libless/for_a_while/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_untargeted
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/libless/for_a_while/source/main.c:
--------------------------------------------------------------------------------
1 | int main(void)
2 | {
3 | while(1);
4 | return 0xDEADBEEF;
5 | }
6 |
7 | //gcc ../example/forawhile.c -o e -I include/ -pie -O3 -Wall -pedantic -std=c11 -Wl,--build-id=none -m64 -mcmodel=large -ffreestanding -nostdlib -nostdinc -fno-builtin
8 |
--------------------------------------------------------------------------------
/libless/return/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_untargeted
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/libless/return/source/main.c:
--------------------------------------------------------------------------------
1 | int main(void)
2 | {
3 | //return EXIT_SUCCESS;
4 | return 0x42;
5 | }
6 |
7 | //gcc ../example/null.c -o e -I include/ -pie -O3 -Wall -pedantic -std=c11 -Wl,--build-id=none -m64 -mcmodel=large -ffreestanding -nostdlib -nostdinc -fno-builtin
8 |
--------------------------------------------------------------------------------
/libless/stress/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_untargeted
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/libless/stress/source/main.c:
--------------------------------------------------------------------------------
1 | int baz = 42;
2 | static int beng = 128;
3 |
4 | typedef int (*pfffft)(double n);
5 |
6 | int bar(double n)
7 | {
8 | static double moo;
9 | moo = baz;
10 | moo += n + 3.14159;
11 | return (int)moo;
12 | }
13 |
14 | char foo(pfffft bar)
15 | {
16 | static int goo = 55;
17 | baz /= 2;
18 | goo += 1;
19 | if(goo % 2)
20 | beng = baz;
21 | return (char)bar((float)(goo == baz) + (double)baz);
22 | }
23 |
24 | int main(void)
25 | {
26 | static char goo;
27 | int i = foo(bar);
28 | while(i > 0)
29 | {
30 | baz++;
31 | --i;
32 | goo = baz + i;
33 | }
34 | return goo;
35 | }
36 |
37 | //gcc ../example/stress.c -o e -I include/ -pie -O3 -Wall -pedantic -std=c11 -Wl,--build-id=none -m64 -mcmodel=large -ffreestanding -nostdlib -nostdinc -fno-builtin
38 |
--------------------------------------------------------------------------------
/posix/pthread/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/posix/pthread/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | void *start_routine(void *arg)
9 | {
10 | while(*(int *)arg == 1)
11 | {
12 | printf(".");
13 | sleep(1);
14 | }
15 |
16 | return NULL;
17 | }
18 |
19 | int main(int argc, char **argv)
20 | {
21 | char message[256];
22 | pthread_t thread;
23 | volatile int run = 1;
24 |
25 | pthread_create(&thread, NULL, start_routine, (void *)&run);
26 | scanf("%s", message); // block until input
27 | run = 0;
28 | pthread_join(thread, NULL);
29 |
30 | return EXIT_SUCCESS;
31 | }
32 |
--------------------------------------------------------------------------------
/posix/pthread_errno/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/posix/pthread_errno/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | void *start_routine(void *arg)
12 | {
13 | while(*(int *)arg == 1)
14 | {
15 | printf("thread> %"PRIxPTR"\n", &errno);
16 | sleep(1);
17 | }
18 |
19 | return NULL;
20 | }
21 |
22 | int main(int argc, char **argv)
23 | {
24 | char message[256];
25 | pthread_t thread;
26 | volatile int run = 1;
27 |
28 | pthread_create(&thread, NULL, start_routine, (void *)&run);
29 | scanf("%s", message); // block until input
30 | printf("main> %"PRIxPTR"\n", &errno);
31 | run = 0;
32 | pthread_join(thread, NULL);
33 |
34 | return EXIT_SUCCESS;
35 | }
36 |
--------------------------------------------------------------------------------
/posix/sigsegv_handling/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/posix/sigsegv_handling/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | static sigjmp_buf jmpbuf;
12 |
13 | void handler(int sig)
14 | {
15 | write(1, "SIGSEGV\n", 8);
16 | siglongjmp(jmpbuf, 1);
17 | }
18 |
19 | int main(int argc, char **argv)
20 | {
21 | char message[256];
22 |
23 | struct sigaction action;
24 |
25 | action.sa_handler = handler;
26 | action.sa_flags = 0; // SA_NODEFER; /* repeated throws are caught */
27 | sigemptyset(&action.sa_mask);
28 | sigaction(SIGSEGV, &action, NULL); // setting a handler may do harm to other threads
29 |
30 | printf("loop\n");
31 | sigsetjmp(jmpbuf, 1);
32 | printf("oops\n");
33 | scanf("%s", message); // wait for input
34 | if(memcmp(message, "exit", 4))
35 | return EXIT_FAILURE;
36 | *((char *)0x42) = 42; /* provoke SIGSEGV */
37 |
38 | //signal(SIGSEGV, SIG_DFL); // reset may harm other "elfs" in multi-thread mode
39 |
40 | return EXIT_SUCCESS;
41 | }
42 |
--------------------------------------------------------------------------------
/posix/sigsegv_pthread_handling/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/posix/sigsegv_pthread_handling/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | /*
13 | __PS4__ is defined in the Makefile
14 | We can compile and run this poc under Linux, FreeBSD and the PS4
15 | Linux is not explicitly checked (used as default)
16 | */
17 | #ifdef __PS4__
18 | #include
19 |
20 | FILE *__stdinp;
21 | FILE **__stdinp_addr;
22 | FILE *__stdoutp;
23 | FILE **__stdoutp_addr;
24 | FILE *__stderrp;
25 | FILE **__stderrp_addr;
26 | int __isthreaded;
27 | int *__isthreaded_addr;
28 | #endif
29 |
30 | /* Constants */
31 | enum{ ThreadCount = 32 };
32 |
33 | /* Types */
34 | typedef struct
35 | {
36 | unsigned int id;
37 | int *errnoAddress;
38 | sigjmp_buf threadJump;
39 | pthread_t thread;
40 | }
41 | ThreadData;
42 |
43 | static ThreadData threadData[ThreadCount];
44 |
45 | int ThreadCreate(unsigned int id, void *(*f)(void *))
46 | {
47 | if(id >= ThreadCount)// || threadData[id].id != 0)
48 | return 0;
49 | printf("ThreadCreate %i %p\n", id, f);
50 | fflush(stdout);
51 |
52 | threadData[id].id = id;
53 | pthread_create(&threadData[id].thread, NULL, f, &threadData[id]);
54 |
55 | return 1;
56 | }
57 |
58 | void sigsegvHandler(int sig)
59 | {
60 | volatile int i;
61 |
62 | if(sig != SIGSEGV)
63 | return;
64 |
65 | //write(1, "SIGSEGV\n", 8);
66 | for(i = 0; i < ThreadCount; ++i)
67 | if(threadData[i].errnoAddress == &errno)
68 | siglongjmp(threadData[i].threadJump, 1);
69 | }
70 |
71 | void *t1(void *data)
72 | {
73 | ThreadData *td = (ThreadData *)data;
74 | td->errnoAddress = &errno;
75 |
76 | printf("t1 %p %p\n", td, &errno);
77 | fflush(stdout);
78 |
79 | if(sigsetjmp(td->threadJump, 1) == 0)
80 | {
81 | // do
82 | *(char *)0x42 = 42;
83 | }
84 | //while (1);
85 |
86 | return NULL;
87 | }
88 |
89 | void *t2(void *data)
90 | {
91 | ThreadData *td = (ThreadData *)data;
92 | td->errnoAddress = &errno;
93 |
94 | printf("t2 %p %p\n", td, &errno);
95 | fflush(stdout);
96 |
97 | if(sigsetjmp(td->threadJump, 1) == 0)
98 | {
99 | // do
100 | uint32_t i;
101 | for(i = 0; i < (uint32_t) - 1 / 4; ++i)
102 | ;
103 | *(char *)0x42 = 42;
104 | }
105 |
106 | return NULL;
107 | }
108 |
109 | int main(int argc, char **argv)
110 | {
111 | struct sigaction action;
112 |
113 | #ifdef __PS4__
114 | int libc = sceKernelLoadStartModule("libSceLibcInternal.sprx", 0, NULL, 0, 0, 0);
115 | sceKernelDlsym(libc, "__stdinp", (void **)&__stdinp_addr);
116 | sceKernelDlsym(libc, "__stdoutp", (void **)&__stdoutp_addr);
117 | sceKernelDlsym(libc, "__stderrp", (void **)&__stderrp_addr);
118 | sceKernelDlsym(libc, "__isthreaded", (void **)&__isthreaded_addr);
119 | __stdinp = *__stdinp_addr;
120 | __stdoutp = *__stdoutp_addr;
121 | __stderrp = *__stderrp_addr;
122 | __isthreaded = *__isthreaded_addr;
123 | #endif
124 |
125 | action.sa_handler = sigsegvHandler;
126 | action.sa_flags = 0; // SA_NODEFER; /* repeated throws are caught */
127 | sigemptyset(&action.sa_mask);
128 | sigaction(SIGSEGV, &action, NULL);
129 |
130 | ThreadCreate(0, t1);
131 | ThreadCreate(1, t2);
132 |
133 | pthread_join(threadData[0].thread, NULL);
134 | pthread_join(threadData[1].thread, NULL);
135 |
136 | return EXIT_SUCCESS;
137 | }
138 |
--------------------------------------------------------------------------------
/posix/stdio_redirect/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/posix/stdio_redirect/source/main.c:
--------------------------------------------------------------------------------
1 | #define _XOPEN_SOURCE 700
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | #include
14 |
15 | #include
16 |
17 | /*
18 | __PS4__ is defined in the Makefile
19 | We can compile and run this poc under Linux, FreeBSD and the PS4
20 | Linux is not explicitly checked (used as default)
21 | */
22 | #ifdef __PS4__
23 | #include
24 |
25 | FILE *__stdinp;
26 | FILE **__stdinp_addr;
27 | FILE *__stdoutp;
28 | FILE **__stdoutp_addr;
29 | FILE *__stderrp;
30 | FILE **__stderrp_addr;
31 | int __isthreaded;
32 | int *__isthreaded_addr;
33 | #endif
34 |
35 | void stdIORedirect(int to, int stdfd[3], fpos_t stdpos[3])
36 | {
37 | int stdid[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
38 | FILE *stdf[3] = {stdin, stdout, stderr};
39 | int i;
40 |
41 | for(i = 0; i < 3; ++i)
42 | {
43 | fflush(stdf[i]);
44 | fgetpos(stdf[i], &stdpos[i]);
45 |
46 | stdfd[i] = dup(stdid[i]);
47 | close(stdid[i]);
48 | dup(to);
49 |
50 | clearerr(stdf[i]);
51 | setbuf(stdf[i], NULL);
52 | }
53 | }
54 |
55 | void stdIOReset(int stdfd[3], fpos_t stdpos[3])
56 | {
57 | int stdid[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
58 | FILE *stdf[3] = {stdin, stdout, stderr};
59 | int i;
60 |
61 | for(i = 0; i < 3; ++i)
62 | {
63 | fflush(stdf[i]);
64 |
65 | close(stdid[i]);
66 | dup(stdfd[i]);
67 | close(stdfd[i]);
68 |
69 | fsetpos(stdf[i], &stdpos[i]);
70 | clearerr(stdf[i]);
71 | }
72 | }
73 |
74 | int main(int argc, char **argv)
75 | {
76 | int server, client;
77 | struct sockaddr_in serverAddress, clientAddress;
78 | char message[256];
79 | int stdfd[3];
80 | fpos_t stdpos[3];
81 |
82 | #ifdef __PS4__
83 | int libc = sceKernelLoadStartModule("libSceLibcInternal.sprx", 0, NULL, 0, 0, 0);
84 | sceKernelDlsym(libc, "__stdinp", (void **)&__stdinp_addr);
85 | sceKernelDlsym(libc, "__stdoutp", (void **)&__stdoutp_addr);
86 | sceKernelDlsym(libc, "__stderrp", (void **)&__stderrp_addr);
87 | sceKernelDlsym(libc, "__isthreaded", (void **)&__isthreaded_addr);
88 | __stdinp = *__stdinp_addr;
89 | __stdoutp = *__stdoutp_addr;
90 | __stderrp = *__stderrp_addr;
91 | __isthreaded = *__isthreaded_addr;
92 | #endif
93 |
94 | memset(&serverAddress, 0, sizeof(serverAddress));
95 | #ifdef __FreeBSD__ //parent of our __PS4__
96 | serverAddress.sin_len = sizeof(serverAddress);
97 | #endif
98 | serverAddress.sin_family = AF_INET;
99 | serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
100 | serverAddress.sin_port = htons(9025);
101 |
102 | memset(&clientAddress, 0, sizeof(clientAddress));
103 |
104 | server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
105 | if(server < 0)
106 | return EXIT_FAILURE;
107 |
108 | if(bind(server, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0)
109 | {
110 | close(server);
111 | return EXIT_FAILURE;
112 | }
113 |
114 | if(listen(server, 10) < 0)
115 | {
116 | close(server);
117 | return EXIT_FAILURE;
118 | }
119 |
120 | //signal(SIGPIPE, SIG_IGN); // Warning - please google
121 |
122 | while(1)
123 | {
124 | client = accept(server, NULL, NULL);
125 |
126 | if(client < 0)
127 | continue;
128 |
129 | //printf("Foo\n");
130 |
131 | stdIORedirect(client, stdfd, stdpos);
132 |
133 | //printf("Bar\n");
134 |
135 | do
136 | {
137 | int r = scanf("%s", message);
138 | if(r == EOF)
139 | break;
140 |
141 | if(r == 1)
142 | {
143 | printf("%s\n", message);
144 | fflush(stdout);
145 | }
146 | }
147 | while(memcmp(message, "exit", 4));
148 |
149 | stdIOReset(stdfd, stdpos);
150 |
151 | //printf("Baz\n");
152 |
153 | close(client);
154 | }
155 |
156 | close(server);
157 | }
158 |
--------------------------------------------------------------------------------
/ps4sdk/kernel_execute/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/ps4sdk/kernel_execute/include/kmain.h:
--------------------------------------------------------------------------------
1 | #ifndef KMainH
2 | #define KMainH
3 |
4 | #include
5 |
6 | typedef int (*RunnableInt)();
7 |
8 | int kmain1(struct thread *td, void *uap);
9 | int kmain2(struct thread *td, void *uap);
10 | int kmain3(struct thread *td, void *uap);
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/ps4sdk/kernel_execute/source/kmain.c:
--------------------------------------------------------------------------------
1 | #undef _SYS_CDEFS_H_
2 | #undef _SYS_TYPES_H_
3 | #undef _SYS_PARAM_H_
4 | #undef _SYS_MALLOC_H_
5 |
6 | #define _XOPEN_SOURCE 700
7 | #define __BSD_VISIBLE 1
8 | #define _KERNEL
9 | #define _WANT_UCRED
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #undef offsetof
18 | #include
19 | #include
20 |
21 | #include "kmain.h"
22 |
23 | // kernel functions called, in user-land function ... yay for evil voodoo Oo?!
24 | int kmain1(struct thread *td, void *uap)
25 | {
26 | char *mem = (char *)uap;
27 |
28 | struct malloc_type *mt = ps4KernelDlSym("M_TEMP");
29 |
30 | void *kmem = malloc(32, mt, M_ZERO | M_WAITOK);
31 |
32 | copyin(mem, kmem, 32);
33 | strcpy(kmem, "Goodbye, cruel world.");
34 | copyout(kmem, mem, 32);
35 |
36 | free(kmem, mt);
37 |
38 | RunnableInt sceSblACMgrIsVideoplayerProcess = (RunnableInt)ps4KernelDlSym("sceSblACMgrIsVideoplayerProcess");
39 | ps4KernelThreadSetReturn(td, sceSblACMgrIsVideoplayerProcess(td)); //see kmain2's content & return
40 |
41 | return EINVAL;
42 | }
43 |
44 | int kmain2(struct thread *td, void *uap)
45 | {
46 | RunnableInt sceSblACMgrIsVideoplayerProcess = (RunnableInt)ps4KernelDlSym("sceSblACMgrIsVideoplayerProcess");
47 | ps4KernelFunctionPatchToReturn((void *)sceSblACMgrIsVideoplayerProcess, 0);
48 |
49 | ps4KernelThreadSetReturn(td, sceSblACMgrIsVideoplayerProcess(td)); // important notice from kernel!
50 | return 0;
51 | }
52 |
53 | int kmain3(struct thread *td, void *uap)
54 | {
55 | RunnableInt sceSblACMgrIsVideoplayerProcess = (RunnableInt)ps4KernelDlSym("sceSblACMgrIsVideoplayerProcess");
56 | void *sceSblACMgrIsShellcoreProcess = ps4KernelDlSym("sceSblACMgrIsShellcoreProcess");
57 | ps4KernelFunctionPatchToJump((void *)sceSblACMgrIsVideoplayerProcess, sceSblACMgrIsShellcoreProcess);
58 |
59 | ps4KernelThreadSetReturn(td, sceSblACMgrIsVideoplayerProcess(td));
60 | return 0;
61 | }
62 |
--------------------------------------------------------------------------------
/ps4sdk/kernel_execute/source/main.c:
--------------------------------------------------------------------------------
1 | #define _WANT_UCRED
2 | #define _XOPEN_SOURCE 700
3 | #define __BSD_VISIBLE 1
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | #include "kmain.h"
19 |
20 | int main(int argc, char **argv)
21 | {
22 | void *sceSblACMgrIsVideoplayerProcess;
23 | char *mem;
24 | int64_t ret;
25 | int r;
26 |
27 | printf("uid: %zu\n", getuid());
28 | ps4KernelCall(ps4KernelPrivilegeEscalate);
29 | printf("uid: %zu\n", getuid());
30 |
31 | sceSblACMgrIsVideoplayerProcess = (void *)ps4KernelCall(ps4KernelDlSym, "sceSblACMgrIsVideoplayerProcess");
32 |
33 | mem = malloc(64);
34 | memset(mem, 0x90, 64);
35 | strcpy(mem, "Hello World!");
36 |
37 | printf("mem: %p: %s\n", mem, mem);
38 | ps4StandardIoPrintHexDump(mem, 48);
39 | r = ps4KernelExecute((void *)kmain1, mem, &ret, NULL);
40 | printf("mem: %p: %s\n", mem, mem);
41 | ps4StandardIoPrintHexDump(mem, 48);
42 | printf("[K1] r: %i, ret: %"PRIxPTR"\n", r, ret);
43 |
44 | ps4KernelCall(ps4KernelMemoryCopy, sceSblACMgrIsVideoplayerProcess, mem, 32);
45 | ps4StandardIoPrintHexDump(mem, 48);
46 |
47 | r = ps4KernelExecute((void *)kmain2, mem, &ret, NULL);
48 | printf("[K2] r: %i, ret: %"PRIxPTR"\n", r, ret);
49 |
50 | ps4KernelCall(ps4KernelMemoryCopy, sceSblACMgrIsVideoplayerProcess, mem, 32);
51 | ps4StandardIoPrintHexDump(mem, 48);
52 |
53 | r = ps4KernelExecute((void *)kmain3, mem, &ret, NULL);
54 | printf("[K3] r: %i, ret: %"PRIxPTR"\n", r, ret);
55 |
56 | ps4KernelCall(ps4KernelMemoryCopy, sceSblACMgrIsVideoplayerProcess, mem, 32);
57 | ps4StandardIoPrintHexDump(mem, 48);
58 |
59 | free(mem);
60 |
61 | return EXIT_SUCCESS;
62 | }
63 |
--------------------------------------------------------------------------------
/ps4sdk/protected_memory/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/ps4sdk/protected_memory/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | // see posix/shm_open example
6 | int main(int argc, char **argv)
7 | {
8 | Ps4MemoryProtected *pm;
9 | unsigned char *w;
10 | unsigned char *e;
11 | int i;
12 |
13 | ps4MemoryProtectedCreate(&pm, 1234);
14 | ps4MemoryProtectedGetWritableAddress(pm, (void **)&w);
15 | ps4MemoryProtectedGetExecutableAddress(pm, (void **)&e);
16 |
17 | for(i = 0; i < 1234; i += 2)
18 | {
19 | w[i] = 0xeb; // jump
20 | w[i + 1] = 0xfe; // to self (loop infinitely)
21 | }
22 |
23 | // jump somewhere "even" => infinite jump loop
24 | void (*run)(void) = (void (*)(void))(e + 8);
25 | run();
26 |
27 | // Never
28 | ps4MemoryProtectedDestroy(pm);
29 |
30 | return EXIT_SUCCESS;
31 | }
32 |
--------------------------------------------------------------------------------
/ps4sdk/shared_memory/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/ps4sdk/shared_memory/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 |
7 | int main(int argc, char **argv)
8 | {
9 | //shm interface to keep stable memory between reloads, if needed
10 | Ps4MemoryShared *foo, *bar, *baz;
11 | void *foom;
12 | void *barm;
13 | void *bazm;
14 | size_t s;
15 |
16 |
17 | ps4MemorySharedOpen(&foo, 0x6000 * 3, "/foo");
18 | ps4MemorySharedOpen(&bar, 0x5000 * 2, "/bar");
19 | ps4MemorySharedOpen(&baz, 0, "/foo"); // reopen
20 |
21 | printf("Ps4MemoryShared *foo %p\n", foo);
22 | printf("Ps4MemoryShared *bar %p\n", bar);
23 | printf("Ps4MemoryShared *baz %p\n", baz);
24 |
25 | ps4MemorySharedGetSize(foo, &s);
26 | printf("ps4MemorySharedSize *foo %p\n", s);
27 | ps4MemorySharedGetSize(bar, &s);
28 | printf("ps4MemorySharedSize *bar %p\n", s);
29 | ps4MemorySharedGetSize(baz, &s);
30 | printf("ps4MemorySharedSize *baz %p\n", s);
31 |
32 | ps4MemorySharedGetAddress(foo, &foom);
33 | ps4MemorySharedGetAddress(bar, &barm);
34 | ps4MemorySharedGetAddress(baz, &bazm);
35 |
36 | printf("%s\n", foom);
37 | printf("%s\n", barm);
38 | printf("%s\n", bazm);
39 |
40 | printf("void *foom %p\n", foom);
41 | printf("void *barm %p\n", barm);
42 | printf("void *bazm %p\n", bazm);
43 |
44 | strcpy(foom, "I am foo");
45 | strcpy(barm, "I am bar");
46 | strcpy(bazm, "I am baz");
47 |
48 | printf("%s\n", foom);
49 | printf("%s\n", barm);
50 | printf("%s\n", bazm);
51 |
52 | ps4MemorySharedClose(bar); // leave /bar data
53 | ps4MemorySharedOpen(&bar, 0x4000 * 6, "/bar");
54 | printf("Ps4MemoryShared *bar %p\n", bar);
55 | ps4MemorySharedGetSize(bar, &s);
56 | printf("ps4MemorySharedSize *bar %p\n", s);
57 | ps4MemorySharedGetAddress(bar, &barm);
58 | printf("void *barm %p\n", barm);
59 | printf("%s\n", barm); // /bar data still there
60 | strcpy(barm, "I am yyy");
61 | printf("%s\n", barm);
62 | ps4MemorySharedUnlink(bar); // remove /bar data
63 |
64 | ps4MemorySharedClose(foo); // leave data
65 | ps4MemorySharedOpen(&bar, 0, "/foo"); // open new alias
66 | printf("Ps4MemoryShared *bar %p\n", bar);
67 | ps4MemorySharedGetSize(bar, &s);
68 | printf("ps4MemorySharedSize *bar %p\n", s);
69 | ps4MemorySharedGetAddress(bar, barm);
70 | printf("void *barm %p\n", barm);
71 | printf("%s\n", barm); // /foo data still there in "bar" struct
72 | strcpy(barm, "I am xxx");
73 | printf("%s\n", barm);
74 | ps4MemorySharedUnlink(bar); // remove /foo data
75 |
76 | printf("void *bazm %p\n", bazm);
77 | printf("%s\n", bazm);
78 | ps4MemorySharedUnlink(baz); // remove /baz data
79 |
80 | return EXIT_SUCCESS;
81 | }
82 |
--------------------------------------------------------------------------------
/ps4sdk/system_call_hook/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/ps4sdk/system_call_hook/include/kmain.h:
--------------------------------------------------------------------------------
1 | #ifndef KMainH
2 | #define KMainH
3 |
4 | #include
5 |
6 | int kmain(struct thread *td, void *uap);
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/ps4sdk/system_call_hook/source/kmain.c:
--------------------------------------------------------------------------------
1 | #define _KERNEL
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 | #include
11 |
12 | #include
13 |
14 | #include "kmain.h"
15 |
16 | typedef struct Ps4RandomizedPathHookArgument
17 | {
18 | uint64_t zero;
19 | void *path;
20 | uint64_t length;
21 | }
22 | Ps4RandomizedPathHookArgument;
23 |
24 | int ps4RandomizedPathHook(struct thread *td, Ps4KernelSystemCallHookArgument *uap)
25 | {
26 | memcpy(((Ps4RandomizedPathHookArgument *)uap->uap)->path, "mrfoo\0", 6);
27 | return PS4_KERNEL_SYSTEM_CALL_HOOK_CONTROL_CONTINUE;
28 | }
29 |
30 | int kmain(struct thread *td, void *uap)
31 | {
32 | Ps4KernelSystemCallHook *h = NULL;
33 |
34 | if(uap)
35 | {
36 | ps4KernelSystemCallHookDestroy((Ps4KernelSystemCallHook *)uap);
37 | }
38 | else
39 | {
40 | ps4KernelSystemCallHookCreate(&h, SYS_randomized_path);
41 | ps4KernelSystemCallHookAdd(h, (void *)ps4RandomizedPathHook, PS4_KERNEL_SYSTEM_CALL_HOOK_TYPE_GENERIC_POST);
42 | }
43 |
44 | ps4KernelThreadSetReturn(td, (register_t)h);
45 | return PS4_OK;
46 | }
47 |
--------------------------------------------------------------------------------
/ps4sdk/system_call_hook/source/main.c:
--------------------------------------------------------------------------------
1 | #define _WANT_UCRED
2 | #define _XOPEN_SOURCE 700
3 | #define __BSD_VISIBLE 1
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | #include "kmain.h"
19 |
20 | char *getRandomizedPath()
21 | {
22 | char path[16];
23 | int length = 11;
24 | char *r;
25 | // on 1.75 using path alone will null out (override) the first 4 bytes
26 | // return probably a two value struct with val1 = null
27 | syscall(SYS_randomized_path, 0, path + 4, &length);
28 | r = malloc(12);
29 | r[0] = '/';
30 | strcpy(r, path + 4);
31 | return r;
32 | }
33 |
34 | void printHook(Ps4KernelSystemCallHook *h)
35 | {
36 | Ps4KernelSystemCallHookArgument a;
37 | Ps4KernelSystemCallHookArgument *arg = &a;
38 |
39 | ps4KernelCall(ps4KernelMemoryCopy, h, arg, sizeof(Ps4KernelSystemCallHookArgument));
40 |
41 | printf(
42 | "hook[%p] =\n"
43 | "{\n"
44 | "\tclone: %p,\n"
45 | "\thandler: %p,\n"
46 | "\tprologue: %p,\n"
47 | "\thook: %p,\n"
48 | "\thookType: %p,\n"
49 | "\thookCount: %p,\n"
50 | "\thookSize: %p,\n"
51 | "\thookTypeCurrent: %p,\n"
52 | "\tlock: %p,\n"
53 | "\tentryCount: %p,\n"
54 | "\tcallCount: %p,\n"
55 | "\tsystemCalls: %p,\n"
56 | "\tnumber: %p,\n"
57 | "\toriginalCall: %p,\n"
58 | "\tthread: %p,\n"
59 | "\tuap: %p,\n"
60 | "\tsysret: %p,\n"
61 | "\treturns[%p]:\n"
62 | "\t{\n"
63 | "\t\t0: %p,\n"
64 | "\t\t1: %p,\n"
65 | "\t}\n"
66 | "\tuserArgument: %p,\n"
67 | "\tallocate: %p,\n"
68 | "\tfree: %p,\n"
69 | "\tmt: %p\n"
70 | "}\n",
71 | arg,
72 | arg->clone,
73 | arg->handler,
74 | arg->prologue,
75 | arg->hook,
76 | arg->hookType,
77 | arg->hookCount,
78 | arg->hookSize,
79 | arg->hookTypeCurrent,
80 | arg->lock,
81 | arg->entryCount,
82 | arg->callCount,
83 | arg->systemCalls,
84 | arg->number,
85 | arg->originalCall,
86 | arg->thread,
87 | arg->uap,
88 | arg->sysret,
89 | arg->returns,
90 | arg->returns[0],
91 | arg->returns[1],
92 | arg->userArgument,
93 | arg->allocate,
94 | arg->free,
95 | arg->mt
96 | );
97 |
98 | //for(int i = 0; i < arg->hookCount; ++i)
99 | // printf("hook[%i]: %p %p\n", i, arg->hook[i], arg->hookType[i]);
100 | }
101 |
102 | int main(int argc, char **argv)
103 | {
104 | void *hook;
105 | int r;
106 |
107 | r = ps4KernelExecute((void *)kmain, NULL, (void *)&hook, NULL);
108 |
109 | char *p = getRandomizedPath();
110 | printf("%s\n", p);
111 | printf("%p\n", hook);
112 | printHook(hook);
113 |
114 | r = ps4KernelExecute((void *)kmain, (void *)hook, NULL, NULL);
115 |
116 | return EXIT_SUCCESS;
117 | }
118 |
--------------------------------------------------------------------------------
/sce/modules/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/sce/modules/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 |
7 | #include
8 |
9 | enum{ ModulesSize = 1024 };
10 |
11 | void printModuleList(SceKernelModule *modules, size_t size)
12 | {
13 | int i;
14 |
15 | printf("SceKernelModule[%zu] = {", size);
16 | for(i = 0; i < size; ++i)
17 | printf("%02X,", modules[i]);
18 | printf("}\n");
19 | }
20 |
21 |
22 | void printModuleInfo(SceKernelModuleInfo *moduleInfo)
23 | {
24 | int i;
25 |
26 | printf("struct SceKernelModuleInfo\n");
27 | printf("{\n");
28 | printf("\tname: %s\n", moduleInfo->name);
29 | for(i = 0; i < moduleInfo->segmentCount; ++i)
30 | {
31 | printf("\t\tsegment[%i].address: %p\n", i, moduleInfo->segmentInfo[i].address);
32 | printf("\t\tsegment[%i].size: %u\n", i, moduleInfo->segmentInfo[i].size);
33 | printf("\t\tsegment[%i].prot: %i\n", i, moduleInfo->segmentInfo[i].prot);
34 | }
35 | printf("\tsegment count: %u\n", moduleInfo->segmentCount);
36 | printf("\tfingerprint: ");
37 | for(i = 0; i < 20; ++i)
38 | printf("%02X", moduleInfo->fingerprint[i]);
39 | printf("\n");
40 | printf("}\n");
41 | }
42 |
43 | void stopUnloadModule(SceKernelModule module)
44 | {
45 | int r;
46 | SceKernelModule modules[ModulesSize];
47 | size_t moduleCount;
48 |
49 | r = sceKernelStopUnloadModule(module, 0, NULL, 0, NULL, NULL);
50 | printf("sceKernelStopUnloadModule(%02X) = %i\n", module, r);
51 |
52 | r = sceKernelGetModuleList(modules, ModulesSize, &moduleCount);
53 | printf("sceKernelGetModuleList = %i\n", r);
54 | printModuleList(modules, moduleCount);
55 | }
56 |
57 | void loadStartModule(const char *moduleName)
58 | {
59 | int r;
60 | SceKernelModule module;
61 | SceKernelModule modules[ModulesSize];
62 | size_t moduleCount;
63 |
64 | module = sceKernelLoadStartModule(moduleName, 0, NULL, 0, NULL, NULL);
65 | printf("sceKernelLoadStartModule(%s) = %02X\n", moduleName, module);
66 |
67 | r = sceKernelGetModuleList(modules, ModulesSize, &moduleCount);
68 | printf("sceKernelGetModuleList = %i\n", r);
69 | printModuleList(modules, moduleCount);
70 | }
71 |
72 | int main(int argc, char **argv)
73 | {
74 | SceKernelModule modules[ModulesSize];
75 | size_t moduleCount;
76 | SceKernelModuleInfo *moduleInfo;
77 | int r, i;
78 |
79 | moduleCount = 0;
80 | r = sceKernelGetModuleList(modules, ModulesSize, &moduleCount);
81 | printf("sceKernelGetModuleList = %i\n", r);
82 | printModuleList(modules, moduleCount);
83 |
84 | moduleInfo = malloc(moduleCount * sizeof(SceKernelModuleInfo));
85 |
86 | for(i = 0; i < moduleCount; ++i)
87 | {
88 | moduleInfo[i].size = sizeof(SceKernelModuleInfo);
89 | r = sceKernelGetModuleInfo(modules[i], &moduleInfo[i]);
90 | printf("sceKernelGetModuleInfo(%02X) = %i\n", modules[i], r);
91 | printModuleInfo(&moduleInfo[i]);
92 | }
93 |
94 | // Try to unload to free resources like video to reinitialize them
95 | // Video (open) did still not work though
96 | // Crashes on return to the browser (obviously)
97 | // Also crashes on unload of libSceWebKit2 imidiately
98 | // which could maybe be caught though.
99 |
100 | /*
101 | for(i = 0; i < moduleCount; ++i)
102 | if(strcmp(moduleInfo[i].name, "libSceWebKit2.sprx"))
103 | stopUnloadModule(modules[i]);
104 |
105 | // try to free potential dependency survivors
106 | for(i = 0; i < moduleCount; ++i)
107 | if(strcmp(moduleInfo[i].name, "libSceWebKit2.sprx"))
108 | stopUnloadModule(modules[i]);
109 |
110 | for(i = 0; i < moduleCount; ++i)
111 | loadStartModule(moduleInfo[i].name);
112 |
113 | free(moduleInfo);
114 | */
115 |
116 | return EXIT_SUCCESS;
117 | }
118 |
--------------------------------------------------------------------------------
/sce/resolve/Makefile:
--------------------------------------------------------------------------------
1 | ifndef Ps4Sdk
2 | ifdef ps4sdk
3 | Ps4Sdk := $(ps4sdk)
4 | endif
5 | ifdef PS4SDK
6 | Ps4Sdk := $(PS4SDK)
7 | endif
8 | ifndef Ps4Sdk
9 | $(error Neither PS4SDK, Ps4Sdk nor ps4sdk set)
10 | endif
11 | endif
12 |
13 | target ?= ps4_elf
14 |
15 | include $(Ps4Sdk)/make/ps4sdk.mk
16 |
--------------------------------------------------------------------------------
/sce/resolve/source/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | #include
11 |
12 | #define NAME_SIZE 128
13 |
14 | int main(int argc, char **argv)
15 | {
16 | int i, r;
17 |
18 | char moduleName[NAME_SIZE];
19 | char symbolName[NAME_SIZE];
20 | int module;
21 | void *symbol;
22 |
23 | // prevent const ro.data array
24 | char *m1 = "libSceLibcInternal.sprx";
25 | char *m2 = "libkernel.sprx";
26 | char *m3 = "librt.sprx";
27 | char *m4 = "libC.sprx";
28 | char *modules[] = {m1, m2, m3, m4};
29 |
30 | printf("Input: \n");
31 | printf("Output: \n");
32 | printf("Exit Input: exit -\n");
33 |
34 | while(1)
35 | {
36 | moduleName[0] = '\0';
37 | symbolName[0] = '\0';
38 | module = 0;
39 | symbol = NULL;
40 |
41 | if(scanf("%s %s", moduleName, symbolName) < 2)
42 | break;
43 |
44 | if(strncmp(moduleName, "exit", 4) == 0)
45 | break;
46 |
47 | module = sceKernelLoadStartModule(moduleName, 0, NULL, 0, NULL, NULL);
48 | r = sceKernelDlsym(module, symbolName, &symbol);
49 |
50 | // fuzzy search if no resolve was possible
51 | for(i = 0; i < sizeof(modules) / sizeof(modules[0]) && r != 0; ++i)
52 | {
53 | if(strcmp(modules[i], moduleName) == 0)
54 | continue;
55 | module = sceKernelLoadStartModule(modules[i], 0, NULL, 0, NULL, NULL);
56 | r = sceKernelDlsym(module, symbolName, &symbol);
57 | if(r == 0)
58 | strcpy(moduleName, modules[i]);
59 | }
60 |
61 | if(r != 0)
62 | {
63 | strcpy(moduleName, "-");
64 | strcpy(symbolName, "-");
65 | module = 0;
66 | symbol = NULL;
67 | }
68 |
69 | if(printf("%s %s %i %"PRIxPTR"\n", moduleName, symbolName, module, symbol) < 0)
70 | break;
71 | }
72 |
73 | return EXIT_SUCCESS;
74 | }
75 |
--------------------------------------------------------------------------------