Skip to content

Commit 448c908

Browse files
committed
[Dwarf] Support __ptrauth qualifier in metadata nodes
Emit `__ptrauth`-qualified types as `DIDerivedType` metadata nodes in IR with tag `DW_TAG_LLVM_ptrauth_type`, baseType referring to the type which has the qualifier applied, and the following parameters representing the signing schema: - `ptrAuthKey` (integer) - `ptrAuthIsAddressDiscriminated` (boolean) - `ptrAuthExtraDiscriminator` (integer) - `ptrAuthIsaPointer` (boolean) - `ptrAuthAuthenticatesNullValues` (boolean)
1 parent 5b342e6 commit 448c908

File tree

15 files changed

+387
-100
lines changed

15 files changed

+387
-100
lines changed

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,13 @@ namespace llvm {
262262
std::optional<unsigned> DWARFAddressSpace = std::nullopt,
263263
StringRef Name = "", DINodeArray Annotations = nullptr);
264264

265+
/// Create a __ptrauth qualifier.
266+
DIDerivedType *createPtrAuthQualifiedType(DIType *FromTy, unsigned Key,
267+
bool IsAddressDiscriminated,
268+
unsigned ExtraDiscriminator,
269+
bool IsaPointer,
270+
bool authenticatesNullValues);
271+
265272
/// Create debugging information entry for a pointer to member.
266273
/// \param PointeeTy Type pointed to by this pointer.
267274
/// \param SizeInBits Size.

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 113 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/SmallVector.h"
2121
#include "llvm/ADT/StringRef.h"
2222
#include "llvm/ADT/iterator_range.h"
23+
#include "llvm/BinaryFormat/Dwarf.h"
2324
#include "llvm/IR/Constants.h"
2425
#include "llvm/IR/Metadata.h"
2526
#include "llvm/IR/PseudoProbe.h"
@@ -745,7 +746,9 @@ class DIType : public DIScope {
745746

746747
unsigned getLine() const { return Line; }
747748
uint64_t getSizeInBits() const { return SizeInBits; }
748-
uint32_t getAlignInBits() const { return SubclassData32; }
749+
uint32_t getAlignInBits() const {
750+
return (getTag() == dwarf::DW_TAG_LLVM_ptrauth_type ? 0 : SubclassData32);
751+
}
749752
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
750753
uint64_t getOffsetInBits() const { return OffsetInBits; }
751754
DIFlags getFlags() const { return Flags; }
@@ -972,6 +975,40 @@ class DIStringType : public DIType {
972975
///
973976
/// TODO: Split out members (inheritance, fields, methods, etc.).
974977
class DIDerivedType : public DIType {
978+
public:
979+
/// Pointer authentication (__ptrauth) metadata.
980+
struct PtrAuthData {
981+
union {
982+
struct {
983+
unsigned Key : 4;
984+
unsigned IsAddressDiscriminated : 1;
985+
unsigned ExtraDiscriminator : 16;
986+
unsigned IsaPointer : 1;
987+
unsigned AuthenticatesNullValues : 1;
988+
} Data;
989+
unsigned RawData;
990+
} Payload;
991+
992+
PtrAuthData(unsigned FromRawData) { Payload.RawData = FromRawData; }
993+
PtrAuthData(unsigned Key, bool IsDiscr, unsigned Discriminator,
994+
bool IsaPointer, bool AuthenticatesNullValues) {
995+
assert(Key < 16);
996+
assert(Discriminator <= 0xffff);
997+
Payload.Data.Key = Key;
998+
Payload.Data.IsAddressDiscriminated = IsDiscr;
999+
Payload.Data.ExtraDiscriminator = Discriminator;
1000+
Payload.Data.IsaPointer = IsaPointer;
1001+
Payload.Data.AuthenticatesNullValues = AuthenticatesNullValues;
1002+
}
1003+
bool operator==(struct PtrAuthData Other) const {
1004+
return Payload.RawData == Other.Payload.RawData;
1005+
}
1006+
bool operator!=(struct PtrAuthData Other) const {
1007+
return !(*this == Other);
1008+
}
1009+
};
1010+
1011+
private:
9751012
friend class LLVMContextImpl;
9761013
friend class MDNode;
9771014

@@ -982,59 +1019,70 @@ class DIDerivedType : public DIType {
9821019
DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
9831020
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
9841021
uint64_t OffsetInBits,
985-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1022+
std::optional<unsigned> DWARFAddressSpace,
1023+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
9861024
ArrayRef<Metadata *> Ops)
9871025
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
9881026
AlignInBits, OffsetInBits, Flags, Ops),
989-
DWARFAddressSpace(DWARFAddressSpace) {}
1027+
DWARFAddressSpace(DWARFAddressSpace) {
1028+
if (PtrAuthData)
1029+
SubclassData32 = PtrAuthData->Payload.RawData;
1030+
}
9901031
~DIDerivedType() = default;
9911032
static DIDerivedType *
9921033
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File,
9931034
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
9941035
uint32_t AlignInBits, uint64_t OffsetInBits,
995-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1036+
std::optional<unsigned> DWARFAddressSpace,
1037+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
9961038
Metadata *ExtraData, DINodeArray Annotations, StorageType Storage,
9971039
bool ShouldCreate = true) {
9981040
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
9991041
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
1000-
DWARFAddressSpace, Flags, ExtraData, Annotations.get(),
1001-
Storage, ShouldCreate);
1042+
DWARFAddressSpace, PtrAuthData, Flags, ExtraData,
1043+
Annotations.get(), Storage, ShouldCreate);
10021044
}
10031045
static DIDerivedType *
10041046
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
10051047
unsigned Line, Metadata *Scope, Metadata *BaseType,
10061048
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
1007-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1049+
std::optional<unsigned> DWARFAddressSpace,
1050+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10081051
Metadata *ExtraData, Metadata *Annotations, StorageType Storage,
10091052
bool ShouldCreate = true);
10101053

