[llvm] 501522b - [RISCV] Support RISC-V ELF attributes sections in llvm-readobj.

Kai Wang via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 1 06:56:16 PDT 2020


Author: Kai Wang
Date: 2020-04-01T21:50:11+08:00
New Revision: 501522b5b2a1b2620370c2885da7caa7ed3b5c73

URL: https://github.com/llvm/llvm-project/commit/501522b5b2a1b2620370c2885da7caa7ed3b5c73
DIFF: https://github.com/llvm/llvm-project/commit/501522b5b2a1b2620370c2885da7caa7ed3b5c73.diff

LOG: [RISCV] Support RISC-V ELF attributes sections in llvm-readobj.

Enable llvm-readobj to handle RISC-V ELF attribute sections.

Differential Revision: https://reviews.llvm.org/D75833

Added: 
    llvm/test/MC/RISCV/attribute-with-option.s
    llvm/test/tools/llvm-readobj/ELF/RISCV/attribute.s
    llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-section-size.test
    llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-version.test
    llvm/test/tools/llvm-readobj/ELF/RISCV/lit.local.cfg
    llvm/test/tools/llvm-readobj/ELF/RISCV/section-types.test
    llvm/test/tools/llvm-readobj/ELF/RISCV/validate-attr-section.test

Modified: 
    llvm/lib/Support/ELFAttributeParser.cpp
    llvm/tools/llvm-readobj/ELFDumper.cpp
    llvm/unittests/Support/ELFAttributeParserTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Support/ELFAttributeParser.cpp b/llvm/lib/Support/ELFAttributeParser.cpp
