@@ -32,14 +32,25 @@ getDataSlice(ArrayRef<uint8_t> Data, uint64_t Offset, uint64_t Size) {
3232}
3333
3434template <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 ) {
3737 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);
3940 if (!Slice)
4041 return Slice.takeError ();
4142
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 ();
4354}
4455
4556template <endianness E>
@@ -100,6 +111,119 @@ uint64_t SFrameParser<E>::getAbsoluteStartAddress(
100111 return Result;
101112}
102113
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+
103227template class LLVM_EXPORT_TEMPLATE llvm::object::SFrameParser<endianness::big>;
104228template class LLVM_EXPORT_TEMPLATE
105229 llvm::object::SFrameParser<endianness::little>;
0 commit comments