[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
This commit is contained in:
Victor Campos 2022-07-12 16:10:58 +01:00
parent 807b8cb06c
commit 08c6840f25
9 changed files with 140 additions and 12 deletions

View File

@ -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)

View File

@ -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<uint8_t> 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();

View File

@ -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<Error> 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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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