3131#include " llvm/Support/TarWriter.h"
3232#include " llvm/Support/raw_ostream.h"
3333
34+ #include < tuple>
35+
3436using namespace llvm ;
3537using namespace llvm ::ELF;
3638using namespace llvm ::object;
@@ -878,11 +880,14 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
878880// of zero or more type-length-value fields. We want to find a field of a
879881// certain type. It seems a bit too much to just store a 32-bit value, perhaps
880882// the ABI is unnecessarily complicated.
881- template <class ELFT > static uint32_t readAndFeatures (const InputSection &sec) {
883+ template <class ELFT >
884+ static std::pair<uint32_t , std::optional<std::array<uint8_t , 16 >>>
885+ readGnuProperty (const InputSection &sec) {
882886 using Elf_Nhdr = typename ELFT::Nhdr;
883887 using Elf_Note = typename ELFT::Note;
884888
885889 uint32_t featuresSet = 0 ;
890+ std::optional<std::array<uint8_t , 16 >> aarch64PauthAbiTag;
886891 ArrayRef<uint8_t > data = sec.content ();
887892 auto reportFatal = [&](const uint8_t *place, const char *msg) {
888893 fatal (toString (sec.file ) + " :(" + sec.name + " +0x" +
@@ -924,6 +929,19 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
924929 if (size < 4 )
925930 reportFatal (place, " FEATURE_1_AND entry is too short" );
926931 featuresSet |= read32<ELFT::TargetEndianness>(desc.data ());
932+ } else if (config->emachine == EM_AARCH64 &&
933+ type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
934+ if (aarch64PauthAbiTag != std::nullopt )
935+ reportFatal (data.data (),
936+ " multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH properties "
937+ " are not allowed" );
938+ if (size != 16 )
939+ reportFatal (
940+ data.data (),
941+ " size of GNU_PROPERTY_AARCH64_FEATURE_PAUTH property must be 16" );
942+ aarch64PauthAbiTag = std::array<uint8_t , 16 >{};
943+ memcpy (aarch64PauthAbiTag->data (), desc.data (),
944+ aarch64PauthAbiTag->size ());
927945 }
928946
929947 // Padding is present in the note descriptor, if necessary.
@@ -934,7 +952,7 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
934952 data = data.slice (nhdr->getSize (sec.addralign ));
935953 }
936954
937- return featuresSet;
955+ return { featuresSet, aarch64PauthAbiTag} ;
938956}
939957
940958// Extract compatibility info for aarch64 pointer authentication from the
@@ -966,13 +984,15 @@ static void readAArch64PauthAbiTag(const InputSection &sec, ObjFile<ELFT> &f) {
966984 " (ARM expected)" );
967985
968986 ArrayRef<uint8_t > desc = note.getDesc (sec.addralign );
969- if (desc.size () < 16 ) {
970- reportError (" too short AArch64 PAuth compatibility info "
971- " (at least 16 bytes expected)" );
987+ if (desc.size () != 16 ) {
988+ reportError (" invalid AArch64 PAuth compatibility info length "
989+ " (exactly 16 bytes expected)" );
972990 return ;
973991 }
974992
975- f.aarch64PauthAbiTag = SmallVector<uint8_t , 0 >(iterator_range (desc));
993+ f.aarch64PauthAbiTag = std::array<uint8_t , 16 >{};
994+ memcpy (f.aarch64PauthAbiTag ->data (), desc.data (),
995+ f.aarch64PauthAbiTag ->size ());
976996}
977997
978998template <class ELFT >
@@ -1029,12 +1049,18 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
10291049 // .note.gnu.property containing a single AND'ed bitmap, we discard an input
10301050 // file's .note.gnu.property section.
10311051 if (name == " .note.gnu.property" ) {
1032- this ->andFeatures = readAndFeatures<ELFT>(InputSection (*this , sec, name));
1052+ std::tie (this ->andFeatures , this ->aarch64PauthAbiTag ) =
1053+ readGnuProperty<ELFT>(InputSection (*this , sec, name));
10331054 return &InputSection::discarded;
10341055 }
10351056
10361057 if (config->emachine == EM_AARCH64 &&
10371058 name == " .note.AARCH64-PAUTH-ABI-tag" ) {
1059+ // TODO: proper handling of both ways of ELF marking in one file
1060+ // To be implemented after the following PRs are merged:
1061+ // - https://github.com/ARM-software/abi-aa/pull/240
1062+ // - https://github.com/llvm/llvm-project/pull/72714
1063+ assert (this ->aarch64PauthAbiTag == std::nullopt );
10381064 readAArch64PauthAbiTag<ELFT>(InputSection (*this , sec, name), *this );
10391065 return &InputSection::discarded;
10401066 }
0 commit comments