//===- lib/MC/MCSFrame.cpp - MCSFrame implementation ----------------------===// // // 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/MC/MCSFrame.h" #include "llvm/BinaryFormat/SFrame.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/EndianStream.h" using namespace llvm; using namespace sframe; namespace { // Emitting these field-by-field, instead of constructing the actual structures // lets Streamer do target endian-fixups for free. class SFrameEmitterImpl { MCObjectStreamer &Streamer; ABI SFrameABI; MCSymbol *FDESubSectionStart; MCSymbol *FRESubSectionStart; MCSymbol *FRESubSectionEnd; public: SFrameEmitterImpl(MCObjectStreamer &Streamer) : Streamer(Streamer) { assert(Streamer.getContext() .getObjectFileInfo() ->getSFrameABIArch() .has_value()); SFrameABI = *Streamer.getContext().getObjectFileInfo()->getSFrameABIArch(); FDESubSectionStart = Streamer.getContext().createTempSymbol(); FRESubSectionStart = Streamer.getContext().createTempSymbol(); FRESubSectionEnd = Streamer.getContext().createTempSymbol(); } void emitPreamble() { Streamer.emitInt16(Magic); Streamer.emitInt8(static_cast(Version::V2)); Streamer.emitInt8(0); } void emitHeader() { emitPreamble(); // sfh_abi_arch Streamer.emitInt8(static_cast(SFrameABI)); // sfh_cfa_fixed_fp_offset Streamer.emitInt8(0); // sfh_cfa_fixed_ra_offset Streamer.emitInt8(0); // sfh_auxhdr_len Streamer.emitInt8(0); // shf_num_fdes Streamer.emitInt32(0); // shf_num_fres Streamer.emitInt32(0); // shf_fre_len Streamer.emitAbsoluteSymbolDiff(FRESubSectionEnd, FRESubSectionStart, sizeof(int32_t)); // shf_fdeoff. With no sfh_auxhdr, these immediately follow this header. Streamer.emitInt32(0); // shf_freoff Streamer.emitAbsoluteSymbolDiff(FRESubSectionStart, FDESubSectionStart, sizeof(uint32_t)); } void emitFDEs() { Streamer.emitLabel(FDESubSectionStart); } void emitFREs() { Streamer.emitLabel(FRESubSectionStart); Streamer.emitLabel(FRESubSectionEnd); } }; } // end anonymous namespace void MCSFrameEmitter::emit(MCObjectStreamer &Streamer) { MCContext &Context = Streamer.getContext(); SFrameEmitterImpl Emitter(Streamer); MCSection *Section = Context.getObjectFileInfo()->getSFrameSection(); // Not strictly necessary, but gas always aligns to 8, so match that. Section->ensureMinAlignment(Align(8)); Streamer.switchSection(Section); MCSymbol *SectionStart = Context.createTempSymbol(); Streamer.emitLabel(SectionStart); Emitter.emitHeader(); Emitter.emitFDEs(); Emitter.emitFREs(); }