[llvm] [Object] Parsing and dumping of SFrame Frame Row Entries (PR #151301)
Pavel Labath via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 6 02:28:41 PDT 2025
================
@@ -100,6 +111,116 @@ uint64_t SFrameParser<E>::getAbsoluteStartAddress(
return Result;
}
+template <typename EndianT>
+static Error readArray(ArrayRef<uint8_t> Data, uint64_t Count, uint64_t &Offset,
+ SmallVectorImpl<int32_t> &Vec) {
+ Expected<ArrayRef<EndianT>> RawArray =
+ getDataSliceAsArrayOf<EndianT>(Data, Offset, Count);
+ if (!RawArray)
+ return RawArray.takeError();
+ Offset += Count * sizeof(EndianT);
+ Vec.resize(Count);
+ llvm::copy(*RawArray, Vec.begin());
+ return Error::success();
+}
+
+template <typename T, endianness E>
+static Error readFRE(ArrayRef<uint8_t> Data, uint64_t &Offset,
+ typename SFrameParser<E>::FrameRowEntry &FRE) {
+ Expected<sframe::FrameRowEntry<T, E>> RawFRE =
+ getDataSliceAs<sframe::FrameRowEntry<T, E>>(Data, Offset);
+ if (!RawFRE)
+ return RawFRE.takeError();
+
+ Offset += sizeof(*RawFRE);
+ FRE.StartAddress = RawFRE->StartAddress;
+ FRE.Info.Info = RawFRE->Info.Info;
+
+ switch (FRE.Info.getOffsetSize()) {
+ case sframe::FREOffset::B1:
+ return readArray<sframe::detail::packed<int8_t, E>>(
+ Data, FRE.Info.getOffsetCount(), Offset, FRE.Offsets);
+ case sframe::FREOffset::B2:
+ return readArray<sframe::detail::packed<int16_t, E>>(
+ Data, FRE.Info.getOffsetCount(), Offset, FRE.Offsets);
+ case sframe::FREOffset::B4:
+ return readArray<sframe::detail::packed<int32_t, E>>(
+ Data, FRE.Info.getOffsetCount(), Offset, FRE.Offsets);
+ default:
+ return createError("unsupported/unknown offset size");
+ }
+}
+
+template <endianness E> Error SFrameParser<E>::FallibleFREIterator::inc() {
+ if (++Idx == Size)
+ return Error::success();
+
+ switch (FREType) {
+ case sframe::FREType::Addr1:
+ return readFRE<uint8_t, E>(Data, Offset, FRE);
+ case sframe::FREType::Addr2:
+ return readFRE<uint16_t, E>(Data, Offset, FRE);
+ case sframe::FREType::Addr4:
+ return readFRE<uint32_t, E>(Data, Offset, FRE);
+ default:
+ return createError("invalid/unsupported FRE type");
+ }
+}
+
+template <endianness E>
+iterator_range<typename SFrameParser<E>::fre_iterator>
+SFrameParser<E>::fres(const sframe::FuncDescEntry<E> &FDE, Error &Err) const {
+ uint64_t Offset = getFREBase() + FDE.StartFREOff;
+ fre_iterator BeforeBegin = make_fallible_itr(
+ FallibleFREIterator(Data, FDE.getFREType(), -1, FDE.NumFREs, Offset),
+ Err);
+ fre_iterator End = make_fallible_end(
+ FallibleFREIterator(Data, FDE.getFREType(), FDE.NumFREs, FDE.NumFREs,
+ /*Offset=*/0));
+ return {++BeforeBegin, End};
+}
+
+static std::optional<int32_t> getOffset(ArrayRef<int32_t> Offsets, size_t Idx) {
+ if (Offsets.size() > Idx)
+ return Offsets[Idx];
+ return std::nullopt;
+}
+
+template <endianness E>
+std::optional<int32_t>
+SFrameParser<E>::getCFAOffset(const FrameRowEntry &FRE) const {
+ return getOffset(FRE.Offsets, 0);
----------------
labath wrote:
Yeah, I expect that the implementation of these functions will need to change when adding a new ABI. In fact, it looks like the recently updated specification adds support for the s390x architecture/ABI. The offset numbers don't really change, but their interpretation is a lot more complicated (mainly to account for the fact that FP/RA registers can be saved in another register.
That will most likely mean changing the interface (return value) of these functions as well.
I added a comment as requested. I will also look into adding s390x support to make the parser complete.
https://github.com/llvm/llvm-project/pull/151301
More information about the llvm-commits
mailing list