Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: tests/dynamic_code_loading/dynamic_modify_test.c

Issue 5738003: Resurrect Petr's 64-bit dynamic code modification CL:... (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tests/dynamic_code_loading/dynamic_load_test.c ('k') | tests/dynamic_code_loading/nacl.scons » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <stdio.h> 9 #include <stdio.h>
10 #include <stdint.h>
10 #include <stdlib.h> 11 #include <stdlib.h>
11 #include <string.h> 12 #include <string.h>
12 #include <sys/mman.h> 13 #include <sys/mman.h>
13 14
14 #include <sys/nacl_syscalls.h> 15 #include <sys/nacl_syscalls.h>
15 16
16 #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"
19
20 #if defined(__x86_64__)
21 #define BUF_SIZE 64
22 #else
23 #define BUF_SIZE 32
24 #endif
17 25
18 #define NACL_BUNDLE_SIZE 32 26 #define NACL_BUNDLE_SIZE 32
19 /* 27 /*
20 * TODO(bsy): get this value from the toolchain. Get the toolchain 28 * TODO(bsy): get this value from the toolchain. Get the toolchain
21 * team to provide this value. 29 * team to provide this value.
22 */ 30 */
23 #define NUM_BUNDLES_FOR_HLT 3 31 #define NUM_BUNDLES_FOR_HLT 3
24 32
25 /* TODO(mseaborn): Add a symbol to the linker script for finding the 33 /* TODO(mseaborn): Add a symbol to the linker script for finding the
26 end of the static code segment more accurately. The value below is 34 end of the static code segment more accurately. The value below is
27 an approximation. */ 35 an approximation. */
28 #define DYNAMIC_CODE_SEGMENT_START 0x80000 36 #define DYNAMIC_CODE_SEGMENT_START 0x80000
29 /* TODO(mseaborn): Add a symbol to the linker script for finding the 37 /* TODO(mseaborn): Add a symbol to the linker script for finding the
30 end of the dynamic code region. The value below is duplicated in 38 end of the dynamic code region. The value below is duplicated in
31 nacl.scons, passed via --section-start. */ 39 nacl.scons, passed via --section-start. */
32 #define DYNAMIC_CODE_SEGMENT_END 0x1000000 40 #define DYNAMIC_CODE_SEGMENT_END 0x1000000
33 41
42 struct code_section {
43 char *name;
44 char *start;
45 char *end;
46 };
34 47
35 char *next_addr = (char *) DYNAMIC_CODE_SEGMENT_START; 48 struct code_section illegal_code_sections[] = {
49 { "misaligned_replacement",
50 &template_func_misaligned_replacement,
51 &template_func_misaligned_replacement_end },
52 { "illegal_register_replacement",
53 &template_func_illegal_register_replacement,
54 &template_func_illegal_register_replacement_end },
55 { "illegal_guard_replacement",
56 &template_func_illegal_guard_replacement,
57 &template_func_illegal_guard_replacement_end },
58 { "illegal_call_target",
59 &template_func_illegal_call_target,
60 &template_func_illegal_call_target_end },
61 { "illegal_constant_replacement",
62 &template_func_illegal_constant_replacement,
63 &template_func_illegal_constant_replacement_end },
64 };
36 65
37 char *allocate_code_space(int pages) { 66 uint8_t *next_addr = (uint8_t *) DYNAMIC_CODE_SEGMENT_START;
38 char *addr = next_addr; 67
68 uint8_t *allocate_code_space(int pages) {
69 uint8_t *addr = next_addr;
39 next_addr += 0x10000 * pages; 70 next_addr += 0x10000 * pages;
40 assert(next_addr < (char *) DYNAMIC_CODE_SEGMENT_END); 71 assert(next_addr < (uint8_t *) DYNAMIC_CODE_SEGMENT_END);
41 return addr; 72 return addr;
42 } 73 }
43 74
44 void fill_int32(uint8_t *data, size_t size, int32_t value) { 75 void fill_int32(uint8_t *data, size_t size, int32_t value) {
45 int i; 76 int i;
46 assert(size % 4 == 0); 77 assert(size % 4 == 0);
47 /* All the archs we target supported unaligned word read/write, but 78 /* All the archs we target supported unaligned word read/write, but
48 check that the pointer is aligned anyway. */ 79 check that the pointer is aligned anyway. */
49 assert(((uintptr_t) data) % 4 == 0); 80 assert(((uintptr_t) data) % 4 == 0);
50 for (i = 0; i < size / 4; i++) 81 for (i = 0; i < size / 4; i++)
(...skipping 14 matching lines...) Expand all
65 awkward because we have to output them in data mode, in which the 96 awkward because we have to output them in data mode, in which the
66 assembler wants to output zeroes instead of NOPs for padding. 97 assembler wants to output zeroes instead of NOPs for padding.
67 Also, the assembler won't put in a terminating HLT, which we need 98 Also, the assembler won't put in a terminating HLT, which we need
68 on x86-32. So we do the padding at run time. */ 99 on x86-32. So we do the padding at run time. */
69 void copy_and_pad_fragment(void *dest, 100 void copy_and_pad_fragment(void *dest,
70 int dest_size, 101 int dest_size,
71 const char *fragment_start, 102 const char *fragment_start,
72 const char *fragment_end) { 103 const char *fragment_end) {
73 int fragment_size = fragment_end - fragment_start; 104 int fragment_size = fragment_end - fragment_start;
74 assert(dest_size % 32 == 0); 105 assert(dest_size % 32 == 0);
75 assert(fragment_size < dest_size); 106 assert(fragment_size <= dest_size);
76 fill_nops(dest, dest_size); 107 fill_nops(dest, dest_size);
77 memcpy(dest, fragment_start, fragment_size); 108 memcpy(dest, fragment_start, fragment_size);
78 } 109 }
79 110
80 /* Check that we can't dynamically rewrite code. */ 111 /* Check that we can't dynamically rewrite code. */
81 void test_replacing_code() { 112 void test_replacing_code() {
82 uint8_t *load_area = allocate_code_space(1); 113 uint8_t *load_area = allocate_code_space(1);
83 uint8_t buf[32]; 114 uint8_t buf[BUF_SIZE];
84 int rc; 115 int rc;
85 int (*func)(); 116 int (*func)();
86 117
87 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 118 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
88 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 119 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
89 assert(rc == 0); 120 assert(rc == 0);
90 func = (int (*)()) (uintptr_t) load_area; 121 func = (int (*)()) (uintptr_t) load_area;
91 rc = func(); 122 rc = func();
92 assert(rc == 1234); 123 assert(rc == 1234);
93 124
94 /* write replacement to the same location */ 125 /* write replacement to the same location */
95 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 126 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
96 &template_func_replacement_end); 127 &template_func_replacement_end);
97 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf)); 128 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf));
98 assert(rc == 0); 129 assert(rc == 0);
99 func = (int (*)()) (uintptr_t) load_area; 130 func = (int (*)()) (uintptr_t) load_area;
100 rc = func(); 131 rc = func();
101 assert(rc == 4321); 132 assert(rc == 4321);
102 } 133 }
103 134
104 135
105 /* Check that we can dynamically rewrite code. */ 136 /* Check that we can dynamically rewrite code. */
106 void test_replacing_code_unaligned() { 137 void test_replacing_code_unaligned() {
107 uint8_t *load_area = allocate_code_space(1); 138 uint8_t *load_area = allocate_code_space(1);
108 uint8_t buf[32]; 139 uint8_t buf[BUF_SIZE];
109 int first_diff = 0; 140 int first_diff = 0;
110 int rc; 141 int rc;
111 int (*func)(); 142 int (*func)();
112 143
113 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 144 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
114 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 145 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
115 assert(rc == 0); 146 assert(rc == 0);
116 func = (int (*)()) (uintptr_t) load_area; 147 func = (int (*)()) (uintptr_t) load_area;
117 rc = func(); 148 rc = func();
118 assert(rc == 1234); 149 assert(rc == 1234);
119 150
120
121 /* write replacement to the same location, unaligned */ 151 /* write replacement to the same location, unaligned */
122 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 152 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
123 &template_func_replacement_end); 153 &template_func_replacement_end);
124 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) { 154 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) {
125 first_diff++; 155 first_diff++;
126 } 156 }
127 assert(first_diff>0); 157 assert(first_diff > 0 && first_diff <= sizeof(buf));
128 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff, 158 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff,
129 sizeof(buf)-first_diff); 159 sizeof(buf)-first_diff);
130 assert(rc == 0); 160 assert(rc == 0);
131 func = (int (*)()) (uintptr_t) load_area; 161 func = (int (*)()) (uintptr_t) load_area;
132 rc = func(); 162 rc = func();
133 assert(rc == 4321); 163 assert(rc == 4321);
134 } 164 }
135 165
136 /* Check that we can dynamically delete code. */ 166 /* Check that we can dynamically delete code. */
137 void test_deleting_code() { 167 void test_deleting_code() {
138 uint8_t *load_area = allocate_code_space(1); 168 uint8_t *load_area = allocate_code_space(1);
139 uint8_t buf[32]; 169 uint8_t buf[BUF_SIZE];
140 int first_diff = 0;
141 int rc; 170 int rc;
142 int (*func)(); 171 int (*func)();
143 172
144 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 173 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
145 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 174 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
146 assert(rc == 0); 175 assert(rc == 0);
147 func = (int (*)()) (uintptr_t) load_area; 176 func = (int (*)()) (uintptr_t) load_area;
148 rc = func(); 177 rc = func();
149 assert(rc == 1234); 178 assert(rc == 1234);
150 179
151 rc = nacl_dyncode_delete(load_area, sizeof buf); 180 rc = nacl_dyncode_delete(load_area, sizeof buf);
152 assert(rc == 0); 181 assert(rc == 0);
153 assert(load_area[0] != buf[0]); 182 assert(load_area[0] != buf[0]);
154 } 183 }
155 184
185 /* Check code replacement constraints */
186 void test_illegal_code_replacment() {
187 uint8_t *load_area = allocate_code_space(1);
188 uint8_t buf[BUF_SIZE];
189 int rc;
190 int i;
191 int (*func)();
192
193 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
194 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
195 assert(rc == 0);
196 func = (int (*)()) (uintptr_t) load_area;
197 rc = func();
198 assert(rc == 1234);
199
200 for (i = 0;
201 i < (sizeof(illegal_code_sections) / sizeof(struct code_section));
202 i++) {
203 printf("\t%s\n", illegal_code_sections[i].name);
204
205 /* write illegal replacement to the same location */
206 copy_and_pad_fragment(buf, sizeof(buf), illegal_code_sections[i].start,
207 illegal_code_sections[i].end);
208 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf));
209 assert(rc != 0);
210 func = (int (*)()) (uintptr_t) load_area;
211 rc = func();
212 assert(rc == 1234);
213 }
214 }
156 215
157 /* Check that we can't dynamically rewrite code. */ 216 /* Check that we can't dynamically rewrite code. */
158 void test_replacing_code_disabled() { 217 void test_replacing_code_disabled() {
159 uint8_t *load_area = allocate_code_space(1); 218 uint8_t *load_area = allocate_code_space(1);
160 uint8_t buf[32]; 219 uint8_t buf[BUF_SIZE];
161 int rc; 220 int rc;
162 int (*func)(); 221 int (*func)();
163 222
164 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 223 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
165 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 224 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
166 assert(rc == 0); 225 assert(rc == 0);
167 func = (int (*)()) (uintptr_t) load_area; 226 func = (int (*)()) (uintptr_t) load_area;
168 rc = func(); 227 rc = func();
169 assert(rc == 1234); 228 assert(rc == 1234);
170 229
171 /* write replacement to the same location */ 230 /* write replacement to the same location */
172 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 231 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
173 &template_func_replacement_end); 232 &template_func_replacement_end);
174 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf)); 233 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf));
175 assert(rc != 0); 234 assert(rc != 0);
176 func = (int (*)()) (uintptr_t) load_area; 235 func = (int (*)()) (uintptr_t) load_area;
177 rc = func(); 236 rc = func();
178 assert(rc == 1234); 237 assert(rc == 1234);
179 } 238 }
180 239
181 /* Check that we can dynamically rewrite code. */ 240 /* Check that we can dynamically rewrite code. */
182 void test_replacing_code_unaligned_disabled() { 241 void test_replacing_code_unaligned_disabled() {
183 uint8_t *load_area = allocate_code_space(1); 242 uint8_t *load_area = allocate_code_space(1);
184 uint8_t buf[32]; 243 uint8_t buf[BUF_SIZE];
185 int first_diff = 0; 244 int first_diff = 0;
186 int rc; 245 int rc;
187 int (*func)(); 246 int (*func)();
188 247
189 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 248 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
190 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 249 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
191 assert(rc == 0); 250 assert(rc == 0);
192 func = (int (*)()) (uintptr_t) load_area; 251 func = (int (*)()) (uintptr_t) load_area;
193 rc = func(); 252 rc = func();
194 assert(rc == 1234); 253 assert(rc == 1234);
195 254
196 /* write replacement to the same location, unaligned */ 255 /* write replacement to the same location, unaligned */
197 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 256 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
198 &template_func_replacement_end); 257 &template_func_replacement_end);
199 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) { 258 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) {
200 first_diff++; 259 first_diff++;
201 } 260 }
202 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff, 261 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff,
203 sizeof(buf)-first_diff); 262 sizeof(buf)-first_diff);
204 assert(rc != 0); 263 assert(rc != 0);
205 func = (int (*)()) (uintptr_t) load_area; 264 func = (int (*)()) (uintptr_t) load_area;
206 rc = func(); 265 rc = func();
207 assert(rc == 1234); 266 assert(rc == 1234);
208 } 267 }
209 268
210 269
211 /* Check that we can't delete code */ 270 /* Check that we can't delete code */
212 void test_deleting_code_disabled() { 271 void test_deleting_code_disabled() {
213 uint8_t *load_area = allocate_code_space(1); 272 uint8_t *load_area = allocate_code_space(1);
214 uint8_t buf[32]; 273 uint8_t buf[BUF_SIZE];
215 int first_diff = 0;
216 int rc; 274 int rc;
217 int (*func)(); 275 int (*func)();
218 276
219 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 277 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
220 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 278 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
221 assert(rc == 0); 279 assert(rc == 0);
222 func = (int (*)()) (uintptr_t) load_area; 280 func = (int (*)()) (uintptr_t) load_area;
223 rc = func(); 281 rc = func();
224 assert(rc == 1234); 282 assert(rc == 1234);
225 283
226 rc = nacl_dyncode_delete(load_area, sizeof buf); 284 rc = nacl_dyncode_delete(load_area, sizeof buf);
227 assert(rc != 0); 285 assert(rc != 0);
228 assert(load_area[0] == buf[0]); 286 assert(load_area[0] == buf[0]);
229 } 287 }
230 288
231 void run_test(const char *test_name, void (*test_func)(void)) { 289 void run_test(const char *test_name, void (*test_func)(void)) {
232 printf("Running %s...\n", test_name); 290 printf("Running %s...\n", test_name);
233 test_func(); 291 test_func();
234 } 292 }
235 293
236 int is_replacement_enabled() { 294 int is_replacement_enabled() {
237 char trash; 295 char trash;
238 return (0 == nacl_dyncode_modify(allocate_code_space(1), &trash, 0)); 296 return (0 == nacl_dyncode_modify(allocate_code_space(1), &trash, 0));
239 } 297 }
240 298
241 #define RUN_TEST(test_func) (run_test(#test_func, test_func)) 299 #define RUN_TEST(test_func) (run_test(#test_func, test_func))
242 300
243 int main() { 301 int TestMain() {
244 /* Turn off stdout buffering to aid debugging in case of a crash. */ 302 /* Turn off stdout buffering to aid debugging in case of a crash. */
245 setvbuf(stdout, NULL, _IONBF, 0); 303 setvbuf(stdout, NULL, _IONBF, 0);
246 304
247 if (is_replacement_enabled()) { 305 if (is_replacement_enabled()) {
248 printf("Code replacement ENABLED\n"); 306 printf("Code replacement ENABLED\n");
249 RUN_TEST(test_replacing_code); 307 RUN_TEST(test_replacing_code);
250 RUN_TEST(test_replacing_code_unaligned); 308 RUN_TEST(test_replacing_code_unaligned);
251 RUN_TEST(test_deleting_code); 309 RUN_TEST(test_deleting_code);
310 RUN_TEST(test_illegal_code_replacment);
252 } else { 311 } else {
253 printf("Code replacement DISABLED\n"); 312 printf("Code replacement DISABLED\n");
254 RUN_TEST(test_replacing_code_disabled); 313 RUN_TEST(test_replacing_code_disabled);
255 RUN_TEST(test_replacing_code_unaligned_disabled); 314 RUN_TEST(test_replacing_code_unaligned_disabled);
256 RUN_TEST(test_deleting_code_disabled); 315 RUN_TEST(test_deleting_code_disabled);
257 } 316 }
258 317
259 return 0; 318 return 0;
260 } 319 }
261 320
321 int main() {
322 return RunTests(TestMain);
323 }
324
OLDNEW
« no previous file with comments | « tests/dynamic_code_loading/dynamic_load_test.c ('k') | tests/dynamic_code_loading/nacl.scons » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698