-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[Object] Parsing and dumping of SFrame FDEs #149828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
c797a3e
fa55874
aee3776
c9845ee
7c7a5f3
ee148a6
9faaa0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,23 +14,34 @@ | |
| using namespace llvm; | ||
| using namespace llvm::object; | ||
|
|
||
| template <typename T> | ||
| static Expected<const T &> getDataSliceAs(ArrayRef<uint8_t> Data, | ||
| uint64_t Offset) { | ||
| static_assert(std::is_trivial_v<T>); | ||
| if (Data.size() < Offset + sizeof(T)) { | ||
| static Expected<ArrayRef<uint8_t>> | ||
| getDataSlice(ArrayRef<uint8_t> Data, uint64_t Offset, uint64_t Size) { | ||
| // Check for overflow. | ||
| if (Offset + Size < Offset || Offset + Size < Size || | ||
jh7370 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Offset + Size > Data.size()) { | ||
| return createStringError( | ||
| formatv("unexpected end of data at offset {0:x} while reading [{1:x}, " | ||
| "{2:x})", | ||
| Data.size(), Offset, Offset + sizeof(T)) | ||
| Data.size(), Offset, Offset + Size) | ||
| .str(), | ||
| object_error::unexpected_eof); | ||
| } | ||
| return *reinterpret_cast<const T *>(Data.data() + Offset); | ||
| return Data.slice(Offset, Size); | ||
| } | ||
|
|
||
| template <typename T> | ||
| static Expected<const T &> getDataSliceAs(ArrayRef<uint8_t> Data, | ||
| uint64_t Offset) { | ||
| static_assert(std::is_trivial_v<T>); | ||
| Expected<ArrayRef<uint8_t>> Slice = getDataSlice(Data, Offset, sizeof(T)); | ||
| if (!Slice) | ||
| return Slice.takeError(); | ||
|
|
||
| return *reinterpret_cast<const T *>(Slice->data()); | ||
| } | ||
|
|
||
| template <endianness E> | ||
| Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t> Contents) { | ||
| Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t> Contents, uint64_t SectionAddress) { | ||
| Expected<const sframe::Preamble<E> &> Preamble = | ||
| getDataSliceAs<sframe::Preamble<E>>(Contents, 0); | ||
| if (!Preamble) | ||
|
|
@@ -48,7 +59,42 @@ Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t> Contents) { | |
| getDataSliceAs<sframe::Header<E>>(Contents, 0); | ||
| if (!Header) | ||
| return Header.takeError(); | ||
| return SFrameParser(Contents, *Header); | ||
| return SFrameParser(Contents, SectionAddress, *Header); | ||
| } | ||
|
|
||
|
|
||
| template<endianness E> | ||
| Expected<ArrayRef<uint8_t>> SFrameParser<E>::getAuxHeader() const { | ||
| return getDataSlice(Data, sizeof(Header), Header.AuxHdrLen); | ||
| } | ||
|
|
||
| template<endianness E> | ||
| Expected<ArrayRef<sframe::FuncDescEntry<E>>> SFrameParser<E>::fdes() const { | ||
| Expected<ArrayRef<uint8_t>> Slice = getDataSlice( | ||
| Data, getFDEBegin(), Header.NumFDEs * sizeof(sframe::FuncDescEntry<E>)); | ||
| if (!Slice) | ||
| return Slice.takeError(); | ||
| return ArrayRef( | ||
| reinterpret_cast<const sframe::FuncDescEntry<E> *>(Slice->data()), | ||
| Header.NumFDEs); | ||
| } | ||
|
|
||
| template<endianness E> | ||
| uint64_t SFrameParser<E>::getAbsoluteStartAddress(typename FDERange::iterator FDE) const { | ||
| uint64_t Result = SectionAddress + FDE->StartAddress; | ||
|
|
||
| if ((getPreamble().Flags.value() & sframe::Flags::FDEFuncStartPCRel) == | ||
| sframe::Flags::FDEFuncStartPCRel) { | ||
| uintptr_t DataPtr = reinterpret_cast<uintptr_t>(Data.data()); | ||
| uintptr_t FDEPtr = reinterpret_cast<uintptr_t>(&*FDE); | ||
|
|
||
| assert(DataPtr <= FDEPtr); | ||
|
||
| assert(FDEPtr < DataPtr + Data.size()); | ||
|
|
||
| Result += FDEPtr - DataPtr; | ||
| } | ||
|
|
||
| return Result; | ||
| } | ||
|
|
||
| template class llvm::object::SFrameParser<endianness::big>; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ibhagatgnu, I'm a little but unsure about this part. This is the interpretation I get from the specification, and I think it matches this endiannes-flipping code in libsframe. However, that's not what happens in the actual parsing code. Can I assume the last part to be an omission/bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@labath the SFrame FDE offset is the offset of the FDE sub-section from the end of the SFrame header. So, the omission in the sframe_decode is harmless, but should be done for doc purposes and clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand. The value I linked to is used to locate the FDEs, so if
sfh_fdeoffis not zero, it will end up looking at the wrong place. Or are you saying that it does not matter in practice because the value will always be zero? That, I suppose is true (and I don't see why would anyone use a value other than zero here), but the spec does allow it so I suppose someone could do it.I guess my main question is whether I've implemented the FDE location code correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, using the FDEoffset is the right thing to do. You are right that the spec allows non-zero value for fde_offset. So I correct my previous statement: the omission in sframe_decode should be corrected to use the fde_offset to be fully compliant.