1 // Copyright 2008 Google Inc. 2 // Author: Lincoln Smith 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 // codetable.cc: 17 // Classes to implement the Code Table 18 // described in sections 5.5, 5.6 and 7 of 19 // RFC 3284 - The VCDIFF Generic Differencing and Compression Data Format. 20 // The RFC text can be found at http://www.faqs.org/rfcs/rfc3284.html 21 22 #include <config.h> 23 #include "addrcache.h" 24 #include "codetable.h" 25 #include "logging.h" 26 #include "vcdiff_defs.h" // VCD_MAX_MODES 27 28 namespace open_vcdiff { 29 30 const char* VCDiffInstructionName(VCDiffInstructionType inst) { 31 switch (inst) { 32 case VCD_NOOP: 33 return "NOOP"; 34 case VCD_ADD: 35 return "ADD"; 36 case VCD_RUN: 37 return "RUN"; 38 case VCD_COPY: 39 return "COPY"; 40 default: 41 LOG(ERROR) << "Unexpected instruction type " << inst << LOG_ENDL; 42 return ""; 43 } 44 } 45 46 // This is the default code table defined in the RFC, section 5.6. 47 // Using a static struct means that the compiler will do the work of 48 // laying out the values in memory rather than having to use loops to do so 49 // at runtime. The letters "N", "A", "R", and "C" are defined as VCD_NOOP, 50 // VCD_ADD, VCD_RUN, and VCD_COPY respectively (see the definition of 51 // struct VCDiffCodeTableData), which allows for a compact 52 // representation of the code table data. 53 // 54 const VCDiffCodeTableData VCDiffCodeTableData::kDefaultCodeTableData = 55 // inst1 56 { { R, // opcode 0 57 A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 1-18 58 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 19-34 59 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 35-50 60 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 51-66 61 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 67-82 62 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 83-98 63 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 99-114 64 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 115-130 65 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 131-146 66 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 147-162 67 A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 163-174 68 A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 175-186 69 A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 187-198 70 A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 199-210 71 A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 211-222 72 A, A, A, A, A, A, A, A, A, A, A, A, // opcodes 223-234 73 A, A, A, A, // opcodes 235-238 74 A, A, A, A, // opcodes 239-242 75 A, A, A, A, // opcodes 243-246 76 C, C, C, C, C, C, C, C, C }, // opcodes 247-255 77 // inst2 78 { N, // opcode 0 79 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 1-18 80 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 19-34 81 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 35-50 82 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 51-66 83 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 67-82 84 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 83-98 85 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 99-114 86 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 115-130 87 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 131-146 88 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, // opcodes 147-162 89 C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 163-174 90 C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 175-186 91 C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 187-198 92 C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 199-210 93 C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 211-222 94 C, C, C, C, C, C, C, C, C, C, C, C, // opcodes 223-234 95 C, C, C, C, // opcodes 235-238 96 C, C, C, C, // opcodes 239-242 97 C, C, C, C, // opcodes 243-246 98 A, A, A, A, A, A, A, A, A }, // opcodes 247-255 99 // size1 100 { 0, // opcode 0 101 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // 1-18 102 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 19-34 103 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 35-50 104 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 51-66 105 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 67-82 106 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 83-98 107 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 99-114 108 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 115-130 109 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 131-146 110 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // 147-162 111 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 163-174 112 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 175-186 113 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 187-198 114 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 199-210 115 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 211-222 116 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, // opcodes 223-234 117 1, 2, 3, 4, // opcodes 235-238 118 1, 2, 3, 4, // opcodes 239-242 119 1, 2, 3, 4, // opcodes 243-246 120 4, 4, 4, 4, 4, 4, 4, 4, 4 }, // opcodes 247-255 121 // size2 122 { 0, // opcode 0 123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 1-18 124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 19-34 125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 35-50 126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 51-66 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 67-82 128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 83-98 129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 99-114 130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 115-130 131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 131-146 132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 147-162 133 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 163-174 134 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 175-186 135 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 187-198 136 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 199-210 137 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 211-222 138 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, // opcodes 223-234 139 4, 4, 4, 4, // opcodes 235-238 140 4, 4, 4, 4, // opcodes 239-242 141 4, 4, 4, 4, // opcodes 243-246 142 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // opcodes 247-255 143 // mode1 144 { 0, // opcode 0 145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 1-18 146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 19-34 147 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // opcodes 35-50 148 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // opcodes 51-66 149 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // opcodes 67-82 150 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // opcodes 83-98 151 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // opcodes 99-114 152 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, // opcodes 115-130 153 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // opcodes 131-146 154 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // opcodes 147-162 155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 163-174 156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 175-186 157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 187-198 158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 199-210 159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 211-222 160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 223-234 161 0, 0, 0, 0, // opcodes 235-238 162 0, 0, 0, 0, // opcodes 239-242 163 0, 0, 0, 0, // opcodes 243-246 164 0, 1, 2, 3, 4, 5, 6, 7, 8 }, // opcodes 247-255 165 // mode2 166 { 0, // opcode 0 167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 1-18 168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 19-34 169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 35-50 170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 51-66 171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 67-82 172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 83-98 173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 99-114 174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 115-130 175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 131-146 176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 147-162 177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // opcodes 163-174 178 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // opcodes 175-186 179 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // opcodes 187-198 180 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // opcodes 199-210 181 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // opcodes 211-222 182 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // opcodes 223-234 183 6, 6, 6, 6, // opcodes 235-238 184 7, 7, 7, 7, // opcodes 239-242 185 8, 8, 8, 8, // opcodes 243-246 186 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; // opcodes 247-255 187 188 bool VCDiffCodeTableData::ValidateOpcode(int opcode, 189 unsigned char inst, 190 unsigned char size, 191 unsigned char mode, 192 unsigned char max_mode, 193 const char* first_or_second) { 194 bool no_errors_found = true; 195 // Check upper limits of inst and mode. inst, size, and mode are 196 // unsigned, so there is no lower limit on them. 197 if (inst > VCD_LAST_INSTRUCTION_TYPE) { 198 LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode << " has invalid " 199 << first_or_second << " instruction type " 200 << static_cast<int>(inst) << LOG_ENDL; 201 no_errors_found = false; 202 } 203 if (mode > max_mode) { 204 LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode << " has invalid " 205 << first_or_second << " mode " 206 << static_cast<int>(mode) << LOG_ENDL; 207 no_errors_found = false; 208 } 209 // A NOOP instruction must have size 0 210 // (and mode 0, which is included in the next rule) 211 if ((inst == VCD_NOOP) && (size != 0)) { 212 LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode << " has " 213 << first_or_second << " instruction NOOP with nonzero size " 214 << static_cast<int>(size) << LOG_ENDL; 215 no_errors_found = false; 216 } 217 // A nonzero mode can only be used with a COPY instruction 218 if ((inst != VCD_COPY) && (mode != 0)) { 219 LOG(ERROR) << "VCDiff: Bad code table; opcode " << opcode 220 << " has non-COPY " 221 << first_or_second << " instruction with nonzero mode " 222 << static_cast<int>(mode) << LOG_ENDL; 223 no_errors_found = false; 224 } 225 return no_errors_found; 226 } 227 228 // If an error is found while validating, continue to validate the rest 229 // of the code table so that all validation errors will appear in 230 // the error log. Otherwise the user would have to fix a single error 231 // and then rerun validation to find the next error. 232 // 233 bool VCDiffCodeTableData::Validate(unsigned char max_mode) const { 234 const int kNumberOfTypesAndModes = VCD_LAST_INSTRUCTION_TYPE + max_mode + 1; 235 bool hasOpcodeForTypeAndMode[VCD_LAST_INSTRUCTION_TYPE + VCD_MAX_MODES]; 236 bool no_errors_found = true; 237 for (int i = 0; i < kNumberOfTypesAndModes; ++i) { 238 hasOpcodeForTypeAndMode[i] = false; 239 } 240 for (int i = 0; i < kCodeTableSize; ++i) { 241 no_errors_found = 242 ValidateOpcode(i, inst1[i], size1[i], mode1[i], max_mode, "first") 243 && no_errors_found; // use as 2nd operand to avoid short-circuit 244 no_errors_found = 245 ValidateOpcode(i, inst2[i], size2[i], mode2[i], max_mode, "second") 246 && no_errors_found; 247 // A valid code table must have an opcode to encode every possible 248 // combination of inst and mode with size=0 as its first instruction, 249 // and NOOP as its second instruction. If this condition fails, 250 // then there exists a set of input instructions that cannot be encoded. 251 if ((size1[i] == 0) && 252 (inst2[i] == VCD_NOOP) && 253 ((static_cast<int>(inst1[i]) + static_cast<int>(mode1[i])) 254 < kNumberOfTypesAndModes)) { 255 hasOpcodeForTypeAndMode[inst1[i] + mode1[i]] = true; 256 } 257 } 258 for (int i = 0; i < kNumberOfTypesAndModes; ++i) { 259 if (i == VCD_NOOP) continue; 260 if (!hasOpcodeForTypeAndMode[i]) { 261 if (i >= VCD_COPY) { 262 LOG(ERROR) << "VCDiff: Bad code table; there is no opcode for inst " 263 "COPY, size 0, mode " << (i - VCD_COPY) << LOG_ENDL; 264 } else { 265 LOG(ERROR) << "VCDiff: Bad code table; there is no opcode for inst " 266 << VCDiffInstructionName(static_cast<VCDiffInstructionType>(i)) 267 << ", size 0, mode 0" << LOG_ENDL; 268 } 269 no_errors_found = false; 270 } 271 } 272 return no_errors_found; 273 } 274 275 bool VCDiffCodeTableData::Validate() const { 276 return Validate(VCDiffAddressCache::DefaultLastMode()); 277 } 278 279 } // namespace open_vcdiff 280