stdlib.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #include <stdlib.h>
  2. #include <sys/mman.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <alloca.h>
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <AK/Assertions.h>
  10. #include <AK/Types.h>
  11. #include <Kernel/Syscall.h>
  12. #include <AK/StdLibExtras.h>
  13. #include <AK/HashMap.h>
  14. #include <AK/AKString.h>
  15. extern "C" {
  16. #define MALLOC_SCRUB_BYTE 0x85
  17. #define FREE_SCRUB_BYTE 0x82
  18. struct MallocHeader {
  19. uint16_t first_chunk_index;
  20. uint16_t chunk_count;
  21. size_t size;
  22. uint32_t compute_xorcheck() const
  23. {
  24. return 0x19820413 ^ ((first_chunk_index << 16) | chunk_count) ^ size;
  25. }
  26. };
  27. struct MallocFooter {
  28. uint32_t xorcheck;
  29. };
  30. #define CHUNK_SIZE 16
  31. #define POOL_SIZE 4 * 1048576
  32. static const size_t malloc_budget = POOL_SIZE;
  33. static byte s_malloc_map[POOL_SIZE / CHUNK_SIZE / 8];
  34. static byte* s_malloc_pool;
  35. static uint32_t s_malloc_sum_alloc = 0;
  36. static uint32_t s_malloc_sum_free = POOL_SIZE;
  37. void* malloc(size_t size)
  38. {
  39. if (size == 0)
  40. return nullptr;
  41. // We need space for the MallocHeader structure at the head of the block.
  42. size_t real_size = size + sizeof(MallocHeader) + sizeof(MallocFooter);
  43. if (s_malloc_sum_free < real_size) {
  44. fprintf(stderr, "malloc(): Out of memory\ns_malloc_sum_free=%u, real_size=%u\n", s_malloc_sum_free, real_size);
  45. assert(false);
  46. }
  47. size_t chunks_needed = real_size / CHUNK_SIZE;
  48. if (real_size % CHUNK_SIZE)
  49. chunks_needed++;
  50. size_t chunks_here = 0;
  51. size_t first_chunk = 0;
  52. for (unsigned i = 0; i < (POOL_SIZE / CHUNK_SIZE / 8); ++i) {
  53. if (s_malloc_map[i] == 0xff) {
  54. // Skip over completely full bucket.
  55. chunks_here = 0;
  56. continue;
  57. }
  58. // FIXME: This scan can be optimized further with TZCNT.
  59. for (unsigned j = 0; j < 8; ++j) {
  60. if ((s_malloc_map[i] & (1<<j))) {
  61. // This is in use, so restart chunks_here counter.
  62. chunks_here = 0;
  63. continue;
  64. }
  65. if (chunks_here == 0) {
  66. // Mark where potential allocation starts.
  67. first_chunk = i * 8 + j;
  68. }
  69. ++chunks_here;
  70. if (chunks_here == chunks_needed) {
  71. auto* header = (MallocHeader*)(s_malloc_pool + (first_chunk * CHUNK_SIZE));
  72. byte* ptr = ((byte*)header) + sizeof(MallocHeader);
  73. header->chunk_count = chunks_needed;
  74. header->first_chunk_index = first_chunk;
  75. header->size = size;
  76. auto* footer = (MallocFooter*)((byte*)header + (header->chunk_count * CHUNK_SIZE) - sizeof(MallocFooter));
  77. footer->xorcheck = header->compute_xorcheck();
  78. for (size_t k = first_chunk; k < (first_chunk + chunks_needed); ++k)
  79. s_malloc_map[k / 8] |= 1 << (k % 8);
  80. s_malloc_sum_alloc += header->chunk_count * CHUNK_SIZE;
  81. s_malloc_sum_free -= header->chunk_count * CHUNK_SIZE;
  82. memset(ptr, MALLOC_SCRUB_BYTE, (header->chunk_count * CHUNK_SIZE) - (sizeof(MallocHeader) + sizeof(MallocFooter)));
  83. return ptr;
  84. }
  85. }
  86. }
  87. fprintf(stderr, "malloc(): Out of memory (no consecutive chunks found for size %u)\n", size);
  88. volatile char* crashme = (char*)0xc007d00d;
  89. *crashme = 0;
  90. return nullptr;
  91. }
  92. static void validate_mallocation(void* ptr, const char* func)
  93. {
  94. auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
  95. if (header->size == 0) {
  96. fprintf(stderr, "%s called on bad pointer %p, size=0\n", func, ptr);
  97. assert(false);
  98. }
  99. auto* footer = (MallocFooter*)((byte*)header + (header->chunk_count * CHUNK_SIZE) - sizeof(MallocFooter));
  100. uint32_t expected_xorcheck = header->compute_xorcheck();
  101. if (footer->xorcheck != expected_xorcheck) {
  102. fprintf(stderr, "%s called on bad pointer %p, xorcheck=%w (expected %w)\n", func, ptr, footer->xorcheck, expected_xorcheck);
  103. assert(false);
  104. }
  105. }
  106. void free(void* ptr)
  107. {
  108. if (!ptr)
  109. return;
  110. validate_mallocation(ptr, "free()");
  111. auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
  112. for (unsigned i = header->first_chunk_index; i < (header->first_chunk_index + header->chunk_count); ++i)
  113. s_malloc_map[i / 8] &= ~(1 << (i % 8));
  114. s_malloc_sum_alloc -= header->chunk_count * CHUNK_SIZE;
  115. s_malloc_sum_free += header->chunk_count * CHUNK_SIZE;
  116. memset(header, FREE_SCRUB_BYTE, header->chunk_count * CHUNK_SIZE);
  117. }
  118. void __malloc_init()
  119. {
  120. s_malloc_pool = (byte*)mmap(nullptr, malloc_budget, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  121. int rc = set_mmap_name(s_malloc_pool, malloc_budget, "malloc pool");
  122. if (rc < 0)
  123. perror("set_mmap_name failed");
  124. }
  125. void* calloc(size_t count, size_t size)
  126. {
  127. size_t new_size = count * size;
  128. auto* ptr = malloc(new_size);
  129. memset(ptr, 0, new_size);
  130. return ptr;
  131. }
  132. void* realloc(void *ptr, size_t size)
  133. {
  134. validate_mallocation(ptr, "realloc()");
  135. auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader)));
  136. size_t old_size = header->size;
  137. if (size == old_size)
  138. return ptr;
  139. auto* new_ptr = malloc(size);
  140. memcpy(new_ptr, ptr, min(old_size, size));
  141. free(ptr);
  142. return new_ptr;
  143. }
  144. void exit(int status)
  145. {
  146. _exit(status);
  147. assert(false);
  148. }
  149. void abort()
  150. {
  151. // FIXME: Implement proper abort().
  152. exit(253);
  153. }
  154. char* getenv(const char* name)
  155. {
  156. for (size_t i = 0; environ[i]; ++i) {
  157. const char* decl = environ[i];
  158. char* eq = strchr(decl, '=');
  159. if (!eq)
  160. continue;
  161. size_t varLength = eq - decl;
  162. char* var = (char*)alloca(varLength + 1);
  163. memcpy(var, decl, varLength);
  164. var[varLength] = '\0';
  165. if (!strcmp(var, name)) {
  166. char* value = eq + 1;
  167. return value;
  168. }
  169. }
  170. return nullptr;
  171. }
  172. int putenv(char* new_var)
  173. {
  174. HashMap<String, String> environment;
  175. auto handle_environment_entry = [&environment] (const char* decl) {
  176. char* eq = strchr(decl, '=');
  177. if (!eq)
  178. return;
  179. size_t var_length = eq - decl;
  180. char* var = (char*)alloca(var_length + 1);
  181. memcpy(var, decl, var_length);
  182. var[var_length] = '\0';
  183. const char* value = eq + 1;
  184. environment.set(var, value);
  185. };
  186. for (size_t i = 0; environ[i]; ++i)
  187. handle_environment_entry(environ[i]);
  188. handle_environment_entry(new_var);
  189. //extern bool __environ_is_malloced;
  190. //if (__environ_is_malloced)
  191. // free(environ);
  192. //__environ_is_malloced = true;
  193. int environment_size = sizeof(char*); // For the null sentinel.
  194. for (auto& it : environment)
  195. environment_size += (int)sizeof(char*) + it.key.length() + 1 + it.value.length() + 1;
  196. char* buffer = (char*)malloc(environment_size);
  197. environ = (char**)buffer;
  198. char* bufptr = buffer + sizeof(char*) * (environment.size() + 1);
  199. int i = 0;
  200. for (auto& it : environment) {
  201. environ[i] = bufptr;
  202. memcpy(bufptr, it.key.characters(), it.key.length());
  203. bufptr += it.key.length();
  204. *(bufptr++) = '=';
  205. memcpy(bufptr, it.value.characters(), it.value.length());
  206. bufptr += it.value.length();
  207. *(bufptr++) = '\0';
  208. ++i;
  209. }
  210. environ[environment.size()] = nullptr;
  211. return 0;
  212. }
  213. double atof(const char* str)
  214. {
  215. dbgprintf("LibC: atof: '%s'\n", str);
  216. assert(false);
  217. }
  218. int atoi(const char* str)
  219. {
  220. size_t len = strlen(str);
  221. int value = 0;
  222. bool isNegative = false;
  223. for (size_t i = 0; i < len; ++i) {
  224. if (i == 0 && str[0] == '-') {
  225. isNegative = true;
  226. continue;
  227. }
  228. if (str[i] < '0' || str[i] > '9')
  229. return value;
  230. value = value * 10;
  231. value += str[i] - '0';
  232. }
  233. return isNegative ? -value : value;
  234. }
  235. long atol(const char* str)
  236. {
  237. static_assert(sizeof(int) == sizeof(long));
  238. return atoi(str);
  239. }
  240. static char ptsname_buf[32];
  241. char* ptsname(int fd)
  242. {
  243. if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
  244. return nullptr;
  245. return ptsname_buf;
  246. }
  247. int ptsname_r(int fd, char* buffer, size_t size)
  248. {
  249. int rc = syscall(SC_ptsname_r, fd, buffer, size);
  250. __RETURN_WITH_ERRNO(rc, rc, -1);
  251. }
  252. static unsigned long s_next_rand = 1;
  253. int rand()
  254. {
  255. s_next_rand = s_next_rand * 1103515245 + 12345;
  256. return((unsigned)(s_next_rand/((RAND_MAX + 1) * 2)) % (RAND_MAX + 1));
  257. }
  258. void srand(unsigned seed)
  259. {
  260. s_next_rand = seed;
  261. }
  262. int abs(int i)
  263. {
  264. return i < 0 ? -i : i;
  265. }
  266. long int random()
  267. {
  268. return rand();
  269. }
  270. void srandom(unsigned seed)
  271. {
  272. srand(seed);
  273. }
  274. int system(const char* command)
  275. {
  276. return execl("/bin/sh", "sh", "-c", command, nullptr);
  277. }
  278. char* mktemp(char*)
  279. {
  280. ASSERT_NOT_REACHED();
  281. }
  282. void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
  283. {
  284. dbgprintf("FIXME(LibC): bsearch(%p, %p, %u, %u, %p)\n", key, base, nmemb, size, compar);
  285. ASSERT_NOT_REACHED();
  286. }
  287. div_t div(int numerator, int denominator)
  288. {
  289. div_t result;
  290. result.quot = numerator / denominator;
  291. result.rem = numerator % denominator;
  292. return result;
  293. }
  294. ldiv_t ldiv(long numerator, long denominator)
  295. {
  296. ldiv_t result;
  297. result.quot = numerator / denominator;
  298. result.rem = numerator % denominator;
  299. return result;
  300. }
  301. size_t mbstowcs(wchar_t*, const char*, size_t)
  302. {
  303. assert(false);
  304. }
  305. int atexit(void (*function)())
  306. {
  307. (void)function;
  308. assert(false);
  309. }
  310. long strtol(const char*, char** endptr, int base)
  311. {
  312. (void)endptr;
  313. (void)base;
  314. assert(false);
  315. }
  316. unsigned long strtoul(const char*, char** endptr, int base)
  317. {
  318. (void)endptr;
  319. (void)base;
  320. assert(false);
  321. }
  322. }