|
| 1 | +//===- lib/MC/MCSFrame.cpp - MCSFrame implementation ----------------------===// |
| 2 | +// |
| 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | + |
| 9 | +#include "llvm/MC/MCSFrame.h" |
| 10 | +#include "llvm/BinaryFormat/SFrame.h" |
| 11 | +#include "llvm/MC/MCContext.h" |
| 12 | +#include "llvm/MC/MCObjectFileInfo.h" |
| 13 | +#include "llvm/MC/MCObjectStreamer.h" |
| 14 | +#include "llvm/MC/MCSection.h" |
| 15 | +#include "llvm/MC/MCSymbol.h" |
| 16 | +#include "llvm/Support/EndianStream.h" |
| 17 | + |
| 18 | +using namespace llvm; |
| 19 | +using namespace sframe; |
| 20 | + |
| 21 | +namespace { |
| 22 | + |
| 23 | +// Emitting these field-by-field, instead of constructing the actual structures |
| 24 | +// lets Streamer do target endian-fixups for free. |
| 25 | + |
| 26 | +class SFrameEmitterImpl { |
| 27 | + MCObjectStreamer &Streamer; |
| 28 | + ABI SFrameABI; |
| 29 | + MCSymbol *FDESubSectionStart; |
| 30 | + MCSymbol *FRESubSectionStart; |
| 31 | + MCSymbol *FRESubSectionEnd; |
| 32 | + |
| 33 | +public: |
| 34 | + SFrameEmitterImpl(MCObjectStreamer &Streamer) : Streamer(Streamer) { |
| 35 | + assert(Streamer.getContext() |
| 36 | + .getObjectFileInfo() |
| 37 | + ->getSFrameABIArch() |
| 38 | + .has_value()); |
| 39 | + SFrameABI = *Streamer.getContext().getObjectFileInfo()->getSFrameABIArch(); |
| 40 | + FDESubSectionStart = Streamer.getContext().createTempSymbol(); |
| 41 | + FRESubSectionStart = Streamer.getContext().createTempSymbol(); |
| 42 | + FRESubSectionEnd = Streamer.getContext().createTempSymbol(); |
| 43 | + } |
| 44 | + |
| 45 | + void emitPreamble() { |
| 46 | + Streamer.emitInt16(Magic); |
| 47 | + Streamer.emitInt8(static_cast<uint8_t>(Version::V2)); |
| 48 | + Streamer.emitInt8(0); |
| 49 | + } |
| 50 | + |
| 51 | + void emitHeader() { |
| 52 | + emitPreamble(); |
| 53 | + // sfh_abi_arch |
| 54 | + Streamer.emitInt8(static_cast<uint8_t>(SFrameABI)); |
| 55 | + // sfh_cfa_fixed_fp_offset |
| 56 | + Streamer.emitInt8(0); |
| 57 | + // sfh_cfa_fixed_ra_offset |
| 58 | + Streamer.emitInt8(0); |
| 59 | + // sfh_auxhdr_len |
| 60 | + Streamer.emitInt8(0); |
| 61 | + // shf_num_fdes |
| 62 | + Streamer.emitInt32(0); |
| 63 | + // shf_num_fres |
| 64 | + Streamer.emitInt32(0); |
| 65 | + // shf_fre_len |
| 66 | + Streamer.emitAbsoluteSymbolDiff(FRESubSectionEnd, FRESubSectionStart, |
| 67 | + sizeof(int32_t)); |
| 68 | + // shf_fdeoff. With no sfh_auxhdr, these immediately follow this header. |
| 69 | + Streamer.emitInt32(0); |
| 70 | + // shf_freoff |
| 71 | + Streamer.emitAbsoluteSymbolDiff(FRESubSectionStart, FDESubSectionStart, |
| 72 | + sizeof(uint32_t)); |
| 73 | + } |
| 74 | + |
| 75 | + void emitFDEs() { Streamer.emitLabel(FDESubSectionStart); } |
| 76 | + |
| 77 | + void emitFREs() { |
| 78 | + Streamer.emitLabel(FRESubSectionStart); |
| 79 | + Streamer.emitLabel(FRESubSectionEnd); |
| 80 | + } |
| 81 | +}; |
| 82 | + |
| 83 | +} // end anonymous namespace |
| 84 | + |
| 85 | +void MCSFrameEmitter::emit(MCObjectStreamer &Streamer) { |
| 86 | + MCContext &Context = Streamer.getContext(); |
| 87 | + SFrameEmitterImpl Emitter(Streamer); |
| 88 | + |
| 89 | + MCSection *Section = Context.getObjectFileInfo()->getSFrameSection(); |
| 90 | + // Not strictly necessary, but gas always aligns to 8, so match that. |
| 91 | + Section->ensureMinAlignment(Align(8)); |
| 92 | + Streamer.switchSection(Section); |
| 93 | + MCSymbol *SectionStart = Context.createTempSymbol(); |
| 94 | + Streamer.emitLabel(SectionStart); |
| 95 | + Emitter.emitHeader(); |
| 96 | + Emitter.emitFDEs(); |
| 97 | + Emitter.emitFREs(); |
| 98 | +} |
0 commit comments