forked from OSchip/llvm-project
[yaml2obj] - Don't allow setting StOther and Other/Visibility at the same time.
This is a follow up discussed in the comments of D66583. Currently, if for example, we have both StOther and Other set in YAML document for a symbol, then yaml2obj reports an "unknown key 'Other'" error. It happens because 'mapOptional()' is never called for 'Other/Visibility' in this case, leaving those unhandled. This message does not describe the reason of the error well. This patch fixes it. Differential revision: https://reviews.llvm.org/D66642 llvm-svn: 370032
This commit is contained in:
parent
37a188b6e8
commit
7a2e21d9f4
|
@ -107,7 +107,12 @@ struct Symbol {
|
||||||
ELF_STB Binding;
|
ELF_STB Binding;
|
||||||
llvm::yaml::Hex64 Value;
|
llvm::yaml::Hex64 Value;
|
||||||
llvm::yaml::Hex64 Size;
|
llvm::yaml::Hex64 Size;
|
||||||
uint8_t Other;
|
Optional<uint8_t> Other;
|
||||||
|
|
||||||
|
// This can be used to set any custom value for the st_other field
|
||||||
|
// when it is not possible to do so using the "Other" field, which only takes
|
||||||
|
// specific named constants.
|
||||||
|
Optional<uint8_t> StOther;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SectionOrType {
|
struct SectionOrType {
|
||||||
|
|
|
@ -464,7 +464,12 @@ toELFSymbols(NameToIdxMap &SN2I, ArrayRef<ELFYAML::Symbol> Symbols,
|
||||||
}
|
}
|
||||||
// else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
|
// else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
|
||||||
Symbol.st_value = Sym.Value;
|
Symbol.st_value = Sym.Value;
|
||||||
Symbol.st_other = Sym.Other;
|
|
||||||
|
if (Sym.Other)
|
||||||
|
Symbol.st_other = *Sym.Other;
|
||||||
|
else if (Sym.StOther)
|
||||||
|
Symbol.st_other = *Sym.StOther;
|
||||||
|
|
||||||
Symbol.st_size = Sym.Size;
|
Symbol.st_size = Sym.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -866,15 +866,28 @@ void MappingTraits<ELFYAML::ProgramHeader>::mapping(
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct NormalizedOther {
|
struct NormalizedOther {
|
||||||
NormalizedOther(IO &)
|
NormalizedOther(IO &) {}
|
||||||
: Visibility(ELFYAML::ELF_STV(0)), Other(ELFYAML::ELF_STO(0)) {}
|
NormalizedOther(IO &, Optional<uint8_t> Original) {
|
||||||
NormalizedOther(IO &, uint8_t Original)
|
if (uint8_t Val = *Original & 0x3)
|
||||||
: Visibility(Original & 0x3), Other(Original & ~0x3) {}
|
Visibility = Val;
|
||||||
|
if (uint8_t Val = *Original & ~0x3)
|
||||||
|
Other = Val;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t denormalize(IO &) { return Visibility | Other; }
|
Optional<uint8_t> denormalize(IO &) {
|
||||||
|
if (!Visibility && !Other)
|
||||||
|
return None;
|
||||||
|
|
||||||
ELFYAML::ELF_STV Visibility;
|
uint8_t Ret = 0;
|
||||||
ELFYAML::ELF_STO Other;
|
if (Visibility)
|
||||||
|
Ret |= *Visibility;
|
||||||
|
if (Other)
|
||||||
|
Ret |= *Other;
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<ELFYAML::ELF_STV> Visibility;
|
||||||
|
Optional<ELFYAML::ELF_STO> Other;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
@ -896,17 +909,16 @@ void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {
|
||||||
// targets (e.g. MIPS) may use it to specify the named bits to set (e.g.
|
// targets (e.g. MIPS) may use it to specify the named bits to set (e.g.
|
||||||
// STO_MIPS_OPTIONAL). For producing broken objects we want to allow writing
|
// STO_MIPS_OPTIONAL). For producing broken objects we want to allow writing
|
||||||
// any value to st_other. To do this we allow one more field called "StOther".
|
// any value to st_other. To do this we allow one more field called "StOther".
|
||||||
// If it is present in a YAML document, we set st_other to that integer,
|
// If it is present in a YAML document, we set st_other to its integer value
|
||||||
// ignoring the other fields.
|
// whatever it is.
|
||||||
Optional<llvm::yaml::Hex64> Other;
|
// obj2yaml should not print 'StOther', it should print 'Visibility' and
|
||||||
IO.mapOptional("StOther", Other);
|
// 'Other' fields instead.
|
||||||
if (Other) {
|
assert(!IO.outputting() || !Symbol.StOther.hasValue());
|
||||||
Symbol.Other = *Other;
|
IO.mapOptional("StOther", Symbol.StOther);
|
||||||
} else {
|
MappingNormalization<NormalizedOther, Optional<uint8_t>> Keys(IO,
|
||||||
MappingNormalization<NormalizedOther, uint8_t> Keys(IO, Symbol.Other);
|
Symbol.Other);
|
||||||
IO.mapOptional("Visibility", Keys->Visibility, ELFYAML::ELF_STV(0));
|
IO.mapOptional("Visibility", Keys->Visibility);
|
||||||
IO.mapOptional("Other", Keys->Other, ELFYAML::ELF_STO(0));
|
IO.mapOptional("Other", Keys->Other);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef MappingTraits<ELFYAML::Symbol>::validate(IO &IO,
|
StringRef MappingTraits<ELFYAML::Symbol>::validate(IO &IO,
|
||||||
|
@ -915,6 +927,8 @@ StringRef MappingTraits<ELFYAML::Symbol>::validate(IO &IO,
|
||||||
return "Index and Section cannot both be specified for Symbol";
|
return "Index and Section cannot both be specified for Symbol";
|
||||||
if (Symbol.NameIndex && !Symbol.Name.empty())
|
if (Symbol.NameIndex && !Symbol.Name.empty())
|
||||||
return "Name and NameIndex cannot both be specified for Symbol";
|
return "Name and NameIndex cannot both be specified for Symbol";
|
||||||
|
if (Symbol.StOther && Symbol.Other)
|
||||||
|
return "StOther cannot be specified for Symbol with either Visibility or Other";
|
||||||
return StringRef();
|
return StringRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,3 +77,32 @@ Symbols:
|
||||||
StOther: 4
|
StOther: 4
|
||||||
- Name: bar
|
- Name: bar
|
||||||
StOther: 0xff
|
StOther: 0xff
|
||||||
|
|
||||||
|
## Check we can't set StOther for a symbol if Visibility or Other is also specified.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj --docnum=5 2>&1 %s | FileCheck %s --check-prefix=ERR2
|
||||||
|
# RUN: not yaml2obj --docnum=6 2>&1 %s | FileCheck %s --check-prefix=ERR2
|
||||||
|
|
||||||
|
# ERR2: error: StOther cannot be specified for Symbol with either Visibility or Other
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS32
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_REL
|
||||||
|
Machine: EM_MIPS
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
StOther: 0
|
||||||
|
Other: [ STO_MIPS_OPTIONAL ]
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS32
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_REL
|
||||||
|
Machine: EM_MIPS
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
StOther: 0
|
||||||
|
Visibility: STV_DEFAULT
|
||||||
|
|
Loading…
Reference in New Issue