memory_buffer_alloc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /*
  2. * Buffer-based memory allocator
  3. *
  4. * Copyright (C) 2006-2014, Brainspark B.V.
  5. *
  6. * This file is part of PolarSSL (http://www.polarssl.org)
  7. * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. */
  25. #if !defined(POLARSSL_CONFIG_FILE)
  26. #include "polarssl/config.h"
  27. #else
  28. #include POLARSSL_CONFIG_FILE
  29. #endif
  30. #if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
  31. #include "polarssl/memory_buffer_alloc.h"
  32. #include <string.h>
  33. #if defined(POLARSSL_MEMORY_DEBUG)
  34. #include <stdio.h>
  35. #if defined(POLARSSL_MEMORY_BACKTRACE)
  36. #include <execinfo.h>
  37. #endif
  38. #endif
  39. #if defined(POLARSSL_THREADING_C)
  40. #include "polarssl/threading.h"
  41. #endif
  42. #if defined(POLARSSL_PLATFORM_C)
  43. #include "polarssl/platform.h"
  44. #else
  45. #define polarssl_fprintf fprintf
  46. #endif
  47. /* Implementation that should never be optimized out by the compiler */
  48. static void polarssl_zeroize( void *v, size_t n ) {
  49. volatile unsigned char *p = v; while( n-- ) *p++ = 0;
  50. }
  51. #define MAGIC1 0xFF00AA55
  52. #define MAGIC2 0xEE119966
  53. #define MAX_BT 20
  54. typedef struct _memory_header memory_header;
  55. struct _memory_header
  56. {
  57. size_t magic1;
  58. size_t size;
  59. size_t alloc;
  60. memory_header *prev;
  61. memory_header *next;
  62. memory_header *prev_free;
  63. memory_header *next_free;
  64. #if defined(POLARSSL_MEMORY_BACKTRACE)
  65. char **trace;
  66. size_t trace_count;
  67. #endif
  68. size_t magic2;
  69. };
  70. typedef struct
  71. {
  72. unsigned char *buf;
  73. size_t len;
  74. memory_header *first;
  75. memory_header *first_free;
  76. size_t current_alloc_size;
  77. int verify;
  78. #if defined(POLARSSL_MEMORY_DEBUG)
  79. size_t malloc_count;
  80. size_t free_count;
  81. size_t total_used;
  82. size_t maximum_used;
  83. size_t header_count;
  84. size_t maximum_header_count;
  85. #endif
  86. #if defined(POLARSSL_THREADING_C)
  87. threading_mutex_t mutex;
  88. #endif
  89. }
  90. buffer_alloc_ctx;
  91. static buffer_alloc_ctx heap;
  92. #if defined(POLARSSL_MEMORY_DEBUG)
  93. static void debug_header( memory_header *hdr )
  94. {
  95. #if defined(POLARSSL_MEMORY_BACKTRACE)
  96. size_t i;
  97. #endif
  98. polarssl_fprintf( stderr, "HDR: PTR(%10u), PREV(%10u), NEXT(%10u), "
  99. "ALLOC(%u), SIZE(%10u)\n",
  100. (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
  101. hdr->alloc, hdr->size );
  102. polarssl_fprintf( stderr, " FPREV(%10u), FNEXT(%10u)\n",
  103. (size_t) hdr->prev_free, (size_t) hdr->next_free );
  104. #if defined(POLARSSL_MEMORY_BACKTRACE)
  105. polarssl_fprintf( stderr, "TRACE: \n" );
  106. for( i = 0; i < hdr->trace_count; i++ )
  107. polarssl_fprintf( stderr, "%s\n", hdr->trace[i] );
  108. polarssl_fprintf( stderr, "\n" );
  109. #endif
  110. }
  111. static void debug_chain()
  112. {
  113. memory_header *cur = heap.first;
  114. polarssl_fprintf( stderr, "\nBlock list\n" );
  115. while( cur != NULL )
  116. {
  117. debug_header( cur );
  118. cur = cur->next;
  119. }
  120. polarssl_fprintf( stderr, "Free list\n" );
  121. cur = heap.first_free;
  122. while( cur != NULL )
  123. {
  124. debug_header( cur );
  125. cur = cur->next_free;
  126. }
  127. }
  128. #endif /* POLARSSL_MEMORY_DEBUG */
  129. static int verify_header( memory_header *hdr )
  130. {
  131. if( hdr->magic1 != MAGIC1 )
  132. {
  133. #if defined(POLARSSL_MEMORY_DEBUG)
  134. polarssl_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
  135. #endif
  136. return( 1 );
  137. }
  138. if( hdr->magic2 != MAGIC2 )
  139. {
  140. #if defined(POLARSSL_MEMORY_DEBUG)
  141. polarssl_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
  142. #endif
  143. return( 1 );
  144. }
  145. if( hdr->alloc > 1 )
  146. {
  147. #if defined(POLARSSL_MEMORY_DEBUG)
  148. polarssl_fprintf( stderr, "FATAL: alloc has illegal value\n" );
  149. #endif
  150. return( 1 );
  151. }
  152. if( hdr->prev != NULL && hdr->prev == hdr->next )
  153. {
  154. #if defined(POLARSSL_MEMORY_DEBUG)
  155. polarssl_fprintf( stderr, "FATAL: prev == next\n" );
  156. #endif
  157. return( 1 );
  158. }
  159. if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
  160. {
  161. #if defined(POLARSSL_MEMORY_DEBUG)
  162. polarssl_fprintf( stderr, "FATAL: prev_free == next_free\n" );
  163. #endif
  164. return( 1 );
  165. }
  166. return( 0 );
  167. }
  168. static int verify_chain()
  169. {
  170. memory_header *prv = heap.first, *cur = heap.first->next;
  171. if( verify_header( heap.first ) != 0 )
  172. {
  173. #if defined(POLARSSL_MEMORY_DEBUG)
  174. polarssl_fprintf( stderr, "FATAL: verification of first header "
  175. "failed\n" );
  176. #endif
  177. return( 1 );
  178. }
  179. if( heap.first->prev != NULL )
  180. {
  181. #if defined(POLARSSL_MEMORY_DEBUG)
  182. polarssl_fprintf( stderr, "FATAL: verification failed: "
  183. "first->prev != NULL\n" );
  184. #endif
  185. return( 1 );
  186. }
  187. while( cur != NULL )
  188. {
  189. if( verify_header( cur ) != 0 )
  190. {
  191. #if defined(POLARSSL_MEMORY_DEBUG)
  192. polarssl_fprintf( stderr, "FATAL: verification of header "
  193. "failed\n" );
  194. #endif
  195. return( 1 );
  196. }
  197. if( cur->prev != prv )
  198. {
  199. #if defined(POLARSSL_MEMORY_DEBUG)
  200. polarssl_fprintf( stderr, "FATAL: verification failed: "
  201. "cur->prev != prv\n" );
  202. #endif
  203. return( 1 );
  204. }
  205. prv = cur;
  206. cur = cur->next;
  207. }
  208. return( 0 );
  209. }
  210. static void *buffer_alloc_malloc( size_t len )
  211. {
  212. memory_header *new, *cur = heap.first_free;
  213. unsigned char *p;
  214. #if defined(POLARSSL_MEMORY_BACKTRACE)
  215. void *trace_buffer[MAX_BT];
  216. size_t trace_cnt;
  217. #endif
  218. if( heap.buf == NULL || heap.first == NULL )
  219. return( NULL );
  220. if( len % POLARSSL_MEMORY_ALIGN_MULTIPLE )
  221. {
  222. len -= len % POLARSSL_MEMORY_ALIGN_MULTIPLE;
  223. len += POLARSSL_MEMORY_ALIGN_MULTIPLE;
  224. }
  225. // Find block that fits
  226. //
  227. while( cur != NULL )
  228. {
  229. if( cur->size >= len )
  230. break;
  231. cur = cur->next_free;
  232. }
  233. if( cur == NULL )
  234. return( NULL );
  235. if( cur->alloc != 0 )
  236. {
  237. #if defined(POLARSSL_MEMORY_DEBUG)
  238. polarssl_fprintf( stderr, "FATAL: block in free_list but allocated "
  239. "data\n" );
  240. #endif
  241. exit( 1 );
  242. }
  243. #if defined(POLARSSL_MEMORY_DEBUG)
  244. heap.malloc_count++;
  245. #endif
  246. // Found location, split block if > memory_header + 4 room left
  247. //
  248. if( cur->size - len < sizeof(memory_header) +
  249. POLARSSL_MEMORY_ALIGN_MULTIPLE )
  250. {
  251. cur->alloc = 1;
  252. // Remove from free_list
  253. //
  254. if( cur->prev_free != NULL )
  255. cur->prev_free->next_free = cur->next_free;
  256. else
  257. heap.first_free = cur->next_free;
  258. if( cur->next_free != NULL )
  259. cur->next_free->prev_free = cur->prev_free;
  260. cur->prev_free = NULL;
  261. cur->next_free = NULL;
  262. #if defined(POLARSSL_MEMORY_DEBUG)
  263. heap.total_used += cur->size;
  264. if( heap.total_used > heap.maximum_used )
  265. heap.maximum_used = heap.total_used;
  266. #endif
  267. #if defined(POLARSSL_MEMORY_BACKTRACE)
  268. trace_cnt = backtrace( trace_buffer, MAX_BT );
  269. cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
  270. cur->trace_count = trace_cnt;
  271. #endif
  272. if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
  273. exit( 1 );
  274. return( ( (unsigned char *) cur ) + sizeof(memory_header) );
  275. }
  276. p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
  277. new = (memory_header *) p;
  278. new->size = cur->size - len - sizeof(memory_header);
  279. new->alloc = 0;
  280. new->prev = cur;
  281. new->next = cur->next;
  282. #if defined(POLARSSL_MEMORY_BACKTRACE)
  283. new->trace = NULL;
  284. new->trace_count = 0;
  285. #endif
  286. new->magic1 = MAGIC1;
  287. new->magic2 = MAGIC2;
  288. if( new->next != NULL )
  289. new->next->prev = new;
  290. // Replace cur with new in free_list
  291. //
  292. new->prev_free = cur->prev_free;
  293. new->next_free = cur->next_free;
  294. if( new->prev_free != NULL )
  295. new->prev_free->next_free = new;
  296. else
  297. heap.first_free = new;
  298. if( new->next_free != NULL )
  299. new->next_free->prev_free = new;
  300. cur->alloc = 1;
  301. cur->size = len;
  302. cur->next = new;
  303. cur->prev_free = NULL;
  304. cur->next_free = NULL;
  305. #if defined(POLARSSL_MEMORY_DEBUG)
  306. heap.header_count++;
  307. if( heap.header_count > heap.maximum_header_count )
  308. heap.maximum_header_count = heap.header_count;
  309. heap.total_used += cur->size;
  310. if( heap.total_used > heap.maximum_used )
  311. heap.maximum_used = heap.total_used;
  312. #endif
  313. #if defined(POLARSSL_MEMORY_BACKTRACE)
  314. trace_cnt = backtrace( trace_buffer, MAX_BT );
  315. cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
  316. cur->trace_count = trace_cnt;
  317. #endif
  318. if( ( heap.verify & MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
  319. exit( 1 );
  320. return( ( (unsigned char *) cur ) + sizeof(memory_header) );
  321. }
  322. static void buffer_alloc_free( void *ptr )
  323. {
  324. memory_header *hdr, *old = NULL;
  325. unsigned char *p = (unsigned char *) ptr;
  326. if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
  327. return;
  328. if( p < heap.buf || p > heap.buf + heap.len )
  329. {
  330. #if defined(POLARSSL_MEMORY_DEBUG)
  331. polarssl_fprintf( stderr, "FATAL: polarssl_free() outside of managed "
  332. "space\n" );
  333. #endif
  334. exit( 1 );
  335. }
  336. p -= sizeof(memory_header);
  337. hdr = (memory_header *) p;
  338. if( verify_header( hdr ) != 0 )
  339. exit( 1 );
  340. if( hdr->alloc != 1 )
  341. {
  342. #if defined(POLARSSL_MEMORY_DEBUG)
  343. polarssl_fprintf( stderr, "FATAL: polarssl_free() on unallocated "
  344. "data\n" );
  345. #endif
  346. exit( 1 );
  347. }
  348. hdr->alloc = 0;
  349. #if defined(POLARSSL_MEMORY_DEBUG)
  350. heap.free_count++;
  351. heap.total_used -= hdr->size;
  352. #endif
  353. // Regroup with block before
  354. //
  355. if( hdr->prev != NULL && hdr->prev->alloc == 0 )
  356. {
  357. #if defined(POLARSSL_MEMORY_DEBUG)
  358. heap.header_count--;
  359. #endif
  360. hdr->prev->size += sizeof(memory_header) + hdr->size;
  361. hdr->prev->next = hdr->next;
  362. old = hdr;
  363. hdr = hdr->prev;
  364. if( hdr->next != NULL )
  365. hdr->next->prev = hdr;
  366. #if defined(POLARSSL_MEMORY_BACKTRACE)
  367. free( old->trace );
  368. #endif
  369. memset( old, 0, sizeof(memory_header) );
  370. }
  371. // Regroup with block after
  372. //
  373. if( hdr->next != NULL && hdr->next->alloc == 0 )
  374. {
  375. #if defined(POLARSSL_MEMORY_DEBUG)
  376. heap.header_count--;
  377. #endif
  378. hdr->size += sizeof(memory_header) + hdr->next->size;
  379. old = hdr->next;
  380. hdr->next = hdr->next->next;
  381. if( hdr->prev_free != NULL || hdr->next_free != NULL )
  382. {
  383. if( hdr->prev_free != NULL )
  384. hdr->prev_free->next_free = hdr->next_free;
  385. else
  386. heap.first_free = hdr->next_free;
  387. if( hdr->next_free != NULL )
  388. hdr->next_free->prev_free = hdr->prev_free;
  389. }
  390. hdr->prev_free = old->prev_free;
  391. hdr->next_free = old->next_free;
  392. if( hdr->prev_free != NULL )
  393. hdr->prev_free->next_free = hdr;
  394. else
  395. heap.first_free = hdr;
  396. if( hdr->next_free != NULL )
  397. hdr->next_free->prev_free = hdr;
  398. if( hdr->next != NULL )
  399. hdr->next->prev = hdr;
  400. #if defined(POLARSSL_MEMORY_BACKTRACE)
  401. free( old->trace );
  402. #endif
  403. memset( old, 0, sizeof(memory_header) );
  404. }
  405. // Prepend to free_list if we have not merged
  406. // (Does not have to stay in same order as prev / next list)
  407. //
  408. if( old == NULL )
  409. {
  410. hdr->next_free = heap.first_free;
  411. heap.first_free->prev_free = hdr;
  412. heap.first_free = hdr;
  413. }
  414. #if defined(POLARSSL_MEMORY_BACKTRACE)
  415. hdr->trace = NULL;
  416. hdr->trace_count = 0;
  417. #endif
  418. if( ( heap.verify & MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
  419. exit( 1 );
  420. }
  421. void memory_buffer_set_verify( int verify )
  422. {
  423. heap.verify = verify;
  424. }
  425. int memory_buffer_alloc_verify()
  426. {
  427. return verify_chain();
  428. }
  429. #if defined(POLARSSL_MEMORY_DEBUG)
  430. void memory_buffer_alloc_status()
  431. {
  432. polarssl_fprintf( stderr,
  433. "Current use: %u blocks / %u bytes, max: %u blocks / "
  434. "%u bytes (total %u bytes), malloc / free: %u / %u\n",
  435. heap.header_count, heap.total_used,
  436. heap.maximum_header_count, heap.maximum_used,
  437. heap.maximum_header_count * sizeof( memory_header )
  438. + heap.maximum_used,
  439. heap.malloc_count, heap.free_count );
  440. if( heap.first->next == NULL )
  441. polarssl_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
  442. else
  443. {
  444. polarssl_fprintf( stderr, "Memory currently allocated:\n" );
  445. debug_chain();
  446. }
  447. }
  448. #endif /* POLARSSL_MEMORY_DEBUG */
  449. #if defined(POLARSSL_THREADING_C)
  450. static void *buffer_alloc_malloc_mutexed( size_t len )
  451. {
  452. void *buf;
  453. polarssl_mutex_lock( &heap.mutex );
  454. buf = buffer_alloc_malloc( len );
  455. polarssl_mutex_unlock( &heap.mutex );
  456. return( buf );
  457. }
  458. static void buffer_alloc_free_mutexed( void *ptr )
  459. {
  460. polarssl_mutex_lock( &heap.mutex );
  461. buffer_alloc_free( ptr );
  462. polarssl_mutex_unlock( &heap.mutex );
  463. }
  464. #endif /* POLARSSL_THREADING_C */
  465. int memory_buffer_alloc_init( unsigned char *buf, size_t len )
  466. {
  467. memset( &heap, 0, sizeof(buffer_alloc_ctx) );
  468. memset( buf, 0, len );
  469. #if defined(POLARSSL_THREADING_C)
  470. polarssl_mutex_init( &heap.mutex );
  471. platform_set_malloc_free( buffer_alloc_malloc_mutexed,
  472. buffer_alloc_free_mutexed );
  473. #else
  474. platform_set_malloc_free( buffer_alloc_malloc, buffer_alloc_free );
  475. #endif
  476. if( (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE )
  477. {
  478. buf += POLARSSL_MEMORY_ALIGN_MULTIPLE
  479. - (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
  480. len -= (size_t) buf % POLARSSL_MEMORY_ALIGN_MULTIPLE;
  481. }
  482. heap.buf = buf;
  483. heap.len = len;
  484. heap.first = (memory_header *) buf;
  485. heap.first->size = len - sizeof(memory_header);
  486. heap.first->magic1 = MAGIC1;
  487. heap.first->magic2 = MAGIC2;
  488. heap.first_free = heap.first;
  489. return( 0 );
  490. }
  491. void memory_buffer_alloc_free()
  492. {
  493. #if defined(POLARSSL_THREADING_C)
  494. polarssl_mutex_free( &heap.mutex );
  495. #endif
  496. polarssl_zeroize( &heap, sizeof(buffer_alloc_ctx) );
  497. }
  498. #endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */