[lld] [llvm] [lld][AArch64][Build Attributes] Add support for converting AArch64 Build Attributes to GNU Properties (PR #131990)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 11 07:55:21 PDT 2025
================
@@ -638,25 +808,144 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
}
}
break;
- case EM_AARCH64:
- // FIXME: BuildAttributes have been implemented in llvm, but not yet in
- // lld. Remove the section so that it does not accumulate in the output
- // file. When support is implemented we expect not to output a build
- // attributes section in files of type ET_EXEC or ET_SHARED, but ld -r
- // ouptut will need a single merged attributes section.
- if (sec.sh_type == SHT_AARCH64_ATTRIBUTES)
+ case EM_AARCH64: {
+ // The specification states that if a file contains both GNU properties
+ // and AArch64 build attributes, they can be assumed to be identical.
+ // Therefore, if a file contains GNU properties, the AArch64 build
+ // attributes are ignored. If a file does not contain GNU properties, we
+ // leverage the existing GNU properties mechanism by populating the
+ // corresponding data structures, which will later be handled by
+ // Driver.cpp::readSecurityNotes. This ensures that AArch64 build
+ // attributes are represented in the linked object file as GNU properties,
+ // which are already supported by the Linux kernel and the dynamic
+ // loader.
+ if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) {
+ StringRef name = check(obj.getSectionName(sec, shstrtab));
+ ArrayRef<uint8_t> contents = check(obj.getSectionContents(sec));
+ AArch64AttributeParser attributes;
+ // For functions that has to warn/err/report.
+ InputSection isec(*this, sec, name);
+ if (Error e = attributes.parse(contents, ELFT::Endianness)) {
+ Warn(ctx) << &isec << ": " << std::move(e);
+ // uint32_t andFeatures = 0;
+ // std::array<uint8_t, 16> aarch64PauthAbiCoreInfoStorage;
+ } else {
+ bool writePauth = false;
+ bool wrtieFeatures = false;
+ KnownAArch64BuildAttrSubsections subSections =
+ extractBuildAttributesSubsections(attributes);
+ if (hasGnuProperties) {
+ if (!gnuPropertiesInformation.aarch64PauthAbiCoreInfo.empty()) {
+ // check for mismatch error
+ auto deserializeArray = [&](size_t offset, bool isBE) {
+ unsigned value = 0;
+ for (size_t i = 0; i < 8; ++i) {
+ value = isBE ? (value << 8) |
+ gnuPropertiesInformation
+ .aarch64PauthAbiCoreInfo[i + offset]
+ : value |=
+ static_cast<uint64_t>(
+ gnuPropertiesInformation
+ .aarch64PauthAbiCoreInfo[i + offset])
+ << (8 * i);
+ };
+ return value;
+ };
+ unsigned gnuPropPauthPlatform = deserializeArray(
+ 0, ELFT::Endianness == llvm::endianness::big);
+ if (subSections.pauth.tagPlatform != gnuPropPauthPlatform)
+ ErrAlways(ctx)
+ << &isec
+ << "Pauth Platform mismatch: file contains both GNU "
+ "properties and AArch64 build attributes sections\nGNU "
+ "properties: "
+ << gnuPropPauthPlatform << "\nAArch64 build attributes: "
+ << subSections.pauth.tagPlatform;
+ unsigned gnuPropPauthScheme = deserializeArray(
+ 8, ELFT::Endianness == llvm::endianness::big);
+ if (subSections.pauth.tagSchema != gnuPropPauthScheme)
+ ErrAlways(ctx)
+ << &isec
+ << "Pauth Schema mismatch: file contains both GNU "
+ "properties and AArch64 build attributes sections\nGNU "
+ "properties: "
+ << gnuPropPauthScheme << "\nAArch64 build attributes: "
+ << subSections.pauth.tagSchema;
+ } else {
+ writePauth = true;
+ }
+ if (subSections.fAndB.tagBTI !=
----------------
sivan-shani wrote:
Prefer to keep specific bits in order to enable us to distinguish between 'no value given' to 'given value of 0' which we might need in the future.
Reduced message size and moved code out
https://github.com/llvm/llvm-project/pull/131990
More information about the llvm-commits
mailing list