[llvm] 4dd5f1c - [yaml2obj] - Add `ELFYAML::YAMLIntUInt` to fix how we parse a relocation `Addend` key.
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 17 04:22:38 PDT 2020
Author: Georgii Rymar
Date: 2020-03-17T14:22:19+03:00
New Revision: 4dd5f1ca9b2b7ae50849efeb7cf3ecfbdb1cf67a
URL: https://github.com/llvm/llvm-project/commit/4dd5f1ca9b2b7ae50849efeb7cf3ecfbdb1cf67a
DIFF: https://github.com/llvm/llvm-project/commit/4dd5f1ca9b2b7ae50849efeb7cf3ecfbdb1cf67a.diff
LOG: [yaml2obj] - Add `ELFYAML::YAMLIntUInt` to fix how we parse a relocation `Addend` key.
This patch makes `Relocation::Addend` to be `ELFYAML::YAMLIntUInt` and not `int64_t`.
`ELFYAML::YAMLIntUInt` it is a new type and it has the following benefits/features:
1) For an 64-bit object any hex/decimal addends
in the range [INT64_MIN, UINT64_MAX] is accepted.
2) For an 32-bit object any hex/decimal addends
in range [INT32_MIN, UINT32_MAX] is accepted.
3) Negative hex numbers like -0xffffffff are not accepted.
4) It is printed as decimal. I.e. obj2yaml will print
something like "Addend: 125", this matches the current behavior.
This fixes all FIXMEs in `relocation-addend.yaml`.
Differential revision: https://reviews.llvm.org/D75527
Added:
Modified:
llvm/include/llvm/ObjectYAML/ELFYAML.h
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml
Removed:
################################################################################
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index 60bb2375901b..44f5d7cd069e 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -65,6 +65,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA)
LLVM_YAML_STRONG_TYPEDEF(StringRef, YAMLFlowString)
+LLVM_YAML_STRONG_TYPEDEF(int64_t, YAMLIntUInt)
// For now, hardcode 64 bits everywhere that 32 or 64 would be needed
// since 64-bit can hold 32-bit values too.
@@ -439,7 +440,7 @@ struct Group : Section {
struct Relocation {
llvm::yaml::Hex64 Offset;
- int64_t Addend;
+ YAMLIntUInt Addend;
ELF_REL Type;
Optional<StringRef> Symbol;
};
@@ -542,6 +543,14 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName)
namespace llvm {
namespace yaml {
+template <> struct ScalarTraits<ELFYAML::YAMLIntUInt> {
+ static void output(const ELFYAML::YAMLIntUInt &Val, void *Ctx,
+ raw_ostream &Out);
+ static StringRef input(StringRef Scalar, void *Ctx,
+ ELFYAML::YAMLIntUInt &Val);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
template <>
struct ScalarEnumerationTraits<ELFYAML::ELF_ET> {
static void enumeration(IO &IO, ELFYAML::ELF_ET &Value);
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index d567153af4c2..e9977b4899ee 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -982,6 +982,38 @@ struct NormalizedOther {
} // end anonymous namespace
+void ScalarTraits<ELFYAML::YAMLIntUInt>::output(const ELFYAML::YAMLIntUInt &Val,
+ void *Ctx, raw_ostream &Out) {
+ Out << Val;
+}
+
+StringRef ScalarTraits<ELFYAML::YAMLIntUInt>::input(StringRef Scalar, void *Ctx,
+ ELFYAML::YAMLIntUInt &Val) {
+ const bool Is64 = static_cast<ELFYAML::Object *>(Ctx)->Header.Class ==
+ ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
+ StringRef ErrMsg = "invalid number";
+ // We do not accept negative hex numbers because their meaning is ambiguous.
+ // For example, would -0xfffffffff mean 1 or INT32_MIN?
+ if (Scalar.empty() || Scalar.startswith("-0x"))
+ return ErrMsg;
+
+ if (Scalar.startswith("-")) {
+ const int64_t MinVal = Is64 ? INT64_MIN : INT32_MIN;
+ long long Int;
+ if (getAsSignedInteger(Scalar, /*Radix=*/0, Int) || (Int < MinVal))
+ return ErrMsg;
+ Val = Int;
+ return "";
+ }
+
+ const uint64_t MaxVal = Is64 ? UINT64_MAX : UINT32_MAX;
+ unsigned long long UInt;
+ if (getAsUnsignedInteger(Scalar, /*Radix=*/0, UInt) || (UInt > MaxVal))
+ return ErrMsg;
+ Val = UInt;
+ return "";
+}
+
void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
IO.mapOptional("Name", Symbol.Name, StringRef());
IO.mapOptional("StName", Symbol.StName);
@@ -1582,7 +1614,7 @@ void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO,
} else
IO.mapRequired("Type", Rel.Type);
- IO.mapOptional("Addend", Rel.Addend, (int64_t)0);
+ IO.mapOptional("Addend", Rel.Addend, (ELFYAML::YAMLIntUInt)0);
}
void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) {
diff --git a/llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml b/llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml
index 53396765fb59..f4ed870357f4 100644
--- a/llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml
@@ -2,36 +2,50 @@
## Case 1: Check a 64-bit object.
-## Case 1.1: Document we accept an addend with the
-## value INT64_MAX = 2^63-1 = 0x7FFFFFFFFFFFFFFF = 9223372036854775807.
+## Case 1.1: Document we accept any hex/decimal addends in [INT64_MIN, UINT64_MAX].
-# RUN: yaml2obj %s -o %t1 -D ADDEND=9223372036854775807
-# RUN: llvm-readobj -r %t1 | FileCheck %s --check-prefix=MAX64
-# RUN: yaml2obj %s -o %t2 -D ADDEND=0x7FFFFFFFFFFFFFFF
-# RUN: llvm-readobj -r %t2 | FileCheck %s --check-prefix=MAX64
+## INT64_MIN == -9223372036854775808
+## UINT64_MAX == 0xffffffffffffffff
-# MAX64: 0x0 R_X86_64_PC32 foo 0x7FFFFFFFFFFFFFFF
+## Addend == UINT64_MAX.
+# RUN: yaml2obj %s -o %t64.decimal.max -DADDEND=18446744073709551615
+# RUN: llvm-readobj -r %t64.decimal.max | FileCheck %s --check-prefix=TEST -DADDEND=0xFFFFFFFFFFFFFFFF
+# RUN: yaml2obj %s -o %t64.hex.max -DADDEND=0xFFFFFFFFFFFFFFFF
+# RUN: llvm-readobj -r %t64.hex.max | FileCheck %s --check-prefix=TEST -DADDEND=0xFFFFFFFFFFFFFFFF
-## Case 1.2: Check we report an error when an addend is greater than INT64_MAX and
-## it is in decimal form. We use (INT64_MAX + 1).
-# RUN: not yaml2obj %s -o %t3 -D ADDEND=9223372036854775808 2>&1 | FileCheck %s --check-prefix=OVERFLOW64
+## Addend == first positive integer.
+# RUN: yaml2obj %s -o %t64.decimal.first.pos -DADDEND=1
+# RUN: llvm-readobj -r %t64.decimal.first.pos | FileCheck %s --check-prefix=TEST -DADDEND=0x1
+# RUN: yaml2obj %s -o %t64.hex.first.pos -DADDEND=0x1
+# RUN: llvm-readobj -r %t64.hex.first.pos | FileCheck %s --check-prefix=TEST -DADDEND=0x1
-# OVERFLOW64: error: invalid number
+## Addend == 0.
+# RUN: yaml2obj %s -o %t64.decimal.null -DADDEND=0
+# RUN: llvm-readobj -r %t64.decimal.null | FileCheck %s --check-prefix=TEST -DADDEND=0x0
+# RUN: yaml2obj %s -o %t64.hex.null -DADDEND=0x0
+# RUN: llvm-readobj -r %t64.hex.null | FileCheck %s --check-prefix=TEST -DADDEND=0x0
-## Case 1.3: Document we accept an addend with the
-## value INT64_MIN = -2^63 = 0x8000000000000000 = -9223372036854775808.
+## Addend == first negative integer.
+# RUN: yaml2obj %s -o %t64.decimal.first.neg -DADDEND=-1
+# RUN: llvm-readobj -r %t64.decimal.first.neg | FileCheck %s --check-prefix=TEST -DADDEND=0xFFFFFFFFFFFFFFFF
+## We do not accept negative hex addends.
+# RUN: not yaml2obj %s -o /dev/null -DADDEND=-0x1 2>&1 | FileCheck %s --check-prefix=ERR
-# RUN: yaml2obj %s -o %t3 -D ADDEND=-9223372036854775808
-# RUN: llvm-readobj -r %t3 | FileCheck %s --check-prefix=MIN64
+## Addend == INT64_MIN.
+# RUN: yaml2obj %s -o %t64.decimal.min -DADDEND=-9223372036854775808
+# RUN: llvm-readobj -r %t64.decimal.min | FileCheck %s --check-prefix=TEST -DADDEND=0x8000000000000000
+# TEST: 0x0 R_{{.*}}_PC32 foo [[ADDEND]]
-# MIN64: 0x0 R_X86_64_PC32 foo 0x8000000000000000
+# Case 1.2: Document we do not accept any hex/decimal addends outside of the range specified.
-## FIXME: We should support the following case instead.
-# RUN: not yaml2obj %s -o /dev/null -D ADDEND=0x8000000000000000 2>&1 | FileCheck %s --check-prefix=OVERFLOW64
+## Addend == 2^64.
+# RUN: not yaml2obj %s -o /dev/null -DADDEND=18446744073709551616 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -o /dev/null -DADDEND=0x10000000000000000 2>&1 | FileCheck %s --check-prefix=ERR
-## Case 1.4: Check we report an error when an addend is less than INT64_MIN and
-## it is in decimal form. We use (INT64_MIN - 1).
-# RUN: not yaml2obj %s -o /dev/null -D ADDEND=-9223372036854775809 2>&1 | FileCheck %s --check-prefix=OVERFLOW64
+## Addend == INT64_MIN - 1.
+# RUN: not yaml2obj %s -o /dev/null -DADDEND=-9223372036854775809 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ERR: invalid number
--- !ELF
FileHeader:
@@ -55,43 +69,47 @@ Symbols:
## Case 2: Check a 32-bit object.
-## Case 2.1: Document we accept an addend with the
-## value INT32_MAX = 2^31-1 = 0x7FFFFFFF = 2,147,483,647.
-
-# RUN: yaml2obj --docnum=2 %s -o %t4 -D ADDEND=2147483647
-# RUN: llvm-readobj -r %t4 | FileCheck %s --check-prefix=MAX32
-# RUN: yaml2obj --docnum=2 %s -o %t5 -D ADDEND=0x7FFFFFFF
-# RUN: cmp %t4 %t5
+## INT32_MIN == -2147483648
+## UINT32_MAX == 0xffffffff
-# MAX32: 0x0 R_386_PC32 foo 0x7FFFFFFF{{$}}
+## Case 2.1: Document we accept any hex/decimal addends in [INT32_MIN, UINT32_MAX].
-## Case 2.2: Check we report an error when an addend is greater than INT32_MAX and
-## it is specified in decimal form. We use (INT32_MAX + 1).
+## Addend == UINT32_MAX.
+# RUN: yaml2obj --docnum=2 %s -o %t32.decimal.max -DADDEND=4294967295
+# RUN: llvm-readobj -r %t32.decimal.max | FileCheck %s --check-prefix=TEST -DADDEND=0xFFFFFFFF
+# RUN: yaml2obj --docnum=2 %s -o %t32.hex.max -DADDEND=0xFFFFFFFF
+# RUN: llvm-readobj -r %t32.hex.max | FileCheck %s --check-prefix=TEST -DADDEND=0xFFFFFFFF
-## FIXME: The following case should fail, see OVERFLOW64.
-# RUN: yaml2obj --docnum=2 %s -o %t6 -D ADDEND=2147483648
-# RUN: llvm-readobj -r %t6 | FileCheck %s --check-prefix=OVERFLOW32-1
+## Addend == first positive integer.
+# RUN: yaml2obj --docnum=2 %s -o %t32.decimal.first.pos -DADDEND=1
+# RUN: llvm-readobj -r %t32.decimal.first.pos | FileCheck %s --check-prefix=TEST -DADDEND=0x1
+# RUN: yaml2obj --docnum=2 %s -o %t32.hex.first.pos -DADDEND=0x1
+# RUN: llvm-readobj -r %t32.hex.first.pos | FileCheck %s --check-prefix=TEST -DADDEND=0x1
-# OVERFLOW32-1: 0x0 R_386_PC32 foo 0x80000000{{$}}
+## Addend == 0.
+# RUN: yaml2obj --docnum=2 %s -o %t32.decimal.null -DADDEND=0
+# RUN: llvm-readobj -r %t32.decimal.null | FileCheck %s --check-prefix=TEST -DADDEND=0x0
+# RUN: yaml2obj --docnum=2 %s -o %t32.hex.null -DADDEND=0x0
+# RUN: llvm-readobj -r %t32.hex.null | FileCheck %s --check-prefix=TEST -DADDEND=0x0
-## Case 2.3: Document we accept an addend with the
-## value INT32_MIN = -2^31 = 0x80000000 = -2,147,483,648.
+## Addend == first negative integer.
+# RUN: yaml2obj --docnum=2 %s -o %t32.decimal.first.neg -DADDEND=-1
+# RUN: llvm-readobj -r %t32.decimal.first.neg | FileCheck %s --check-prefix=TEST -DADDEND=0xFFFFFFFF
+## We do not accept negative hex addends.
+# RUN: not yaml2obj --docnum=2 %s -o /dev/null -DADDEND=-0x1 2>&1 | FileCheck %s --check-prefix=ERR
-# RUN: yaml2obj --docnum=2 %s -o %t7 -D ADDEND=-2147483648
-# RUN: llvm-readobj -r %t7 | FileCheck %s --check-prefix=MIN32
-# RUN: yaml2obj --docnum=2 %s -o %t8 -D ADDEND=0x80000000
-# RUN: cmp %t7 %t8
+## Addend == INT32_MIN
+# RUN: yaml2obj --docnum=2 %s -o %t32.decimal.min -DADDEND=-2147483648
+# RUN: llvm-readobj -r %t32.decimal.min | FileCheck %s --check-prefix=TEST -DADDEND=0x80000000
-# MIN32: 0x0 R_386_PC32 foo 0x80000000{{$}}
+# Case 2.2: Document we do not accept any hex/decimal addends outside of the range specified.
-## Case 2.4: Check we report an error when an addend is less than INT32_MIN and
-## it is in decimal form. We use (INT32_MIN - 1).
+## Addend == 2^32.
+# RUN: not yaml2obj --docnum=2 %s -o /dev/null -DADDEND=4294967296 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj --docnum=2 %s -o /dev/null -DADDEND=0x100000000 2>&1 | FileCheck %s --check-prefix=ERR
-## FIXME: The following case should fail, see OVERFLOW64.
-# RUN: yaml2obj --docnum=2 %s -o %t9 -D ADDEND=-2147483649
-# RUN: llvm-readobj -r %t9 | FileCheck %s --check-prefix=OVERFLOW32-2
-
-# OVERFLOW32-2: 0x0 R_386_PC32 foo 0x7FFFFFFF{{$}}
+## Addend == INT32_MIN - 1.
+# RUN: not yaml2obj --docnum=2 %s -o /dev/null -DADDEND=-2147483649 2>&1 | FileCheck %s --check-prefix=ERR
--- !ELF
FileHeader:
@@ -112,3 +130,12 @@ Sections:
Addend: [[ADDEND]]
Symbols:
- Name: foo
+
+## Case 3: Check we do not allow invalid values.
+# RUN: not yaml2obj %s -D ADDEND=0x1122GGEE 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -D ADDEND=-0x1122GGEE 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -D ADDEND=1234G5 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -D ADDEND=-1234G5 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -D ADDEND=foo 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -D ADDEND=- 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not yaml2obj %s -D ADDEND=--1234 2>&1 | FileCheck %s --check-prefix=ERR
More information about the llvm-commits
mailing list