| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 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 /* | |
| 8 * Hexidecimal text to bytes conversion tools. | |
| 9 */ | |
| 10 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
| 11 #error("This file is not meant for use in the TCB.") | |
| 12 #endif | |
| 13 | |
| 14 #include "native_client/src/trusted/validator/x86/testing/enuminsts/text2hex.h" | |
| 15 | |
| 16 #include <stdio.h> | |
| 17 | |
| 18 #include "native_client/src/include/portability_io.h" | |
| 19 | |
| 20 #define kBufferSize 1024 | |
| 21 | |
| 22 /* Returns the integer corresponding to a hex value in ASCII. This would | |
| 23 * be faster as an array lookup, however since it's only used for command | |
| 24 * line input it doesn't matter. | |
| 25 */ | |
| 26 static unsigned int A2INibble(const char nibble) { | |
| 27 switch (nibble) { | |
| 28 case '0': return 0; | |
| 29 case '1': return 1; | |
| 30 case '2': return 2; | |
| 31 case '3': return 3; | |
| 32 case '4': return 4; | |
| 33 case '5': return 5; | |
| 34 case '6': return 6; | |
| 35 case '7': return 7; | |
| 36 case '8': return 8; | |
| 37 case '9': return 9; | |
| 38 case 'a': | |
| 39 case 'A': return 0xA; | |
| 40 case 'b': | |
| 41 case 'B': return 0xB; | |
| 42 case 'c': | |
| 43 case 'C': return 0xC; | |
| 44 case 'd': | |
| 45 case 'D': return 0xD; | |
| 46 case 'e': | |
| 47 case 'E': return 0xE; | |
| 48 case 'f': | |
| 49 case 'F': return 0xF; | |
| 50 default: break; | |
| 51 } | |
| 52 fprintf(stderr, "bad hex value %c", nibble); | |
| 53 exit(1); | |
| 54 } | |
| 55 | |
| 56 /* Convert a two-character string representing an byte value in hex | |
| 57 * into the corresponding byte value. | |
| 58 */ | |
| 59 static unsigned int A2IByte(const char nibble1, const char nibble2) { | |
| 60 return A2INibble(nibble2) + A2INibble(nibble1) * 0x10; | |
| 61 } | |
| 62 | |
| 63 /* Generates a buffer containing the context message to print. | |
| 64 * Arguments are: | |
| 65 * context - String describing the context (i.e. filename or | |
| 66 * command line argument description). | |
| 67 * line - The line number associated with the context (if negative, | |
| 68 * it assumes that the line number shouldn't be reported). | |
| 69 */ | |
| 70 static const char* TextContext(const char* context, | |
| 71 const int line) { | |
| 72 if (line < 0) { | |
| 73 return context; | |
| 74 } else { | |
| 75 static char buffer[kBufferSize]; | |
| 76 SNPRINTF(buffer, kBufferSize, "%s line %d", context, line); | |
| 77 return buffer; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 /* Installs byte into the byte buffer. Returns the new value for num_bytes. | |
| 82 * Arguments are: | |
| 83 * ibytes - The found sequence of opcode bytes. | |
| 84 * num_bytes - The number of bytes currently in ibytes. | |
| 85 * mini_buf - The buffer containing the two hexidecimal characters to convert. | |
| 86 * context - String describing the context (i.e. filename or | |
| 87 * command line argument description). | |
| 88 * line - The line number associated with the context (if negative, | |
| 89 * it assumes that the line number shouldn't be reported). | |
| 90 */ | |
| 91 static int InstallTextByte(InstByteArray ibytes, | |
| 92 int num_bytes, | |
| 93 const char mini_buf[2], | |
| 94 const char* itext, | |
| 95 const char* context, | |
| 96 const int line) { | |
| 97 if (num_bytes == NACL_ENUM_MAX_INSTRUCTION_BYTES) { | |
| 98 char buffer[kBufferSize]; | |
| 99 SNPRINTF(buffer, kBufferSize, | |
| 100 "%s: opcode sequence too long in '%s'", | |
| 101 TextContext(context, line), itext); | |
| 102 ReportFatalError(buffer); | |
| 103 } | |
| 104 ibytes[num_bytes] = A2IByte(mini_buf[0], mini_buf[1]); | |
| 105 return num_bytes + 1; | |
| 106 } | |
| 107 | |
| 108 /* Reads a line of text defining the sequence of bytes that defines | |
| 109 * an instruction, and converts that to the corresponding sequence of | |
| 110 * opcode bytes. Returns the number of bytes found. Arguments are: | |
| 111 * ibytes - The found sequence of opcode bytes. | |
| 112 * itext - The sequence of bytes to convert. | |
| 113 * context - String describing the context (i.e. filename or | |
| 114 * command line argument description). | |
| 115 * line - The line number associated with the context (if negative, | |
| 116 * it assumes that the line number shouldn't be reported). | |
| 117 */ | |
| 118 int Text2Bytes(InstByteArray ibytes, | |
| 119 const char* itext, | |
| 120 const char* context, | |
| 121 const int line) { | |
| 122 char mini_buf[2]; | |
| 123 size_t mini_buf_index; | |
| 124 char *next; | |
| 125 char ch; | |
| 126 int num_bytes = 0; | |
| 127 Bool continue_translation = TRUE; | |
| 128 | |
| 129 /* Now process text of itext. */ | |
| 130 next = (char*) &itext[0]; | |
| 131 mini_buf_index = 0; | |
| 132 while (continue_translation && (ch = *(next++))) { | |
| 133 switch (ch) { | |
| 134 case '#': | |
| 135 /* Comment, skip reading any more characters. */ | |
| 136 continue_translation = FALSE; | |
| 137 break; | |
| 138 case '0': | |
| 139 case '1': | |
| 140 case '2': | |
| 141 case '3': | |
| 142 case '4': | |
| 143 case '5': | |
| 144 case '6': | |
| 145 case '7': | |
| 146 case '8': | |
| 147 case '9': | |
| 148 case 'a': | |
| 149 case 'b': | |
| 150 case 'c': | |
| 151 case 'd': | |
| 152 case 'e': | |
| 153 case 'f': | |
| 154 case 'A': | |
| 155 case 'B': | |
| 156 case 'C': | |
| 157 case 'D': | |
| 158 case 'E': | |
| 159 case 'F': | |
| 160 /* Hexidecimal character. Add to mini buffer, and install | |
| 161 * if two bytes. | |
| 162 */ | |
| 163 mini_buf[mini_buf_index++] = ch; | |
| 164 if (2 == mini_buf_index) { | |
| 165 num_bytes = InstallTextByte(ibytes, num_bytes, mini_buf, itext, | |
| 166 context, line); | |
| 167 mini_buf_index = 0; | |
| 168 } | |
| 169 break; | |
| 170 case ' ': | |
| 171 case '\t': | |
| 172 case '\n': | |
| 173 /* Space - assume it is a separator between bytes. */ | |
| 174 switch(mini_buf_index) { | |
| 175 case 0: | |
| 176 break; | |
| 177 case 2: | |
| 178 num_bytes = InstallTextByte(ibytes, num_bytes, mini_buf, itext, | |
| 179 context, line); | |
| 180 mini_buf_index = 0; | |
| 181 break; | |
| 182 default: | |
| 183 continue_translation = FALSE; | |
| 184 } | |
| 185 break; | |
| 186 default: { | |
| 187 char buffer[kBufferSize]; | |
| 188 SNPRINTF(buffer, kBufferSize, | |
| 189 "%s: contains bad text:\n '%s'\n", | |
| 190 TextContext(context, line), itext); | |
| 191 ReportFatalError(buffer); | |
| 192 break; | |
| 193 } | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 /* If only a single byte was used to define hex value, convert it. */ | |
| 198 if (mini_buf_index > 0) { | |
| 199 char buffer[kBufferSize]; | |
| 200 SNPRINTF(buffer, kBufferSize, | |
| 201 "%s: Opcode sequence must be an even number of chars '%s'", | |
| 202 TextContext(context, line), itext); | |
| 203 ReportFatalError(buffer); | |
| 204 } | |
| 205 | |
| 206 return num_bytes; | |
| 207 } | |
| OLD | NEW |