OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/precompiler.h" | 5 #include "vm/precompiler.h" |
6 | 6 |
7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
482 I->object_store()->set_async_star_move_next_helper(null_function); | 482 I->object_store()->set_async_star_move_next_helper(null_function); |
483 I->object_store()->set_complete_on_async_return(null_function); | 483 I->object_store()->set_complete_on_async_return(null_function); |
484 I->object_store()->set_async_star_stream_controller(null_class); | 484 I->object_store()->set_async_star_stream_controller(null_class); |
485 DropLibraryEntries(); | 485 DropLibraryEntries(); |
486 } | 486 } |
487 DropClasses(); | 487 DropClasses(); |
488 DropLibraries(); | 488 DropLibraries(); |
489 | 489 |
490 BindStaticCalls(); | 490 BindStaticCalls(); |
491 SwitchICCalls(); | 491 SwitchICCalls(); |
492 Obfuscate(); | |
492 | 493 |
rmacnak
2017/08/23 01:16:50
We should clear the obfuscation table from the obj
Vyacheslav Egorov (Google)
2017/08/23 15:54:52
This is done at the end of Obfuscate()
| |
493 ProgramVisitor::Dedup(); | 494 ProgramVisitor::Dedup(); |
494 | 495 |
495 zone_ = NULL; | 496 zone_ = NULL; |
496 } | 497 } |
497 | 498 |
498 intptr_t symbols_before = -1; | 499 intptr_t symbols_before = -1; |
499 intptr_t symbols_after = -1; | 500 intptr_t symbols_after = -1; |
500 intptr_t capacity = -1; | 501 intptr_t capacity = -1; |
501 if (FLAG_trace_precompiler) { | 502 if (FLAG_trace_precompiler) { |
502 Symbols::GetStats(I, &symbols_before, &capacity); | 503 Symbols::GetStats(I, &symbols_before, &capacity); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
603 current->field_->set_guarded_cid(cid); | 604 current->field_->set_guarded_cid(cid); |
604 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); | 605 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); |
605 if (FLAG_trace_precompiler) { | 606 if (FLAG_trace_precompiler) { |
606 THR_Print( | 607 THR_Print( |
607 "Field %s <- Type %s\n", current->field_->ToCString(), | 608 "Field %s <- Type %s\n", current->field_->ToCString(), |
608 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); | 609 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); |
609 } | 610 } |
610 } | 611 } |
611 } | 612 } |
612 | 613 |
613 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { | 614 static Dart_QualifiedFunctionName vm_entry_points[] = { |
614 // Note that <rootlibrary>.main is not a root. The appropriate main will be | |
615 // discovered through _getMainClosure. | |
616 | |
617 AddSelector(Symbols::NoSuchMethod()); | |
618 | |
619 AddSelector(Symbols::Call()); // For speed, not correctness. | |
620 | |
621 // Allocated from C++. | |
622 Class& cls = Class::Handle(Z); | |
623 for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) { | |
624 ASSERT(isolate()->class_table()->IsValidIndex(cid)); | |
625 if (!isolate()->class_table()->HasValidClassAt(cid)) { | |
626 continue; | |
627 } | |
628 if ((cid == kDynamicCid) || (cid == kVoidCid) || | |
629 (cid == kFreeListElement) || (cid == kForwardingCorpse)) { | |
630 continue; | |
631 } | |
632 cls = isolate()->class_table()->At(cid); | |
633 AddInstantiatedClass(cls); | |
634 } | |
635 | |
636 Dart_QualifiedFunctionName vm_entry_points[] = { | |
637 // Functions | 615 // Functions |
638 {"dart:core", "::", "_completeDeferredLoads"}, | 616 {"dart:core", "::", "_completeDeferredLoads"}, |
639 {"dart:core", "::", "identityHashCode"}, | 617 {"dart:core", "::", "identityHashCode"}, |
640 {"dart:core", "AbstractClassInstantiationError", | 618 {"dart:core", "AbstractClassInstantiationError", |
641 "AbstractClassInstantiationError._create"}, | 619 "AbstractClassInstantiationError._create"}, |
642 {"dart:core", "ArgumentError", "ArgumentError."}, | 620 {"dart:core", "ArgumentError", "ArgumentError."}, |
643 {"dart:core", "ArgumentError", "ArgumentError.value"}, | 621 {"dart:core", "ArgumentError", "ArgumentError.value"}, |
644 {"dart:core", "CyclicInitializationError", "CyclicInitializationError."}, | 622 {"dart:core", "CyclicInitializationError", "CyclicInitializationError."}, |
645 {"dart:core", "FallThroughError", "FallThroughError._create"}, | 623 {"dart:core", "FallThroughError", "FallThroughError._create"}, |
646 {"dart:core", "FormatException", "FormatException."}, | 624 {"dart:core", "FormatException", "FormatException."}, |
(...skipping 21 matching lines...) Expand all Loading... | |
668 #if !defined(PRODUCT) | 646 #if !defined(PRODUCT) |
669 {"dart:_vmservice", "::", "_registerIsolate"}, | 647 {"dart:_vmservice", "::", "_registerIsolate"}, |
670 {"dart:developer", "Metrics", "_printMetrics"}, | 648 {"dart:developer", "Metrics", "_printMetrics"}, |
671 {"dart:developer", "::", "_runExtension"}, | 649 {"dart:developer", "::", "_runExtension"}, |
672 {"dart:isolate", "::", "_runPendingImmediateCallback"}, | 650 {"dart:isolate", "::", "_runPendingImmediateCallback"}, |
673 #endif // !PRODUCT | 651 #endif // !PRODUCT |
674 // Fields | 652 // Fields |
675 {"dart:core", "Error", "_stackTrace"}, | 653 {"dart:core", "Error", "_stackTrace"}, |
676 {"dart:math", "_Random", "_state"}, | 654 {"dart:math", "_Random", "_state"}, |
677 {NULL, NULL, NULL} // Must be terminated with NULL entries. | 655 {NULL, NULL, NULL} // Must be terminated with NULL entries. |
678 }; | 656 }; |
657 | |
658 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { | |
659 // Note that <rootlibrary>.main is not a root. The appropriate main will be | |
660 // discovered through _getMainClosure. | |
661 | |
662 AddSelector(Symbols::NoSuchMethod()); | |
663 | |
664 AddSelector(Symbols::Call()); // For speed, not correctness. | |
665 | |
666 // Allocated from C++. | |
667 Class& cls = Class::Handle(Z); | |
668 for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) { | |
669 ASSERT(isolate()->class_table()->IsValidIndex(cid)); | |
670 if (!isolate()->class_table()->HasValidClassAt(cid)) { | |
671 continue; | |
672 } | |
673 if ((cid == kDynamicCid) || (cid == kVoidCid) || | |
674 (cid == kFreeListElement) || (cid == kForwardingCorpse)) { | |
675 continue; | |
676 } | |
677 cls = isolate()->class_table()->At(cid); | |
678 AddInstantiatedClass(cls); | |
679 } | |
679 | 680 |
680 AddEntryPoints(vm_entry_points); | 681 AddEntryPoints(vm_entry_points); |
681 AddEntryPoints(embedder_entry_points); | 682 AddEntryPoints(embedder_entry_points); |
682 const Library& lib = Library::Handle(I->object_store()->root_library()); | 683 const Library& lib = Library::Handle(I->object_store()->root_library()); |
683 const String& name = String::Handle(String::New("main")); | 684 const String& name = String::Handle(String::New("main")); |
684 const Object& main_closure = Object::Handle(lib.GetFunctionClosure(name)); | 685 const Object& main_closure = Object::Handle(lib.GetFunctionClosure(name)); |
685 if (main_closure.IsClosure()) { | 686 if (main_closure.IsClosure()) { |
686 if (lib.LookupLocalFunction(name) == Function::null()) { | 687 if (lib.LookupLocalFunction(name) == Function::null()) { |
687 // Check whether the function is in exported namespace of library, in | 688 // Check whether the function is in exported namespace of library, in |
688 // this case we have to retain the root library caches. | 689 // this case we have to retain the root library caches. |
(...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2271 Code& target_code_; | 2272 Code& target_code_; |
2272 UnlinkedCallSet canonical_unlinked_calls_; | 2273 UnlinkedCallSet canonical_unlinked_calls_; |
2273 }; | 2274 }; |
2274 | 2275 |
2275 ASSERT(!I->compilation_allowed()); | 2276 ASSERT(!I->compilation_allowed()); |
2276 SwitchICCallsVisitor visitor(Z); | 2277 SwitchICCallsVisitor visitor(Z); |
2277 ProgramVisitor::VisitFunctions(&visitor); | 2278 ProgramVisitor::VisitFunctions(&visitor); |
2278 #endif | 2279 #endif |
2279 } | 2280 } |
2280 | 2281 |
2282 void Precompiler::Obfuscate() { | |
2283 // TODO(dartbug.com/XXX) remove URIs from Scripts and Libraries. | |
2284 | |
2285 // Discard obfuscation mappings to avoid including them into snapshot. | |
2286 I->object_store()->set_obfuscation_map(Array::Handle(Z)); | |
2287 } | |
2288 | |
2281 void Precompiler::FinalizeAllClasses() { | 2289 void Precompiler::FinalizeAllClasses() { |
2282 Library& lib = Library::Handle(Z); | 2290 Library& lib = Library::Handle(Z); |
2283 Class& cls = Class::Handle(Z); | 2291 Class& cls = Class::Handle(Z); |
2284 | 2292 |
2285 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 2293 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
2286 lib ^= libraries_.At(i); | 2294 lib ^= libraries_.At(i); |
2287 if (!lib.Loaded()) { | 2295 if (!lib.Loaded()) { |
2288 String& uri = String::Handle(Z, lib.url()); | 2296 String& uri = String::Handle(Z, lib.url()); |
2289 String& msg = String::Handle( | 2297 String& msg = String::Handle( |
2290 Z, | 2298 Z, |
(...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3323 FieldTypeMap* field_type_map) { | 3331 FieldTypeMap* field_type_map) { |
3324 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); | 3332 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); |
3325 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function); | 3333 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function); |
3326 | 3334 |
3327 ASSERT(FLAG_precompiled_mode); | 3335 ASSERT(FLAG_precompiled_mode); |
3328 const bool optimized = function.IsOptimizable(); // False for natives. | 3336 const bool optimized = function.IsOptimizable(); // False for natives. |
3329 DartPrecompilationPipeline pipeline(zone, field_type_map); | 3337 DartPrecompilationPipeline pipeline(zone, field_type_map); |
3330 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); | 3338 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); |
3331 } | 3339 } |
3332 | 3340 |
3341 Obfuscator::Obfuscator(Thread* thread, const String& private_key) | |
3342 : state_(NULL) { | |
3343 Isolate* isolate = thread->isolate(); | |
3344 Zone* zone = thread->zone(); | |
3345 | |
3346 if (isolate->obfuscate()) { | |
3347 ObjectStore* store = thread->isolate()->object_store(); | |
3348 Array& obfuscation_state = Array::Handle(zone, store->obfuscation_map()); | |
3349 | |
3350 if (store->obfuscation_map() == Array::null()) { | |
3351 const int kInitialPrivateCapacity = 256; | |
3352 obfuscation_state = Array::New(kSavedStateSize); | |
3353 obfuscation_state.SetAt( | |
3354 1, Array::Handle(zone, HashTables::New<ObfuscationMap>( | |
3355 kInitialPrivateCapacity, Heap::kOld))); | |
3356 } | |
3357 | |
3358 state_ = | |
3359 new (zone) ObfuscationState(thread, obfuscation_state, private_key); | |
3360 | |
3361 if (store->obfuscation_map() == Array::null()) { | |
3362 InitializeRenamingMap(isolate); | |
3363 } | |
3364 } | |
3365 } | |
3366 | |
3367 Obfuscator::~Obfuscator() { | |
3368 if (state_ != NULL) { | |
3369 state_->SaveState(); | |
3370 } | |
3371 } | |
3372 | |
3373 void Obfuscator::InitializeRenamingMap(Isolate* isolate) { | |
3374 // Prevent renaming of classes and method names mentioned in the | |
3375 // entry points lists. | |
3376 PreventRenaming(vm_entry_points); | |
3377 PreventRenaming(isolate->embedder_entry_points()); | |
3378 | |
3379 // Prevent renaming of all pseudo-keywords and operators. | |
3380 // Note: not all pseudo-keywords are mentioned in DART_KEYWORD_LIST | |
3381 // (for example 'hide', 'show' and async related keywords are omitted). | |
3382 // Those are protected from renaming as part of all symbols. | |
3383 #define PREVENT_RENAMING(name, value, priority, attr) \ | |
3384 do { \ | |
3385 if (Token::CanBeOverloaded(Token::name) || \ | |
3386 ((Token::attr & Token::kPseudoKeyword) != 0)) { \ | |
3387 PreventRenaming(value); \ | |
3388 } \ | |
3389 } while (0); | |
3390 | |
3391 DART_TOKEN_LIST(PREVENT_RENAMING) | |
3392 DART_KEYWORD_LIST(PREVENT_RENAMING) | |
3393 #undef PREVENT_RENAMING | |
3394 | |
3395 // Protect all symbols from renaming. | |
3396 #define PREVENT_RENAMING(name, value) PreventRenaming(value); | |
3397 PREDEFINED_SYMBOLS_LIST(PREVENT_RENAMING) | |
3398 #undef PREVENT_RENAMING | |
3399 | |
3400 // Protect NativeFieldWrapperClassX names from being obfuscated. Those | |
3401 // classes are created manually by the runtime system. | |
3402 // TODO(dartbug.com/XXX) instead call to Obfuscator::Rename from a place | |
3403 // where these are created. | |
3404 PreventRenaming("NativeFieldWrapperClass1"); | |
3405 PreventRenaming("NativeFieldWrapperClass2"); | |
3406 PreventRenaming("NativeFieldWrapperClass3"); | |
3407 PreventRenaming("NativeFieldWrapperClass4"); | |
3408 | |
3409 // Prevent renaming of ClassID.cid* fields. These fields are injected by | |
3410 // runtime. | |
3411 // TODO(dartbug.com/XXX) instead call to Obfuscator::Rename from a place | |
3412 // where these are created. | |
3413 #define CLASS_LIST_WITH_NULL(V) \ | |
3414 V(Null) \ | |
3415 CLASS_LIST_NO_OBJECT(V) | |
3416 #define PREVENT_RENAMING(clazz) PreventRenaming("cid" #clazz); | |
3417 CLASS_LIST_WITH_NULL(PREVENT_RENAMING) | |
3418 #undef PREVENT_RENAMING | |
3419 #undef CLASS_LIST_WITH_NULL | |
3420 | |
3421 // Prevent renaming of methods that are looked up by method recognizer. | |
3422 // TODO(dartbug.com/XXX) instead call to Obfuscator::Rename from a place | |
3423 // where these are looked up. | |
3424 #define PREVENT_RENAMING(class_name, function_name, recognized_enum, \ | |
3425 result_type, fingerprint) \ | |
3426 do { \ | |
3427 PreventRenaming(#class_name); \ | |
3428 PreventRenaming(#function_name); \ | |
3429 } while (0); | |
3430 RECOGNIZED_LIST(PREVENT_RENAMING) | |
3431 #undef PREVENT_RENAMING | |
3432 | |
3433 // Prevent renaming of methods that are looked up by method recognizer. | |
3434 // TODO(dartbug.com/XXX) instead call to Obfuscator::Rename from a place | |
3435 // where these are looked up. | |
3436 #define PREVENT_RENAMING(class_name, function_name, recognized_enum, \ | |
3437 fingerprint) \ | |
3438 do { \ | |
3439 PreventRenaming(#class_name); \ | |
3440 PreventRenaming(#function_name); \ | |
3441 } while (0); | |
3442 INLINE_WHITE_LIST(PREVENT_RENAMING) | |
3443 INLINE_BLACK_LIST(PREVENT_RENAMING) | |
3444 POLYMORPHIC_TARGET_LIST(PREVENT_RENAMING) | |
3445 #undef PREVENT_RENAMING | |
3446 | |
3447 // These are not mentioned by entry points but are still looked up by name. | |
rmacnak
2017/08/23 01:16:50
They should be mentioned by the entry points. We'r
Vyacheslav Egorov (Google)
2017/08/23 15:54:52
Done.
| |
3448 PreventRenaming("_resolveScriptUri"); | |
3449 PreventRenaming("_printClosure"); | |
3450 PreventRenaming("_uriBaseClosure"); | |
3451 PreventRenaming("_isolateId"); | |
3452 PreventRenaming("_loadPort"); | |
3453 PreventRenaming("_ip"); | |
3454 PreventRenaming("_port"); | |
3455 PreventRenaming("_autoStart"); | |
3456 PreventRenaming("_originCheckDisabled"); | |
3457 PreventRenaming("_isWindows"); | |
3458 PreventRenaming("_isFuchsia"); | |
3459 PreventRenaming("_traceLoading"); | |
3460 PreventRenaming("_getWatchSignalInternal"); | |
3461 PreventRenaming("_signalWatch"); | |
3462 PreventRenaming("main"); | |
3463 | |
3464 // Fast path for common conditional import. See Deobfuscate method. | |
3465 PreventRenaming("dart"); | |
3466 PreventRenaming("library"); | |
3467 PreventRenaming("io"); | |
3468 PreventRenaming("html"); | |
3469 } | |
3470 | |
3471 RawString* Obfuscator::ObfuscationState::RenameImpl(const String& name, | |
3472 bool atomic) { | |
3473 ASSERT(name.IsSymbol()); | |
3474 | |
3475 renamed_ ^= renames_.GetOrNull(name); | |
3476 if (renamed_.IsNull()) { | |
3477 renamed_ = BuildRename(name, atomic); | |
3478 renames_.UpdateOrInsert(name, renamed_); | |
3479 } | |
3480 return renamed_.raw(); | |
3481 } | |
3482 | |
3483 void Obfuscator::PreventRenaming(Dart_QualifiedFunctionName entry_points[]) { | |
3484 for (intptr_t i = 0; entry_points[i].function_name != NULL; i++) { | |
3485 const char* class_name = entry_points[i].class_name; | |
3486 const char* function_name = entry_points[i].function_name; | |
3487 | |
3488 const size_t class_name_len = strlen(class_name); | |
3489 if (strncmp(function_name, class_name, class_name_len) == 0 && | |
3490 function_name[class_name_len] == '.') { | |
3491 const char* ctor_name = function_name + class_name_len + 1; | |
3492 if (ctor_name[0] != '\0') { | |
3493 PreventRenaming(ctor_name); | |
3494 } | |
3495 } else { | |
3496 PreventRenaming(function_name); | |
3497 } | |
3498 PreventRenaming(class_name); | |
3499 } | |
3500 } | |
3501 | |
3502 static const char* const kGetterPrefix = "get:"; | |
3503 static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); | |
3504 static const char* const kSetterPrefix = "set:"; | |
3505 static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); | |
3506 | |
3507 void Obfuscator::PreventRenaming(const char* name) { | |
3508 const char* dot = strchr(name, '.'); | |
3509 if (dot != NULL) { | |
3510 name = dot + 1; | |
3511 } | |
3512 | |
3513 if (name[0] == '\0') { | |
3514 return; | |
3515 } | |
3516 | |
3517 if (strncmp(name, kGetterPrefix, kGetterPrefixLength) == 0) { | |
3518 name = name + kGetterPrefixLength; | |
3519 } else if (strncmp(name, kSetterPrefix, kSetterPrefixLength) == 0) { | |
3520 name = name + kSetterPrefixLength; | |
3521 } | |
3522 | |
3523 state_->PreventRenaming(name); | |
3524 } | |
3525 | |
3526 void Obfuscator::ObfuscationState::SaveState() { | |
3527 saved_state_.SetAt(kSavedStateNameIndex, String::Handle(String::New(name_))); | |
3528 saved_state_.SetAt(kSavedStateRenamesIndex, renames_.Release()); | |
3529 thread_->isolate()->object_store()->set_obfuscation_map(saved_state_); | |
3530 } | |
3531 | |
3532 void Obfuscator::ObfuscationState::PreventRenaming(const char* name) { | |
3533 string_ = Symbols::New(thread_, name); | |
3534 PreventRenaming(string_); | |
3535 } | |
3536 | |
3537 void Obfuscator::ObfuscationState::PreventRenaming(const String& name) { | |
3538 renames_.UpdateOrInsert(name, name); | |
3539 } | |
3540 | |
3541 void Obfuscator::ObfuscationState::NextName() { | |
3542 for (intptr_t i = 0;; i++) { | |
3543 const char digit = name_[i]; | |
3544 if (digit == '\0') { | |
3545 name_[i] = 'a'; | |
3546 } else if (digit < 'Z') { | |
3547 name_[i]++; | |
3548 } else if (digit == 'Z') { | |
3549 name_[i] = 'a'; | |
3550 continue; | |
3551 } else if (digit < 'z') { | |
3552 name_[i]++; | |
3553 } else { | |
3554 name_[i] = 'A'; | |
3555 } | |
3556 break; | |
3557 } | |
3558 } | |
3559 | |
3560 RawString* Obfuscator::ObfuscationState::NewAtomicRename( | |
3561 bool should_be_private) { | |
3562 do { | |
3563 NextName(); | |
3564 renamed_ = Symbols::NewFormatted(thread_, "%s%s", | |
3565 should_be_private ? "_" : "", name_); | |
3566 } while (renames_.ContainsKey(renamed_)); | |
3567 return renamed_.raw(); | |
3568 } | |
3569 | |
3570 RawString* Obfuscator::ObfuscationState::BuildRename(const String& name, | |
3571 bool atomic) { | |
3572 const bool is_private = name.CharAt(0) == '_'; | |
3573 if (!atomic && is_private) { | |
3574 intptr_t i = 0; | |
3575 while (i < name.Length() && name.CharAt(i) != '@') { | |
3576 i++; | |
3577 } | |
3578 const intptr_t end = i; | |
3579 | |
3580 string_ = Symbols::New(thread_, name, 0, end); | |
3581 | |
3582 string_ = RenameImpl(string_, /*atomic=*/true); | |
3583 return Symbols::FromConcat(thread_, string_, private_key_); | |
3584 } else { | |
3585 return NewAtomicRename(is_private); | |
3586 } | |
3587 } | |
3588 | |
3589 void Obfuscator::ObfuscateSymbolInstance(Thread* thread, | |
3590 const Instance& symbol) { | |
3591 const intptr_t kSymbolNameOffset = kWordSize; | |
3592 | |
3593 Object& name_value = String::Handle(); | |
3594 name_value = symbol.RawGetFieldAtOffset(kSymbolNameOffset); | |
3595 if (!name_value.IsString()) { | |
3596 // dart.internal.Symbol constructor does not validate its input. | |
3597 return; | |
3598 } | |
3599 | |
3600 String& name = String::Handle(); | |
3601 name ^= name_value.raw(); | |
3602 | |
3603 // TODO(vegorov) it is quite wasteful to create an obfuscator per-symbol. | |
3604 Obfuscator obfuscator(thread, /*private_key=*/String::Handle()); | |
3605 | |
3606 String& component = String::Handle(); | |
3607 GrowableHandlePtrArray<const String> renamed(thread->zone(), 2); | |
3608 | |
3609 const intptr_t length = name.Length(); | |
3610 intptr_t i = 0, start = 0; | |
3611 while (i < length) { | |
3612 // First look for a '.' in the symbol. | |
3613 start = i; | |
3614 while (i < length && name.CharAt(i) != '.') { | |
3615 i++; | |
3616 } | |
3617 const intptr_t end = i; | |
3618 if (end == length) { | |
3619 break; | |
3620 } | |
3621 | |
3622 if (start != end) { | |
3623 component = Symbols::New(thread, name, start, end - start); | |
3624 component = obfuscator.Rename(component, /*atomic=*/true); | |
3625 renamed.Add(component); | |
3626 } | |
3627 | |
3628 renamed.Add(Symbols::Dot()); | |
3629 i++; // Skip '.' | |
3630 } | |
3631 | |
3632 // Handle the last component [start, length). | |
3633 // If symbol ends up at = and it is not one of '[]=', '==', '<=' or | |
3634 // '>=' then we treat it as a setter symbol of form 'name=' and | |
3635 // obfuscate to rename('name') + '='. | |
3636 const bool is_setter = (length - start) > 1 && | |
3637 name.CharAt(length - 1) == '=' && | |
3638 !(name.Equals(Symbols::AssignIndexToken()) || | |
3639 name.Equals(Symbols::EqualOperator()) || | |
3640 name.Equals(Symbols::GreaterEqualOperator()) || | |
3641 name.Equals(Symbols::LessEqualOperator())); | |
3642 const intptr_t end = length - (is_setter ? 1 : 0); | |
3643 | |
3644 if ((start == 0) && (end == length) && name.IsSymbol()) { | |
3645 component = name.raw(); | |
3646 } else { | |
3647 component = Symbols::New(thread, name, start, end - start); | |
3648 } | |
3649 component = obfuscator.Rename(component, /*atomic=*/true); | |
3650 renamed.Add(component); | |
3651 | |
3652 if (is_setter) { | |
3653 renamed.Add(Symbols::Equals()); | |
3654 } | |
3655 | |
3656 name = Symbols::FromConcatAll(thread, renamed); | |
3657 symbol.RawSetFieldAtOffset(kSymbolNameOffset, name); | |
3658 } | |
3659 | |
3660 void Obfuscator::Deobfuscate(Thread* thread, | |
3661 const GrowableObjectArray& pieces) { | |
3662 const Array& obfuscation_state = Array::Handle( | |
3663 thread->zone(), thread->isolate()->object_store()->obfuscation_map()); | |
3664 if (obfuscation_state.IsNull()) { | |
3665 return; | |
3666 } | |
3667 | |
3668 const Array& renames = Array::Handle( | |
3669 thread->zone(), GetRenamesFromSavedState(obfuscation_state)); | |
3670 | |
3671 ObfuscationMap renames_map(renames.raw()); | |
3672 String& piece = String::Handle(); | |
3673 for (intptr_t i = 0; i < pieces.Length(); i++) { | |
3674 piece ^= pieces.At(i); | |
3675 ASSERT(piece.IsSymbol()); | |
3676 | |
3677 // Fast path: skip '.' | |
3678 if (piece.raw() == Symbols::Dot().raw()) { | |
3679 continue; | |
3680 } | |
3681 | |
3682 // Fast path: check if piece has an identity obfuscation. | |
3683 if (renames_map.GetOrNull(piece) == piece.raw()) { | |
3684 continue; | |
3685 } | |
3686 | |
3687 ObfuscationMap::Iterator it(&renames_map); | |
3688 while (it.MoveNext()) { | |
3689 const intptr_t entry = it.Current(); | |
3690 if (renames_map.GetPayload(entry, 0) == piece.raw()) { | |
3691 piece ^= renames_map.GetKey(entry); | |
3692 pieces.SetAt(i, piece); | |
3693 break; | |
3694 } | |
3695 } | |
3696 } | |
3697 renames_map.Release(); | |
3698 } | |
3699 | |
3333 #endif // DART_PRECOMPILER | 3700 #endif // DART_PRECOMPILER |
3334 | 3701 |
3335 } // namespace dart | 3702 } // namespace dart |
OLD | NEW |