1 : /*
2 : * Copyright (c) 2013 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include <stdarg.h>
8 : #include <stdio.h>
9 : #include <stdlib.h>
10 :
11 : #include "native_client/src/include/portability.h"
12 : #include "native_client/src/shared/platform/nacl_check.h"
13 : #include "native_client/src/shared/platform/nacl_log.h"
14 : #include "native_client/src/trusted/validator_ragel/validator.h"
15 :
16 :
17 : /*
18 : * We don't want to link whole NaCl platform with validator dynamic library,
19 : * but we need NaClLog (it is used in CHECK), so we provide our own
20 : * minimal implementation suitable for testing.
21 : */
22 :
23 0 : void NaClLog(int detail_level, char const *fmt, ...) {
24 0 : va_list ap;
25 0 : UNREFERENCED_PARAMETER(detail_level);
26 0 : va_start(ap, fmt);
27 0 : vprintf(fmt, ap);
28 0 : va_end(ap);
29 0 : if (detail_level == LOG_FATAL)
30 0 : exit(1);
31 0 : }
32 :
33 :
34 : struct CallbackData {
35 : const uint8_t *actual_end;
36 : enum OperandName restricted_register;
37 : Bool valid;
38 : };
39 :
40 :
41 : Bool ExtractRestrictedRegisterCallback(
42 0 : const uint8_t *begin,
43 0 : const uint8_t *end,
44 0 : uint32_t info,
45 0 : void *data) {
46 :
47 0 : struct CallbackData *callback_data = data;
48 0 : if (end <= callback_data->actual_end && (info & VALIDATION_ERRORS_MASK)) {
49 0 : callback_data->valid = FALSE;
50 0 : }
51 0 : if (end == callback_data->actual_end) {
52 0 : callback_data->restricted_register =
53 : (info & RESTRICTED_REGISTER_MASK) >> RESTRICTED_REGISTER_SHIFT;
54 0 : }
55 0 : if (begin < callback_data->actual_end && callback_data->actual_end < end) {
56 : /* Instruction crosses actual chunk boundary. */
57 0 : callback_data->valid = FALSE;
58 0 : return FALSE;
59 : }
60 0 : return TRUE;
61 0 : }
62 :
63 :
64 : /*
65 : * Validate first actual_size bytes of given AMD64 codeblock and return
66 : * validation result and final value of the restricted register.
67 : * This function is used in verify_regular_instructions.py test.
68 : */
69 : VALIDATOR_EXPORT
70 : Bool ValidateAndGetFinalRestrictedRegister(
71 0 : const uint8_t codeblock[],
72 0 : size_t size,
73 0 : size_t actual_size,
74 0 : enum OperandName initial_restricted_register,
75 0 : const NaClCPUFeaturesX86 *cpu_features,
76 0 : enum OperandName *resulting_restricted_register) {
77 :
78 0 : uint32_t options;
79 0 : struct CallbackData callback_data;
80 :
81 0 : CHECK(size % kBundleSize == 0);
82 0 : CHECK(0 < actual_size && actual_size <= size);
83 :
84 0 : callback_data.actual_end = codeblock + actual_size;
85 0 : callback_data.valid = TRUE;
86 :
87 0 : options =
88 : PACK_RESTRICTED_REGISTER_INITIAL_VALUE(initial_restricted_register) |
89 : CALL_USER_CALLBACK_ON_EACH_INSTRUCTION;
90 0 : ValidateChunkAMD64(
91 : codeblock, size,
92 : options,
93 : cpu_features,
94 : ExtractRestrictedRegisterCallback,
95 : &callback_data);
96 :
97 0 : *resulting_restricted_register = callback_data.restricted_register;
98 0 : return callback_data.valid;
99 : }
|