
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).
56 lines
2.0 KiB
C++
56 lines
2.0 KiB
C++
//===- 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 <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)) {
|
|
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<const T *>(Data.data() + Offset);
|
|
}
|
|
|
|
template <endianness E>
|
|
Expected<SFrameParser<E>> SFrameParser<E>::create(ArrayRef<uint8_t> Contents) {
|
|
Expected<const sframe::Preamble<E> &> Preamble =
|
|
getDataSliceAs<sframe::Preamble<E>>(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<unsigned>(Preamble->Version.value())));
|
|
|
|
Expected<const sframe::Header<E> &> Header =
|
|
getDataSliceAs<sframe::Header<E>>(Contents, 0);
|
|
if (!Header)
|
|
return Header.takeError();
|
|
return SFrameParser(Contents, *Header);
|
|
}
|
|
|
|
template class llvm::object::SFrameParser<endianness::big>;
|
|
template class llvm::object::SFrameParser<endianness::little>;
|