index 93be0535d1b9..df955cdf5d30 100644
--- a/llvm/lib/Support/ELFAttributeParser.cpp
+++ b/llvm/lib/Support/ELFAttributeParser.cpp
@@ -217,7 +217,7 @@ Error ELFAttributeParser::parse(ArrayRef<uint8_t> section,
 
     if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
       return createStringError(errc::invalid_argument,
-                               "invalid subsection length " +
+                               "invalid section length " +
                                    Twine(sectionLength) + " at offset 0x" +
                                    utohexstr(cursor.tell() - 4));
 

diff  --git a/llvm/test/MC/RISCV/attribute-with-option.s b/llvm/test/MC/RISCV/attribute-with-option.s
new file mode 100644
index 000000000000..749717cb7a55
--- /dev/null
+++ b/llvm/test/MC/RISCV/attribute-with-option.s
@@ -0,0 +1,21 @@
+## When a user specifies an architecture extension which conflicts with an
+## architecture attribute, we use the architecture attribute instead of the
+## command line option.
+##
+## This test uses option '-mattr=+e' to specify the "e" extension. However,
+## there is an architecture attribute in the file to specify rv32i. We will
+## use rv32i to assemble the file instead of rv32e.
+
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+e -filetype=obj -o - \
+# RUN:   | llvm-readobj -A - | FileCheck %s
+
+.attribute arch, "rv32i2p0"
+## Invalid operand for RV32E, because x16 is an invalid register for RV32E.
+## Use RV32I to assemble, since it will not trigger an assembly error.
+lui x16, 1
+
+## Check that the architecture attribute is not overridden by the command line
+## option.
+# CHECK:      Tag: 5
+# CHECK-NEXT: TagName: arch
+# CHECK-NEXT: Value: rv32i2p0

diff  --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/attribute.s b/llvm/test/tools/llvm-readobj/ELF/RISCV/attribute.s
new file mode 100644
index 000000000000..5ae7bfcb0290
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/attribute.s
@@ -0,0 +1,44 @@
+## Test llvm-readobj & llvm-readelf can decode RISC-V attributes correctly.
+
+# RUN: llvm-mc -triple riscv32 -filetype obj -o %t.rv32.o %s
+# RUN: llvm-mc -triple riscv64 -filetype obj -o %t.rv64.o %s
+# RUN: llvm-readobj --arch-specific %t.rv32.o \
+# RUN:   | FileCheck %s --check-prefix=CHECK-OBJ
+# RUN: llvm-readelf -A %t.rv32.o \
+# RUN:   | FileCheck %s --check-prefix=CHECK-OBJ
+# RUN: llvm-readobj --arch-specific %t.rv64.o \
+# RUN:   | FileCheck %s --check-prefix=CHECK-OBJ
+# RUN: llvm-readelf -A %t.rv64.o \
+# RUN:   | FileCheck %s --check-prefix=CHECK-OBJ
+
+.attribute  Tag_stack_align, 16
+# CHECK-OBJ:      Tag: 4
+# CHECK-OBJ-NEXT: Value: 16
+# CHECK-OBJ-NEXT: TagName: stack_align
+# CHECK-OBJ-NEXT: Description: Stack alignment is 16-bytes
+
+.attribute  Tag_arch, "rv32i2p0_m2p0_a2p0_c2p0"
+# CHECK-OBJ:      Tag: 5
+# CHECK-OBJ-NEXT: TagName: arch
+# CHECK-OBJ-NEXT: Value: rv32i2p0_m2p0_a2p0_c2p0
+
+.attribute  Tag_unaligned_access, 0
+# CHECK-OBJ:      Tag: 6
+# CHECK-OBJ-NEXT: Value: 0
+# CHECK-OBJ-NEXT: TagName: unaligned_access
+# CHECK-OBJ-NEXT: Description: No unaligned access
+
+.attribute  Tag_priv_spec, 2
+# CHECK-OBJ:      Tag: 8
+# CHECK-OBJ-NEXT: TagName: priv_spec
+# CHECK-OBJ-NEXT: Value: 2
+
+.attribute  Tag_priv_spec_minor, 0
+# CHECK-OBJ:      Tag: 10
+# CHECK-OBJ-NEXT: TagName: priv_spec_minor
+# CHECK-OBJ-NEXT: Value: 0
+
+.attribute  Tag_priv_spec_revision, 0
+# CHECK-OBJ:      Tag: 12
+# CHECK-OBJ-NEXT: TagName: priv_spec_revision
+# CHECK-OBJ-NEXT: Value: 0

diff  --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-section-size.test b/llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-section-size.test
new file mode 100644
index 000000000000..524134e1579b
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-section-size.test
@@ -0,0 +1,20 @@
+## This test case is used to ensure the error code is caught by llvm-readobj.
+
+# RUN: yaml2obj %s -D BITS=32 -o %t.32.o
+# RUN: llvm-readobj -A %t.32.o 2>&1 | FileCheck -DFILE=%t %s
+# RUN: yaml2obj %s -D BITS=64 -o %t.64.o
+# RUN: llvm-readobj -A %t.64.o 2>&1 | FileCheck -DFILE=%t %s
+
+# CHECK: warning: '[[FILE]].{{32|64}}.o': invalid section length 0 at offset 0x1
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS[[BITS]]
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_RISCV
+Sections:
+  - Name:    .riscv.attributes
+    Type:    SHT_RISCV_ATTRIBUTES
+## Version: 'A'(0x41), section length: 0
+    Content: 4100000000

diff  --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-version.test b/llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-version.test
new file mode 100644
index 000000000000..9a4d81bcc4f1
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/invalid-attr-version.test
@@ -0,0 +1,21 @@
+## This test case is used to ensure llvm-readobj checks the version of
+## attribute sections correctly.
+
+# RUN: yaml2obj %s -D BITS=32 -o %t.32.o
+# RUN: llvm-readobj -A %t.32.o 2>&1 | FileCheck -DFILE=%t %s
+# RUN: yaml2obj %s -D BITS=64 -o %t.64.o
+# RUN: llvm-readobj -A %t.64.o 2>&1 | FileCheck -DFILE=%t %s
+
+# CHECK: warning: '[[FILE]].{{32|64}}.o': unrecognised FormatVersion: 0x42
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS[[BITS]]
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_RISCV
+Sections:
+  - Name:    .riscv.attributes
+    Type:    SHT_RISCV_ATTRIBUTES
+## Version: 'B'
+    Content: 42

diff  --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/lit.local.cfg b/llvm/test/tools/llvm-readobj/ELF/RISCV/lit.local.cfg
new file mode 100644
index 000000000000..c63820126f8c
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'RISCV' in config.root.targets:
+    config.unsupported = True

diff  --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/section-types.test b/llvm/test/tools/llvm-readobj/ELF/RISCV/section-types.test
new file mode 100644
index 000000000000..d1f35306afb2
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/section-types.test
@@ -0,0 +1,21 @@
+## Show that all RISCV specific section types are properly printed for both
+## LLVM and GNU styles.
+
+# RUN: yaml2obj %s -o %t-riscv.o
+# RUN: llvm-readobj --section-headers %t-riscv.o | FileCheck %s --check-prefix=LLVM
+# RUN: llvm-readelf --section-headers %t-riscv.o | FileCheck %s --check-prefix=GNU
+
+# LLVM:      Name: .riscv.attributes (1)
+# LLVM-NEXT: Type: SHT_RISCV_ATTRIBUTES (0x70000003)
+
+# GNU: [ 1] .riscv.attributes RISCV_ATTRIBUTES
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_RISCV
+Sections:
+  - Name: .riscv.attributes
+    Type: SHT_RISCV_ATTRIBUTES

diff  --git a/llvm/test/tools/llvm-readobj/ELF/RISCV/validate-attr-section.test b/llvm/test/tools/llvm-readobj/ELF/RISCV/validate-attr-section.test
new file mode 100644
index 000000000000..66a5a7a8d31f
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/RISCV/validate-attr-section.test
@@ -0,0 +1,17 @@
+## We only implement attribute section printing for little-endian encoding.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: llvm-readobj -A %t.o | FileCheck %s
+
+# CHECK: Attributes not implemented.
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+## Test big-endian encoding.
+  Data:    ELFDATA2MSB
+  Type:    ET_REL
+  Machine: EM_RISCV
+Sections:
+  - Name: .riscv.attributes
+    Type: SHT_RISCV_ATTRIBUTES

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 24f41ae49469..6d785afd6530 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -52,6 +52,8 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MipsABIFlags.h"
+#include "llvm/Support/RISCVAttributeParser.h"
+#include "llvm/Support/RISCVAttributes.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -2678,6 +2680,7 @@ template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
   const ELFFile<ELFT> *Obj = ObjF->getELFFile();
   switch (Obj->getHeader()->e_machine) {
   case EM_ARM:
+  case EM_RISCV:
     printAttributes();
     break;
   case EM_MIPS: {
@@ -2698,40 +2701,45 @@ template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() {
   }
 }
 
-template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
-  W.startLine() << "Attributes not implemented.\n";
-}
-
 namespace {
 
-template <> void ELFDumper<ELF32LE>::printAttributes() {
-  const ELFFile<ELF32LE> *Obj = ObjF->getELFFile();
-  if (Obj->getHeader()->e_machine != EM_ARM) {
+template <class ELFT> void ELFDumper<ELFT>::printAttributes() {
+  const ELFFile<ELFT> *Obj = ObjF->getELFFile();
+  if (!Obj->isLE()) {
     W.startLine() << "Attributes not implemented.\n";
     return;
   }
 
+  const unsigned Machine = Obj->getHeader()->e_machine;
+  assert((Machine == EM_ARM || Machine == EM_RISCV) &&
+         "Attributes not implemented.");
+
   DictScope BA(W, "BuildAttributes");
-  for (const ELFO::Elf_Shdr &Sec :
-       unwrapOrError(ObjF->getFileName(), Obj->sections())) {
-    if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES)
+  for (const auto &Sec : unwrapOrError(ObjF->getFileName(), Obj->sections())) {
+    if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES &&
+        Sec.sh_type != ELF::SHT_RISCV_ATTRIBUTES)
       continue;
 
     ArrayRef<uint8_t> Contents =
         unwrapOrError(ObjF->getFileName(), Obj->getSectionContents(&Sec));
     if (Contents[0] != ELFAttrs::Format_Version) {
-      errs() << "unrecognised FormatVersion: 0x"
-             << Twine::utohexstr(Contents[0]) << '\n';
+      reportWarning(createError(Twine("unrecognised FormatVersion: 0x") +
+                                Twine::utohexstr(Contents[0])),
+                    ObjF->getFileName());
       continue;
     }
-
     W.printHex("FormatVersion", Contents[0]);
     if (Contents.size() == 1)
       continue;
 
-    // TODO: Print error and delete the redundant FormatVersion check above.
-    if (Error E = ARMAttributeParser(&W).parse(Contents, support::little))
-      consumeError(std::move(E));
+    // TODO: Delete the redundant FormatVersion check above.
+    if (Machine == EM_ARM) {
+      if (Error E = ARMAttributeParser(&W).parse(Contents, support::little))
+        reportWarning(std::move(E), ObjF->getFileName());
+    } else if (Machine == EM_RISCV) {
+      if (Error E = RISCVAttributeParser(&W).parse(Contents, support::little))
+        reportWarning(std::move(E), ObjF->getFileName());
+    }
   }
 }
 
@@ -3569,6 +3577,11 @@ static std::string getSectionTypeString(unsigned Arch, unsigned Type) {
       return "MIPS_ABIFLAGS";
     }
     break;
+  case EM_RISCV:
+    switch (Type) {
+    case SHT_RISCV_ATTRIBUTES:
+      return "RISCV_ATTRIBUTES";
+    }
   }
   switch (Type) {
   case SHT_NULL:

diff  --git a/llvm/unittests/Support/ELFAttributeParserTest.cpp b/llvm/unittests/Support/ELFAttributeParserTest.cpp
index ad4e309d8953..8234d4ee176f 100644
--- a/llvm/unittests/Support/ELFAttributeParserTest.cpp
+++ b/llvm/unittests/Support/ELFAttributeParserTest.cpp
@@ -40,9 +40,9 @@ TEST(AttributeHeaderParser, UnrecognizedFormatVersion) {
   testParseError(bytes, "unrecognized format-version: 0x1");
 }
 
-TEST(AttributeHeaderParser, InvalidSubsectionLength) {
+TEST(AttributeHeaderParser, InvalidSectionLength) {
   static const uint8_t bytes[] = {'A', 3, 0, 0, 0};
-  testParseError(bytes, "invalid subsection length 3 at offset 0x1");
+  testParseError(bytes, "invalid section length 3 at offset 0x1");
 }
 
 TEST(AttributeHeaderParser, UnrecognizedVendorName) {


        


More information about the llvm-commits mailing list