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