@@ -114,13 +114,9 @@ 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.
123- std::string CompartmentName;
119+ struct FunctionCompartmentExport {
124120 // / The IR function corresponding to the function.
125121 const Function &Fn;
126122 // / The symbol for the function
@@ -132,6 +128,24 @@ class RISCVAsmPrinter : public AsmPrinter {
132128 // / The size in bytes of the stack frame, 0 if not used.
133129 uint32_t stackSize = 0 ;
134130 };
131+
132+ /* *
133+ * Struct describing sealing key-like compartment export objects.
134+ */
135+ struct SealingKeyCompartmentExport {
136+ // / The name of the sealing key type.
137+ std::string SealingKeyTypeName;
138+ };
139+
140+ /* *
141+ * Struct describing compartment exports that must be emitted for this
142+ * compilation unit.
143+ */
144+ struct CompartmentExport {
145+ // / The compartment name for the object.
146+ std::string CompartmentName;
147+ std::variant<FunctionCompartmentExport, SealingKeyCompartmentExport> Object;
148+ };
135149 SmallVector<CompartmentExport, 1 > CompartmentEntries;
136150 SmallDenseMap<const Function *, SmallVector<const GlobalAlias *, 1 >, 1 >
137151 CompartmentEntryAliases;
@@ -312,6 +326,16 @@ void RISCVAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
312326 return ;
313327 }
314328
329+ auto CheriotSealingKeyTypeAttrName =
330+ llvm::CHERIoTSealingKeyTypeAttr::getAttrName ();
331+
332+ if (GV->hasAttribute (CheriotSealingKeyTypeAttrName)) {
333+ auto Attr = GV->getAttribute (CheriotSealingKeyTypeAttrName);
334+ CompartmentEntries.push_back (
335+ {std::string (GV->getAttribute (" cheri-compartment" ).getValueAsString ()),
336+ SealingKeyCompartmentExport{Attr.getValueAsString ().str ()}});
337+ }
338+
315339 // Continue through the normal path to emit the global.
316340 return AsmPrinter::emitGlobalVariable (GV);
317341}
@@ -582,20 +606,24 @@ bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
582606 } else
583607 stackSize = MF.getFrameInfo ().getStackSize ();
584608 // FIXME: Get stack size as function attribute if specified
585- CompartmentEntries.push_back (
586- {std::string (Fn.getFnAttribute (" cheri-compartment" ).getValueAsString ()),
587- Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
588- countUsedArgRegisters (MF) + interruptFlag, false , stackSize});
609+ CompartmentEntries.push_back (CompartmentExport{
610+ std::string (Fn.getFnAttribute (" cheri-compartment" ).getValueAsString ()),
611+ FunctionCompartmentExport{
612+ Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
613+ countUsedArgRegisters (MF) + interruptFlag, false , stackSize},
614+ });
589615 } else if (Fn.getCallingConv () == CallingConv::CHERI_LibCall)
590616 CompartmentEntries.push_back (
591- {" libcalls" , Fn,
592- OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
593- countUsedArgRegisters (MF) + interruptFlag});
617+ {" libcalls" ,
618+ FunctionCompartmentExport{
619+ Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
620+ countUsedArgRegisters (MF) + interruptFlag}});
594621 else if (interruptFlag != 0 )
595622 CompartmentEntries.push_back (
596623 {std::string (Fn.getFnAttribute (" cheri-compartment" ).getValueAsString ()),
597- Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
598- countUsedArgRegisters (MF) + interruptFlag, true });
624+ FunctionCompartmentExport{
625+ Fn, OutStreamer->getContext ().getOrCreateSymbol (MF.getName ()),
626+ countUsedArgRegisters (MF) + interruptFlag, true }});
599627
600628 if (EmittedOptionArch)
601629 RTS.emitDirectiveOptionPop ();
@@ -700,50 +728,73 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
700728
701729 if (!CompartmentEntries.empty ()) {
702730 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);
706731 auto CompartmentStartSym = C.getOrCreateSymbol (" __compartment_pcc_start" );
707732 for (auto &Entry : CompartmentEntries) {
708- std::string ExportName = getImportExportTableName (
709- Entry.CompartmentName , Entry.Fn .getName (), Entry.Fn .getCallingConv (),
710- /* IsImport*/ false );
711- auto Sym = C.getOrCreateSymbol (ExportName);
712- 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.
716- if (Entry.Fn .hasExternalLinkage () && !Entry.forceLocal )
717- OutStreamer->emitSymbolAttribute (Sym, MCSA_Global);
718- OutStreamer->emitValueToAlignment (Align (4 ));
719- OutStreamer->emitLabel (Sym);
720- emitLabelDifference (Entry.FnSym , CompartmentStartSym, 2 );
721- auto stackSize = Entry.stackSize ;
722- // Round up to multiple of 8 and divide by 8.
723- stackSize = (stackSize + 7 ) / 8 ;
724- // TODO: We should probably warn if the std::min truncates here.
725- OutStreamer->emitIntValue (std::min (uint32_t (255 ), stackSize), 1 );
726- OutStreamer->emitIntValue (Entry.LiveIns , 1 );
727- OutStreamer->emitELFSize (Sym, MCConstantExpr::create (4 , C));
728-
729- // Emit aliases for this export symbol entry.
730- auto I = CompartmentEntryAliases.find (&Entry.Fn );
731- if (I == CompartmentEntryAliases.end ())
732- continue ;
733- for (const GlobalAlias *GA : I->second ) {
734- std::string AliasExportName = getImportExportTableName (
735- Entry.CompartmentName , GA->getName (), Entry.Fn .getCallingConv (),
733+ if (std::holds_alternative<FunctionCompartmentExport>(Entry.Object )) {
734+ auto *Exports =
735+ C.getELFSection (" .compartment_exports" , ELF::SHT_PROGBITS,
736+ ELF::SHF_ALLOC | ELF::SHF_GNU_RETAIN);
737+ OutStreamer->switchSection (Exports);
738+ auto Fn = std::get<FunctionCompartmentExport>(Entry.Object );
739+ std::string ExportName = getImportExportTableName (
740+ Entry.CompartmentName , Fn.Fn .getName (), Fn.Fn .getCallingConv (),
736741 /* IsImport*/ false );
737- auto AliasExportSym = C.getOrCreateSymbol (AliasExportName);
738-
739- // Emit symbol alias in the export table for the alias using the same
740- // attributes, linkage, and size as the primary entry.
741- OutStreamer->emitSymbolAttribute (AliasExportSym, MCSA_ELF_TypeObject);
742- if (GA->hasExternalLinkage () && !Entry.forceLocal )
743- OutStreamer->emitSymbolAttribute (AliasExportSym, MCSA_Global);
744- OutStreamer->emitAssignment (AliasExportSym,
745- MCSymbolRefExpr::create (Sym, C));
746- OutStreamer->emitELFSize (AliasExportSym, MCConstantExpr::create (4 , C));
742+ auto Sym = C.getOrCreateSymbol (ExportName);
743+ OutStreamer->emitSymbolAttribute (Sym, MCSA_ELF_TypeObject);
744+ // If the function isn't global, don't make its export table entry
745+ // global either. Two different compilation units in the same
746+ // compartment may export different static things.
747+ if (Fn.Fn .hasExternalLinkage () && !Fn.forceLocal )
748+ OutStreamer->emitSymbolAttribute (Sym, MCSA_Global);
749+ OutStreamer->emitValueToAlignment (Align (4 ));
750+ OutStreamer->emitLabel (Sym);
751+ emitLabelDifference (Fn.FnSym , CompartmentStartSym, 2 );
752+ auto stackSize = Fn.stackSize ;
753+ // Round up to multiple of 8 and divide by 8.
754+ stackSize = (stackSize + 7 ) / 8 ;
755+ // TODO: We should probably warn if the std::min truncates here.
756+ OutStreamer->emitIntValue (std::min (uint32_t (255 ), stackSize), 1 );
757+ OutStreamer->emitIntValue (Fn.LiveIns , 1 );
758+ OutStreamer->emitELFSize (Sym, MCConstantExpr::create (4 , C));
759+
760+ // Emit aliases for this export symbol entry.
761+ auto I = CompartmentEntryAliases.find (&Fn.Fn );
762+ if (I == CompartmentEntryAliases.end ())
763+ continue ;
764+ for (const GlobalAlias *GA : I->second ) {
765+ std::string AliasExportName = getImportExportTableName (
766+ Entry.CompartmentName , GA->getName (), Fn.Fn .getCallingConv (),
767+ /* IsImport*/ false );
768+ auto AliasExportSym = C.getOrCreateSymbol (AliasExportName);
769+
770+ // Emit symbol alias in the export table for the alias using the same
771+ // attributes, linkage, and size as the primary entry.
772+ OutStreamer->emitSymbolAttribute (AliasExportSym, MCSA_ELF_TypeObject);
773+ if (GA->hasExternalLinkage () && !Fn.forceLocal )
774+ OutStreamer->emitSymbolAttribute (AliasExportSym, MCSA_Global);
775+ OutStreamer->emitAssignment (AliasExportSym,
776+ MCSymbolRefExpr::create (Sym, C));
777+ OutStreamer->emitELFSize (AliasExportSym,
778+ MCConstantExpr::create (4 , C));
779+ }
780+ } else {
781+ auto SealingKey = std::get<SealingKeyCompartmentExport>(Entry.Object );
782+ auto ExportName = SealingKey.SealingKeyTypeName ;
783+ auto MangledExportName = " __export." + ExportName;
784+ auto *Sym = C.getOrCreateSymbol (MangledExportName);
785+ auto *Exports = C.getELFSection (
786+ " .compartment_exports." + ExportName, ELF::SHT_PROGBITS,
787+ ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP, 0 , ExportName,
788+ true );
789+ OutStreamer->switchSection (Exports);
790+ OutStreamer->emitSymbolAttribute (Sym, MCSA_ELF_TypeObject);
791+ OutStreamer->emitSymbolAttribute (Sym, MCSA_Global);
792+ OutStreamer->emitValueToAlignment (Align (4 ));
793+ OutStreamer->emitLabel (Sym);
794+ OutStreamer->emitIntValue (0 , 2 );
795+ OutStreamer->emitIntValue (0 , 1 );
796+ OutStreamer->emitIntValue (0b100000 , 1 );
797+ OutStreamer->emitELFSize (Sym, MCConstantExpr::create (4 , C));
747798 }
748799 }
749800 }
0 commit comments