Skip to content

Commit 924a1dc

Browse files
[Dwarf] Support __ptrauth qualifier in metadata nodes (llvm#83862)
Reland llvm#82363 after fixing build failure https://lab.llvm.org/buildbot/#/builders/5/builds/41428. Memory sanitizer detects usage of `RawData` union member which is not filled directly. Instead, the code relies on filling `Data` union member, which is a struct consisting of signing schema parameters. According to https://en.cppreference.com/w/cpp/language/union, this is UB: "It is undefined behavior to read from the member of the union that wasn't most recently written". Instead of relying on compiler allowing us to do dirty things, do not use union and only store `RawData`. Particular ptrauth parameters are obtained on demand via bit operations. Original PR description below. 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 e04dd68 commit 924a1dc

File tree

16 files changed

+358
-100
lines changed

16 files changed

+358
-100
lines changed

llvm/include/llvm/IR/DIBuilder.h

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

273+
/// Create a __ptrauth qualifier.
274+
DIDerivedType *createPtrAuthQualifiedType(DIType *FromTy, unsigned Key,
275+
bool IsAddressDiscriminated,
276+
unsigned ExtraDiscriminator,
277+
bool IsaPointer,
278+
bool authenticatesNullValues);
279+
273280
/// Create debugging information entry for a pointer to member.
274281
/// \param PointeeTy Type pointed to by this pointer.
275282
/// \param SizeInBits Size.

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 75 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,35 @@ 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+
// RawData layout:
979+
// - Bits 0..3: Key
980+
// - Bit 4: IsAddressDiscriminated
981+
// - Bits 5..20: ExtraDiscriminator
982+
// - Bit 21: IsaPointer
983+
// - Bit 22: AuthenticatesNullValues
984+
unsigned RawData;
985+
986+
PtrAuthData(unsigned FromRawData) : RawData(FromRawData) {}
987+
PtrAuthData(unsigned Key, bool IsDiscr, unsigned Discriminator,
988+
bool IsaPointer, bool AuthenticatesNullValues) {
989+
assert(Key < 16);
990+
assert(Discriminator <= 0xffff);
991+
RawData = (Key << 0) | (IsDiscr ? (1 << 4) : 0) | (Discriminator << 5) |
992+
(IsaPointer ? (1 << 21) : 0) |
993+
(AuthenticatesNullValues ? (1 << 22) : 0);
994+
}
995+
996+
unsigned key() { return (RawData >> 0) & 0b1111; }
997+
bool isAddressDiscriminated() { return (RawData >> 4) & 1; }
998+
unsigned extraDiscriminator() { return (RawData >> 5) & 0xffff; }
999+
bool isaPointer() { return (RawData >> 21) & 1; }
1000+
bool authenticatesNullValues() { return (RawData >> 22) & 1; }
1001+
};
1002+
1003+
private:
9751004
friend class LLVMContextImpl;
9761005
friend class MDNode;
9771006

@@ -982,59 +1011,70 @@ class DIDerivedType : public DIType {
9821011
DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
9831012
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
9841013
uint64_t OffsetInBits,
985-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1014+
std::optional<unsigned> DWARFAddressSpace,
1015+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
9861016
ArrayRef<Metadata *> Ops)
9871017
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
9881018
AlignInBits, OffsetInBits, Flags, Ops),
989-
DWARFAddressSpace(DWARFAddressSpace) {}
1019+
DWARFAddressSpace(DWARFAddressSpace) {
1020+
if (PtrAuthData)
1021+
SubclassData32 = PtrAuthData->RawData;
1022+
}
9901023
~DIDerivedType() = default;
9911024
static DIDerivedType *
9921025
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File,
9931026
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
9941027
uint32_t AlignInBits, uint64_t OffsetInBits,
995-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1028+
std::optional<unsigned> DWARFAddressSpace,
1029+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
9961030
Metadata *ExtraData, DINodeArray Annotations, StorageType Storage,
9971031
bool ShouldCreate = true) {
9981032
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
9991033
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
1000-
DWARFAddressSpace, Flags, ExtraData, Annotations.get(),
1001-
Storage, ShouldCreate);
1034+
DWARFAddressSpace, PtrAuthData, Flags, ExtraData,
1035+
Annotations.get(), Storage, ShouldCreate);
10021036
}
10031037
static DIDerivedType *
10041038
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
10051039
unsigned Line, Metadata *Scope, Metadata *BaseType,
10061040
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
1007-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1041+
std::optional<unsigned> DWARFAddressSpace,
1042+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10081043
Metadata *ExtraData, Metadata *Annotations, StorageType Storage,
10091044
bool ShouldCreate = true);
10101045

