99#include " llvm/MC/MCSFrame.h"
1010#include " llvm/BinaryFormat/SFrame.h"
1111#include " llvm/MC/MCContext.h"
12+ #include " llvm/MC/MCAsmInfo.h"
1213#include " llvm/MC/MCObjectFileInfo.h"
1314#include " llvm/MC/MCObjectStreamer.h"
1415#include " llvm/MC/MCSection.h"
@@ -20,12 +21,62 @@ using namespace sframe;
2021
2122namespace {
2223
24+ // High-level structure to track info needed to emit a sframe_func_desc_entry
25+ // and its associated FREs.
26+ struct SFrameFDE {
27+ // Reference to the original dwarf frame to avoid copying.
28+ const MCDwarfFrameInfo &DFrame;
29+ // Label where this FDE's FREs start.
30+ MCSymbol *FREStart;
31+
32+ SFrameFDE (const MCDwarfFrameInfo &DF, MCSymbol *FRES)
33+ : DFrame(DF), FREStart(FRES) {}
34+
35+ void emit (MCObjectStreamer &S, const MCSymbol* FRESubSectionStart) {
36+ MCContext &C = S.getContext ();
37+
38+ // sfde_func_start_address
39+ const MCExpr *V = C.getAsmInfo ()->getExprForFDESymbol (
40+ &(*DFrame.Begin ), C.getObjectFileInfo ()->getFDEEncoding (), S);
41+ S.emitValue (V, sizeof (int32_t ));
42+
43+ // sfde_func_size
44+ S.emitAbsoluteSymbolDiff (DFrame.End , DFrame.Begin , sizeof (uint32_t ));
45+
46+ // sfde_func_start_fre_off
47+ auto *F = S.getCurrentFragment ();
48+ const MCExpr *Diff =
49+ MCBinaryExpr::createSub (MCSymbolRefExpr::create (FREStart, C),
50+ MCSymbolRefExpr::create (FRESubSectionStart, C), C);
51+
52+ F->addFixup (MCFixup::create (F->getContents ().size (), Diff,
53+ MCFixup::getDataKindForSize (4 )));
54+ S.emitInt32 (0 );
55+
56+ // sfde_func_start_num_fres
57+ S.emitInt32 (0 );
58+
59+ // sfde_func_info word
60+ FDEInfo I;
61+ I.setFuncInfo (0 /* No pauth key */ , FDEType::PCInc, FREType::Addr1);
62+ S.emitInt8 (I.Info );
63+
64+ // sfde_func_rep_size. Not relevant in non-PCMASK fdes.
65+ S.emitInt8 (0 );
66+
67+ // sfde_func_padding2
68+ S.emitInt16 (0 );
69+ }
70+ };
71+
2372// Emitting these field-by-field, instead of constructing the actual structures
2473// lets Streamer do target endian-fixups for free.
2574
2675class SFrameEmitterImpl {
2776 MCObjectStreamer &Streamer;
77+ SmallVector<SFrameFDE> FDEs;
2878 ABI SFrameABI;
79+
2980 MCSymbol *FDESubSectionStart;
3081 MCSymbol *FRESubSectionStart;
3182 MCSymbol *FRESubSectionEnd;
@@ -36,16 +87,22 @@ class SFrameEmitterImpl {
3687 .getObjectFileInfo ()
3788 ->getSFrameABIArch ()
3889 .has_value ());
90+ FDEs.reserve (Streamer.getDwarfFrameInfos ().size ());
3991 SFrameABI = *Streamer.getContext ().getObjectFileInfo ()->getSFrameABIArch ();
92+
4093 FDESubSectionStart = Streamer.getContext ().createTempSymbol ();
4194 FRESubSectionStart = Streamer.getContext ().createTempSymbol ();
4295 FRESubSectionEnd = Streamer.getContext ().createTempSymbol ();
4396 }
4497
98+ void BuildSFDE (const MCDwarfFrameInfo &DF) {
99+ FDEs.emplace_back (DF, Streamer.getContext ().createTempSymbol ());
100+ }
101+
45102 void emitPreamble () {
46103 Streamer.emitInt16 (Magic);
47104 Streamer.emitInt8 (static_cast <uint8_t >(Version::V2));
48- Streamer.emitInt8 (0 );
105+ Streamer.emitInt8 (static_cast < uint8_t >(Flags::FDEFuncStartPCRel) );
49106 }
50107
51108 void emitHeader () {
@@ -59,9 +116,11 @@ class SFrameEmitterImpl {
59116 // sfh_auxhdr_len
60117 Streamer.emitInt8 (0 );
61118 // shf_num_fdes
62- Streamer.emitInt32 (0 );
119+ Streamer.emitInt32 (FDEs.size ());
120+
63121 // shf_num_fres
64122 Streamer.emitInt32 (0 );
123+
65124 // shf_fre_len
66125 Streamer.emitAbsoluteSymbolDiff (FRESubSectionEnd, FRESubSectionStart,
67126 sizeof (int32_t ));
@@ -72,10 +131,17 @@ class SFrameEmitterImpl {
72131 sizeof (uint32_t ));
73132 }
74133
75- void emitFDEs () { Streamer.emitLabel (FDESubSectionStart); }
134+ void emitFDEs () {
135+ Streamer.emitLabel (FDESubSectionStart);
136+ for (auto &FDE : FDEs) {
137+ FDE.emit (Streamer, FRESubSectionStart);
138+ }
139+ }
76140
77141 void emitFREs () {
78142 Streamer.emitLabel (FRESubSectionStart);
143+ for (auto FDE : FDEs)
144+ Streamer.emitLabel (FDE.FREStart );
79145 Streamer.emitLabel (FRESubSectionEnd);
80146 }
81147};
@@ -84,7 +150,19 @@ class SFrameEmitterImpl {
84150
85151void MCSFrameEmitter::emit (MCObjectStreamer &Streamer) {
86152 MCContext &Context = Streamer.getContext ();
153+ // If this target doesn't support sframes, return now. Gas doesn't warn in
154+ // this case, but if we want to, it should be done at option-parsing time,
155+ // rather than here.
156+ if (!Streamer.getContext ().getObjectFileInfo ()->getSFrameABIArch ().has_value ())
157+ return ;
158+
87159 SFrameEmitterImpl Emitter (Streamer);
160+ ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos ();
161+
162+ // Both the header itself and the FDEs include various offsets and counts.
163+ // Therefore, all of this must be precomputed.
164+ for (const auto & DFrame : FrameArray)
165+ Emitter.BuildSFDE (DFrame);
88166
89167 MCSection *Section = Context.getObjectFileInfo ()->getSFrameSection ();
90168 // Not strictly necessary, but gas always aligns to 8, so match that.
0 commit comments