
This continues the sframe implementation discussed previously. Of note, this also adds some target dependent functions to the object file. Additional fields will be needed later. It would be possible to do all of this inside the sframe implementation itself if it feels a little messy and specialized, but generally I think that target info goes with target info. Another question is if we want a sentinel value for unimplemented sframe abi arches, or a std::optional. Both work.
99 lines
3.1 KiB
C++
99 lines
3.1 KiB
C++
//===- 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<uint8_t>(Version::V2));
|
|
Streamer.emitInt8(0);
|
|
}
|
|
|
|
void emitHeader() {
|
|
emitPreamble();
|
|
// sfh_abi_arch
|
|
Streamer.emitInt8(static_cast<uint8_t>(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();
|
|
}
|