1 /**
2 * Copyright (c) 2021-2022 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 "field_data_accessor.h"
17
18 #include "utils/leb128.h"
19
20 namespace panda::panda_file {
21
FieldDataAccessor(const File &panda_file, File::EntityId field_id)22 FieldDataAccessor::FieldDataAccessor(const File &panda_file, File::EntityId field_id)
23 : panda_file_(panda_file), field_id_(field_id)
24 {
25 auto sp = panda_file_.GetSpanFromId(field_id_);
26
27 auto class_idx = helpers::Read<IDX_SIZE>(&sp);
28 auto type_idx = helpers::Read<IDX_SIZE>(&sp);
29
30 class_off_ = panda_file.ResolveClassIndex(field_id, class_idx).GetOffset();
31 type_off_ = panda_file.ResolveClassIndex(field_id, type_idx).GetOffset();
32
33 name_off_ = helpers::Read<ID_SIZE>(&sp);
34
35 is_external_ = panda_file_.IsExternal(field_id_);
36
37 if (!is_external_) {
38 access_flags_ = helpers::ReadULeb128(&sp);
39 tagged_values_sp_ = sp;
40 size_ = 0;
41 } else {
42 access_flags_ = 0;
43 size_ = panda_file_.GetIdFromPointer(sp.data()).GetOffset() - field_id_.GetOffset();
44 }
45 }
46
GetValueInternal()47 std::optional<FieldDataAccessor::FieldValue> FieldDataAccessor::GetValueInternal()
48 {
49 panda_file_.ThrowIfWithCheck(tagged_values_sp_.Size() == 0U, File::INVALID_FILE_OFFSET, File::FIELD_DATA_ACCESSOR);
50
51 auto sp = tagged_values_sp_;
52 auto tag = static_cast<FieldTag>(sp[0]);
53 FieldValue value;
54
55 if (tag == FieldTag::INT_VALUE) {
56 panda_file_.ThrowIfWithCheck(sp.Size() == 0U, File::INVALID_FILE_OFFSET, File::FIELD_DATA_ACCESSOR);
57 sp = sp.SubSpan(1);
58 value = static_cast<uint32_t>(helpers::ReadLeb128(&sp));
59 } else if (tag == FieldTag::VALUE) {
60 panda_file_.ThrowIfWithCheck(sp.Size() == 0U, File::INVALID_FILE_OFFSET, File::FIELD_DATA_ACCESSOR);
61 sp = sp.SubSpan(1);
62
63 switch (GetType()) {
64 case Type(Type::TypeId::F32).GetFieldEncoding(): {
65 value = static_cast<uint32_t>(helpers::Read<sizeof(uint32_t)>(&sp));
66 break;
67 }
68 case Type(Type::TypeId::I64).GetFieldEncoding():
69 case Type(Type::TypeId::U64).GetFieldEncoding():
70 case Type(Type::TypeId::F64).GetFieldEncoding(): {
71 auto offset = static_cast<uint32_t>(helpers::Read<sizeof(uint32_t)>(&sp));
72 auto value_sp = panda_file_.GetSpanFromId(File::EntityId(offset));
73 value = static_cast<uint64_t>(helpers::Read<sizeof(uint64_t)>(value_sp));
74 break;
75 }
76 default: {
77 value = static_cast<uint32_t>(helpers::Read<sizeof(uint32_t)>(&sp));
78 break;
79 }
80 }
81 }
82
83 runtime_annotations_sp_ = sp;
84
85 if (tag == FieldTag::INT_VALUE || tag == FieldTag::VALUE) {
86 return value;
87 }
88
89 return {};
90 }
91
92 } // namespace panda::panda_file
93