10111054
TempDIDerivedType cloneImpl() const {
1012-
return getTemporary(
1013-
getContext(), getTag(), getName(), getFile(), getLine(), getScope(),
1014-
getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(),
1015-
getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations());
1055+
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
1056+
getScope(), getBaseType(), getSizeInBits(),
1057+
getAlignInBits(), getOffsetInBits(),
1058+
getDWARFAddressSpace(), getPtrAuthData(), getFlags(),
1059+
getExtraData(), getAnnotations());
10161060
}
10171061

10181062
public:
1019-
DEFINE_MDNODE_GET(
1020-
DIDerivedType,
1021-
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
1022-
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
1023-
uint32_t AlignInBits, uint64_t OffsetInBits,
1024-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1025-
Metadata *ExtraData = nullptr, Metadata *Annotations = nullptr),
1026-
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
1027-
OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations))
1063+
DEFINE_MDNODE_GET(DIDerivedType,
1064+
(unsigned Tag, MDString *Name, Metadata *File,
1065+
unsigned Line, Metadata *Scope, Metadata *BaseType,
1066+
uint64_t SizeInBits, uint32_t AlignInBits,
1067+
uint64_t OffsetInBits,
1068+
std::optional<unsigned> DWARFAddressSpace,
1069+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
1070+
Metadata *ExtraData = nullptr,
1071+
Metadata *Annotations = nullptr),
1072+
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1073+
AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData,
1074+
Flags, ExtraData, Annotations))
10281075
DEFINE_MDNODE_GET(DIDerivedType,
10291076
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
10301077
DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
10311078
uint32_t AlignInBits, uint64_t OffsetInBits,
1032-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1079+
std::optional<unsigned> DWARFAddressSpace,
1080+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10331081
Metadata *ExtraData = nullptr,
10341082
DINodeArray Annotations = nullptr),
10351083
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1036-
AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
1037-
ExtraData, Annotations))
1084+
AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData,
1085+
Flags, ExtraData, Annotations))
10381086

10391087
TempDIDerivedType clone() const { return cloneImpl(); }
10401088

@@ -1048,6 +1096,48 @@ class DIDerivedType : public DIType {
10481096
return DWARFAddressSpace;
10491097
}
10501098