10111046
TempDIDerivedType cloneImpl() const {
1012-
return getTemporary(
1013-
getContext(), getTag(), getName(), getFile(), getLine(), getScope(),
1014-
getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(),
1015-
getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations());
1047+
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
1048+
getScope(), getBaseType(), getSizeInBits(),
1049+
getAlignInBits(), getOffsetInBits(),
1050+
getDWARFAddressSpace(), getPtrAuthData(), getFlags(),
1051+
getExtraData(), getAnnotations());
10161052
}
10171053

10181054
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))
1055+
DEFINE_MDNODE_GET(DIDerivedType,
1056+
(unsigned Tag, MDString *Name, Metadata *File,
1057+
unsigned Line, Metadata *Scope, Metadata *BaseType,
1058+
uint64_t SizeInBits, uint32_t AlignInBits,
1059+
uint64_t OffsetInBits,
1060+
std::optional<unsigned> DWARFAddressSpace,
1061+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
1062+
Metadata *ExtraData = nullptr,
1063+
Metadata *Annotations = nullptr),
1064+
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1065+
AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData,
1066+
Flags, ExtraData, Annotations))
10281067
DEFINE_MDNODE_GET(DIDerivedType,
10291068
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
10301069
DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
10311070
uint32_t AlignInBits, uint64_t OffsetInBits,
1032-
std::optional<unsigned> DWARFAddressSpace, DIFlags Flags,
1071+
std::optional<unsigned> DWARFAddressSpace,
1072+
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10331073
Metadata *ExtraData = nullptr,
10341074
DINodeArray Annotations = nullptr),
10351075
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1036-
AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
1037-
ExtraData, Annotations))
1076+
AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData,
1077+
Flags, ExtraData, Annotations))
10381078

10391079
TempDIDerivedType clone() const { return cloneImpl(); }
10401080

@@ -1048,6 +1088,8 @@ class DIDerivedType : public DIType {
10481088
return DWARFAddressSpace;
10491089
}
10501090

1091+
std::optional<PtrAuthData> getPtrAuthData() const;
1092+
10511093
/// Get extra data associated with this derived type.
10521094
///
10531095
/// Class type for pointer-to-members, objective-c property node for ivars,
@@ -1087,6 +1129,16 @@ class DIDerivedType : public DIType {
10871129
}
10881130
};
10891131

1132+
inline bool operator==(DIDerivedType::PtrAuthData Lhs,
1133+
DIDerivedType::PtrAuthData Rhs) {
1134+
return Lhs.RawData == Rhs.RawData;
1135+
}
1136+
1137+
inline bool operator!=(DIDerivedType::PtrAuthData Lhs,
1138+
DIDerivedType::PtrAuthData Rhs) {
1139+
return !(Lhs == Rhs);
1140+
}
1141+
10901142
/// Composite types.
10911143
///
10921144
/// TODO: Detach from DerivedTypeBase (split out MDEnumType?).

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5184,7 +5184,11 @@ bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) {
51845184
/// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0,
51855185
/// line: 7, scope: !1, baseType: !2, size: 32,
51865186
/// align: 32, offset: 0, flags: 0, extraData: !3,
5187-
/// dwarfAddressSpace: 3)
5187+
/// dwarfAddressSpace: 3, ptrAuthKey: 1,
5188+
/// ptrAuthIsAddressDiscriminated: true,
5189+
/// ptrAuthExtraDiscriminator: 0x1234,
5190+
/// ptrAuthIsaPointer: 1, ptrAuthAuthenticatesNullValues:1
5191+
/// )
51885192
bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) {
51895193
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
51905194
REQUIRED(tag, DwarfTagField, ); \
@@ -5199,19 +5203,30 @@ bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) {
51995203
OPTIONAL(flags, DIFlagField, ); \
52005204
OPTIONAL(extraData, MDField, ); \
52015205
OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); \
5202-
OPTIONAL(annotations, MDField, );
5206+
OPTIONAL(annotations, MDField, ); \
5207+
OPTIONAL(ptrAuthKey, MDUnsignedField, (0, 7)); \
5208+
OPTIONAL(ptrAuthIsAddressDiscriminated, MDBoolField, ); \
5209+
OPTIONAL(ptrAuthExtraDiscriminator, MDUnsignedField, (0, 0xffff)); \
5210+
OPTIONAL(ptrAuthIsaPointer, MDBoolField, ); \
5211+
OPTIONAL(ptrAuthAuthenticatesNullValues, MDBoolField, );
52035212
PARSE_MD_FIELDS();
52045213
#undef VISIT_MD_FIELDS
52055214

