• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 LIBPANDAFILE_CODE_DATA_ACCESSOR_INL_H_
17 #define LIBPANDAFILE_CODE_DATA_ACCESSOR_INL_H_
18 
19 #include <algorithm>
20 #include "code_data_accessor.h"
21 
22 namespace ark::panda_file {
23 
24 template <class Callback>
EnumerateCatchBlocks(const Callback & cb)25 inline void CodeDataAccessor::TryBlock::EnumerateCatchBlocks(const Callback &cb)
26 {
27     auto sp = catchBlocksSp_;
28     for (size_t i = 0; i < numCatches_; i++) {
29         CatchBlock catchBlock(sp);
30         if (!cb(catchBlock)) {
31             return;
32         }
33         sp = sp.SubSpan(catchBlock.GetSize());
34     }
35     size_ = sp.data() - data_.data();
36 }
37 
SkipCatchBlocks()38 inline void CodeDataAccessor::TryBlock::SkipCatchBlocks()
39 {
40     EnumerateCatchBlocks([](const CatchBlock & /* unused */) { return true; });
41 }
42 
43 template <class Callback>
EnumerateTryBlocks(const Callback & cb)44 inline void CodeDataAccessor::EnumerateTryBlocks(const Callback &cb)
45 {
46     EnumerateTryBlocksImpl(cb);
47 }
48 
49 template <class Callback>
EnumerateTryBlocksImpl(const Callback & cb)50 void CodeDataAccessor::EnumerateTryBlocksImpl(const Callback &cb)
51 {
52     auto sp = tryBlocksSp_;
53 
54     for (size_t i = 0; i < triesSize_; i++) {
55         TryBlock tryBlock(sp);
56         uint32_t startPc = tryBlock.GetStartPc();
57         uint32_t length = tryBlock.GetLength();
58         if (codeSize_ == 0 || startPc >= codeSize_ || (startPc + length) > codeSize_) {
59             LOG(FATAL, PANDAFILE) << "Invalid TryBlock at index " << i << ": start=" << startPc << ", length=" << length
60                                   << ", codeSize=" << codeSize_;
61         }
62 
63         size_t trySize = tryBlock.GetSize();
64         if (trySize > sp.Size()) {
65             LOG(FATAL, PANDAFILE) << "TryBlock size overflow at index " << i << ": trySize=" << trySize
66                                   << ", spSize=" << sp.Size();
67         }
68 
69         if (!cb(tryBlock)) {
70             return;
71         }
72 
73         sp = sp.SubSpan(trySize);
74     }
75     size_ = pandaFile_.GetIdFromPointer(sp.data()).GetOffset() - codeId_.GetOffset();
76 }
77 
SkipTryBlocks()78 inline void CodeDataAccessor::SkipTryBlocks()
79 {
80     EnumerateTryBlocks([](const TryBlock & /* unused */) { return true; });
81 }
82 
83 // static
GetNumVregs(const File & pf,File::EntityId codeId)84 inline uint32_t CodeDataAccessor::GetNumVregs(const File &pf, File::EntityId codeId)
85 {
86     uint32_t numVregs;
87     auto sp = pf.GetSpanFromId(codeId);
88     numVregs = helpers::ReadULeb128(&sp);
89     return numVregs;
90 }
91 
92 // static
GetInstructions(const File & pf,File::EntityId codeId,uint32_t * vregs)93 inline const uint8_t *CodeDataAccessor::GetInstructions(const File &pf, File::EntityId codeId, uint32_t *vregs)
94 {
95     auto sp = pf.GetSpanFromId(codeId);
96     *vregs = helpers::ReadULeb128(&sp);
97     helpers::SkipULeb128(&sp);  // num_args
98     helpers::SkipULeb128(&sp);  // code_size
99     helpers::SkipULeb128(&sp);  // tries_size
100     return sp.data();
101 }
102 
103 }  // namespace ark::panda_file
104 
105 #endif  // LIBPANDAFILE_CODE_DATA_ACCESSOR_INL_H_
106