#include #include #include #include #include #include #include #define CHECK(c,m) do{if(!(c)){fprintf(stderr,"FAIL: %s\n",m);return 1;}}while(0) static int page_aligned( const void *p, size_t page ) { return( p != 0 && ( (size_t)p % page ) == 0 ); } int main( void ) { long ps; size_t page; pid_t pid; int status; __mpu_UNIT_t code[3] = { 0x00, 0x00, 0x00 }; __cpu_init(); ps = sysconf( _SC_PAGESIZE ); CHECK( ps > 0, "host page size" ); page = (size_t)ps; CHECK( CPU_ABI_MAX_ALIGN == 16U, "ABI maximum natural alignment" ); CHECK( CPU_ABI_STACK_ALIGN == 16U, "ABI stack alignment" ); CHECK( CPU_ABI_ARGUMENT_BLOCK_ALIGN == 16U, "ABI argument block alignment" ); CHECK( CPU_DATA_NULL_GUARD_SIZE == 16U, "DATA NULL guard size" ); CHECK( CPU_NULL_PTR == __mpu_UINT64_C( 0 ), "NULL PTR64 encoding" ); CHECK( __cpu_data_alloc( 1 ) == 0, "allocate one-byte DATA" ); CHECK( __cpu_data_size() == 1, "DATA architectural size is exact" ); CHECK( page_aligned( __cpu_data_ptr(), page ), "DATA host base is page aligned" ); CHECK( __cpu_data_ptr()[0] == 0, "anonymous DATA mapping is zero-filled" ); __cpu_data_ptr()[0] = 0x5a; CHECK( __cpu_data_ptr()[0] == 0x5a, "DATA mapping is writable" ); CHECK( __cpu_stack_alloc( 1 ) == 0, "allocate one-byte STACK" ); CHECK( __cpu_stack_size() == 1, "STACK architectural size is exact" ); CHECK( page_aligned( __cpu_stack_ptr(), page ), "STACK host base is page aligned" ); CHECK( __cpu_stack_ptr()[0] == 0, "anonymous STACK mapping is zero-filled" ); CHECK( __cpu_sp == 1 && __cpu_fp == 1, "empty STACK uses exact architectural size" ); CHECK( __cpu_program_alloc( sizeof( code ) ) == 0, "allocate PROGRAM for loading" ); CHECK( __cpu_program_size() == sizeof( code ), "PROGRAM architectural size is exact" ); CHECK( page_aligned( __cpu_program_ptr(), page ), "PROGRAM host base is page aligned" ); memcpy( __cpu_program_ptr(), code, sizeof( code ) ); __cpu_program_ptr()[0] = 0x12; /* PROGRAM is writable during image loading. */ CHECK( __cpu_program_ptr()[0] == 0x12, "PROGRAM writable before protect" ); CHECK( __cpu_program_protect() == 0, "protect PROGRAM read-only" ); /* Verify host protection without crashing the test process itself. */ pid = fork(); CHECK( pid >= 0, "fork for PROGRAM protection test" ); if( pid == 0 ) { volatile __mpu_UNIT_t *p = __cpu_program_ptr(); p[0] = 0x34; _exit( 0 ); } CHECK( waitpid( pid, &status, 0 ) == pid, "wait for protection child" ); CHECK( WIFSIGNALED( status ), "PROGRAM host write is trapped" ); CHECK( WTERMSIG( status ) == SIGSEGV || WTERMSIG( status ) == SIGBUS, "PROGRAM write fault signal"); /* Reallocation must unmap the protected image and create a fresh RW mapping. */ CHECK( __cpu_program_alloc( 2 ) == 0, "reallocate PROGRAM after protection" ); CHECK( __cpu_program_size() == 2, "reallocated PROGRAM exact size" ); __cpu_program_ptr()[0] = 0x56; CHECK( __cpu_program_ptr()[0] == 0x56, "new PROGRAM mapping writable for loading" ); __cpu_free_context(); puts( "libcpu anonymous-mmap memory regression: PASS" ); return( 0 ); }