• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (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
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "verification/job_queue/job.h"
17 #include "verification/job_queue/job_queue.h"
18 #include "verification/job_queue/cache.h"
19 
20 #include "verification/absint/panda_types.h"
21 #include "verification/absint/absint.h"
22 
23 #include "runtime/include/thread_scopes.h"
24 #include "runtime/include/runtime.h"
25 #include "libpandabase/utils/logger.h"
26 
27 #include "verification/debug/breakpoint/breakpoint.h"
28 
29 namespace panda::verifier {
30 
UpdateTypes(PandaTypes * panda_types_ptr,const Job & job)31 bool UpdateTypes(PandaTypes *panda_types_ptr, const Job &job)
32 {
33     auto &panda_types = *panda_types_ptr;
34     bool result = true;
35     job.ForAllCachedClasses([&panda_types, &result](const CacheOfRuntimeThings::CachedClass &klass) {
36         auto type = panda_types.TypeOf(klass);
37         result = result && type.IsValid();
38     });
39     job.ForAllCachedMethods([&panda_types](const CacheOfRuntimeThings::CachedMethod &method) {
40         panda_types.NormalizedMethodSignature(method);
41     });
42     job.ForAllCachedFields([&panda_types, &result](const CacheOfRuntimeThings::CachedField &field) {
43         auto &klass_ref = CacheOfRuntimeThings::GetRef(field.klass);
44         auto &type_ref = CacheOfRuntimeThings::GetRef(field.type);
45         if (Valid(klass_ref) && Valid(type_ref)) {
46             auto class_type = panda_types.TypeOf(klass_ref);
47             auto field_type = panda_types.TypeOf(type_ref);
48             result = result && class_type.IsValid() && field_type.IsValid();
49         } else {
50             result = false;
51         }
52     });
53     return result;
54 }
55 
Verify(PandaTypes * panda_types,const Job & job)56 bool Verify(PandaTypes *panda_types, const Job &job)
57 {
58     auto verif_context = PrepareVerificationContext(panda_types, job);
59     auto result = VerifyMethod(VerificationLevel::LEVEL0, &verif_context);
60     return result != VerificationStatus::ERROR;
61 }
62 
SetResult(Method * method,bool result)63 void SetResult(Method *method, bool result)
64 {
65     auto &runtime = *Runtime::GetCurrent();
66     auto &verif_options = runtime.GetVerificationOptions();
67     if (verif_options.Mode.VerifierDoesNotFail) {
68         result = true;
69     }
70     method->SetVerified(result);
71 }
72 
VerifierThread(size_t n)73 void VerifierThread(size_t n)
74 {
75     while (true) {
76         bool result = true;
77 
78         auto *job_ptr = JobQueue::GetJob();
79         if (job_ptr == nullptr) {
80             break;
81         }
82         auto &job = *job_ptr;
83         auto &method = job.JobMethod();
84 
85         if (method.IsVerified()) {
86             // method may be marked as verified during marking all
87             // methods in runtime libraries
88             JobQueue::DisposeJob(&job);
89             continue;
90         }
91 
92         LOG(DEBUG, VERIFIER) << "Verification of method '" << method.GetFullName() << std::hex << "' ( 0x"
93                              << method.GetUniqId() << ", 0x" << reinterpret_cast<uintptr_t>(&method) << ")";
94 
95         auto &panda_types = JobQueue::GetPandaTypes(n);
96 
97         DBG_MANAGED_BRK(panda::verifier::debug::Component::VERIFIER, job.JobCachedMethod().id, 0xFFFF);
98 
99         ASSERT(method.GetInstructions() == job.JobCachedMethod().bytecode);
100 
101         if (job.Options().Check()[MethodOption::CheckType::TYPING]) {
102             result = UpdateTypes(&panda_types, job);
103             if (!result) {
104                 LOG(DEBUG, VERIFIER) << "Cannot update types from cached classes";
105             }
106         }
107 
108         if (job.Options().Check()[MethodOption::CheckType::ABSINT]) {
109             result = result && Verify(&panda_types, job);
110         }
111 
112         LOG(INFO, VERIFIER) << "Verification result for method '" << method.GetFullName() << std::hex << "' ( 0x"
113                             << method.GetUniqId() << ", 0x" << reinterpret_cast<uintptr_t>(&method)
114                             << "): " << (result ? "OK" : "FAIL");
115 
116         SetResult(&method, result);
117         JobQueue::DisposeJob(&job);
118     }
119     bool show_subtyping =
120         Runtime::GetCurrentSync([](auto &instance) { return instance.GetVerificationOptions().Debug.Show.TypeSystem; });
121     if (show_subtyping) {
122         LOG(DEBUG, VERIFIER) << "Typesystem of verifier thread #" << n;
123         auto &panda_types = JobQueue::GetPandaTypes(n);
124         panda_types.DisplayTypeSystem([](auto str) { LOG(DEBUG, VERIFIER) << str; });
125     }
126 }
127 
128 }  // namespace panda::verifier
129