@@ -540,102 +540,14 @@ uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &sym) const {
540540 this );
541541}
542542
543+ // Forward declarations:
543544template <typename ELFT>
544- static void parseGnuPropertyNote (Ctx &ctx, ELFFileBase &f,
545- uint32_t featureAndType,
546- ArrayRef<uint8_t > &desc, const uint8_t *base,
547- ArrayRef<uint8_t > *data = nullptr ) {
548- auto err = [&](const uint8_t *place) -> ELFSyncStream {
549- auto diag = Err (ctx);
550- diag << &f << " :(" << " .note.gnu.property+0x"
551- << Twine::utohexstr (place - base) << " ): " ;
552- return diag;
553- };
554-
555- while (!desc.empty ()) {
556- const uint8_t *place = desc.data ();
557- if (desc.size () < 8 )
558- return void (err (place) << " program property is too short" );
559- uint32_t type = read32<ELFT::Endianness>(desc.data ());
560- uint32_t size = read32<ELFT::Endianness>(desc.data () + 4 );
561- desc = desc.slice (8 );
562- if (desc.size () < size)
563- return void (err (place) << " program property is too short" );
564-
565- if (type == featureAndType) {
566- // We found a FEATURE_1_AND field. There may be more than one of these
567- // in a .note.gnu.property section, for a relocatable object we
568- // accumulate the bits set.
569- if (size < 4 )
570- return void (err (place) << " FEATURE_1_AND entry is too short" );
571- f.andFeatures |= read32<ELFT::Endianness>(desc.data ());
572- } else if (ctx.arg .emachine == EM_AARCH64 &&
573- type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
574- ArrayRef<uint8_t > contents = data ? *data : desc;
575- if (!f.aarch64PauthAbiCoreInfo .empty ()) {
576- return void (
577- err (contents.data ())
578- << " multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are "
579- " not supported" );
580- } else if (size != 16 ) {
581- return void (err (contents.data ())
582- << " GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry "
583- " is invalid: expected 16 bytes, but got "
584- << size);
585- }
586- f.aarch64PauthAbiCoreInfo = desc;
587- }
588-
589- // Padding is present in the note descriptor, if necessary.
590- desc = desc.slice (alignTo<(ELFT::Is64Bits ? 8 : 4 )>(size));
591- }
592- }
593-
594- // Read the following info from the .note.gnu.property section and write it to
595- // the corresponding fields in `ObjFile`:
596- // - Feature flags (32 bits) representing x86 or AArch64 features for
597- // hardware-assisted call flow control;
598- // - AArch64 PAuth ABI core info (16 bytes).
599- template <class ELFT >
600- static gnuPropertiesInfo readGnuProperty (Ctx &ctx, const InputSection &sec,
601- ObjFile<ELFT> &f) {
602- using Elf_Nhdr = typename ELFT::Nhdr;
603- using Elf_Note = typename ELFT::Note;
604-
605- ArrayRef<uint8_t > data = sec.content ();
606- auto err = [&](const uint8_t *place) -> ELFSyncStream {
607- auto diag = Err (ctx);
608- diag << sec.file << " :(" << sec.name << " +0x"
609- << Twine::utohexstr (place - sec.content ().data ()) << " ): " ;
610- return diag;
611- };
612- while (!data.empty ()) {
613- // Read one NOTE record.
614- auto *nhdr = reinterpret_cast <const Elf_Nhdr *>(data.data ());
615- if (data.size () < sizeof (Elf_Nhdr) ||
616- data.size () < nhdr->getSize (sec.addralign ))
617- return (err (data.data ()) << " data is too short" , gnuPropertiesInfo{});
618-
619- Elf_Note note (*nhdr);
620- if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName () != " GNU" ) {
621- data = data.slice (nhdr->getSize (sec.addralign ));
622- continue ;
623- }
624-
625- uint32_t featureAndType = ctx.arg .emachine == EM_AARCH64
626- ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
627- : GNU_PROPERTY_X86_FEATURE_1_AND;
628-
629- // Read a body of a NOTE record, which consists of type-length-value fields.
630- ArrayRef<uint8_t > desc = note.getDesc (sec.addralign );
631- const uint8_t *base = sec.content ().data ();
632- parseGnuPropertyNote<ELFT>(ctx, f, featureAndType, desc, base, &data);
633-
634- // Go to next NOTE record to look for more FEATURE_1_AND descriptions.
635- data = data.slice (nhdr->getSize (sec.addralign ));
636- }
637- return gnuPropertiesInfo{f.andFeatures , f.aarch64PauthAbiCoreInfo };
638- }
545+ static void parseGnuPropertyNote (Ctx &, ELFFileBase &, uint32_t ,
546+ ArrayRef<uint8_t > &, const uint8_t *,
547+ ArrayRef<uint8_t > * = nullptr );
548+ template <typename ELFT>
549+ static gnuPropertiesInfo readGnuProperty (Ctx &, const InputSection &,
550+ ObjFile<ELFT> &);
639551
640552template <class ELFT >
641553static void
@@ -1526,6 +1438,103 @@ std::vector<uint32_t> SharedFile::parseVerneed(const ELFFile<ELFT> &obj,
15261438 return verneeds;
15271439}
15281440
1441+ template <typename ELFT>
1442+ static void parseGnuPropertyNote (Ctx &ctx, ELFFileBase &f,
1443+ uint32_t featureAndType,
1444+ ArrayRef<uint8_t > &desc, const uint8_t *base,
1445+ ArrayRef<uint8_t > *data) {
1446+ auto err = [&](const uint8_t *place) -> ELFSyncStream {
1447+ auto diag = Err (ctx);
1448+ diag << &f << " :(" << " .note.gnu.property+0x"
1449+ << Twine::utohexstr (place - base) << " ): " ;
1450+ return diag;
1451+ };
1452+
1453+ while (!desc.empty ()) {
1454+ const uint8_t *place = desc.data ();
1455+ if (desc.size () < 8 )
1456+ return void (err (place) << " program property is too short" );
1457+ uint32_t type = read32<ELFT::Endianness>(desc.data ());
1458+ uint32_t size = read32<ELFT::Endianness>(desc.data () + 4 );
1459+ desc = desc.slice (8 );
1460+ if (desc.size () < size)
1461+ return void (err (place) << " program property is too short" );
1462+
1463+ if (type == featureAndType) {
1464+ // We found a FEATURE_1_AND field. There may be more than one of these
1465+ // in a .note.gnu.property section, for a relocatable object we
1466+ // accumulate the bits set.
1467+ if (size < 4 )
1468+ return void (err (place) << " FEATURE_1_AND entry is too short" );
1469+ f.andFeatures |= read32<ELFT::Endianness>(desc.data ());
1470+ } else if (ctx.arg .emachine == EM_AARCH64 &&
1471+ type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
1472+ ArrayRef<uint8_t > contents = data ? *data : desc;
1473+ if (!f.aarch64PauthAbiCoreInfo .empty ()) {
1474+ return void (
1475+ err (contents.data ())
1476+ << " multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are "
1477+ " not supported" );
1478+ } else if (size != 16 ) {
1479+ return void (err (contents.data ())
1480+ << " GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry "
1481+ " is invalid: expected 16 bytes, but got "
1482+ << size);
1483+ }
1484+ f.aarch64PauthAbiCoreInfo = desc;
1485+ }
1486+
1487+ // Padding is present in the note descriptor, if necessary.
1488+ desc = desc.slice (alignTo<(ELFT::Is64Bits ? 8 : 4 )>(size));
1489+ }
1490+ }
1491+
1492+ // Read the following info from the .note.gnu.property section and write it to
1493+ // the corresponding fields in `ObjFile`:
1494+ // - Feature flags (32 bits) representing x86 or AArch64 features for
1495+ // hardware-assisted call flow control;
1496+ // - AArch64 PAuth ABI core info (16 bytes).
1497+ template <class ELFT >
1498+ static gnuPropertiesInfo readGnuProperty (Ctx &ctx, const InputSection &sec,
1499+ ObjFile<ELFT> &f) {
1500+ using Elf_Nhdr = typename ELFT::Nhdr;
1501+ using Elf_Note = typename ELFT::Note;
1502+
1503+ ArrayRef<uint8_t > data = sec.content ();
1504+ auto err = [&](const uint8_t *place) -> ELFSyncStream {
1505+ auto diag = Err (ctx);
1506+ diag << sec.file << " :(" << sec.name << " +0x"
1507+ << Twine::utohexstr (place - sec.content ().data ()) << " ): " ;
1508+ return diag;
1509+ };
1510+ while (!data.empty ()) {
1511+ // Read one NOTE record.
1512+ auto *nhdr = reinterpret_cast <const Elf_Nhdr *>(data.data ());
1513+ if (data.size () < sizeof (Elf_Nhdr) ||
1514+ data.size () < nhdr->getSize (sec.addralign ))
1515+ return (err (data.data ()) << " data is too short" , gnuPropertiesInfo{});
1516+
1517+ Elf_Note note (*nhdr);
1518+ if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName () != " GNU" ) {
1519+ data = data.slice (nhdr->getSize (sec.addralign ));
1520+ continue ;
1521+ }
1522+
1523+ uint32_t featureAndType = ctx.arg .emachine == EM_AARCH64
1524+ ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
1525+ : GNU_PROPERTY_X86_FEATURE_1_AND;
1526+
1527+ // Read a body of a NOTE record, which consists of type-length-value fields.
1528+ ArrayRef<uint8_t > desc = note.getDesc (sec.addralign );
1529+ const uint8_t *base = sec.content ().data ();
1530+ parseGnuPropertyNote<ELFT>(ctx, f, featureAndType, desc, base, &data);
1531+
1532+ // Go to next NOTE record to look for more FEATURE_1_AND descriptions.
1533+ data = data.slice (nhdr->getSize (sec.addralign ));
1534+ }
1535+ return gnuPropertiesInfo{f.andFeatures , f.aarch64PauthAbiCoreInfo };
1536+ }
1537+
15291538// Parse PT_GNU_PROPERTY segments in DSO. The process is similar to
15301539// readGnuProperty, but we don't have the InputSection information.
15311540template <typename ELFT>
0 commit comments