@@ -114,12 +114,10 @@ class RISCVAsmPrinter : public AsmPrinter {
114114
115115private:
116116 /* *
117- * Struct describing compartment exports that must be emitted for this
118- * compilation unit.
117+ * Struct describing function-like compartment export objects.
119118 */
120- struct CompartmentExport
121- {
122- // / The compartment name for the function.
119+ struct FunctionCompartmentExport {
120+ // / The compartment name for the object.
123121 std::string CompartmentName;
124122 // / The IR function corresponding to the function.
125123 const Function &Fn;
@@ -132,9 +130,26 @@ class RISCVAsmPrinter : public AsmPrinter {
132130 // / The size in bytes of the stack frame, 0 if not used.
133131 uint32_t stackSize = 0 ;
134132 };
135- SmallVector<CompartmentExport, 1 > CompartmentEntries;
133+
134+ /* *
135+ * Struct describing sealing key-like compartment export objects.
136+ */
137+ struct SealingKeyCompartmentExport {
138+ // / The compartment name for the object.
139+ std::string CompartmentName;
140+ // / The name of the sealing key type.
141+ std::string SealingKeyTypeName;
142+
143+ bool operator ==(const SealingKeyCompartmentExport &Other) {
144+ return this ->CompartmentName == Other.CompartmentName &&
145+ this ->SealingKeyTypeName == Other.SealingKeyTypeName ;
146+ }
147+ };
148+
149+ SmallVector<FunctionCompartmentExport, 1 > FNCompartmentEntries;
150+ SmallVector<SealingKeyCompartmentExport, 1 > SKCompartmentEntries;
136151 SmallDenseMap<const Function *, SmallVector<const GlobalAlias *, 1 >, 1 >
137- CompartmentEntryAliases ;
152+ FnCompartmentEntryAliases ;
138153
139154 void emitAttributes (const MCSubtargetInfo &SubtargetInfo);
140155
@@ -312,6 +327,20 @@ void RISCVAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
312327 return ;
313328 }
314329
330+ auto CheriotSealingKeyTypeAttrName =
331+ llvm::CHERIoTSealingKeyTypeAttr::getAttrName ();
332+
333+ if (GV->hasAttribute (CheriotSealingKeyTypeAttrName)) {
334+ auto Attr = GV->getAttribute (CheriotSealingKeyTypeAttrName);
335+ auto Entry = SealingKeyCompartmentExport{
336+ std::string (GV->getAttribute (" cheri-compartment" ).getValueAsString ()),
337+ Attr.getValueAsString ().str ()};
338+ if (std::find (SKCompartmentEntries.begin (), SKCompartmentEntries.end (),
339+ Entry) == SKCompartmentEntries.end ()) {
340+ SKCompartmentEntries.push_back (Entry);
341+ }
342+ }
343+
315344 // Continue through the normal path to emit the global.
316345 return AsmPrinter::emitGlobalVariable (GV);
317346}
@@ -320,9 +349,12 @@ void RISCVAsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {
320349 AsmPrinter::emitGlobalAlias (M, GA);
321350
322351 const MCSubtargetInfo &SubtargetInfo = *TM.getMCSubtargetInfo ();
352+ auto CheriotSealingKeyTypeAttrName =
353+ llvm::CHERIoTSealingKeyTypeAttr::getAttrName ();
354+
323355 if (SubtargetInfo.hasFeature (RISCV::FeatureVendorXCheriot)) {
324356 if (auto *Fn = dyn_cast<Function>(GA.getAliasee ()->stripPointerCasts ())) {
325- CompartmentEntryAliases [Fn].push_back (&GA);
357+ FnCompartmentEntryAliases [Fn].push_back (&GA);
326358 }
327359 }
328360}
@@ -582,17 +614,17 @@ bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
582614 } else
583615 stackSize = MF.getFrameInfo ().getStackSize ();
584616 // FIXME: Get stack size as function attribute if specified
585- CompartmentEntries .push_back (
617+ FNCompartmentEntries .push_back (
586618 {std::string (Fn.getFnAttribute (" cheri-compartment" ).getValueAsString ()),
587619 Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
588620 countUsedArgRegisters (MF) + interruptFlag, false , stackSize});
589621 } else if (Fn.getCallingConv () == CallingConv::CHERI_LibCall)
590- CompartmentEntries .push_back (
622+ FNCompartmentEntries .push_back (
591623 {" libcalls" , Fn,
592624 OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
593625 countUsedArgRegisters (MF) + interruptFlag});
594626 else if (interruptFlag != 0 )
595- CompartmentEntries .push_back (
627+ FNCompartmentEntries .push_back (
596628 {std::string (Fn.getFnAttribute (" cheri-compartment" ).getValueAsString ()),
597629 Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
598630 countUsedArgRegisters (MF) + interruptFlag, true });
@@ -698,21 +730,21 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
698730 RISCVTargetStreamer &RTS =
699731 static_cast <RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer ());
700732
701- if (!CompartmentEntries .empty ()) {
733+ if (!FNCompartmentEntries .empty ()) {
702734 auto &C = OutStreamer->getContext ();
703- auto *Exports = C.getELFSection (" .compartment_exports" , ELF::SHT_PROGBITS,
704- ELF::SHF_ALLOC | ELF::SHF_GNU_RETAIN);
705- OutStreamer->switchSection (Exports);
706735 auto CompartmentStartSym = C.getOrCreateSymbol (" __compartment_pcc_start" );
707- for (auto &Entry : CompartmentEntries) {
736+ for (auto &Entry : FNCompartmentEntries) {
737+ auto *Exports = C.getELFSection (" .compartment_exports" , ELF::SHT_PROGBITS,
738+ ELF::SHF_ALLOC | ELF::SHF_GNU_RETAIN);
739+ OutStreamer->switchSection (Exports);
708740 std::string ExportName = getImportExportTableName (
709741 Entry.CompartmentName , Entry.Fn .getName (), Entry.Fn .getCallingConv (),
710742 /* IsImport*/ false );
711743 auto Sym = C.getOrCreateSymbol (ExportName);
712744 OutStreamer->emitSymbolAttribute (Sym, MCSA_ELF_TypeObject);
713- // If the function isn't global, don't make its export table entry global
714- // either. Two different compilation units in the same compartment may
715- // export different static things.
745+ // If the function isn't global, don't make its export table entry
746+ // global either. Two different compilation units in the same
747+ // compartment may export different static things.
716748 if (Entry.Fn .hasExternalLinkage () && !Entry.forceLocal )
717749 OutStreamer->emitSymbolAttribute (Sym, MCSA_Global);
718750 OutStreamer->emitValueToAlignment (Align (4 ));
@@ -727,8 +759,8 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
727759 OutStreamer->emitELFSize (Sym, MCConstantExpr::create (4 , C));
728760
729761 // Emit aliases for this export symbol entry.
730- auto I = CompartmentEntryAliases .find (&Entry.Fn );
731- if (I == CompartmentEntryAliases .end ())
762+ auto I = FnCompartmentEntryAliases .find (&Entry.Fn );
763+ if (I == FnCompartmentEntryAliases .end ())
732764 continue ;
733765 for (const GlobalAlias *GA : I->second ) {
734766 std::string AliasExportName = getImportExportTableName (
@@ -747,6 +779,29 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
747779 }
748780 }
749781 }
782+
783+ if (!SKCompartmentEntries.empty ()) {
784+ auto &C = OutStreamer->getContext ();
785+ for (auto &Entry : SKCompartmentEntries) {
786+ auto ExportName = Entry.SealingKeyTypeName ;
787+ auto MangledExportName = " __export." + ExportName;
788+ auto *Sym = C.getOrCreateSymbol (MangledExportName);
789+ auto *Exports = C.getELFSection (
790+ " .compartment_exports." + ExportName, ELF::SHT_PROGBITS,
791+ ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP, 0 , ExportName,
792+ true );
793+ OutStreamer->switchSection (Exports);
794+ OutStreamer->emitSymbolAttribute (Sym, MCSA_ELF_TypeObject);
795+ OutStreamer->emitSymbolAttribute (Sym, MCSA_Global);
796+ OutStreamer->emitValueToAlignment (Align (4 ));
797+ OutStreamer->emitLabel (Sym);
798+ OutStreamer->emitIntValue (0 , 2 );
799+ OutStreamer->emitIntValue (0 , 1 );
800+ OutStreamer->emitIntValue (0b100000 , 1 );
801+ OutStreamer->emitELFSize (Sym, MCConstantExpr::create (4 , C));
802+ }
803+ }
804+
750805 // Generate CHERIoT imports if there are any.
751806 auto &CHERIoTCompartmentImports =
752807 static_cast <RISCVTargetMachine &>(TM).ImportedObjects ;
0 commit comments