Skip to content

Commit 8f65e7b

Browse files
[Dwarf] Support __ptrauth qualifier in metadata nodes (#82363)
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) Co-authored-by: Ahmed Bougacha <[email protected]>
1 parent 8fa3301 commit 8f65e7b

File tree

16 files changed

+388
-100
lines changed

16 files changed

+388
-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: 101 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ class DIType : public DIScope {
745745

746746
unsigned getLine() const { return Line; }
747747
uint64_t getSizeInBits() const { return SizeInBits; }
748-
uint32_t getAlignInBits() const { return SubclassData32; }
748+
uint32_t getAlignInBits() const;
749749
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
750750
uint64_t getOffsetInBits() const { return OffsetInBits; }
751751
DIFlags getFlags() const { return Flags; }
@@ -972,6 +972,40 @@ class DIStringType : public DIType {
972972
///
973973
/// TODO: Split out members (inheritance, fields, methods, etc.).
974974
class DIDerivedType : public DIType {
975+
public:
976+
/// Pointer authentication (__ptrauth) metadata.
977+
struct PtrAuthData {
978+
union {
979+
struct {
980+
unsigned Key : 4;
981+
unsigned IsAddressDiscriminated : 1;
982+
unsigned ExtraDiscriminator : 16;
983+
unsigned IsaPointer : 1;
984+
unsigned AuthenticatesNullValues : 1;
985+
} Data;
986+
unsigned RawData;
987+
} Payload;
988+
989+
PtrAuthData(unsigned FromRawData) { Payload.RawData = FromRawData; }
990+
PtrAuthData(unsigned Key, bool IsDiscr, unsigned Discriminator,
991+
bool IsaPointer, bool AuthenticatesNullValues) {
992+
assert(Key < 16);
993+
assert(Discriminator <= 0xffff);
994+
Payload.Data.Key = Key;
995+
Payload.Data.IsAddressDiscriminated = IsDiscr;
996+
Payload.Data.ExtraDiscriminator = Discriminator;
997+
Payload.Data.IsaPointer = IsaPointer;
998+
Payload.Data.AuthenticatesNullValues = AuthenticatesNullValues;
999+
}
1000+
bool operator==(struct PtrAuthData Other) const {
1001+
return Payload.RawData == Other.Payload.RawData;
1002+
}
1003+
bool operator!=(struct PtrAuthData Other) const {
1004+
return !(*this == Other);
1005+
}
1006+
};
1007+
1008+
private:
9751009
friend class LLVMContextImpl;
9761010
friend class MDNode;
9771011

@@ -982,59 +1016,70 @@ class DIDerivedType : public DIType {
9821016
DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
9831017
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
9841018
uint64_t OffsetInBits,
985-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1019+
std::optional<unsigned> DWARFAddressSpace,
1020+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
9861021
ArrayRef<Metadata *> Ops)
9871022
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
9881023
AlignInBits, OffsetInBits, Flags, Ops),
989-
DWARFAddressSpace(DWARFAddressSpace) {}
1024+
DWARFAddressSpace(DWARFAddressSpace) {
1025+
if (PtrAuthData)
1026+
SubclassData32 = PtrAuthData->Payload.RawData;
1027+
}
9901028
~DIDerivedType() = default;
9911029
static DIDerivedType *
9921030
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File,
9931031
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
9941032
uint32_t AlignInBits, uint64_t OffsetInBits,
995-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1033+
std::optional<unsigned> DWARFAddressSpace,
1034+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
9961035
Metadata *ExtraData, DINodeArray Annotations, StorageType Storage,
9971036
bool ShouldCreate = true) {
9981037
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
9991038
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
1000-
DWARFAddressSpace, Flags, ExtraData, Annotations.get(),
1001-
Storage, ShouldCreate);
1039+
DWARFAddressSpace, PtrAuthData, Flags, ExtraData,
1040+
Annotations.get(), Storage, ShouldCreate);
10021041
}
10031042
static DIDerivedType *
10041043
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
10051044
unsigned Line, Metadata *Scope, Metadata *BaseType,
10061045
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
1007-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1046+
std::optional<unsigned> DWARFAddressSpace,
1047+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10081048
Metadata *ExtraData, Metadata *Annotations, StorageType Storage,
10091049
bool ShouldCreate = true);
10101050

10111051
TempDIDerivedType cloneImpl() const {
1012-
return getTemporary(
1013-
getContext(), getTag(), getName(), getFile(), getLine(), getScope(),
1014-
getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(),
1015-
getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations());
1052+
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
1053+
getScope(), getBaseType(), getSizeInBits(),
1054+
getAlignInBits(), getOffsetInBits(),
1055+
getDWARFAddressSpace(), getPtrAuthData(), getFlags(),
1056+
getExtraData(), getAnnotations());
10161057
}
10171058

