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