From aa7ada1dfbe21a0c83474eb3de54e08eb607f8b8 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 21 Jul 2025 08:46:21 +0200 Subject: [Object] Beginnings of SFrame parser and dumper (#147294) This PR adds the SFrameParser class and uses it from llvm-readobj to dump the section contents. Currently, it only supports parsing the SFrame section header. Other parts of the section will be added in follow-up patches. llvm-readobj uses the same sframe flag syntax as GNU readelf, but I have not attempted match the output format of the tool. I'm starting with the "llvm" output format because it's easier to generate and lets us tweak the format to make it useful for testing the generation code. If needed, support for the GNU format could be added by overriding this functionality in the GNU ELF Dumper. For more information, see the [sframe specification](https://sourceware.org/binutils/wiki/sframe) and the related [RFC](https://discourse.llvm.org/t/rfc-adding-sframe-support-to-llvm/86900). --- llvm/lib/Object/SFrameParser.cpp | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 llvm/lib/Object/SFrameParser.cpp (limited to 'llvm/lib/Object/SFrameParser.cpp') diff --git a/llvm/lib/Object/SFrameParser.cpp b/llvm/lib/Object/SFrameParser.cpp new file mode 100644 index 000000000000..2d74d1d6b382 --- /dev/null +++ b/llvm/lib/Object/SFrameParser.cpp @@ -0,0 +1,55 @@ +//===- SFrameParser.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/SFrameParser.h" +#include "llvm/BinaryFormat/SFrame.h" +#include "llvm/Object/Error.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::object; + +template +static Expected getDataSliceAs(ArrayRef Data, + uint64_t Offset) { + static_assert(std::is_trivial_v); + if (Data.size() < Offset + sizeof(T)) { + return createStringError( + formatv("unexpected end of data at offset {0:x} while reading [{1:x}, " + "{2:x})", + Data.size(), Offset, Offset + sizeof(T)) + .str(), + object_error::unexpected_eof); + } + return *reinterpret_cast(Data.data() + Offset); +} + +template +Expected> SFrameParser::create(ArrayRef Contents) { + Expected &> Preamble = + getDataSliceAs>(Contents, 0); + if (!Preamble) + return Preamble.takeError(); + + if (Preamble->Magic != sframe::Magic) + return createError( + formatv("invalid magic number ({0:x+4})", Preamble->Magic.value())); + if (Preamble->Version != sframe::Version::V2) + return createError( + formatv("invalid/unsupported version number ({0})", + static_cast(Preamble->Version.value()))); + + Expected &> Header = + getDataSliceAs>(Contents, 0); + if (!Header) + return Header.takeError(); + return SFrameParser(Contents, *Header); +} + +template class llvm::object::SFrameParser; +template class llvm::object::SFrameParser; -- cgit v1.2.3