| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2010 The Native Client Authors. All rights reserved. | 2 * Copyright 2010 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can | 3 * Use of this source code is governed by a BSD-style license that can |
| 4 * be found in the LICENSE file. | 4 * be found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <assert.h> | 7 #include <assert.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| 11 #include <stdlib.h> | 11 #include <stdlib.h> |
| 12 #include <string.h> | 12 #include <string.h> |
| 13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
| 14 | 14 |
| 15 #include <sys/nacl_syscalls.h> | 15 #include <sys/nacl_syscalls.h> |
| 16 | 16 |
| 17 #include "native_client/tests/dynamic_code_loading/templates.h" | 17 #include "native_client/tests/dynamic_code_loading/templates.h" |
| 18 #include "native_client/tests/inbrowser_test_runner/test_runner.h" | 18 #include "native_client/tests/inbrowser_test_runner/test_runner.h" |
| 19 | 19 |
| 20 #if defined(__x86_64__) |
| 21 /* On x86-64, template functions do not fit in 32-byte buffers */ |
| 22 #define BUF_SIZE 64 |
| 23 #elif defined(__i386__) || defined(__arm__) |
| 24 #define BUF_SIZE 32 |
| 25 #else |
| 26 #error "Unknown Platform" |
| 27 #endif |
| 28 |
| 29 #if defined(__i386__) || defined(__x86_64__) |
| 20 #define NACL_BUNDLE_SIZE 32 | 30 #define NACL_BUNDLE_SIZE 32 |
| 31 #elif defined(__arm__) |
| 32 #define NACL_BUNDLE_SIZE 16 |
| 33 #else |
| 34 #error "Unknown Platform" |
| 35 #endif |
| 36 |
| 21 /* | 37 /* |
| 22 * TODO(bsy): get this value from the toolchain. Get the toolchain | 38 * TODO(bsy): get this value from the toolchain. Get the toolchain |
| 23 * team to provide this value. | 39 * team to provide this value. |
| 24 */ | 40 */ |
| 25 #define NUM_BUNDLES_FOR_HLT 3 | 41 #define NUM_BUNDLES_FOR_HLT 3 |
| 26 | 42 |
| 27 /* | 43 /* |
| 28 * This is an address that is well into the dynamic code region and page | 44 * This is an address that is well into the dynamic code region and page |
| 29 * aligned. There is a test below specifically for installing a function | 45 * aligned. There is a test below specifically for installing a function |
| 30 * at the very beginning of the dynamic code region. | 46 * at the very beginning of the dynamic code region. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 /* Getting the assembler to pad our code fragments in templates.S is | 102 /* Getting the assembler to pad our code fragments in templates.S is |
| 87 awkward because we have to output them in data mode, in which the | 103 awkward because we have to output them in data mode, in which the |
| 88 assembler wants to output zeroes instead of NOPs for padding. | 104 assembler wants to output zeroes instead of NOPs for padding. |
| 89 Also, the assembler won't put in a terminating HLT, which we need | 105 Also, the assembler won't put in a terminating HLT, which we need |
| 90 on x86-32. So we do the padding at run time. */ | 106 on x86-32. So we do the padding at run time. */ |
| 91 void copy_and_pad_fragment(void *dest, | 107 void copy_and_pad_fragment(void *dest, |
| 92 int dest_size, | 108 int dest_size, |
| 93 const char *fragment_start, | 109 const char *fragment_start, |
| 94 const char *fragment_end) { | 110 const char *fragment_end) { |
| 95 int fragment_size = fragment_end - fragment_start; | 111 int fragment_size = fragment_end - fragment_start; |
| 96 assert(dest_size % 32 == 0); | 112 assert(dest_size % NACL_BUNDLE_SIZE == 0); |
| 97 assert(fragment_size < dest_size); | 113 assert(fragment_size <= dest_size); |
| 98 fill_nops(dest, dest_size); | 114 fill_nops(dest, dest_size); |
| 99 memcpy(dest, fragment_start, fragment_size); | 115 memcpy(dest, fragment_start, fragment_size); |
| 100 } | 116 } |
| 101 | 117 |
| 102 /* Check that we can load and run code. */ | 118 /* Check that we can load and run code. */ |
| 103 void test_loading_code() { | 119 void test_loading_code() { |
| 104 void *load_area = allocate_code_space(1); | 120 void *load_area = allocate_code_space(1); |
| 105 uint8_t buf[32]; | 121 uint8_t buf[BUF_SIZE]; |
| 106 int rc; | 122 int rc; |
| 107 int (*func)(); | 123 int (*func)(); |
| 108 | 124 |
| 109 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 125 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
| 110 | 126 |
| 111 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 127 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
| 112 assert(rc == 0); | 128 assert(rc == 0); |
| 113 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 129 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
| 114 /* Need double cast otherwise gcc complains with "ISO C forbids | 130 /* Need double cast otherwise gcc complains with "ISO C forbids |
| 115 conversion of object pointer to function pointer type | 131 conversion of object pointer to function pointer type |
| 116 [-pedantic]". */ | 132 [-pedantic]". */ |
| 117 func = (int (*)()) (uintptr_t) load_area; | 133 func = (int (*)()) (uintptr_t) load_area; |
| 118 rc = func(); | 134 rc = func(); |
| 119 assert(rc == 1234); | 135 assert(rc == 1234); |
| 120 } | 136 } |
| 121 | 137 |
| 122 /* The syscall may have to mmap() shared memory temporarily, | 138 /* The syscall may have to mmap() shared memory temporarily, |
| 123 so there is some interaction with page size. | 139 so there is some interaction with page size. |
| 124 Check that we can load to non-page-aligned addresses. */ | 140 Check that we can load to non-page-aligned addresses. */ |
| 125 void test_loading_code_non_page_aligned() { | 141 void test_loading_code_non_page_aligned() { |
| 126 char *load_area = allocate_code_space(1); | 142 char *load_area = allocate_code_space(1); |
| 127 uint8_t buf[32]; | 143 uint8_t buf[BUF_SIZE]; |
| 128 int rc; | 144 int rc; |
| 129 | 145 |
| 130 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 146 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
| 131 | 147 |
| 132 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 148 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
| 133 assert(rc == 0); | 149 assert(rc == 0); |
| 134 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 150 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
| 135 | 151 |
| 136 load_area += 32; | 152 load_area += sizeof(buf); |
| 137 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 153 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
| 138 assert(rc == 0); | 154 assert(rc == 0); |
| 139 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 155 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
| 140 } | 156 } |
| 141 | 157 |
| 142 /* Since there is an interaction with page size, we also test loading | 158 /* Since there is an interaction with page size, we also test loading |
| 143 a multi-page chunk of code. */ | 159 a multi-page chunk of code. */ |
| 144 void test_loading_large_chunk() { | 160 void test_loading_large_chunk() { |
| 145 char *load_area = allocate_code_space(2); | 161 char *load_area = allocate_code_space(2); |
| 146 int size = 0x20000; | 162 int size = 0x20000; |
| 147 uint8_t *data = alloca(size); | 163 uint8_t *data = alloca(size); |
| 148 int rc; | 164 int rc; |
| 149 | 165 |
| 150 fill_nops(data, size); | 166 fill_nops(data, size); |
| 151 rc = nacl_load_code(load_area, data, size); | 167 rc = nacl_load_code(load_area, data, size); |
| 152 assert(rc == 0); | 168 assert(rc == 0); |
| 153 assert(memcmp(load_area, data, size) == 0); | 169 assert(memcmp(load_area, data, size) == 0); |
| 154 } | 170 } |
| 155 | 171 |
| 156 void test_loading_zero_size() { | 172 void test_loading_zero_size() { |
| 157 char *load_area = allocate_code_space(1); | 173 char *load_area = allocate_code_space(1); |
| 158 int rc = nacl_load_code(load_area, &template_func, 0); | 174 int rc = nacl_load_code(load_area, &template_func, 0); |
| 159 assert(rc == 0); | 175 assert(rc == 0); |
| 160 } | 176 } |
| 161 | 177 |
| 162 /* Check that we can load code at the very beginning of the dynamic section. */ | 178 /* Check that we can load code at the very beginning of the dynamic section. */ |
| 163 void test_loading_code_on_first_dynamic_page() { | 179 void test_loading_code_on_first_dynamic_page() { |
| 164 const unsigned int kPageMask = 0xFFFF; | 180 const unsigned int kPageMask = 0xFFFF; |
| 165 void *load_area = (void*)((uintptr_t)(etext + kPageMask) & ~kPageMask); | 181 void *load_area = (void*)((uintptr_t)(etext + kPageMask) & ~kPageMask); |
| 166 uint8_t buf[32]; | 182 uint8_t buf[BUF_SIZE]; |
| 167 int rc; | 183 int rc; |
| 168 int (*func)(); | 184 int (*func)(); |
| 169 | 185 |
| 170 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 186 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
| 171 | 187 |
| 172 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 188 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
| 173 assert(rc == 0); | 189 assert(rc == 0); |
| 174 assert(memcmp(load_area, buf, sizeof(buf)) == 0); | 190 assert(memcmp(load_area, buf, sizeof(buf)) == 0); |
| 175 /* Need double cast otherwise gcc complains with "ISO C forbids | 191 /* Need double cast otherwise gcc complains with "ISO C forbids |
| 176 conversion of object pointer to function pointer type | 192 conversion of object pointer to function pointer type |
| 177 [-pedantic]". */ | 193 [-pedantic]". */ |
| 178 func = (int (*)()) (uintptr_t) load_area; | 194 func = (int (*)()) (uintptr_t) load_area; |
| 179 rc = func(); | 195 rc = func(); |
| 180 assert(rc == 1234); | 196 assert(rc == 1234); |
| 181 } | 197 } |
| 182 | 198 |
| 183 /* In general, the failure tests don't check that loading fails for | 199 /* In general, the failure tests don't check that loading fails for |
| 184 the reason we expect. TODO(mseaborn): We could do this by | 200 the reason we expect. TODO(mseaborn): We could do this by |
| 185 comparing with expected log output. */ | 201 comparing with expected log output. */ |
| 186 | 202 |
| 187 void test_fail_on_validation_error() { | 203 void test_fail_on_validation_error() { |
| 188 void *load_area = allocate_code_space(1); | 204 void *load_area = allocate_code_space(1); |
| 189 uint8_t buf[32]; | 205 uint8_t buf[BUF_SIZE]; |
| 190 int rc; | 206 int rc; |
| 191 | 207 |
| 192 copy_and_pad_fragment(buf, sizeof(buf), &invalid_code, &invalid_code_end); | 208 copy_and_pad_fragment(buf, sizeof(buf), &invalid_code, &invalid_code_end); |
| 193 | 209 |
| 194 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 210 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
| 195 assert(rc == -EINVAL); | 211 assert(rc == -EINVAL); |
| 196 } | 212 } |
| 197 | 213 |
| 198 void test_fail_on_non_bundle_aligned_dest_addresses() { | 214 void test_fail_on_non_bundle_aligned_dest_addresses() { |
| 199 char *load_area = allocate_code_space(1); | 215 char *load_area = allocate_code_space(1); |
| 200 int rc; | 216 int rc; |
| 201 uint8_t nops[32]; | 217 uint8_t nops[BUF_SIZE]; |
| 202 | 218 |
| 203 fill_nops(nops, sizeof(nops)); | 219 fill_nops(nops, sizeof(nops)); |
| 204 | 220 |
| 205 /* Test unaligned destination. */ | 221 /* Test unaligned destination. */ |
| 206 rc = nacl_load_code(load_area + 1, nops, 32); | 222 rc = nacl_load_code(load_area + 1, nops, NACL_BUNDLE_SIZE); |
| 207 assert(rc == -EINVAL); | 223 assert(rc == -EINVAL); |
| 208 rc = nacl_load_code(load_area + 4, nops, 32); | 224 rc = nacl_load_code(load_area + 4, nops, NACL_BUNDLE_SIZE); |
| 209 assert(rc == -EINVAL); | 225 assert(rc == -EINVAL); |
| 210 | 226 |
| 211 /* Test unaligned size. */ | 227 /* Test unaligned size. */ |
| 212 rc = nacl_load_code(load_area, nops + 1, 31); | 228 rc = nacl_load_code(load_area, nops + 1, NACL_BUNDLE_SIZE - 1); |
| 213 assert(rc == -EINVAL); | 229 assert(rc == -EINVAL); |
| 214 rc = nacl_load_code(load_area, nops + 4, 28); | 230 rc = nacl_load_code(load_area, nops + 4, NACL_BUNDLE_SIZE - 4); |
| 215 assert(rc == -EINVAL); | 231 assert(rc == -EINVAL); |
| 216 | 232 |
| 217 /* Check that the code we're trying works otherwise. */ | 233 /* Check that the code we're trying works otherwise. */ |
| 218 rc = nacl_load_code(load_area, nops, 32); | 234 rc = nacl_load_code(load_area, nops, NACL_BUNDLE_SIZE); |
| 219 assert(rc == 0); | 235 assert(rc == 0); |
| 220 } | 236 } |
| 221 | 237 |
| 222 /* In principle we could load into the initially-loaded executable's | 238 /* In principle we could load into the initially-loaded executable's |
| 223 code area, but at the moment we don't allow it. */ | 239 code area, but at the moment we don't allow it. */ |
| 224 void test_fail_on_load_to_static_code_area() { | 240 void test_fail_on_load_to_static_code_area() { |
| 225 int size = &hlts_end - &hlts; | 241 int size = &hlts_end - &hlts; |
| 226 int rc = nacl_load_code(&hlts, &hlts, size); | 242 int rc = nacl_load_code(&hlts, &hlts, size); |
| 227 assert(rc == -EFAULT); | 243 assert(rc == -EFAULT); |
| 228 } | 244 } |
| 229 | 245 |
| 230 uint8_t block_in_data_segment[64]; | 246 uint8_t block_in_data_segment[64]; |
| 231 | 247 |
| 232 void test_fail_on_load_to_data_area() { | 248 void test_fail_on_load_to_data_area() { |
| 233 uint8_t *data; | 249 uint8_t *data; |
| 234 int rc; | 250 int rc; |
| 235 | 251 |
| 236 fill_hlts(block_in_data_segment, sizeof(block_in_data_segment)); | 252 fill_hlts(block_in_data_segment, sizeof(block_in_data_segment)); |
| 237 | 253 |
| 238 /* Align to 32 byte boundary so that we don't fail for a reason | 254 /* Align to bundle size so that we don't fail for a reason |
| 239 we're not testing for. */ | 255 we're not testing for. */ |
| 240 data = block_in_data_segment; | 256 data = block_in_data_segment; |
| 241 while (((int) data) % 32 != 0) | 257 while (((int) data) % NACL_BUNDLE_SIZE != 0) |
| 242 data++; | 258 data++; |
| 243 rc = nacl_load_code(data, data, 32); | 259 rc = nacl_load_code(data, data, NACL_BUNDLE_SIZE); |
| 244 assert(rc == -EFAULT); | 260 assert(rc == -EFAULT); |
| 245 } | 261 } |
| 246 | 262 |
| 247 void test_fail_on_overwrite() { | 263 void test_fail_on_overwrite() { |
| 248 void *load_area = allocate_code_space(1); | 264 void *load_area = allocate_code_space(1); |
| 249 uint8_t buf[32]; | 265 uint8_t buf[BUF_SIZE]; |
| 250 int rc; | 266 int rc; |
| 251 | 267 |
| 252 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); | 268 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); |
| 253 | 269 |
| 254 rc = nacl_load_code(load_area, buf, sizeof(buf)); | 270 rc = nacl_load_code(load_area, buf, sizeof(buf)); |
| 255 assert(rc == 0); | 271 assert(rc == 0); |
| 256 | 272 |
| 257 copy_and_pad_fragment(buf, sizeof(buf), &template_func, | 273 copy_and_pad_fragment(buf, sizeof(buf), &template_func, |
| 258 &template_func_end); | 274 &template_func_end); |
| 259 | 275 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 307 |
| 292 rc = nacl_load_code(load_area, &branch_forwards, size); | 308 rc = nacl_load_code(load_area, &branch_forwards, size); |
| 293 assert(rc == 0); | 309 assert(rc == 0); |
| 294 rc = nacl_load_code(load_area + size, &branch_backwards, size); | 310 rc = nacl_load_code(load_area + size, &branch_backwards, size); |
| 295 assert(rc == 0); | 311 assert(rc == 0); |
| 296 } | 312 } |
| 297 | 313 |
| 298 void test_end_of_code_region() { | 314 void test_end_of_code_region() { |
| 299 int rc; | 315 int rc; |
| 300 void *dest; | 316 void *dest; |
| 301 uint8_t data[32]; | 317 uint8_t data[BUF_SIZE]; |
| 302 fill_nops(data, sizeof(data)); | 318 fill_nops(data, sizeof(data)); |
| 303 | 319 |
| 304 /* This tries to load into the data segment, which is definitely not | 320 /* This tries to load into the data segment, which is definitely not |
| 305 allowed. */ | 321 allowed. */ |
| 306 dest = (uint8_t *) DYNAMIC_CODE_SEGMENT_END; | 322 dest = (uint8_t *) DYNAMIC_CODE_SEGMENT_END; |
| 307 rc = nacl_load_code(dest, data, sizeof(data)); | 323 rc = nacl_load_code(dest, data, sizeof(data)); |
| 308 assert(rc == -EFAULT); | 324 assert(rc == -EFAULT); |
| 309 | 325 |
| 310 /* This tries to load into the last bundle of the code region, which | 326 /* This tries to load into the last bundle of the code region, which |
| 311 sel_ldr disallows just in case there is some CPU bug in which the | 327 sel_ldr disallows just in case there is some CPU bug in which the |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 | 383 |
| 368 /* Test again to make sure we didn't run out of space. */ | 384 /* Test again to make sure we didn't run out of space. */ |
| 369 RUN_TEST(test_loading_code); | 385 RUN_TEST(test_loading_code); |
| 370 | 386 |
| 371 return 0; | 387 return 0; |
| 372 } | 388 } |
| 373 | 389 |
| 374 int main() { | 390 int main() { |
| 375 return RunTests(TestMain); | 391 return RunTests(TestMain); |
| 376 } | 392 } |
| OLD | NEW |