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

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: added test for double-break condition 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 { "illegal_constant_replacement",
61 &template_func_illegal_constant_replacement,
62 &template_func_illegal_constant_replacement_end },
63 };
36 64
37 char *allocate_code_space(int pages) { 65 uint8_t *next_addr = (uint8_t *) DYNAMIC_CODE_SEGMENT_START;
38 char *addr = next_addr; 66
67 uint8_t *allocate_code_space(int pages) {
68 uint8_t *addr = next_addr;
39 next_addr += 0x10000 * pages; 69 next_addr += 0x10000 * pages;
40 assert(next_addr < (char *) DYNAMIC_CODE_SEGMENT_END); 70 assert(next_addr < (uint8_t *) DYNAMIC_CODE_SEGMENT_END);
41 return addr; 71 return addr;
42 } 72 }
43 73
44 void fill_int32(uint8_t *data, size_t size, int32_t value) { 74 void fill_int32(uint8_t *data, size_t size, int32_t value) {
45 int i; 75 int i;
46 assert(size % 4 == 0); 76 assert(size % 4 == 0);
47 /* All the archs we target supported unaligned word read/write, but 77 /* All the archs we target supported unaligned word read/write, but
48 check that the pointer is aligned anyway. */ 78 check that the pointer is aligned anyway. */
49 assert(((uintptr_t) data) % 4 == 0); 79 assert(((uintptr_t) data) % 4 == 0);
50 for (i = 0; i < size / 4; i++) 80 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 95 awkward because we have to output them in data mode, in which the
66 assembler wants to output zeroes instead of NOPs for padding. 96 assembler wants to output zeroes instead of NOPs for padding.
67 Also, the assembler won't put in a terminating HLT, which we need 97 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. */ 98 on x86-32. So we do the padding at run time. */
69 void copy_and_pad_fragment(void *dest, 99 void copy_and_pad_fragment(void *dest,
70 int dest_size, 100 int dest_size,
71 const char *fragment_start, 101 const char *fragment_start,
72 const char *fragment_end) { 102 const char *fragment_end) {
73 int fragment_size = fragment_end - fragment_start; 103 int fragment_size = fragment_end - fragment_start;
74 assert(dest_size % 32 == 0); 104 assert(dest_size % 32 == 0);
75 assert(fragment_size < dest_size); 105 assert(fragment_size <= dest_size);
76 fill_nops(dest, dest_size); 106 fill_nops(dest, dest_size);
77 memcpy(dest, fragment_start, fragment_size); 107 memcpy(dest, fragment_start, fragment_size);
78 } 108 }
79 109
80 /* Check that we can't dynamically rewrite code. */ 110 /* Check that we can't dynamically rewrite code. */
81 void test_replacing_code() { 111 void test_replacing_code() {
82 uint8_t *load_area = allocate_code_space(1); 112 uint8_t *load_area = allocate_code_space(1);
83 uint8_t buf[32]; 113 uint8_t buf[BUF_SIZE];
84 int rc; 114 int rc;
85 int (*func)(); 115 int (*func)();
86 116
87 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 117 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
88 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 118 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
89 assert(rc == 0); 119 assert(rc == 0);
90 func = (int (*)()) (uintptr_t) load_area; 120 func = (int (*)()) (uintptr_t) load_area;
91 rc = func(); 121 rc = func();
92 assert(rc == 1234); 122 assert(rc == 1234);
93 123
94 /* write replacement to the same location */ 124 /* write replacement to the same location */
95 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 125 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
96 &template_func_replacement_end); 126 &template_func_replacement_end);
97 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf)); 127 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf));
98 assert(rc == 0); 128 assert(rc == 0);
99 func = (int (*)()) (uintptr_t) load_area; 129 func = (int (*)()) (uintptr_t) load_area;
100 rc = func(); 130 rc = func();
101 assert(rc == 4321); 131 assert(rc == 4321);
102 } 132 }
103 133
104 134
105 /* Check that we can dynamically rewrite code. */ 135 /* Check that we can dynamically rewrite code. */
106 void test_replacing_code_unaligned() { 136 void test_replacing_code_unaligned() {
107 uint8_t *load_area = allocate_code_space(1); 137 uint8_t *load_area = allocate_code_space(1);
108 uint8_t buf[32]; 138 uint8_t buf[BUF_SIZE];
109 int first_diff = 0; 139 int first_diff = 0;
110 int rc; 140 int rc;
111 int (*func)(); 141 int (*func)();
112 142
113 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 143 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
114 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 144 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
115 assert(rc == 0); 145 assert(rc == 0);
116 func = (int (*)()) (uintptr_t) load_area; 146 func = (int (*)()) (uintptr_t) load_area;
117 rc = func(); 147 rc = func();
118 assert(rc == 1234); 148 assert(rc == 1234);
119 149
120
121 /* write replacement to the same location, unaligned */ 150 /* write replacement to the same location, unaligned */
122 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 151 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
123 &template_func_replacement_end); 152 &template_func_replacement_end);
124 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) { 153 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) {
125 first_diff++; 154 first_diff++;
126 } 155 }
127 assert(first_diff>0); 156 assert(first_diff>0 && first_diff<=sizeof(buf));
bsy 2011/01/05 00:56:22 spaces around <= and >
elijahtaylor (use chromium) 2011/01/05 21:08:48 Fixed.
128 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff, 157 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff,
129 sizeof(buf)-first_diff); 158 sizeof(buf)-first_diff);
130 assert(rc == 0); 159 assert(rc == 0);
131 func = (int (*)()) (uintptr_t) load_area; 160 func = (int (*)()) (uintptr_t) load_area;
132 rc = func(); 161 rc = func();
133 assert(rc == 4321); 162 assert(rc == 4321);
134 } 163 }
135 164
136 /* Check that we can dynamically delete code. */ 165 /* Check that we can dynamically delete code. */
137 void test_deleting_code() { 166 void test_deleting_code() {
138 uint8_t *load_area = allocate_code_space(1); 167 uint8_t *load_area = allocate_code_space(1);
139 uint8_t buf[32]; 168 uint8_t buf[BUF_SIZE];
140 int first_diff = 0;
141 int rc; 169 int rc;
142 int (*func)(); 170 int (*func)();
143 171
144 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 172 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
145 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 173 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
146 assert(rc == 0); 174 assert(rc == 0);
147 func = (int (*)()) (uintptr_t) load_area; 175 func = (int (*)()) (uintptr_t) load_area;
148 rc = func(); 176 rc = func();
149 assert(rc == 1234); 177 assert(rc == 1234);
150 178
151 rc = nacl_dyncode_delete(load_area, sizeof buf); 179 rc = nacl_dyncode_delete(load_area, sizeof buf);
152 assert(rc == 0); 180 assert(rc == 0);
153 assert(load_area[0] != buf[0]); 181 assert(load_area[0] != buf[0]);
154 } 182 }
155 183
184 /* Check code replacement constraints */
185 void test_illegal_code_replacment() {
186 uint8_t *load_area = allocate_code_space(1);
187 uint8_t buf[BUF_SIZE];
188 int rc;
189 int i;
190 int (*func)();
191
192 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
193 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
194 assert(rc == 0);
195 func = (int (*)()) (uintptr_t) load_area;
196 rc = func();
197 assert(rc == 1234);
198
199 for (i = 0;
200 i < (sizeof(illegal_code_sections) / sizeof(struct code_section));
201 i++) {
202 printf("\t%s\n", illegal_code_sections[i].name);
203
204 /* write illegal replacement to the same location */
205 copy_and_pad_fragment(buf, sizeof(buf), illegal_code_sections[i].start,
206 illegal_code_sections[i].end);
207 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf));
208 assert(rc != 0);
209 func = (int (*)()) (uintptr_t) load_area;
210 rc = func();
211 assert(rc == 1234);
212 }
213 }
156 214
157 /* Check that we can't dynamically rewrite code. */ 215 /* Check that we can't dynamically rewrite code. */
158 void test_replacing_code_disabled() { 216 void test_replacing_code_disabled() {
159 uint8_t *load_area = allocate_code_space(1); 217 uint8_t *load_area = allocate_code_space(1);
160 uint8_t buf[32]; 218 uint8_t buf[BUF_SIZE];
161 int rc; 219 int rc;
162 int (*func)(); 220 int (*func)();
163 221
164 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 222 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
165 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 223 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
166 assert(rc == 0); 224 assert(rc == 0);
167 func = (int (*)()) (uintptr_t) load_area; 225 func = (int (*)()) (uintptr_t) load_area;
168 rc = func(); 226 rc = func();
169 assert(rc == 1234); 227 assert(rc == 1234);
170 228
171 /* write replacement to the same location */ 229 /* write replacement to the same location */
172 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 230 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
173 &template_func_replacement_end); 231 &template_func_replacement_end);
174 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf)); 232 rc = nacl_dyncode_modify(load_area, buf, sizeof(buf));
175 assert(rc != 0); 233 assert(rc != 0);
176 func = (int (*)()) (uintptr_t) load_area; 234 func = (int (*)()) (uintptr_t) load_area;
177 rc = func(); 235 rc = func();
178 assert(rc == 1234); 236 assert(rc == 1234);
179 } 237 }
180 238
181 /* Check that we can dynamically rewrite code. */ 239 /* Check that we can dynamically rewrite code. */
182 void test_replacing_code_unaligned_disabled() { 240 void test_replacing_code_unaligned_disabled() {
183 uint8_t *load_area = allocate_code_space(1); 241 uint8_t *load_area = allocate_code_space(1);
184 uint8_t buf[32]; 242 uint8_t buf[BUF_SIZE];
185 int first_diff = 0; 243 int first_diff = 0;
186 int rc; 244 int rc;
187 int (*func)(); 245 int (*func)();
188 246
189 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 247 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
190 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 248 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
191 assert(rc == 0); 249 assert(rc == 0);
192 func = (int (*)()) (uintptr_t) load_area; 250 func = (int (*)()) (uintptr_t) load_area;
193 rc = func(); 251 rc = func();
194 assert(rc == 1234); 252 assert(rc == 1234);
195 253
196 /* write replacement to the same location, unaligned */ 254 /* write replacement to the same location, unaligned */
197 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement, 255 copy_and_pad_fragment(buf, sizeof(buf), &template_func_replacement,
198 &template_func_replacement_end); 256 &template_func_replacement_end);
199 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) { 257 while (buf[first_diff] == load_area[first_diff] && first_diff < sizeof buf) {
200 first_diff++; 258 first_diff++;
201 } 259 }
202 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff, 260 rc = nacl_dyncode_modify(load_area+first_diff, buf+first_diff,
203 sizeof(buf)-first_diff); 261 sizeof(buf)-first_diff);
204 assert(rc != 0); 262 assert(rc != 0);
205 func = (int (*)()) (uintptr_t) load_area; 263 func = (int (*)()) (uintptr_t) load_area;
206 rc = func(); 264 rc = func();
207 assert(rc == 1234); 265 assert(rc == 1234);
208 } 266 }
209 267
210 268
211 /* Check that we can't delete code */ 269 /* Check that we can't delete code */
212 void test_deleting_code_disabled() { 270 void test_deleting_code_disabled() {
213 uint8_t *load_area = allocate_code_space(1); 271 uint8_t *load_area = allocate_code_space(1);
214 uint8_t buf[32]; 272 uint8_t buf[BUF_SIZE];
215 int first_diff = 0;
216 int rc; 273 int rc;
217 int (*func)(); 274 int (*func)();
218 275
219 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end); 276 copy_and_pad_fragment(buf, sizeof(buf), &template_func, &template_func_end);
220 rc = nacl_dyncode_create(load_area, buf, sizeof(buf)); 277 rc = nacl_dyncode_create(load_area, buf, sizeof(buf));
221 assert(rc == 0); 278 assert(rc == 0);
222 func = (int (*)()) (uintptr_t) load_area; 279 func = (int (*)()) (uintptr_t) load_area;
223 rc = func(); 280 rc = func();
224 assert(rc == 1234); 281 assert(rc == 1234);
225 282
226 rc = nacl_dyncode_delete(load_area, sizeof buf); 283 rc = nacl_dyncode_delete(load_area, sizeof buf);
227 assert(rc != 0); 284 assert(rc != 0);
228 assert(load_area[0] == buf[0]); 285 assert(load_area[0] == buf[0]);
229 } 286 }
230 287
231 void run_test(const char *test_name, void (*test_func)(void)) { 288 void run_test(const char *test_name, void (*test_func)(void)) {
232 printf("Running %s...\n", test_name); 289 printf("Running %s...\n", test_name);
233 test_func(); 290 test_func();
234 } 291 }
235 292
236 int is_replacement_enabled() { 293 int is_replacement_enabled() {
237 char trash; 294 char trash;
238 return (0 == nacl_dyncode_modify(allocate_code_space(1), &trash, 0)); 295 return (0 == nacl_dyncode_modify(allocate_code_space(1), &trash, 0));
239 } 296 }
240 297
241 #define RUN_TEST(test_func) (run_test(#test_func, test_func)) 298 #define RUN_TEST(test_func) (run_test(#test_func, test_func))
242 299
243 int main() { 300 int TestMain() {
244 /* Turn off stdout buffering to aid debugging in case of a crash. */ 301 /* Turn off stdout buffering to aid debugging in case of a crash. */
245 setvbuf(stdout, NULL, _IONBF, 0); 302 setvbuf(stdout, NULL, _IONBF, 0);
246 303
247 if (is_replacement_enabled()) { 304 if (is_replacement_enabled()) {
248 printf("Code replacement ENABLED\n"); 305 printf("Code replacement ENABLED\n");
249 RUN_TEST(test_replacing_code); 306 RUN_TEST(test_replacing_code);
250 RUN_TEST(test_replacing_code_unaligned); 307 RUN_TEST(test_replacing_code_unaligned);
251 RUN_TEST(test_deleting_code); 308 RUN_TEST(test_deleting_code);
309 RUN_TEST(test_illegal_code_replacment);
252 } else { 310 } else {
253 printf("Code replacement DISABLED\n"); 311 printf("Code replacement DISABLED\n");
254 RUN_TEST(test_replacing_code_disabled); 312 RUN_TEST(test_replacing_code_disabled);
255 RUN_TEST(test_replacing_code_unaligned_disabled); 313 RUN_TEST(test_replacing_code_unaligned_disabled);
256 RUN_TEST(test_deleting_code_disabled); 314 RUN_TEST(test_deleting_code_disabled);
257 } 315 }
258 316
259 return 0; 317 return 0;
260 } 318 }
261 319
320 int main() {
321 return RunTests(TestMain);
322 }
323
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698