Skip to content

Commit 6ce089d

Browse files
Generate skeleton SFrame Function Description Entries.
1 parent 2e9944a commit 6ce089d

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

llvm/lib/MC/MCSFrame.cpp

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
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

2122
namespace {
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

2675
class 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

85151
void 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.

llvm/test/MC/ELF/cfi-sframe.s

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,23 @@ f1:
1010
nop
1111
.cfi_endproc
1212

13+
f2:
14+
.cfi_startproc
15+
nop
16+
nop
17+
.cfi_endproc
18+
1319
// CHECK: SFrame section '.sframe' {
1420
// CHECK-NEXT: Header {
1521
// CHECK-NEXT: Magic: 0xDEE2
1622
// CHECK-NEXT: Version: V2 (0x2)
17-
// CHECK-NEXT: Flags [ (0x0)
23+
// CHECK-NEXT: Flags [ (0x4)
1824
// CHECK: ABI: AMD64EndianLittle (0x3)
1925
// CHECK-NEXT: CFA fixed FP offset (unused): 0
2026
// CHECK-NEXT: CFA fixed RA offset: 0
2127
// CHECK-NEXT: Auxiliary header length: 0
22-
// CHECK-NEXT: Num FDEs: 0
28+
// CHECK-NEXT: Num FDEs: 2
2329
// CHECK-NEXT: Num FREs: 0
2430
// CHECK-NEXT: FRE subsection length: 0
2531
// CHECK-NEXT: FDE subsection offset: 0
26-
// CHECK-NEXT: FRE subsection offset: 0
32+
// CHECK-NEXT: FRE subsection offset: 40

0 commit comments

Comments
 (0)