6565#include " llvm/Support/TargetSelect.h"
6666#include " llvm/Support/TimeProfiler.h"
6767#include " llvm/Support/raw_ostream.h"
68+ #include < algorithm>
6869#include < cstdlib>
6970#include < tuple>
7071#include < utility>
@@ -459,6 +460,8 @@ static void checkOptions() {
459460 error (" -z force-bti only supported on AArch64" );
460461 if (config->zBtiReport != " none" )
461462 error (" -z bti-report only supported on AArch64" );
463+ if (config->zPauthReport != " none" )
464+ error (" -z pauth-report only supported on AArch64" );
462465 }
463466
464467 if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
@@ -558,6 +561,7 @@ constexpr const char *knownZFlags[] = {
558561 " nognustack" ,
559562 " nokeep-text-section-prefix" ,
560563 " nopack-relative-relocs" ,
564+ " nopack-relative-auth-relocs" ,
561565 " norelro" ,
562566 " noseparate-code" ,
563567 " nostart-stop-gc" ,
@@ -566,6 +570,7 @@ constexpr const char *knownZFlags[] = {
566570 " origin" ,
567571 " pac-plt" ,
568572 " pack-relative-relocs" ,
573+ " pack-relative-auth-relocs" ,
569574 " rel" ,
570575 " rela" ,
571576 " relro" ,
@@ -583,7 +588,7 @@ constexpr const char *knownZFlags[] = {
583588static bool isKnownZFlag (StringRef s) {
584589 return llvm::is_contained (knownZFlags, s) ||
585590 s.starts_with (" common-page-size=" ) || s.starts_with (" bti-report=" ) ||
586- s.starts_with (" cet-report=" ) ||
591+ s.starts_with (" cet-report=" ) || s. starts_with ( " pauth-report= " ) ||
587592 s.starts_with (" dead-reloc-in-nonalloc=" ) ||
588593 s.starts_with (" max-page-size=" ) || s.starts_with (" stack-size=" ) ||
589594 s.starts_with (" start-stop-visibility=" );
@@ -1504,7 +1509,8 @@ static void readConfigs(opt::InputArgList &args) {
15041509 }
15051510
15061511 auto reports = {std::make_pair (" bti-report" , &config->zBtiReport ),
1507- std::make_pair (" cet-report" , &config->zCetReport )};
1512+ std::make_pair (" cet-report" , &config->zCetReport ),
1513+ std::make_pair (" pauth-report" , &config->zPauthReport )};
15081514 for (opt::Arg *arg : args.filtered (OPT_z)) {
15091515 std::pair<StringRef, StringRef> option =
15101516 StringRef (arg->getValue ()).split (' =' );
@@ -1661,6 +1667,9 @@ static void readConfigs(opt::InputArgList &args) {
16611667 getPackDynRelocs (args);
16621668 }
16631669
1670+ config->relrPackAuthDynRelocs = getZFlag (
1671+ args, " pack-relative-auth-relocs" , " nopack-relative-auth-relocs" , false );
1672+
16641673 if (auto *arg = args.getLastArg (OPT_symbol_ordering_file)){
16651674 if (args.hasArg (OPT_call_graph_ordering_file))
16661675 error (" --symbol-ordering-file and --call-graph-order-file "
@@ -2647,6 +2656,47 @@ static uint32_t getAndFeatures() {
26472656 return ret;
26482657}
26492658
2659+ static void getAarch64PauthInfo () {
2660+ if (ctx.objectFiles .empty ())
2661+ return ;
2662+
2663+ auto NonEmptyIt = std::find_if (
2664+ ctx.objectFiles .begin (), ctx.objectFiles .end (),
2665+ [](const ELFFileBase *f) { return !f->aarch64PauthAbiTag .empty (); });
2666+ if (NonEmptyIt == ctx.objectFiles .end ())
2667+ return ;
2668+
2669+ ctx.aarch64PauthAbiTag = (*NonEmptyIt)->aarch64PauthAbiTag ;
2670+ StringRef F1 = (*NonEmptyIt)->getName ();
2671+ for (ELFFileBase *F : ArrayRef (ctx.objectFiles )) {
2672+ StringRef F2 = F->getName ();
2673+ const SmallVector<uint8_t , 0 > &D1 = ctx.aarch64PauthAbiTag ;
2674+ const SmallVector<uint8_t , 0 > &D2 = F->aarch64PauthAbiTag ;
2675+ if (D1.empty () != D2.empty ()) {
2676+ auto Helper = [](StringRef Report, const Twine &Msg) {
2677+ if (Report == " warning" )
2678+ warn (Msg);
2679+ else if (Report == " error" )
2680+ error (Msg);
2681+ };
2682+
2683+ Helper (config->zPauthReport ,
2684+ (D1.empty () ? F1.str () : F2.str ()) +
2685+ " has no AArch64 PAuth compatibility info while " +
2686+ (D1.empty () ? F2.str () : F1.str ()) +
2687+ " has one; either all or no input files must have it" );
2688+ }
2689+
2690+ if (!D1.empty () && !D2.empty () &&
2691+ !std::equal (D1.begin (), D1.end (), D2.begin (), D2.end ()))
2692+ errorOrWarn (
2693+ " incompatible values of AArch64 PAuth compatibility info found"
2694+ " \n " +
2695+ F1 + " : 0x" + toHex (ArrayRef (D1.data (), D1.size ())) + " \n " + F2 +
2696+ " : 0x" + toHex (ArrayRef (D2.data (), D2.size ())));
2697+ }
2698+ }
2699+
26502700static void initSectionsAndLocalSyms (ELFFileBase *file, bool ignoreComdats) {
26512701 switch (file->ekind ) {
26522702 case ELF32LEKind:
@@ -2984,6 +3034,9 @@ void LinkerDriver::link(opt::InputArgList &args) {
29843034 // contain a hint to tweak linker's and loader's behaviors.
29853035 config->andFeatures = getAndFeatures ();
29863036
3037+ if (config->emachine == EM_AARCH64)
3038+ getAarch64PauthInfo ();
3039+
29873040 // The Target instance handles target-specific stuff, such as applying
29883041 // relocations or writing a PLT section. It also contains target-dependent
29893042 // values such as a default image base address.
0 commit comments