10181059
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))
1060+
DEFINE_MDNODE_GET(DIDerivedType,
1061+
(unsigned Tag, MDString *Name, Metadata *File,
1062+
unsigned Line, Metadata *Scope, Metadata *BaseType,
1063+
uint64_t SizeInBits, uint32_t AlignInBits,
1064+
uint64_t OffsetInBits,
1065+
std::optional<unsigned> DWARFAddressSpace,
1066+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
1067+
Metadata *ExtraData = nullptr,
1068+
Metadata *Annotations = nullptr),
1069+
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1070+
AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData,
1071+
Flags, ExtraData, Annotations))
10281072
DEFINE_MDNODE_GET(DIDerivedType,
10291073
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
10301074
DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
10311075
uint32_t AlignInBits, uint64_t OffsetInBits,
1032-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1076+
std::optional<unsigned> DWARFAddressSpace,
1077+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10331078
Metadata *ExtraData = nullptr,
10341079
DINodeArray Annotations = nullptr),
10351080
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1036-
AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
1037-
ExtraData, Annotations))
1081+
AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData,
1082+
Flags, ExtraData, Annotations))
10381083

10391084
TempDIDerivedType clone() const { return cloneImpl(); }
10401085

@@ -1048,6 +1093,39 @@ class DIDerivedType : public DIType {
10481093
return DWARFAddressSpace;
10491094
}
10501095

1096+
std::optional<PtrAuthData> getPtrAuthData() const;
1097+
1098+
/// \returns The PointerAuth key.
1099+
std::optional<unsigned> getPtrAuthKey() const {
1100+
if (auto PtrAuthData = getPtrAuthData())
1101+
return (unsigned)PtrAuthData->Payload.Data.Key;
1102+
return std::nullopt;
1103+
}
1104+
/// \returns The PointerAuth address discrimination bit.
1105+
std::optional<bool> isPtrAuthAddressDiscriminated() const {
1106+
if (auto PtrAuthData = getPtrAuthData())
1107+
return (bool)PtrAuthData->Payload.Data.IsAddressDiscriminated;
1108+
return std::nullopt;
1109+
}
1110+
/// \returns The PointerAuth extra discriminator.
1111+
std::optional<unsigned> getPtrAuthExtraDiscriminator() const {
1112+
if (auto PtrAuthData = getPtrAuthData())
1113+
return (unsigned)PtrAuthData->Payload.Data.ExtraDiscriminator;
1114+
return std::nullopt;
1115+
}
1116+
/// \returns The PointerAuth IsaPointer bit.
1117+
std::optional<bool> isPtrAuthIsaPointer() const {
1118+
if (auto PtrAuthData = getPtrAuthData())
1119+
return (bool)PtrAuthData->Payload.Data.IsaPointer;
1120+
return std::nullopt;
1121+
}
1122+
/// \returns The PointerAuth authenticates null values bit.
1123+
std::optional<bool> getPtrAuthAuthenticatesNullValues() const {
1124+
if (auto PtrAuthData = getPtrAuthData())
1125+
return (bool)PtrAuthData->Payload.Data.AuthenticatesNullValues;
1126+
return std::nullopt;
1127+
}
1128+
10511129
/// Get extra data associated with this derived type.
10521130
///
10531131
/// 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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,11 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N,
18041804

18051805
Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get()));
18061806

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

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
@@ -2135,6 +2135,17 @@ static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N,
21352135
Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace,
21362136
/* ShouldSkipZero */ false);
21372137
Printer.printMetadata("annotations", N->getRawAnnotations());
2138+
if (auto Key = N->getPtrAuthKey())
2139+
Printer.printInt("ptrAuthKey", *Key);
2140+
if (auto AddrDisc = N->isPtrAuthAddressDiscriminated())
2141+
Printer.printBool("ptrAuthIsAddressDiscriminated", *AddrDisc);
2142+
if (auto Disc = N->getPtrAuthExtraDiscriminator())
2143+
Printer.printInt("ptrAuthExtraDiscriminator", *Disc);
2144+
if (auto IsaPointer = N->isPtrAuthIsaPointer())
2145+
Printer.printBool("ptrAuthIsaPointer", *IsaPointer);
2146+
if (auto AuthenticatesNullValues = N->getPtrAuthAuthenticatesNullValues())
2147+
Printer.printBool("ptrAuthAuthenticatesNullValues",
2148+
*AuthenticatesNullValues);
21382149
Out << ")";
21392150
}
21402151

0 commit comments

Comments
 (0)