1010#include " llvm/BinaryFormat/SFrame.h"
1111#include " llvm/Object/Error.h"
1212#include " llvm/Support/FormatVariadic.h"
13+ #include " llvm/Support/MathExtras.h"
1314
1415using namespace llvm ;
1516using namespace llvm ::object;
1617
17- template <typename T>
18- static Expected<const T &> getDataSliceAs (ArrayRef<uint8_t > Data,
19- uint64_t Offset) {
20- static_assert (std::is_trivial_v<T>);
21- if (Data.size () < Offset + sizeof (T)) {
18+ static Expected<ArrayRef<uint8_t >>
19+ getDataSlice (ArrayRef<uint8_t > Data, uint64_t Offset, uint64_t Size) {
20+ uint64_t End = SaturatingAdd (Offset, Size);
21+ // Data.size() cannot be UINT64_MAX, as it would occupy the whole address
22+ // space.
23+ if (End > Data.size ()) {
2224 return createStringError (
2325 formatv (" unexpected end of data at offset {0:x} while reading [{1:x}, "
2426 " {2:x})" ,
25- Data.size (), Offset, Offset + sizeof (T) )
27+ Data.size (), Offset, End )
2628 .str (),
2729 object_error::unexpected_eof);
2830 }
29- return *reinterpret_cast <const T *>(Data.data () + Offset);
31+ return Data.slice (Offset, Size);
32+ }
33+
34+ template <typename T>
35+ static Expected<const T &> getDataSliceAs (ArrayRef<uint8_t > Data,
36+ uint64_t Offset) {
37+ static_assert (std::is_trivial_v<T>);
38+ Expected<ArrayRef<uint8_t >> Slice = getDataSlice (Data, Offset, sizeof (T));
39+ if (!Slice)
40+ return Slice.takeError ();
41+
42+ return *reinterpret_cast <const T *>(Slice->data ());
3043}
3144
3245template <endianness E>
33- Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t > Contents) {
46+ Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t > Contents,
47+ uint64_t SectionAddress) {
3448 Expected<const sframe::Preamble<E> &> Preamble =
3549 getDataSliceAs<sframe::Preamble<E>>(Contents, 0 );
3650 if (!Preamble)
@@ -48,7 +62,42 @@ Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t> Contents) {
4862 getDataSliceAs<sframe::Header<E>>(Contents, 0 );
4963 if (!Header)
5064 return Header.takeError ();
51- return SFrameParser (Contents, *Header);
65+ return SFrameParser (Contents, SectionAddress, *Header);
66+ }
67+
68+ template <endianness E>
69+ Expected<ArrayRef<uint8_t >> SFrameParser<E>::getAuxHeader() const {
70+ return getDataSlice (Data, sizeof (Header), Header.AuxHdrLen );
71+ }
72+
73+ template <endianness E>
74+ Expected<ArrayRef<sframe::FuncDescEntry<E>>> SFrameParser<E>::fdes() const {
75+ Expected<ArrayRef<uint8_t >> Slice = getDataSlice (
76+ Data, getFDEBase (), Header.NumFDEs * sizeof (sframe::FuncDescEntry<E>));
77+ if (!Slice)
78+ return Slice.takeError ();
79+ return ArrayRef (
80+ reinterpret_cast <const sframe::FuncDescEntry<E> *>(Slice->data ()),
81+ Header.NumFDEs );
82+ }
83+
84+ template <endianness E>
85+ uint64_t SFrameParser<E>::getAbsoluteStartAddress(
86+ typename FDERange::iterator FDE) const {
87+ uint64_t Result = SectionAddress + FDE->StartAddress ;
88+
89+ if ((getPreamble ().Flags .value () & sframe::Flags::FDEFuncStartPCRel) ==
90+ sframe::Flags::FDEFuncStartPCRel) {
91+ uintptr_t DataPtr = reinterpret_cast <uintptr_t >(Data.data ());
92+ uintptr_t FDEPtr = reinterpret_cast <uintptr_t >(&*FDE);
93+
94+ assert (DataPtr <= FDEPtr && FDEPtr < DataPtr + Data.size () &&
95+ " Iterator does not belong to this object!" );
96+
97+ Result += FDEPtr - DataPtr;
98+ }
99+
100+ return Result;
52101}
53102
54103template class LLVM_EXPORT_TEMPLATE llvm::object::SFrameParser<endianness::big>;
0 commit comments