| Index: src/trusted/validator/driver/ncval.cc
|
| diff --git a/src/trusted/validator/driver/ncval.cc b/src/trusted/validator/driver/ncval.cc
|
| index c9736e6e33c8ad34911e75784135472c689325e0..ffde8f4dd22a770e5b3001267f4e53522643b797 100644
|
| --- a/src/trusted/validator/driver/ncval.cc
|
| +++ b/src/trusted/validator/driver/ncval.cc
|
| @@ -55,14 +55,17 @@ struct UserData {
|
| vector<Error> *errors;
|
| vector<Jump> *jumps;
|
| set<uint32_t> *bad_jump_targets;
|
| + uint32_t flags;
|
| UserData(Segment segment,
|
| vector<Error> *errors,
|
| vector<Jump> *jumps,
|
| - set<uint32_t> *bad_jump_targets)
|
| + set<uint32_t> *bad_jump_targets,
|
| + uint32_t flags)
|
| : segment(segment),
|
| errors(errors),
|
| jumps(jumps),
|
| - bad_jump_targets(bad_jump_targets) {
|
| + bad_jump_targets(bad_jump_targets),
|
| + flags(flags) {
|
| }
|
| };
|
|
|
| @@ -94,6 +97,11 @@ Bool ProcessInstruction(
|
| }
|
| }
|
|
|
| + // If we are not disabling non-temporals, they should pass validation, and
|
| + // the corresponding validation_info bit is simply cleared.
|
| + if (user_data.flags != DISABLE_NONTEMPORALS)
|
| + validation_info &= ~UNSUPPORTED_INSTRUCTION;
|
| +
|
| Bool result = (validation_info & (VALIDATION_ERRORS_MASK | BAD_JUMP_TARGET))
|
| ? FALSE
|
| : TRUE;
|
| @@ -120,6 +128,11 @@ Bool ProcessInstruction(
|
| errors.push_back(Error(offset, "required CPU feature not found"));
|
| }
|
|
|
| + if (validation_info & UNSUPPORTED_INSTRUCTION) {
|
| + validation_info &= ~UNSUPPORTED_INSTRUCTION;
|
| + errors.push_back(Error(offset, "unsupported instruction"));
|
| + }
|
| +
|
| if (validation_info & FORBIDDEN_BASE_REGISTER) {
|
| validation_info &= ~FORBIDDEN_BASE_REGISTER;
|
| errors.push_back(Error(offset, "improper memory address - bad base"));
|
| @@ -192,9 +205,18 @@ Bool ProcessError(
|
| uint32_t validation_info, void *user_data_ptr) {
|
| UNREFERENCED_PARAMETER(begin);
|
| UNREFERENCED_PARAMETER(end);
|
| - UNREFERENCED_PARAMETER(validation_info);
|
| - UNREFERENCED_PARAMETER(user_data_ptr);
|
| - return FALSE;
|
| + UserData &user_data = *reinterpret_cast<UserData *>(user_data_ptr);
|
| +
|
| + // We do the same thing as in ProcessInstruction(): If we are not disabling
|
| + // non-temporals, they should pass validation, and the corresponding
|
| + // validation_info bit is simply cleared.
|
| + if (user_data.flags != DISABLE_NONTEMPORALS)
|
| + validation_info &= ~UNSUPPORTED_INSTRUCTION;
|
| +
|
| + Bool result = (validation_info & (VALIDATION_ERRORS_MASK | BAD_JUMP_TARGET))
|
| + ? FALSE
|
| + : TRUE;
|
| + return result;
|
| }
|
|
|
|
|
| @@ -209,7 +231,8 @@ typedef Bool ValidateChunkFunc(
|
| bool ValidateX86(
|
| const Segment &segment,
|
| ValidateChunkFunc validate_chunk,
|
| - vector<Error> *errors) {
|
| + vector<Error> *errors,
|
| + uint32_t flags) {
|
|
|
| errors->clear();
|
|
|
| @@ -233,7 +256,7 @@ bool ValidateX86(
|
| vector<Jump> jumps;
|
| set<uint32_t> bad_jump_targets;
|
|
|
| - UserData user_data(segment, errors, &jumps, &bad_jump_targets);
|
| + UserData user_data(segment, errors, &jumps, &bad_jump_targets, flags);
|
|
|
| // TODO(shcherbina): customize from command line
|
|
|
| @@ -258,7 +281,7 @@ bool ValidateX86(
|
| CHECK(result == validate_chunk(
|
| segment.data, segment.size,
|
| 0, &kFullCPUIDFeatures,
|
| - ProcessError, NULL));
|
| + ProcessError, &user_data));
|
|
|
| return static_cast<bool>(result);
|
| }
|
| @@ -319,24 +342,28 @@ bool ValidateArm(const Segment &segment, vector<Error> *errors) {
|
|
|
| void Usage() {
|
| fprintf(stderr, "Usage:\n");
|
| - fprintf(stderr, " ncval [-v] <ELF file>\n");
|
| + fprintf(stderr, " ncval [-vd] <ELF file>\n");
|
| }
|
|
|
|
|
| struct Options {
|
| - Options() : input_file(NULL), verbose(false) {}
|
| + Options() : input_file(NULL), verbose(false), flags(0) {}
|
| const char *input_file;
|
| bool verbose;
|
| + uint32_t flags;
|
| };
|
|
|
|
|
| void ParseOptions(int argc, char **argv, Options *options) {
|
| int opt;
|
| - while ((opt = getopt(argc, argv, "v")) != -1) {
|
| + while ((opt = getopt(argc, argv, "vd")) != -1) {
|
| switch (opt) {
|
| case 'v':
|
| options->verbose = true;
|
| break;
|
| + case 'd':
|
| + options->flags = DISABLE_NONTEMPORALS;
|
| + break;
|
| default:
|
| fprintf(stderr, "ERROR: unknown option: [%c]\n\n", opt);
|
| Usage();
|
| @@ -368,10 +395,12 @@ int main(int argc, char **argv) {
|
| bool result = false;
|
| switch (architecture) {
|
| case elf_load::X86_32:
|
| - result = ValidateX86(segment, ValidateChunkIA32, &errors);
|
| + result = ValidateX86(segment, ValidateChunkIA32, &errors,
|
| + options.flags);
|
| break;
|
| case elf_load::X86_64:
|
| - result = ValidateX86(segment, ValidateChunkAMD64, &errors);
|
| + result = ValidateX86(segment, ValidateChunkAMD64, &errors,
|
| + options.flags);
|
| break;
|
| case elf_load::ARM:
|
| result = ValidateArm(segment, &errors);
|
|
|