1099+
std::optional<PtrAuthData> getPtrAuthData() const {
1100+
return getTag() == dwarf::DW_TAG_LLVM_ptrauth_type
1101+
? std::optional<PtrAuthData>(PtrAuthData(SubclassData32))
1102+
: std::nullopt;
1103+
}
1104+
1105+
/// \returns The PointerAuth key.
1106+
std::optional<unsigned> getPtrAuthKey() const {
1107+
if (auto PtrAuthData = getPtrAuthData())
1108+
return (unsigned)PtrAuthData->Payload.Data.Key;
1109+
else
1110+
return std::nullopt;
1111+
}
1112+
/// \returns The PointerAuth address discrimination bit.
1113+
std::optional<bool> isPtrAuthAddressDiscriminated() const {
1114+
if (auto PtrAuthData = getPtrAuthData())
1115+
return (bool)PtrAuthData->Payload.Data.IsAddressDiscriminated;
1116+
else
1117+
return std::nullopt;
1118+
}
1119+
/// \returns The PointerAuth extra discriminator.
1120+
std::optional<unsigned> getPtrAuthExtraDiscriminator() const {
1121+
if (auto PtrAuthData = getPtrAuthData())
1122+
return (unsigned)PtrAuthData->Payload.Data.ExtraDiscriminator;
1123+
else
1124+
return std::nullopt;
1125+
}
1126+
/// \returns The PointerAuth IsaPointer bit.
1127+
std::optional<bool> isPtrAuthIsaPointer() const {
1128+
if (auto PtrAuthData = getPtrAuthData())
1129+
return (bool)PtrAuthData->Payload.Data.IsaPointer;
1130+
else
1131+
return std::nullopt;
1132+
}
1133+
/// \returns The PointerAuth authenticates null values bit.
1134+
std::optional<bool> getPtrAuthAuthenticatesNullValues() const {
1135+
if (auto PtrAuthData = getPtrAuthData())
1136+
return (bool)PtrAuthData->Payload.Data.AuthenticatesNullValues;
1137+
else
1138+
return std::nullopt;
1139+
}
1140+
10511141
/// Get extra data associated with this derived type.
10521142
///
10531143
/// Class type for pointer-to-members, objective-c property node for ivars,

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5130,7 +5130,11 @@ bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) {
51305130
/// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0,
51315131
/// line: 7, scope: !1, baseType: !2, size: 32,
51325132
/// align: 32, offset: 0, flags: 0, extraData: !3,
5133-
/// dwarfAddressSpace: 3)
5133+
/// dwarfAddressSpace: 3, ptrAuthKey: 1,
5134+
/// ptrAuthIsAddressDiscriminated: true,
5135+
/// ptrAuthExtraDiscriminator: 0x1234,
5136+
/// ptrAuthIsaPointer: 1, ptrAuthAuthenticatesNullValues:1
5137+
/// )
51345138
bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) {
51355139
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
51365140
REQUIRED(tag, DwarfTagField, ); \
@@ -5145,19 +5149,30 @@ bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) {
51455149
OPTIONAL(flags, DIFlagField, ); \
51465150
OPTIONAL(extraData, MDField, ); \
51475151
OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); \
5148-
OPTIONAL(annotations, MDField, );
5152+
OPTIONAL(annotations, MDField, ); \
5153+
OPTIONAL(ptrAuthKey, MDUnsignedField, (0, 7)); \
5154+
OPTIONAL(ptrAuthIsAddressDiscriminated, MDBoolField, ); \
5155+
OPTIONAL(ptrAuthExtraDiscriminator, MDUnsignedField, (0, 0xffff)); \
5156+
OPTIONAL(ptrAuthIsaPointer, MDBoolField, ); \
5157+
OPTIONAL(ptrAuthAuthenticatesNullValues, MDBoolField, );
51495158
PARSE_MD_FIELDS();
51505159
#undef VISIT_MD_FIELDS
51515160

51525161
std::optional<unsigned> DWARFAddressSpace;
51535162
if (dwarfAddressSpace.Val != UINT32_MAX)
51545163
DWARFAddressSpace = dwarfAddressSpace.Val;
5164+
std::optional<DIDerivedType::PtrAuthData> PtrAuthData;
5165+
if (ptrAuthKey.Val)
5166+
PtrAuthData = DIDerivedType::PtrAuthData(
5167+
(unsigned)ptrAuthKey.Val, ptrAuthIsAddressDiscriminated.Val,
5168+
(unsigned)ptrAuthExtraDiscriminator.Val, ptrAuthIsaPointer.Val,
5169+
ptrAuthAuthenticatesNullValues.Val);
51555170

