| OLD | NEW |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 for (int access_size = 1; access_size <= 8; access_size *= 2) { | 162 for (int access_size = 1; access_size <= 8; access_size *= 2) { |
| 163 std::string name = | 163 std::string name = |
| 164 base::StringPrintf("asan_check_%d_byte_write_access", access_size); | 164 base::StringPrintf("asan_check_%d_byte_write_access", access_size); |
| 165 AddHookRef(name, AsanBasicBlockTransform::kWriteAccess, access_size, 0, | 165 AddHookRef(name, AsanBasicBlockTransform::kWriteAccess, access_size, 0, |
| 166 true); | 166 true); |
| 167 name += "_no_flags"; | 167 name += "_no_flags"; |
| 168 AddHookRef(name, AsanBasicBlockTransform::kWriteAccess, access_size, 0, | 168 AddHookRef(name, AsanBasicBlockTransform::kWriteAccess, access_size, 0, |
| 169 false); | 169 false); |
| 170 } | 170 } |
| 171 | 171 |
| 172 const _InstructionType strings[] = { I_CMPS, I_MOVS, I_STOS }; | 172 const _InstructionType strings[] = {I_CMPS, I_LODS, I_MOVS, I_STOS}; |
| 173 int strings_length = arraysize(strings); | 173 int strings_length = arraysize(strings); |
| 174 | 174 |
| 175 for (int access_size = 1; access_size <= 4; access_size *= 2) { | 175 for (int access_size = 1; access_size <= 4; access_size *= 2) { |
| 176 for (int inst = 0; inst < strings_length; ++inst) { | 176 for (int inst = 0; inst < strings_length; ++inst) { |
| 177 uint16_t opcode = strings[inst]; | 177 uint16_t opcode = strings[inst]; |
| 178 const char* opcode_str = | 178 const char* opcode_str = |
| 179 reinterpret_cast<const char*>(GET_MNEMONIC_NAME(opcode)); | 179 reinterpret_cast<const char*>(GET_MNEMONIC_NAME(opcode)); |
| 180 std::string name = | 180 std::string name = |
| 181 base::StringPrintf("asan_check_repz_%d_byte_%s_access", | 181 base::StringPrintf("asan_check_repz_%d_byte_%s_access", |
| 182 access_size, opcode_str); | 182 access_size, opcode_str); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 { AsanBasicBlockTransform::kWriteAccess, 4, 0, true }; | 779 { AsanBasicBlockTransform::kWriteAccess, 4, 0, true }; |
| 780 ASSERT_TRUE(iter_inst->references().begin()->second.block() | 780 ASSERT_TRUE(iter_inst->references().begin()->second.block() |
| 781 == hooks_check_access_[check_4_byte_write_key]); | 781 == hooks_check_access_[check_4_byte_write_key]); |
| 782 ASSERT_TRUE((iter_inst++)->representation().opcode == I_CALL); | 782 ASSERT_TRUE((iter_inst++)->representation().opcode == I_CALL); |
| 783 ASSERT_TRUE((iter_inst++)->representation().opcode == I_MOV); | 783 ASSERT_TRUE((iter_inst++)->representation().opcode == I_MOV); |
| 784 | 784 |
| 785 ASSERT_TRUE(iter_inst == basic_block_->instructions().end()); | 785 ASSERT_TRUE(iter_inst == basic_block_->instructions().end()); |
| 786 } | 786 } |
| 787 | 787 |
| 788 TEST_F(AsanTransformTest, InstrumentableStringInstructions) { | 788 TEST_F(AsanTransformTest, InstrumentableStringInstructions) { |
| 789 static const uint8_t lodsd[1] = {0xAD}; |
| 790 static const uint8_t lodsw[2] = {0x66, 0xAD}; |
| 791 static const uint8_t lodsb[1] = {0xAC}; |
| 792 |
| 789 static const uint8_t movsd[1] = {0xA5}; | 793 static const uint8_t movsd[1] = {0xA5}; |
| 790 static const uint8_t movsw[2] = {0x66, 0xA5}; | 794 static const uint8_t movsw[2] = {0x66, 0xA5}; |
| 791 static const uint8_t movsb[1] = {0xA4}; | 795 static const uint8_t movsb[1] = {0xA4}; |
| 792 | 796 |
| 793 static const uint8_t cmpsd[1] = {0xA7}; | 797 static const uint8_t cmpsd[1] = {0xA7}; |
| 794 static const uint8_t cmpsw[2] = {0x66, 0xA7}; | 798 static const uint8_t cmpsw[2] = {0x66, 0xA7}; |
| 795 static const uint8_t cmpsb[1] = {0xA6}; | 799 static const uint8_t cmpsb[1] = {0xA6}; |
| 796 | 800 |
| 797 static const uint8_t stosd[1] = {0xAB}; | 801 static const uint8_t stosd[1] = {0xAB}; |
| 798 static const uint8_t stosw[2] = {0x66, 0xAB}; | 802 static const uint8_t stosw[2] = {0x66, 0xAB}; |
| 799 static const uint8_t stosb[1] = {0xAA}; | 803 static const uint8_t stosb[1] = {0xAA}; |
| 800 | 804 |
| 805 EXPECT_TRUE(AddInstructionFromBuffer(lodsd, sizeof(lodsd))); |
| 806 EXPECT_TRUE(AddInstructionFromBuffer(lodsw, sizeof(lodsw))); |
| 807 EXPECT_TRUE(AddInstructionFromBuffer(lodsb, sizeof(lodsb))); |
| 801 EXPECT_TRUE(AddInstructionFromBuffer(movsd, sizeof(movsd))); | 808 EXPECT_TRUE(AddInstructionFromBuffer(movsd, sizeof(movsd))); |
| 802 EXPECT_TRUE(AddInstructionFromBuffer(movsw, sizeof(movsw))); | 809 EXPECT_TRUE(AddInstructionFromBuffer(movsw, sizeof(movsw))); |
| 803 EXPECT_TRUE(AddInstructionFromBuffer(movsb, sizeof(movsb))); | 810 EXPECT_TRUE(AddInstructionFromBuffer(movsb, sizeof(movsb))); |
| 804 EXPECT_TRUE(AddInstructionFromBuffer(cmpsd, sizeof(cmpsd))); | 811 EXPECT_TRUE(AddInstructionFromBuffer(cmpsd, sizeof(cmpsd))); |
| 805 EXPECT_TRUE(AddInstructionFromBuffer(cmpsw, sizeof(cmpsw))); | 812 EXPECT_TRUE(AddInstructionFromBuffer(cmpsw, sizeof(cmpsw))); |
| 806 EXPECT_TRUE(AddInstructionFromBuffer(cmpsb, sizeof(cmpsb))); | 813 EXPECT_TRUE(AddInstructionFromBuffer(cmpsb, sizeof(cmpsb))); |
| 807 EXPECT_TRUE(AddInstructionFromBuffer(stosd, sizeof(stosd))); | 814 EXPECT_TRUE(AddInstructionFromBuffer(stosd, sizeof(stosd))); |
| 808 EXPECT_TRUE(AddInstructionFromBuffer(stosw, sizeof(stosw))); | 815 EXPECT_TRUE(AddInstructionFromBuffer(stosw, sizeof(stosw))); |
| 809 EXPECT_TRUE(AddInstructionFromBuffer(stosb, sizeof(stosb))); | 816 EXPECT_TRUE(AddInstructionFromBuffer(stosb, sizeof(stosb))); |
| 810 | 817 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 825 EXPECT_TRUE(bb_transform.instrumentation_happened()); | 832 EXPECT_TRUE(bb_transform.instrumentation_happened()); |
| 826 | 833 |
| 827 // Each instrumentable instructions implies 1 new instructions. | 834 // Each instrumentable instructions implies 1 new instructions. |
| 828 uint32_t expected_basic_block_size = count_instructions + basic_block_size; | 835 uint32_t expected_basic_block_size = count_instructions + basic_block_size; |
| 829 | 836 |
| 830 // Validate basic block size. | 837 // Validate basic block size. |
| 831 ASSERT_EQ(basic_block_->instructions().size(), expected_basic_block_size); | 838 ASSERT_EQ(basic_block_->instructions().size(), expected_basic_block_size); |
| 832 } | 839 } |
| 833 | 840 |
| 834 TEST_F(AsanTransformTest, InstrumentableRepzStringInstructions) { | 841 TEST_F(AsanTransformTest, InstrumentableRepzStringInstructions) { |
| 842 static const uint8_t lodsd[2] = {0xF3, 0xAD}; |
| 843 static const uint8_t lodsw[3] = {0xF3, 0x66, 0xAD}; |
| 844 static const uint8_t lodsb[2] = {0xF3, 0xAC}; |
| 845 |
| 835 static const uint8_t movsd[2] = {0xF3, 0xA5}; | 846 static const uint8_t movsd[2] = {0xF3, 0xA5}; |
| 836 static const uint8_t movsw[3] = {0xF3, 0x66, 0xA5}; | 847 static const uint8_t movsw[3] = {0xF3, 0x66, 0xA5}; |
| 837 static const uint8_t movsb[2] = {0xF3, 0xA4}; | 848 static const uint8_t movsb[2] = {0xF3, 0xA4}; |
| 838 | 849 |
| 839 static const uint8_t cmpsd[2] = {0xF3, 0xA7}; | 850 static const uint8_t cmpsd[2] = {0xF3, 0xA7}; |
| 840 static const uint8_t cmpsw[3] = {0xF3, 0x66, 0xA7}; | 851 static const uint8_t cmpsw[3] = {0xF3, 0x66, 0xA7}; |
| 841 static const uint8_t cmpsb[2] = {0xF3, 0xA6}; | 852 static const uint8_t cmpsb[2] = {0xF3, 0xA6}; |
| 842 | 853 |
| 843 static const uint8_t stosd[2] = {0xF3, 0xAB}; | 854 static const uint8_t stosd[2] = {0xF3, 0xAB}; |
| 844 static const uint8_t stosw[3] = {0xF3, 0x66, 0xAB}; | 855 static const uint8_t stosw[3] = {0xF3, 0x66, 0xAB}; |
| 845 static const uint8_t stosb[2] = {0xF3, 0xAA}; | 856 static const uint8_t stosb[2] = {0xF3, 0xAA}; |
| 846 | 857 |
| 858 EXPECT_TRUE(AddInstructionFromBuffer(lodsd, sizeof(lodsd))); |
| 859 EXPECT_TRUE(AddInstructionFromBuffer(lodsw, sizeof(lodsw))); |
| 860 EXPECT_TRUE(AddInstructionFromBuffer(lodsb, sizeof(lodsb))); |
| 847 EXPECT_TRUE(AddInstructionFromBuffer(movsd, sizeof(movsd))); | 861 EXPECT_TRUE(AddInstructionFromBuffer(movsd, sizeof(movsd))); |
| 848 EXPECT_TRUE(AddInstructionFromBuffer(movsw, sizeof(movsw))); | 862 EXPECT_TRUE(AddInstructionFromBuffer(movsw, sizeof(movsw))); |
| 849 EXPECT_TRUE(AddInstructionFromBuffer(movsb, sizeof(movsb))); | 863 EXPECT_TRUE(AddInstructionFromBuffer(movsb, sizeof(movsb))); |
| 850 EXPECT_TRUE(AddInstructionFromBuffer(cmpsd, sizeof(cmpsd))); | 864 EXPECT_TRUE(AddInstructionFromBuffer(cmpsd, sizeof(cmpsd))); |
| 851 EXPECT_TRUE(AddInstructionFromBuffer(cmpsw, sizeof(cmpsw))); | 865 EXPECT_TRUE(AddInstructionFromBuffer(cmpsw, sizeof(cmpsw))); |
| 852 EXPECT_TRUE(AddInstructionFromBuffer(cmpsb, sizeof(cmpsb))); | 866 EXPECT_TRUE(AddInstructionFromBuffer(cmpsb, sizeof(cmpsb))); |
| 853 EXPECT_TRUE(AddInstructionFromBuffer(stosd, sizeof(stosd))); | 867 EXPECT_TRUE(AddInstructionFromBuffer(stosd, sizeof(stosd))); |
| 854 EXPECT_TRUE(AddInstructionFromBuffer(stosw, sizeof(stosw))); | 868 EXPECT_TRUE(AddInstructionFromBuffer(stosw, sizeof(stosw))); |
| 855 EXPECT_TRUE(AddInstructionFromBuffer(stosb, sizeof(stosb))); | 869 EXPECT_TRUE(AddInstructionFromBuffer(stosb, sizeof(stosb))); |
| 856 | 870 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 expected.insert("asan_check_32_byte_read_access_no_flags"); | 1195 expected.insert("asan_check_32_byte_read_access_no_flags"); |
| 1182 expected.insert("asan_check_1_byte_write_access_no_flags"); | 1196 expected.insert("asan_check_1_byte_write_access_no_flags"); |
| 1183 expected.insert("asan_check_2_byte_write_access_no_flags"); | 1197 expected.insert("asan_check_2_byte_write_access_no_flags"); |
| 1184 expected.insert("asan_check_4_byte_write_access_no_flags"); | 1198 expected.insert("asan_check_4_byte_write_access_no_flags"); |
| 1185 expected.insert("asan_check_8_byte_write_access_no_flags"); | 1199 expected.insert("asan_check_8_byte_write_access_no_flags"); |
| 1186 expected.insert("asan_check_10_byte_write_access_no_flags"); | 1200 expected.insert("asan_check_10_byte_write_access_no_flags"); |
| 1187 expected.insert("asan_check_16_byte_write_access_no_flags"); | 1201 expected.insert("asan_check_16_byte_write_access_no_flags"); |
| 1188 expected.insert("asan_check_32_byte_write_access_no_flags"); | 1202 expected.insert("asan_check_32_byte_write_access_no_flags"); |
| 1189 | 1203 |
| 1190 expected.insert("asan_check_repz_4_byte_cmps_access"); | 1204 expected.insert("asan_check_repz_4_byte_cmps_access"); |
| 1205 expected.insert("asan_check_repz_4_byte_lods_access"); |
| 1191 expected.insert("asan_check_repz_4_byte_movs_access"); | 1206 expected.insert("asan_check_repz_4_byte_movs_access"); |
| 1192 expected.insert("asan_check_repz_4_byte_stos_access"); | 1207 expected.insert("asan_check_repz_4_byte_stos_access"); |
| 1193 expected.insert("asan_check_repz_2_byte_cmps_access"); | 1208 expected.insert("asan_check_repz_2_byte_cmps_access"); |
| 1209 expected.insert("asan_check_repz_2_byte_lods_access"); |
| 1194 expected.insert("asan_check_repz_2_byte_movs_access"); | 1210 expected.insert("asan_check_repz_2_byte_movs_access"); |
| 1195 expected.insert("asan_check_repz_2_byte_stos_access"); | 1211 expected.insert("asan_check_repz_2_byte_stos_access"); |
| 1196 expected.insert("asan_check_repz_1_byte_cmps_access"); | 1212 expected.insert("asan_check_repz_1_byte_cmps_access"); |
| 1213 expected.insert("asan_check_repz_1_byte_lods_access"); |
| 1197 expected.insert("asan_check_repz_1_byte_movs_access"); | 1214 expected.insert("asan_check_repz_1_byte_movs_access"); |
| 1198 expected.insert("asan_check_repz_1_byte_stos_access"); | 1215 expected.insert("asan_check_repz_1_byte_stos_access"); |
| 1199 | 1216 |
| 1200 expected.insert("asan_check_4_byte_cmps_access"); | 1217 expected.insert("asan_check_4_byte_cmps_access"); |
| 1218 expected.insert("asan_check_4_byte_lods_access"); |
| 1201 expected.insert("asan_check_4_byte_movs_access"); | 1219 expected.insert("asan_check_4_byte_movs_access"); |
| 1202 expected.insert("asan_check_4_byte_stos_access"); | 1220 expected.insert("asan_check_4_byte_stos_access"); |
| 1203 expected.insert("asan_check_2_byte_cmps_access"); | 1221 expected.insert("asan_check_2_byte_cmps_access"); |
| 1222 expected.insert("asan_check_2_byte_lods_access"); |
| 1204 expected.insert("asan_check_2_byte_movs_access"); | 1223 expected.insert("asan_check_2_byte_movs_access"); |
| 1205 expected.insert("asan_check_2_byte_stos_access"); | 1224 expected.insert("asan_check_2_byte_stos_access"); |
| 1206 expected.insert("asan_check_1_byte_cmps_access"); | 1225 expected.insert("asan_check_1_byte_cmps_access"); |
| 1226 expected.insert("asan_check_1_byte_lods_access"); |
| 1207 expected.insert("asan_check_1_byte_movs_access"); | 1227 expected.insert("asan_check_1_byte_movs_access"); |
| 1208 expected.insert("asan_check_1_byte_stos_access"); | 1228 expected.insert("asan_check_1_byte_stos_access"); |
| 1209 | 1229 |
| 1210 // We expect all of the instrumentation functions to have been added. | 1230 // We expect all of the instrumentation functions to have been added. |
| 1211 Intersect(imports, expected, &results); | 1231 Intersect(imports, expected, &results); |
| 1212 if (!hot_patching) { | 1232 if (!hot_patching) { |
| 1213 EXPECT_EQ(expected, results); | 1233 EXPECT_EQ(expected, results); |
| 1214 } else { | 1234 } else { |
| 1215 // These should not be present in hot patching mode. | 1235 // These should not be present in hot patching mode. |
| 1216 EXPECT_TRUE(results.empty()); | 1236 EXPECT_TRUE(results.empty()); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 expected.insert("_asan_check_32_byte_read_access_no_flags"); | 1364 expected.insert("_asan_check_32_byte_read_access_no_flags"); |
| 1345 expected.insert("_asan_check_1_byte_write_access_no_flags"); | 1365 expected.insert("_asan_check_1_byte_write_access_no_flags"); |
| 1346 expected.insert("_asan_check_2_byte_write_access_no_flags"); | 1366 expected.insert("_asan_check_2_byte_write_access_no_flags"); |
| 1347 expected.insert("_asan_check_4_byte_write_access_no_flags"); | 1367 expected.insert("_asan_check_4_byte_write_access_no_flags"); |
| 1348 expected.insert("_asan_check_8_byte_write_access_no_flags"); | 1368 expected.insert("_asan_check_8_byte_write_access_no_flags"); |
| 1349 expected.insert("_asan_check_10_byte_write_access_no_flags"); | 1369 expected.insert("_asan_check_10_byte_write_access_no_flags"); |
| 1350 expected.insert("_asan_check_16_byte_write_access_no_flags"); | 1370 expected.insert("_asan_check_16_byte_write_access_no_flags"); |
| 1351 expected.insert("_asan_check_32_byte_write_access_no_flags"); | 1371 expected.insert("_asan_check_32_byte_write_access_no_flags"); |
| 1352 | 1372 |
| 1353 expected.insert("_asan_check_repz_4_byte_cmps_access"); | 1373 expected.insert("_asan_check_repz_4_byte_cmps_access"); |
| 1374 expected.insert("_asan_check_repz_4_byte_lods_access"); |
| 1354 expected.insert("_asan_check_repz_4_byte_movs_access"); | 1375 expected.insert("_asan_check_repz_4_byte_movs_access"); |
| 1355 expected.insert("_asan_check_repz_4_byte_stos_access"); | 1376 expected.insert("_asan_check_repz_4_byte_stos_access"); |
| 1356 expected.insert("_asan_check_repz_2_byte_cmps_access"); | 1377 expected.insert("_asan_check_repz_2_byte_cmps_access"); |
| 1378 expected.insert("_asan_check_repz_2_byte_lods_access"); |
| 1357 expected.insert("_asan_check_repz_2_byte_movs_access"); | 1379 expected.insert("_asan_check_repz_2_byte_movs_access"); |
| 1358 expected.insert("_asan_check_repz_2_byte_stos_access"); | 1380 expected.insert("_asan_check_repz_2_byte_stos_access"); |
| 1359 expected.insert("_asan_check_repz_1_byte_cmps_access"); | 1381 expected.insert("_asan_check_repz_1_byte_cmps_access"); |
| 1382 expected.insert("_asan_check_repz_1_byte_lods_access"); |
| 1360 expected.insert("_asan_check_repz_1_byte_movs_access"); | 1383 expected.insert("_asan_check_repz_1_byte_movs_access"); |
| 1361 expected.insert("_asan_check_repz_1_byte_stos_access"); | 1384 expected.insert("_asan_check_repz_1_byte_stos_access"); |
| 1362 | 1385 |
| 1363 expected.insert("_asan_check_4_byte_cmps_access"); | 1386 expected.insert("_asan_check_4_byte_cmps_access"); |
| 1387 expected.insert("_asan_check_4_byte_lods_access"); |
| 1364 expected.insert("_asan_check_4_byte_movs_access"); | 1388 expected.insert("_asan_check_4_byte_movs_access"); |
| 1365 expected.insert("_asan_check_4_byte_stos_access"); | 1389 expected.insert("_asan_check_4_byte_stos_access"); |
| 1366 expected.insert("_asan_check_2_byte_cmps_access"); | 1390 expected.insert("_asan_check_2_byte_cmps_access"); |
| 1391 expected.insert("_asan_check_2_byte_lods_access"); |
| 1367 expected.insert("_asan_check_2_byte_movs_access"); | 1392 expected.insert("_asan_check_2_byte_movs_access"); |
| 1368 expected.insert("_asan_check_2_byte_stos_access"); | 1393 expected.insert("_asan_check_2_byte_stos_access"); |
| 1369 expected.insert("_asan_check_1_byte_cmps_access"); | 1394 expected.insert("_asan_check_1_byte_cmps_access"); |
| 1395 expected.insert("_asan_check_1_byte_lods_access"); |
| 1370 expected.insert("_asan_check_1_byte_movs_access"); | 1396 expected.insert("_asan_check_1_byte_movs_access"); |
| 1371 expected.insert("_asan_check_1_byte_stos_access"); | 1397 expected.insert("_asan_check_1_byte_stos_access"); |
| 1372 | 1398 |
| 1373 StringSet results; | 1399 StringSet results; |
| 1374 Intersect(symbols, expected, &results); | 1400 Intersect(symbols, expected, &results); |
| 1375 EXPECT_THAT(results, ContainerEq(expected)); | 1401 EXPECT_THAT(results, ContainerEq(expected)); |
| 1376 | 1402 |
| 1377 // Expect at least some of the Asan instrumentation symbols to be referenced. | 1403 // Expect at least some of the Asan instrumentation symbols to be referenced. |
| 1378 size_t instrumentation_references = 0; | 1404 size_t instrumentation_references = 0; |
| 1379 StringSet::const_iterator str_it = expected.begin(); | 1405 StringSet::const_iterator str_it = expected.begin(); |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 | 1914 |
| 1889 // We check |padding_before| to see if the block has been prepared for hot | 1915 // We check |padding_before| to see if the block has been prepared for hot |
| 1890 // patching. | 1916 // patching. |
| 1891 size_t expected_padding = hot_patched_set_.count(block) ? 5U : 0U; | 1917 size_t expected_padding = hot_patched_set_.count(block) ? 5U : 0U; |
| 1892 EXPECT_EQ(expected_padding, block->padding_before()); | 1918 EXPECT_EQ(expected_padding, block->padding_before()); |
| 1893 } | 1919 } |
| 1894 } | 1920 } |
| 1895 | 1921 |
| 1896 } // namespace transforms | 1922 } // namespace transforms |
| 1897 } // namespace instrument | 1923 } // namespace instrument |
| OLD | NEW |