diff --git a/llvm/docs/PCSectionsMetadata.rst b/llvm/docs/PCSectionsMetadata.rst new file mode 100644 --- /dev/null +++ b/llvm/docs/PCSectionsMetadata.rst @@ -0,0 +1,54 @@ +========================= +LLVM PC Sections Metadata +========================= + +.. contents:: + :local: + +Introduction +============ + +PC Sections Metadata can be attached to instructions and functions, for which +addresses, viz. program counters (PCs), are to be emitted in specially encoded +binary sections. Metadata is assigned as an ``MDNode`` of the ``MD_pcsections`` +kind; the following section describes the metadata format. + +Metadata Format +=============== + +An arbitrary number of interleaved ``MDString`` and constant operators can be +added, where a new ``MDString`` always denotes a section name, followed by an +arbitrary number of auxiliary constant data encoded along the PC of the +instruction or function. The first operator must be a ``MDString`` denoting the +first section. + +.. code-block:: none + + !0 = !{ + !"" + [ , iXX ... ] + [ !" + [ , iXX ... ] + ... ] + } + +The occurrence of "section#1", "section#2", ..., "section#N" in the metadata +causes the backend to emit the PC for the associated instruction or function to +all named sections. For each emitted PC in a section #N, the constants +"aux-consts#N" will be emitted after the PC. + +Binary Encoding +=============== + +*Instructions* result in emitting a single PC, and *functions* result in +emission of the start of the function and a 32-bit size. This is followed by +the auxiliary constants that followed the respective section name in the +``MD_pcsections`` metadata. + +To avoid relocations in the final binary, each PC address stored at ``entry`` +is a relative relocation, computed as ``pc - entry``. To decode, a user has to +compute ``entry + *entry``. + +The size of each entry depends on the code model. With large and medium sized +code models, the entry size matches pointer size. For any smaller code model +the entry size is just 32 bits. diff --git a/llvm/docs/Reference.rst b/llvm/docs/Reference.rst --- a/llvm/docs/Reference.rst +++ b/llvm/docs/Reference.rst @@ -33,6 +33,7 @@ MarkedUpDisassembly MIRLangRef OptBisect + PCSectionsMetadata PDB/index PointerAuth ScudoHardenedAllocator diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def --- a/llvm/include/llvm/IR/FixedMetadataKinds.def +++ b/llvm/include/llvm/IR/FixedMetadataKinds.def @@ -47,3 +47,4 @@ LLVM_FIXED_MD_KIND(MD_exclude, "exclude", 33) LLVM_FIXED_MD_KIND(MD_memprof, "memprof", 34) LLVM_FIXED_MD_KIND(MD_callsite, "callsite", 35) +LLVM_FIXED_MD_KIND(MD_pcsections, "pcsections", 36) diff --git a/llvm/include/llvm/IR/MDBuilder.h b/llvm/include/llvm/IR/MDBuilder.h --- a/llvm/include/llvm/IR/MDBuilder.h +++ b/llvm/include/llvm/IR/MDBuilder.h @@ -112,6 +112,14 @@ /// prologue for the "function" santizier. MDNode *createRTTIPointerPrologue(Constant *PrologueSig, Constant *RTTI); + //===------------------------------------------------------------------===// + // PC sections metadata. + //===------------------------------------------------------------------===// + + /// Return metadata for PC sections. + MDNode *createPCSections(ArrayRef Sections, + ArrayRef> AuxData); + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/llvm/lib/IR/MDBuilder.cpp b/llvm/lib/IR/MDBuilder.cpp --- a/llvm/lib/IR/MDBuilder.cpp +++ b/llvm/lib/IR/MDBuilder.cpp @@ -158,6 +158,28 @@ return MDNode::get(Context, Ops); } +MDNode * +MDBuilder::createPCSections(ArrayRef Sections, + ArrayRef> AuxData) { + SmallVector Ops; + + for (size_t i = 0; i < Sections.size(); i++) { + const StringRef &S = Sections[i]; + Ops.push_back(createString(S)); + + // If auxiliary data for this section exists, append it. + if (i < AuxData.size()) { + const ArrayRef &AuxConsts = AuxData[i]; + for (Constant *C : AuxConsts) { + if (C) + Ops.push_back(createConstant(C)); + } + } + } + + return MDNode::get(Context, Ops); +} + MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) { SmallVector Args(1, nullptr); if (Extra)