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

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

Powered by Google App Engine
This is Rietveld 408576698