• 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 #ifndef PANDA_VERIFICATION_CFLOW_JUMPS_MAP_H_
17 #define PANDA_VERIFICATION_CFLOW_JUMPS_MAP_H_
18 
19 #include "instructions_map.h"
20 
21 #include "util/index.h"
22 #include "util/addr_map.h"
23 #include "util/lazy.h"
24 
25 #include "runtime/include/mem/panda_containers.h"
26 
27 #include <cstdint>
28 
29 namespace panda::verifier {
30 class JumpsMap {
31 public:
32     struct FromTo {
33         const void *From;
34         const void *To;
35     };
36 
PutJump(const void * pc_jump_ptr,const void * pc_target_ptr)37     bool PutJump(const void *pc_jump_ptr, const void *pc_target_ptr)
38     {
39         if (!AddrMap_.IsInAddressSpace(pc_jump_ptr) || !AddrMap_.IsInAddressSpace(pc_target_ptr)) {
40             return false;
41         }
42         bool target_already_marked = AddrMap_.HasMark(pc_target_ptr);
43         if (!AddrMap_.Mark(pc_target_ptr)) {
44             return false;
45         }
46         FromTo_.push_back({pc_jump_ptr, pc_target_ptr});
47         if (!target_already_marked) {
48             Target_.push_back(pc_target_ptr);
49         }
50         return true;
51     }
52 
JumpsMap(const void * pc_start_ptr,const void * pc_end_ptr)53     JumpsMap(const void *pc_start_ptr, const void *pc_end_ptr) : AddrMap_(pc_start_ptr, pc_end_ptr) {}
JumpsMap(const void * pc_start_ptr,size_t size)54     JumpsMap(const void *pc_start_ptr, size_t size)
55         : JumpsMap(pc_start_ptr, reinterpret_cast<const void *>(reinterpret_cast<uintptr_t>(pc_start_ptr) + size - 1))
56     {
57     }
58     JumpsMap() = delete;
59     ~JumpsMap() = default;
60 
61     template <typename PtrType, typename Callback>
EnumerateAllTargets(Callback cb)62     void EnumerateAllTargets(Callback cb) const
63     {
64         for (const auto &tgt : Target_) {
65             if (!cb(reinterpret_cast<PtrType>(tgt))) {
66                 return;
67             }
68         }
69     }
70 
71     template <typename PtrType>
AllTargetsLazy()72     auto AllTargetsLazy() const
73     {
74         return Transform(ConstLazyFetch(Target_),
75                          [](const void *ptr) -> PtrType { return reinterpret_cast<PtrType>(const_cast<void *>(ptr)); });
76     }
77 
78     template <typename PtrType, typename Callback>
EnumerateAllJumpsToTarget(PtrType pc_target_ptr,Callback cb)79     void EnumerateAllJumpsToTarget(PtrType pc_target_ptr, Callback cb) const
80     {
81         // it is slow, but this operation is assumed to be very rare, only on
82         // cflow verification failures, so we here trade speed of this function
83         // for much faster positive path checks
84         for (const auto &from_to : FromTo_) {
85             if (from_to.To == reinterpret_cast<const void *>(pc_target_ptr)) {
86                 if (!cb(reinterpret_cast<PtrType>(from_to.From))) {
87                     return;
88                 }
89             }
90         }
91     }
IsConflictingWith(const InstructionsMap & inst_map)92     bool IsConflictingWith(const InstructionsMap &inst_map) const
93     {
94         return AddrMap_.HasCommonMarks(inst_map.AddrMap_);
95     }
96     template <typename PtrType>
GetFirstConflictingJump(const InstructionsMap & inst_map,PtrType * pc_jump_ptr,PtrType * pc_target_ptr)97     bool GetFirstConflictingJump(const InstructionsMap &inst_map, PtrType *pc_jump_ptr, PtrType *pc_target_ptr) const
98     {
99         if (!AddrMap_.GetFirstCommonMark(inst_map.AddrMap_, pc_target_ptr)) {
100             return false;
101         }
102         *pc_jump_ptr = nullptr;
103         EnumerateAllJumpsToTarget<PtrType>(*pc_target_ptr, [&pc_jump_ptr](PtrType jmp_ptr) {
104             *pc_jump_ptr = jmp_ptr;
105             return false;
106         });
107         ASSERT(*pc_jump_ptr != nullptr);
108         return true;
109     }
110 
111 private:
112     AddrMap AddrMap_;
113     PandaVector<const void *> Target_;
114     PandaVector<FromTo> FromTo_;
115 };
116 }  // namespace panda::verifier
117 
118 #endif  // PANDA_VERIFICATION_CFLOW_JUMPS_MAP_H_
119