├── .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 | --------------------------------------------------------------------------------