52065215
std::optional<unsigned> DWARFAddressSpace;
52075216
if (dwarfAddressSpace.Val != UINT32_MAX)
52085217
DWARFAddressSpace = dwarfAddressSpace.Val;
5218+
std::optional<DIDerivedType::PtrAuthData> PtrAuthData;
5219+
if (ptrAuthKey.Val)
5220+
PtrAuthData.emplace(
5221+
(unsigned)ptrAuthKey.Val, ptrAuthIsAddressDiscriminated.Val,
5222+
(unsigned)ptrAuthExtraDiscriminator.Val, ptrAuthIsaPointer.Val,
5223+
ptrAuthAuthenticatesNullValues.Val);
52095224

52105225
Result = GET_OR_DISTINCT(DIDerivedType,
52115226
(Context, tag.Val, name.Val, file.Val, line.Val,
52125227
scope.Val, baseType.Val, size.Val, align.Val,
5213-
offset.Val, DWARFAddressSpace, flags.Val,
5214-
extraData.Val, annotations.Val));
5228+
offset.Val, DWARFAddressSpace, PtrAuthData,
5229+
flags.Val, extraData.Val, annotations.Val));
52155230
return false;
52165231
}
52175232

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 13 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,17 @@ 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+
if (Record[14])
1578+
PtrAuthData.emplace(Record[14]);
1579+
}
15711580

15721581
IsDistinct = Record[0];
15731582
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
@@ -1577,7 +1586,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15771586
getMDOrNull(Record[3]), Record[4],
15781587
getDITypeRefOrNull(Record[5]),
15791588
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
1580-
Record[9], DWARFAddressSpace, Flags,
1589+
Record[9], DWARFAddressSpace, PtrAuthData, Flags,
15811590
getDITypeRefOrNull(Record[11]), Annotations)),
15821591
NextMetadataNo);
15831592
NextMetadataNo++;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,11 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N,
18291829

18301830
Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get()));
18311831

1832+
if (auto PtrAuthData = N->getPtrAuthData())
1833+
Record.push_back(PtrAuthData->RawData);
1834+
else
1835+
Record.push_back(0);
1836+
18321837
Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev);
18331838
Record.clear();
18341839
}

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,18 @@ 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 PtrAuthData = DTy->getPtrAuthData()) {
807+
addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_key, dwarf::DW_FORM_data1,
808+
PtrAuthData->key());
809+
if (PtrAuthData->isAddressDiscriminated())
810+
addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_address_discriminated);
811+
addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_extra_discriminator,
812+
dwarf::DW_FORM_data2, PtrAuthData->extraDiscriminator());
813+
if (PtrAuthData->isaPointer())
814+
addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_isa_pointer);
815+
if (PtrAuthData->authenticatesNullValues())
816+
addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values);
817+
}
806818
}
807819

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

llvm/lib/IR/AsmWriter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,16 @@ static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N,
21412141
Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace,
21422142
/* ShouldSkipZero */ false);
21432143
Printer.printMetadata("annotations", N->getRawAnnotations());
2144+
if (auto PtrAuthData = N->getPtrAuthData()) {
2145+
Printer.printInt("ptrAuthKey", PtrAuthData->key());
2146+
Printer.printBool("ptrAuthIsAddressDiscriminated",
2147+
PtrAuthData->isAddressDiscriminated());
2148+
Printer.printInt("ptrAuthExtraDiscriminator",
2149+
PtrAuthData->extraDiscriminator());
2150+
Printer.printBool("ptrAuthIsaPointer", PtrAuthData->isaPointer());
2151+
Printer.printBool("ptrAuthAuthenticatesNullValues",
2152+
PtrAuthData->authenticatesNullValues());
2153+
}
21442154
Out << ")";
21452155
}
21462156

0 commit comments

Comments
 (0)