From 08c6840f254ccc1d93da2e1f79d398d30f8b3862 Mon Sep 17 00:00:00 2001 From: Victor Campos Date: Tue, 12 Jul 2022 16:10:58 +0100 Subject: [PATCH] [ARM] Parse Tag_also_compatible_with attribute The ARM Attribute Parser used to parse the value of also_compatible_with as it is, disregarding the way it is encoded. This patch does a context aware parsing of the also_compatible_with attribute. Additionally, some error handling is also done for incorrect cases. Reviewed By: pratlucas Differential Revision: https://reviews.llvm.org/D130913 --- llvm/include/llvm/Support/ARMAttributeParser.h | 1 + llvm/include/llvm/Support/ScopedPrinter.h | 10 +++ llvm/lib/Support/ARMAttributeParser.cpp | 97 ++++++++++++++++++++-- ...e-eabi_attribute-also_compatible_with-integer.s | 10 +++ ...i_attribute-also_compatible_with-invalid_arch.s | 6 ++ ...bi_attribute-also_compatible_with-invalid_tag.s | 6 ++ ...eabi_attribute-also_compatible_with-recursive.s | 6 ++ ...ve-eabi_attribute-also_compatible_with-string.s | 10 +++ llvm/test/MC/ARM/directive-eabi_attribute.s | 6 +- 9 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-integer.s create mode 100644 llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s create mode 100644 llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s create mode 100644 llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s create mode 100644 llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-string.s diff --git a/llvm/include/llvm/Support/ARMAttributeParser.h b/llvm/include/llvm/Support/ARMAttributeParser.h index cbb5701..d1d9531 100644 --- a/llvm/include/llvm/Support/ARMAttributeParser.h +++ b/llvm/include/llvm/Support/ARMAttributeParser.h @@ -70,6 +70,7 @@ class ARMAttributeParser : public ELFAttributeParser { Error PACRET_use(ARMBuildAttrs::AttrType tag); Error BTI_use(ARMBuildAttrs::AttrType tag); Error nodefaults(ARMBuildAttrs::AttrType tag); + Error also_compatible_with(ARMBuildAttrs::AttrType tag); public: ARMAttributeParser(ScopedPrinter *sw) diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h index c9eabfb..40af8dc 100644 --- a/llvm/include/llvm/Support/ScopedPrinter.h +++ b/llvm/include/llvm/Support/ScopedPrinter.h @@ -344,6 +344,10 @@ public: startLine() << Label << ": " << Value << "\n"; } + void printStringEscaped(StringRef Label, StringRef Value) { + printStringEscapedImpl(Label, Value); + } + void printBinary(StringRef Label, StringRef Str, ArrayRef Value) { printBinaryImpl(Label, Str, Value, false); } @@ -478,6 +482,12 @@ private: startLine() << Label << ": " << Str << " (" << Value << ")\n"; } + virtual void printStringEscapedImpl(StringRef Label, StringRef Value) { + startLine() << Label << ": "; + OS.write_escaped(Value); + OS << '\n'; + } + void scopedBegin(char Symbol) { startLine() << Symbol << '\n'; indent(); diff --git a/llvm/lib/Support/ARMAttributeParser.cpp b/llvm/lib/Support/ARMAttributeParser.cpp index 03c0c7a..69a969f 100644 --- a/llvm/lib/Support/ARMAttributeParser.cpp +++ b/llvm/lib/Support/ARMAttributeParser.cpp @@ -9,6 +9,8 @@ #include "llvm/Support/ARMAttributeParser.h" #include "llvm/ADT/STLArrayExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ScopedPrinter.h" using namespace llvm; @@ -62,6 +64,7 @@ const ARMAttributeParser::DisplayHandler ARMAttributeParser::displayRoutines[] = ATTRIBUTE_HANDLER(PACRET_use), ATTRIBUTE_HANDLER(BTI_use), ATTRIBUTE_HANDLER(nodefaults), + ATTRIBUTE_HANDLER(also_compatible_with), }; #undef ATTRIBUTE_HANDLER @@ -81,15 +84,15 @@ Error ARMAttributeParser::stringAttribute(AttrType tag) { return Error::success(); } +static const char *CPU_arch_strings[] = { + "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", + "ARM v6", "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", + "ARM v6S-M", "ARM v7E-M", "ARM v8-A", "ARM v8-R", "ARM v8-M Baseline", + "ARM v8-M Mainline", nullptr, nullptr, nullptr, "ARM v8.1-M Mainline", + "ARM v9-A"}; + Error ARMAttributeParser::CPU_arch(AttrType tag) { - static const char *strings[] = { - "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6", - "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M", - "ARM v7E-M", "ARM v8-A", "ARM v8-R", - "ARM v8-M Baseline", "ARM v8-M Mainline", nullptr, nullptr, nullptr, - "ARM v8.1-M Mainline", "ARM v9-A" - }; - return parseStringAttribute("CPU_arch", tag, makeArrayRef(strings)); + return parseStringAttribute("CPU_arch", tag, makeArrayRef(CPU_arch_strings)); } Error ARMAttributeParser::CPU_arch_profile(AttrType tag) { @@ -380,6 +383,84 @@ Error ARMAttributeParser::nodefaults(AttrType tag) { return Error::success(); } +Error ARMAttributeParser::also_compatible_with(AttrType tag) { + // Parse value as a C string first in order to print it in escaped form later. + // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch. + Optional returnValue; + + SmallString<8> Description; + raw_svector_ostream DescStream(Description); + + uint64_t InitialOffset = cursor.tell(); + StringRef RawStringValue = de.getCStrRef(cursor); + uint64_t FinalOffset = cursor.tell(); + cursor.seek(InitialOffset); + uint64_t InnerTag = de.getULEB128(cursor); + + bool ValidInnerTag = + any_of(tagToStringMap, [InnerTag](const TagNameItem &Item) { + return Item.attr == InnerTag; + }); + + if (!ValidInnerTag) { + returnValue = + createStringError(errc::argument_out_of_domain, + Twine(InnerTag) + " is not a valid tag number"); + } else { + switch (InnerTag) { + case ARMBuildAttrs::CPU_arch: { + uint64_t InnerValue = de.getULEB128(cursor); + auto strings = makeArrayRef(CPU_arch_strings); + if (InnerValue >= strings.size()) { + returnValue = createStringError( + errc::argument_out_of_domain, + Twine(InnerValue) + " is not a valid " + + ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + + " value"); + } else { + DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + << " = " << InnerValue; + if (strings[InnerValue]) + DescStream << " (" << strings[InnerValue] << ')'; + } + break; + } + case ARMBuildAttrs::also_compatible_with: + returnValue = createStringError( + errc::invalid_argument, + ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + + " cannot be recursively defined"); + break; + case ARMBuildAttrs::CPU_raw_name: + case ARMBuildAttrs::CPU_name: + case ARMBuildAttrs::compatibility: + case ARMBuildAttrs::conformance: { + StringRef InnerValue = de.getCStrRef(cursor); + DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + << " = " << InnerValue; + break; + } + default: { + uint64_t InnerValue = de.getULEB128(cursor); + DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + << " = " << InnerValue; + } + } + } + + DictScope scope(*sw, "Attribute"); + sw->printNumber("Tag", tag); + sw->printString("TagName", + ELFAttrs::attrTypeAsString(tag, tagToStringMap, false)); + sw->printStringEscaped("Value", RawStringValue); + if (!Description.empty()) { + sw->printString("Description", Description); + } + cursor.seek(FinalOffset); + + return returnValue ? std::move(*returnValue) : Error::success(); +} + Error ARMAttributeParser::handler(uint64_t tag, bool &handled) { handled = false; for (unsigned AHI = 0, AHE = array_lengthof(displayRoutines); AHI != AHE; diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-integer.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-integer.s new file mode 100644 index 0000000..afb5a0c --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-integer.s @@ -0,0 +1,10 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - | \ +@ RUN: FileCheck %s + +.eabi_attribute Tag_also_compatible_with, "\015\001" +@ CHECK: Attribute +@ CHECK: Tag: 65 +@ CHECK: TagName: also_compatible_with +@ CHECK: Value: \015\001 +@ CHECK: Description: Tag_PCS_config = 1 diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s new file mode 100644 index 0000000..1bbd0f2 --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - 2>&1 | \ +@ RUN: FileCheck %s --check-prefix=CHECK-WARNING + +.eabi_attribute Tag_also_compatible_with, "\006\143" +@ CHECK-WARNING: 99 is not a valid Tag_CPU_arch value diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s new file mode 100644 index 0000000..e459701 --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - 2>&1 | \ +@ RUN: FileCheck %s --check-prefix=CHECK-WARNING + +.eabi_attribute Tag_also_compatible_with, "\074\001" +@ CHECK-WARNING: 60 is not a valid tag number diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s new file mode 100644 index 0000000..fa6174e --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - 2>&1 | \ +@ RUN: FileCheck %s --check-prefix=CHECK-WARNING + +.eabi_attribute Tag_also_compatible_with, "\101\006\017" +@ CHECK-WARNING: Tag_also_compatible_with cannot be recursively defined diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-string.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-string.s new file mode 100644 index 0000000..f578120 --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-string.s @@ -0,0 +1,10 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - | \ +@ RUN: FileCheck %s + +.eabi_attribute Tag_also_compatible_with, "\005Cortex-A7" +@ CHECK: Attribute +@ CHECK: Tag: 65 +@ CHECK: TagName: also_compatible_with +@ CHECK: Value: \005Cortex-A7 +@ CHECK: Description: Tag_CPU_name = Cortex-A7 diff --git a/llvm/test/MC/ARM/directive-eabi_attribute.s b/llvm/test/MC/ARM/directive-eabi_attribute.s index fd2719e..6b35428 100644 --- a/llvm/test/MC/ARM/directive-eabi_attribute.s +++ b/llvm/test/MC/ARM/directive-eabi_attribute.s @@ -234,13 +234,11 @@ @ CHECK-OBJ-NEXT: TagName: nodefaults @ CHECK-OBJ-NEXT: Description: Unspecified Tags UNDEFINED .eabi_attribute Tag_also_compatible_with, "\006\017" -@ The value for Tag_also_compatible_with should be a pair of a tag (ULEB128) + -@ a value (ULEB128 + null or NTBS). llvm-readobj doesn't now how to process -@ this yet, so we use the encoded value explicitly here. @ CHECK: .eabi_attribute 65, "\006\017" @ CHECK-OBJ: Tag: 65 @ CHECK-OBJ-NEXT: TagName: also_compatible_with -@ CHECK-OBJ-NEXT: Value: +@ CHECK-OBJ-NEXT: Value: \006\017 +@ CHECK-OBJ-NEXT: Description: Tag_CPU_arch = 15 (ARM v8-R) .eabi_attribute Tag_T2EE_use, 0 @ CHECK: .eabi_attribute 66, 0 @ CHECK-OBJ: Tag: 66 -- 2.7.4