This is an archive of the discontinued LLVM Phabricator instance.

[yaml2obj] - Add a way to override sh_flags section field.
ClosedPublic

Authored by grimar on Dec 12 2019, 4:50 AM.

Details

Summary

Currently we have the Flags property that allows to
set flags for a section. The problem is that it does not
allow us to set an arbitrary values, because of bit fields
validation under the hood. An arbitrary values can be used
to test specific broken cases.

We probably do not want to relax the validation, so this
patch adds a ShSize property that allows to
override the sh_size. It is inline with others Sh* properties
we have already.

Diff Detail

Event Timeline

grimar created this revision.Dec 12 2019, 4:50 AM

This looks fine to me. I do have one question though: is it possible to allow Flags to take two different kinds of value (i.e. a list or a number)? If so, we don't need an extra field - if a number is specified, then use that and do no validation, otherwise try to map the list values to the flags and do validation. The other fields make sense because they allow overriding a value which is also used for something else (e.g. ShOffset allows overriding the section's offset, but the actual offset is still used for writing data).

This looks fine to me. I do have one question though: is it possible to allow Flags to take two different kinds of value (i.e. a list or a number)? If so, we don't need an extra field - if a number is specified, then use that and do no validation, otherwise try to map the list values to the flags and do validation. The other fields make sense because they allow overriding a value which is also used for something else (e.g. ShOffset allows overriding the section's offset, but the actual offset is still used for writing data).

Currently we map Flags as ScalarBitSetTraits<ELFYAML::ELF_SHF>, it is defined as Optional<ELF_SHF> Flags;,
so seems we will need to add a new type to perform mapping.

I guess a correct way to implement that would be to do something like we did for st_other, where we needed to support both flags
and numeric values, i.e. to use the MappingNormalization and add something like NormalizedOther and StOtherPiece:
https://github.com/llvm-mirror/llvm/blob/master/lib/ObjectYAML/ELFYAML.cpp#L868
https://github.com/llvm-mirror/llvm/blob/master/lib/ObjectYAML/ELFYAML.cpp#L974
https://github.com/llvm-mirror/llvm/blob/master/lib/ObjectYAML/ELFYAML.cpp#L852

Perhaps it is possible to write a bit less code, since "a list or a number" case sounds simpler,
though it is not clear yet. Perphaps easier would be to stick to format of st_other and allow to mix flags
and values, like: [SHF_ALLOC, 0xFEFEFEFE] then.

It is not that hard to implement probably, but my concern is the next:
For st_other we knew it adds a complexity to the code, but we had no choice probably as the format
of the st_other was kind of special.

But does it worth adding such a complexity to the code to implement the same for Flags?

jhenderson accepted this revision.Dec 12 2019, 7:37 AM

Okay, LGTM. Might want to give @MaskRay a chance to chime in before committing.

This revision is now accepted and ready to land.Dec 12 2019, 7:37 AM
MaskRay accepted this revision.EditedDec 12 2019, 9:15 PM

Keeping both ShFlags and Flags is fine if you think doing things the Other way is hard to implement.

I investigated this a bit. The most difficult part is reading. yamlize has to make the decision whether a value is scalar or not, bitset or not early. If we want to parse both an integer (Hex64) and an array of strings, it will be difficult.

template <typename T>
typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
  bool DoClear;
  if ( io.beginBitSetScalar(DoClear) ) {
    if ( DoClear )
      Val = T();
    ScalarBitSetTraits<T>::bitset(io, Val);
    io.endBitSetScalar();
  }
}

The problem is that it does not allow us to set an arbitrary values

values->value

llvm/test/tools/yaml2obj/ELF/override-shflags.yaml
73

workaround (noun) -> work around

This revision was automatically updated to reflect the committed changes.
grimar marked an inline comment as done.