Index: llvm/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -65,6 +65,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA) LLVM_YAML_STRONG_TYPEDEF(StringRef, YAMLFlowString) +LLVM_YAML_STRONG_TYPEDEF(int64_t, YAMLInt) // 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 Relocation { llvm::yaml::Hex64 Offset; - int64_t Addend; + YAMLInt Addend; ELF_REL Type; Optional Symbol; }; @@ -542,6 +543,12 @@ namespace llvm { namespace yaml { +template <> struct ScalarTraits { + static void output(const ELFYAML::YAMLInt &Val, void *Ctx, raw_ostream &Out); + static StringRef input(StringRef Scalar, void *Ctx, ELFYAML::YAMLInt &Val); + static QuotingType mustQuote(StringRef) { return QuotingType::None; } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_ET &Value); Index: llvm/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFYAML.cpp +++ llvm/lib/ObjectYAML/ELFYAML.cpp @@ -982,6 +982,53 @@ } // end anonymous namespace +void ScalarTraits::output(const ELFYAML::YAMLInt &Val, + void *Ctx, raw_ostream &Out) { + Out << Val; +} + +StringRef ScalarTraits::input(StringRef Scalar, void *Ctx, + ELFYAML::YAMLInt &Val) { + const bool Is64 = static_cast(Ctx)->Header.Class == + ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); + StringRef ErrMsg = "invalid number"; + + if (Scalar.startswith("-")) { + // Do not allow "-0xFE". It looks strange. + if (Scalar.drop_front().startswith("0x")) + return ErrMsg; + + long long Int; + if (getAsSignedInteger(Scalar, /*Radix=*/0, Int)) + return ErrMsg; + + // For a 32-bit target we allow decimals in a range of a + // signed 32-bit integer. + if (!Is64 && (Int > INT32_MAX || Int < INT32_MIN)) + return ErrMsg; + + Val = Int; + return StringRef(); + } + + unsigned long long UInt; + if (getAsUnsignedInteger(Scalar, /*Radix=*/0, UInt)) + return ErrMsg; + + // For a 32-bit target the value shouldn't be greater than UINT32_MAX. + if (!Is64 && (UInt > UINT32_MAX)) + return ErrMsg; + + // Any hex value in a 32/64 bit unsigned integer range is accepted. + // A decimal can't be larger than a value of a signed 32/64 bits integer. + if (!Scalar.startswith("0x")) + if ((Is64 && (UInt > INT64_MAX)) || (!Is64 && (UInt > INT32_MAX))) + return ErrMsg; + + Val = UInt; + return {}; +} + void MappingTraits::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Name", Symbol.Name, StringRef()); IO.mapOptional("StName", Symbol.StName); @@ -1582,7 +1629,7 @@ } else IO.mapRequired("Type", Rel.Type); - IO.mapOptional("Addend", Rel.Addend, (int64_t)0); + IO.mapOptional("Addend", Rel.Addend, (ELFYAML::YAMLInt)0); } void MappingTraits::mapping(IO &IO, ELFYAML::Object &Object) { Index: llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml =================================================================== --- llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml +++ llvm/test/tools/yaml2obj/ELF/relocation-addend.yaml @@ -14,24 +14,23 @@ ## Case 1.2: Check we report an error when an addend is greater than INT64_MAX and ## it is in a decimal form. We use (INT64_MAX + 1). -# RUN: not yaml2obj %s -o %t3 -D ADDEND=9223372036854775808 2>&1 | FileCheck %s --check-prefix=OVERFLOW64 +# RUN: not yaml2obj %s -o %t3 -D ADDEND=9223372036854775808 2>&1 | FileCheck %s --check-prefix=INVALID -# OVERFLOW64: error: invalid number +# INVALID: error: invalid number ## Case 1.3: Document we accept an addend with the ## value = INT64_MIN = -2^63 = 0x8000000000000000 = -9223372036854775808. # RUN: yaml2obj %s -o %t3 -D ADDEND=-9223372036854775808 # RUN: llvm-readobj -r %t3 | FileCheck %s --check-prefix=MIN64 +# RUN: yaml2obj %s -o %t4 -D ADDEND=0x8000000000000000 +# RUN: llvm-readobj -r %t4 | FileCheck %s --check-prefix=MIN64 ## MIN64: 0x0 R_X86_64_PC32 foo 0x8000000000000000 -## 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 - ## Case 1.4: Check we report an error when an addend is less than INT64_MIN and ## it is in a decimal form. We use (INT64_MIN - 1). -# RUN: not yaml2obj %s -o /dev/null -D ADDEND=-9223372036854775809 2>&1 | FileCheck %s --check-prefix=OVERFLOW64 +# RUN: not yaml2obj %s -o /dev/null -D ADDEND=-9223372036854775809 2>&1 | FileCheck %s --check-prefix=INVALID --- !ELF FileHeader: @@ -69,11 +68,7 @@ ## Case 2.2: Check we report an error when an addend is greater than INT32_MAX and ## it is specified in a decimal form. We use (INT32_MAX + 1). -## 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 - -# OVERFLOW32-1: 0x0 R_386_PC32 foo 0x80000000{{$}} +# RUN: not yaml2obj --docnum=2 %s -o /dev/null -D ADDEND=2147483648 2>&1 | FileCheck %s --check-prefix=INVALID ## Case 2.3: Document we accept an addend with the ## value = INT32_MIN = -2^31 = 0x80000000 = -2,147,483,648. @@ -89,11 +84,13 @@ ## Case 2.4: Check we report an error when an addend is less than INT32_MIN and ## it is in a decimal form. We use (INT32_MIN - 1). -## 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 +# RUN: not yaml2obj --docnum=2 %s -o /dev/null -D ADDEND=-2147483649 2>&1 | FileCheck %s --check-prefix=INVALID -# OVERFLOW32-2: 0x0 R_386_PC32 foo 0x7FFFFFFF{{$}} +## Case 2.5: ELFCLASS32 objects use 32 bits fields to store an addend. +## Hence it does not make sence to allow addend greater than UINT32_MAX. +## Check we report an error in this case. +# RUN: not yaml2obj --docnum=2 %s -D ADDEND=0x100000000 2>&1 | FileCheck %s --check-prefix=INVALID +# RUN: not yaml2obj --docnum=2 %s -D ADDEND=4294967296 2>&1 | FileCheck %s --check-prefix=INVALID --- !ELF FileHeader: @@ -115,3 +112,15 @@ Addend: [[ADDEND]] Symbols: - Name: foo + +## Case 3: Check we do not allow a minus before the hex value of an addend. +## I.e. we do not allow "-0xFE". +# RUN: not yaml2obj --docnum=1 %s -D ADDEND=-0x1 2>&1 | FileCheck %s --check-prefix=INVALID +# RUN: not yaml2obj --docnum=2 %s -D ADDEND=-0x1 2>&1 | FileCheck %s --check-prefix=INVALID + +## Case 4: Check we do not allow invalid values. +# RUN: not yaml2obj --docnum=1 %s -D ADDEND=0x1122QQEE 2>&1 | FileCheck %s --check-prefix=INVALID +# RUN: not yaml2obj --docnum=2 %s -D ADDEND=-0x1122QQEE 2>&1 | FileCheck %s --check-prefix=INVALID +# RUN: not yaml2obj --docnum=1 %s -D ADDEND=1234Q5 2>&1 | FileCheck %s --check-prefix=INVALID +# RUN: not yaml2obj --docnum=2 %s -D ADDEND=-1234Q5 2>&1 | FileCheck %s --check-prefix=INVALID +# RUN: not yaml2obj --docnum=2 %s -D ADDEND=foo 2>&1 | FileCheck %s --check-prefix=INVALID