51565171
Result = GET_OR_DISTINCT(DIDerivedType,
51575172
(Context, tag.Val, name.Val, file.Val, line.Val,
51585173
scope.Val, baseType.Val, size.Val, align.Val,
5159-
offset.Val, DWARFAddressSpace, flags.Val,
5160-
extraData.Val, annotations.Val));
5174+
offset.Val, DWARFAddressSpace, PtrAuthData,
5175+
flags.Val, extraData.Val, annotations.Val));
51615176
return false;
51625177
}
51635178

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15561556
break;
15571557
}
15581558
case bitc::METADATA_DERIVED_TYPE: {
1559-
if (Record.size() < 12 || Record.size() > 14)
1559+
if (Record.size() < 12 || Record.size() > 15)
15601560
return error("Invalid record");
15611561

15621562
// DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means
@@ -1566,8 +1566,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15661566
DWARFAddressSpace = Record[12] - 1;
15671567

15681568
Metadata *Annotations = nullptr;
1569-
if (Record.size() > 13 && Record[13])
1570-
Annotations = getMDOrNull(Record[13]);
1569+
std::optional<DIDerivedType::PtrAuthData> PtrAuthData;
1570+
1571+
// Only look for annotations/ptrauth if both are allocated.
1572+
// If not, we can't tell which was intended to be embedded, as both ptrauth
1573+
// and annotations have been expected at Record[13] at various times.
1574+
if (Record.size() > 14) {
1575+
if (Record[13])
1576+
Annotations = getMDOrNull(Record[13]);
1577+
1578+
if (Record[14])
1579+
PtrAuthData = DIDerivedType::PtrAuthData(Record[14]);
1580+
}
15711581

15721582
IsDistinct = Record[0];
15731583
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
@@ -1577,7 +1587,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15771587
getMDOrNull(Record[3]), Record[4],
15781588
getDITypeRefOrNull(Record[5]),
15791589
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
1580-
Record[9], DWARFAddressSpace, Flags,
1590+
Record[9], DWARFAddressSpace, PtrAuthData, Flags,
15811591
getDITypeRefOrNull(Record[11]), Annotations)),
15821592
NextMetadataNo);
15831593
NextMetadataNo++;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,9 +1801,13 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N,
18011801
Record.push_back(*DWARFAddressSpace + 1);
18021802
else
18031803
Record.push_back(0);
1804-
18051804
Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get()));
18061805

1806+
if (auto PtrAuthData = N->getPtrAuthData())
1807+
Record.push_back(PtrAuthData->Payload.RawData);
1808+
else
1809+
Record.push_back(0);
1810+
18071811
Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev);
18081812
Record.clear();
18091813
}

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,20 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
803803
if (DTy->getDWARFAddressSpace())
804804
addUInt(Buffer, dwarf::DW_AT_address_class, dwarf::DW_FORM_data4,
805805
*DTy->getDWARFAddressSpace());
806+
if (auto Key = DTy->getPtrAuthKey())
807+
addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_key, dwarf::DW_FORM_data1, *Key);
808+
if (auto AddrDisc = DTy->isPtrAuthAddressDiscriminated())
809+
if (AddrDisc.value())
810+
addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_address_discriminated);
811+
if (auto Disc = DTy->getPtrAuthExtraDiscriminator())
812+
addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_extra_discriminator,
813+
dwarf::DW_FORM_data2, *Disc);
814+
if (auto IsaPointer = DTy->isPtrAuthIsaPointer())
815+
if (*IsaPointer)
816+
addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_isa_pointer);
817+
if (auto AuthenticatesNullValues = DTy->getPtrAuthAuthenticatesNullValues())
818+
if (*AuthenticatesNullValues)
819+
addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values);
806820
}
807821

808822
void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) {

llvm/lib/IR/AsmWriter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,6 +2104,17 @@ static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N,
21042104
Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace,
21052105
/* ShouldSkipZero */ false);
21062106
Printer.printMetadata("annotations", N->getRawAnnotations());
2107+
if (auto Key = N->getPtrAuthKey())
2108+
Printer.printInt("ptrAuthKey", *Key);
2109+
if (auto AddrDisc = N->isPtrAuthAddressDiscriminated())
2110+
Printer.printBool("ptrAuthIsAddressDiscriminated", *AddrDisc);
2111+
if (auto Disc = N->getPtrAuthExtraDiscriminator())
2112+
Printer.printInt("ptrAuthExtraDiscriminator", *Disc);
2113+
if (auto IsaPointer = N->isPtrAuthIsaPointer())
2114+
Printer.printBool("ptrAuthIsaPointer", *IsaPointer);
2115+
if (auto AuthenticatesNullValues = N->getPtrAuthAuthenticatesNullValues())
2116+
Printer.printBool("ptrAuthAuthenticatesNullValues",
2117+
*AuthenticatesNullValues);
21072118
Out << ")";
21082119
}
21092120

0 commit comments

Comments
 (0)