@@ -32,14 +32,25 @@ getDataSlice(ArrayRef<uint8_t> Data, uint64_t Offset, uint64_t Size) {
32
32
}
33
33
34
34
template <typename T>
35
- static Expected<const T &> getDataSliceAs ( ArrayRef<uint8_t > Data,
36
- uint64_t Offset ) {
35
+ static Expected<ArrayRef<T>>
36
+ getDataSliceAsArrayOf (ArrayRef< uint8_t > Data, uint64_t Offset, uint64_t Count ) {
37
37
static_assert (std::is_trivial_v<T>);
38
- Expected<ArrayRef<uint8_t >> Slice = getDataSlice (Data, Offset, sizeof (T));
38
+ Expected<ArrayRef<uint8_t >> Slice =
39
+ getDataSlice (Data, Offset, sizeof (T) * Count);
39
40
if (!Slice)
40
41
return Slice.takeError ();
41
42
42
- return *reinterpret_cast <const T *>(Slice->data ());
43
+ return ArrayRef (reinterpret_cast <const T *>(Slice->data ()), Count);
44
+ }
45
+
46
+ template <typename T>
47
+ static Expected<const T &> getDataSliceAs (ArrayRef<uint8_t > Data,
48
+ uint64_t Offset) {
49
+ Expected<ArrayRef<T>> Array = getDataSliceAsArrayOf<T>(Data, Offset, 1 );
50
+ if (!Array)
51
+ return Array.takeError ();
52
+
53
+ return Array->front ();
43
54
}
44
55
45
56
template <endianness E>
@@ -100,6 +111,119 @@ uint64_t SFrameParser<E>::getAbsoluteStartAddress(
100
111
return Result;
101
112
}
102
113
114
+ template <typename EndianT>
115
+ static Error readArray (ArrayRef<uint8_t > Data, uint64_t Count, uint64_t &Offset,
116
+ SmallVectorImpl<int32_t > &Vec) {
117
+ Expected<ArrayRef<EndianT>> RawArray =
118
+ getDataSliceAsArrayOf<EndianT>(Data, Offset, Count);
119
+ if (!RawArray)
120
+ return RawArray.takeError ();
121
+ Offset += Count * sizeof (EndianT);
122
+ Vec.resize (Count);
123
+ llvm::copy (*RawArray, Vec.begin ());
124
+ return Error::success ();
125
+ }
126
+
127
+ template <typename T, endianness E>
128
+ static Error readFRE (ArrayRef<uint8_t > Data, uint64_t &Offset,
129
+ typename SFrameParser<E>::FrameRowEntry &FRE) {
130
+ Expected<sframe::FrameRowEntry<T, E>> RawFRE =
131
+ getDataSliceAs<sframe::FrameRowEntry<T, E>>(Data, Offset);
132
+ if (!RawFRE)
133
+ return RawFRE.takeError ();
134
+
135
+ Offset += sizeof (*RawFRE);
136
+ FRE.StartAddress = RawFRE->StartAddress ;
137
+ FRE.Info .Info = RawFRE->Info .Info ;
138
+
139
+ switch (FRE.Info .getOffsetSize ()) {
140
+ case sframe::FREOffset::B1:
141
+ return readArray<sframe::detail::packed<int8_t , E>>(
142
+ Data, FRE.Info .getOffsetCount (), Offset, FRE.Offsets );
143
+ case sframe::FREOffset::B2:
144
+ return readArray<sframe::detail::packed<int16_t , E>>(
145
+ Data, FRE.Info .getOffsetCount (), Offset, FRE.Offsets );
146
+ case sframe::FREOffset::B4:
147
+ return readArray<sframe::detail::packed<int32_t , E>>(
148
+ Data, FRE.Info .getOffsetCount (), Offset, FRE.Offsets );
149
+ default :
150
+ return createError (" unsupported/unknown offset size" );
151
+ }
152
+ }
153
+
154
+ template <endianness E> Error SFrameParser<E>::FallibleFREIterator::inc() {
155
+ if (++Idx == Size)
156
+ return Error::success ();
157
+
158
+ switch (FREType) {
159
+ case sframe::FREType::Addr1:
160
+ return readFRE<uint8_t , E>(Data, Offset, FRE);
161
+ case sframe::FREType::Addr2:
162
+ return readFRE<uint16_t , E>(Data, Offset, FRE);
163
+ case sframe::FREType::Addr4:
164
+ return readFRE<uint32_t , E>(Data, Offset, FRE);
165
+ default :
166
+ return createError (" invalid/unsupported FRE type" );
167
+ }
168
+ }
169
+
170
+ template <endianness E>
171
+ iterator_range<typename SFrameParser<E>::fre_iterator>
172
+ SFrameParser<E>::fres(const sframe::FuncDescEntry<E> &FDE, Error &Err) const {
173
+ uint64_t Offset = getFREBase () + FDE.StartFREOff ;
174
+ fre_iterator BeforeBegin = make_fallible_itr (
175
+ FallibleFREIterator (Data, FDE.getFREType (), -1 , FDE.NumFREs , Offset),
176
+ Err);
177
+ fre_iterator End = make_fallible_end (
178
+ FallibleFREIterator (Data, FDE.getFREType (), FDE.NumFREs , FDE.NumFREs ,
179
+ /* Offset=*/ 0 ));
180
+ return {++BeforeBegin, End};
181
+ }
182
+
183
+ static std::optional<int32_t > getOffset (ArrayRef<int32_t > Offsets, size_t Idx) {
184
+ if (Offsets.size () > Idx)
185
+ return Offsets[Idx];
186
+ return std::nullopt;
187
+ }
188
+
189
+ // The interpretation of offsets is ABI-specific. The implementation of this and
190
+ // the following functions may need to be adjusted when adding support for a new
191
+ // ABI.
192
+ template <endianness E>
193
+ std::optional<int32_t >
194
+ SFrameParser<E>::getCFAOffset(const FrameRowEntry &FRE) const {
195
+ return getOffset (FRE.Offsets , 0 );
196
+ }
197
+
198
+ template <endianness E>
199
+ std::optional<int32_t >
200
+ SFrameParser<E>::getRAOffset(const FrameRowEntry &FRE) const {
201
+ if (usesFixedRAOffset ())
202
+ return Header.CFAFixedRAOffset ;
203
+ return getOffset (FRE.Offsets , 1 );
204
+ }
205
+
206
+ template <endianness E>
207
+ std::optional<int32_t >
208
+ SFrameParser<E>::getFPOffset(const FrameRowEntry &FRE) const {
209
+ if (usesFixedFPOffset ())
210
+ return Header.CFAFixedFPOffset ;
211
+ return getOffset (FRE.Offsets , usesFixedRAOffset () ? 1 : 2 );
212
+ }
213
+
214
+ template <endianness E>
215
+ ArrayRef<int32_t >
216
+ SFrameParser<E>::getExtraOffsets(const FrameRowEntry &FRE) const {
217
+ size_t UsedOffsets = 1 ; // CFA
218
+ if (!usesFixedRAOffset ())
219
+ ++UsedOffsets;
220
+ if (!usesFixedFPOffset ())
221
+ ++UsedOffsets;
222
+ if (FRE.Offsets .size () > UsedOffsets)
223
+ return ArrayRef (FRE.Offsets ).drop_front (UsedOffsets);
224
+ return {};
225
+ }
226
+
103
227
template class LLVM_EXPORT_TEMPLATE llvm::object::SFrameParser<endianness::big>;
104
228
template class LLVM_EXPORT_TEMPLATE
105
229
llvm::object::SFrameParser<endianness::little>;
0 commit comments