In preparation for the proposed linker ABI changes (https://github.com/hjl-tools/linux-abi/wiki/linux-abi-draft.pdf, https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-cet.pdf), this patch enables emission of the .note.gnu.property section to ELF object files when building CET-enabled modules.
Details
Diff Detail
Event Timeline
Updated to use full 8/4 byte integers to store the flags rather than using 1 byte and padding.
Enabled readobj to parse sections that use 32 bits for the data on 64-bit targets (like gcc currently does) and added explicit alignment to the section generation.
llvm/tools/llvm-readobj/ELFDumper.cpp | ||
---|---|---|
3504 | This format string is wrong for a uint64_t. If you set a bad bit in the upper 32-bits this justs prints <unknown flags: 0x0> |
I think this should be splitted into 2 patches: one for codegen and one for llvm-readobj tool.
llvm/tools/llvm-readobj/ELFDumper.cpp | ||
---|---|---|
3475 | That looks odd. ELFT::uint can be 4 or 8 and Elf_Word is 4, so It is the same as if (DataSize == 4 || DataSize == 8) I would go with that then. It is also probably better to return early: if (DataSize != 4 && DataSize != 8) { OS << format("<corrupt length: 0x%x>\n", DataSize); break; } ... | |
3479 | And here then you can use something like following then | |
3480 | You can move it below the if (CFProtection == 0) since it is only used later. | |
3489 | I think you can avoid using if (First) here, because it is always true here, no? | |
3497 | Actually, it seems you can get rid of the First variable and just check the flags: if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_IBT) { CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_IBT; OS << "IBT"; if (CFProtection) OS << ", "; } if (CFProtection & GNU_PROPERTY_X86_FEATURE_1_SHSTK) { CFProtection &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK; OS << "SHSTK"; if (CFProtection) OS << ", "; } if (CFProtection) OS << format("<unknown flags: 0x%x>", CFProtection); |
Made changes to the readobj part per comments. Will wait on comment from @craig.topper before splitting the patch.
llvm/lib/Target/X86/X86AsmPrinter.cpp | ||
---|---|---|
566–569 | Can't you use EmitBytes to achieve this? |
llvm/lib/Target/X86/X86AsmPrinter.cpp | ||
---|---|---|
557 | I would move this assert to the beginning of the scope if (FeatureFlagsAnd) { assert((TT.isArch32Bit() || TT.isArch64Bit()) && ... But actually.. is it really possible to arch be 16 bits in X86AsmPrinter? |
Replaced assertion with a more explicit error at the start of the code path. Changed the emission of the "GNU\0" byte sequence to use EmitBytes with the StringRef constructor specifically to include the trailing zero byte.
The ELF.h file is no longer affected by this patch since D47473 was commited.
llvm/lib/Target/X86/X86AsmPrinter.cpp | ||
---|---|---|
545 | This could be uint8_t, though I think this better be just unsigned. | |
556 | Do you need this cast? | |
558 | This better be moved closer to the location of using // Emitting note header. int WordSize = TT.isArch64Bit() ? 8 : 4; EmitAlignment(WordSize == 4 ? 2 : 3); | |
llvm/test/CodeGen/X86/note-cet-property.ll | ||
2 | Can you add a check for the 32-bit target too? (Since you implement both in patch). |
Changes made per comments.
llvm/lib/Target/X86/X86AsmPrinter.cpp | ||
---|---|---|
556 | Unfortunately, yes. The compilation fails without it. |
llvm/lib/Target/X86/X86AsmPrinter.cpp | ||
---|---|---|
556 | I think you just need to add |
llvm/lib/Target/X86/X86AsmPrinter.cpp | ||
---|---|---|
547 | This if looks not checked by the test case? |
Added an extra flag to the test, so that both flag-reading paths are covered. Since flags are module-wide, if there need to be tests covering them separately they would have to be put in new files.
This could be uint8_t, though I think this better be just unsigned.