123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- # This file is part of asmc, a bootstrapping OS with minimal seed
- # Copyright (C) 2018 Giovanni Mascellani <gio@debian.org>
- # https://gitlab.com/giomasce/asmc
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- const MALLOC_MAX_NUM 100000
- const MALLOC_GUARD_SIZE 32
- const MALLOC_GUARD_BYTE 0xd4
- const MALLOC_GARBAGE_BYTE 0x5c
- $malloc_data
- $malloc_num
- fun _malloc_init 0 {
- if malloc_data 0 == {
- @malloc_data MALLOC_MAX_NUM 16 * platform_allocate = ;
- }
- }
- fun malloc 1 {
- $size
- @size 0 param = ;
- _malloc_init ;
- # Add two guards
- $alloc_size
- @alloc_size size MALLOC_GUARD_SIZE + MALLOC_GUARD_SIZE + = ;
- # Get memory from platform
- $ptr
- @ptr alloc_size platform_allocate = ;
- ptr 1024 1024 * 100 * < "check_malloc: too much alloc" assert_msg ;
- # Compute useful pointers
- $buf_begin
- $buf_end
- $ptr_end
- @buf_begin ptr MALLOC_GUARD_SIZE + = ;
- @buf_end buf_begin size + = ;
- @ptr_end buf_end MALLOC_GUARD_SIZE + = ;
- # Bookkeeping
- malloc_num MALLOC_MAX_NUM < "malloc: too many mallocations" assert_msg ;
- malloc_data malloc_num 16 * + size = ;
- malloc_data malloc_num 16 * + 4 + buf_begin = ;
- malloc_data malloc_num 16 * + 8 + 0 = ;
- malloc_data malloc_num 16 * + 12 + __frame_ptr 4 + ** = ;
- @malloc_num malloc_num 1 + = ;
- # Debug
- # "malloc: " log ;
- # ptr itoa log ;
- # " / " log ;
- # buf_begin itoa log ;
- # " / " log ;
- # buf_end itoa log ;
- # " / " log ;
- # ptr_end itoa log ;
- # "\n" log ;
- # Fill the guards with the guard byte
- ptr MALLOC_GUARD_BYTE MALLOC_GUARD_SIZE memset ;
- buf_end MALLOC_GUARD_BYTE MALLOC_GUARD_SIZE memset ;
- # Fill the allocated zone with garbage bytes, so that the program does not depend on it being nulled
- buf_begin MALLOC_GARBAGE_BYTE size memset ;
- buf_begin ret ;
- }
- fun _malloc_find_index 1 {
- $ptr
- @ptr 0 param = ;
- $i
- @i 0 = ;
- while i malloc_num < {
- if malloc_data i 16 * + 4 + ** ptr == {
- i ret ;
- }
- @i i 1 + = ;
- }
- "Unallocated address: " log ;
- ptr itoa log ;
- "\n" log ;
- 0 "_malloc_find_index: requested memory region was not allocated" assert_msg ;
- }
- fun free 1 {
- $buf_begin
- @buf_begin 0 param = ;
- if buf_begin 0 == {
- ret ;
- }
- # Find the allocation index
- $i
- @i buf_begin _malloc_find_index = ;
- # Check the region is allocated and mark it as allocated
- malloc_data i 16 * + 8 + ** 0 == "free: double free" assert_msg ;
- malloc_data i 16 * + 8 + 1 = ;
- $size
- @size malloc_data i 16 * + ** = ;
- # Compute useful pointers
- $ptr
- $buf_end
- $ptr_end
- @ptr buf_begin MALLOC_GUARD_SIZE - = ;
- @buf_end buf_begin size + = ;
- @ptr_end buf_end MALLOC_GUARD_SIZE + = ;
- # Debug
- # "free: " log ;
- # ptr itoa log ;
- # " / " log ;
- # buf_begin itoa log ;
- # " / " log ;
- # buf_end itoa log ;
- # " / " log ;
- # ptr_end itoa log ;
- # "\n" log ;
- # Check the guard zones have not been touched
- ptr MALLOC_GUARD_BYTE MALLOC_GUARD_SIZE memcheck "free: leading guard zone has been touched" assert_msg ;
- buf_end MALLOC_GUARD_BYTE MALLOC_GUARD_SIZE memcheck "free: trailing guard zone has been touched" assert_msg ;
- # Fill the allocated zone with guard bytes, to protect against use-after-free
- buf_begin MALLOC_GUARD_BYTE size memset ;
- }
- fun _malloc_get_size 1 {
- $ptr
- @ptr 0 param = ;
- $i
- @i ptr _malloc_find_index = ;
- malloc_data i 16 * + ** ret ;
- }
- fun malloc_stats 0 {
- $i
- @i 0 = ;
- $non_freed
- @non_freed 0 = ;
- $total_size
- @total_size 0 = ;
- $non_freed_size
- @non_freed_size 0 = ;
- while i malloc_num < {
- $size
- $buf_begin
- $freed
- @size malloc_data i 16 * + ** = ;
- @buf_begin malloc_data i 16 * + 4 + ** = ;
- @freed malloc_data i 16 * + 8 + ** = ;
- # Compute useful pointers
- $ptr
- $buf_end
- $ptr_end
- @ptr buf_begin MALLOC_GUARD_SIZE - = ;
- @buf_end buf_begin size + = ;
- @ptr_end buf_end MALLOC_GUARD_SIZE + = ;
- freed 0 == freed 1 == || "malloc_stats: malloc data corruption" assert_msg ;
- # Count regions that were never freed
- if freed ! {
- @non_freed non_freed 1 + = ;
- @non_freed_size non_freed_size size + = ;
- }
- @total_size total_size size + = ;
- # Check that nothing was touched after free
- if freed {
- ptr MALLOC_GUARD_BYTE MALLOC_GUARD_SIZE memcheck "malloc_stats: leading guard zone has been touched after free" assert_msg ;
- buf_end MALLOC_GUARD_BYTE MALLOC_GUARD_SIZE memcheck "malloc_stats: trailing guard zone has been touched after free" assert_msg ;
- buf_begin MALLOC_GUARD_BYTE size memcheck "malloc_stats: memory region has been touched after free" assert_msg ;
- }
- @i i 1 + = ;
- }
- "The program did " log ;
- malloc_num itoa log ;
- " allocations (totalling " log ;
- total_size itoa log ;
- " bytes); " log ;
- non_freed itoa log ;
- " of them were never free-ed (totalling " log ;
- non_freed_size itoa log ;
- " bytes).\n" log ;
- }
|