This is an archive of the discontinued LLVM Phabricator instance.

[yaml2obj] - Don't allow setting StOther and Other/Visibility at the same time.
ClosedPublic

Authored by grimar on Aug 23 2019, 4:53 AM.

Details

Summary

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.

Diff Detail

Event Timeline

grimar created this revision.Aug 23 2019, 4:53 AM
jhenderson added inline comments.Aug 23 2019, 5:40 AM
include/llvm/ObjectYAML/ELFYAML.h
112 ↗(On Diff #216809)

sh_other -> st_other

113–115 ↗(On Diff #216809)

I don't think you need the majority of this comment. How about

"when it is not possible to do so using the "Other" field, which only takes specific named constants".

lib/ObjectYAML/ELFEmitter.cpp
471 ↗(On Diff #216809)

I just want to be clear that st_other is zero-initialized?

lib/ObjectYAML/ELFYAML.cpp
914–915 ↗(On Diff #216809)

What if it's not possible to represent the value of st_other using Visibility and Other?

931 ↗(On Diff #216809)

Maybe "StOther cannot be specified for Symbol with either Visibility or Other"?

test/tools/yaml2obj/elf-symbol-stother.yaml
81 ↗(On Diff #216809)

How about "Check we can't set StOther for a symbol if Visibility or Other is also specified."

MaskRay added inline comments.Aug 24 2019, 6:42 AM
lib/ObjectYAML/ELFEmitter.cpp
471 ↗(On Diff #216809)

It is uninitialized.

grimar marked an inline comment as done.Aug 24 2019, 10:01 AM
grimar added inline comments.
lib/ObjectYAML/ELFEmitter.cpp
471 ↗(On Diff #216809)

It is uninitialized.

I think you're mistaken. It should be initialized because of 'Ret.resize(Symbols.size() + 1)' call. It is value initialized, i.e. zero initialized in this case.
(https://en.cppreference.com/w/cpp/container/vector/resize).

That is how it works for st_name or st_shndx I think. Am I missing something?

MaskRay added inline comments.Aug 25 2019, 11:38 PM
lib/ObjectYAML/ELFEmitter.cpp
471 ↗(On Diff #216809)

Sorry, I was mistaken. I didn't notice the vector::resize call above. The elements are value initialized (zeroed), so the code is ok.

grimar updated this revision to Diff 217138.Aug 26 2019, 6:49 AM
grimar marked 9 inline comments as done.
  • Addressed review comments.
include/llvm/ObjectYAML/ELFYAML.h
113–115 ↗(On Diff #216809)

LG, thanks!

lib/ObjectYAML/ELFYAML.cpp
914–915 ↗(On Diff #216809)

Yes, this is a right question that I thought about too, but still have no good answer for now.

It is related to obj2yaml, not to yaml2obj and technically the straightforward way to solve this for the common case would probably be
to know somehow if the mapping operation failed or not. Then we can fall back to dumping the field just as "StOther" in some cases.
I think the existent API can't handle that.

There are other options probably. We can perhaps stop trying dumping st_other as flags at all, because:

PPC64 stores int values in this field, not just flags:

// Special values for the st_other field in the symbol table entry for PPC64.
enum {
  STO_PPC64_LOCAL_BIT = 5,
  STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT)
};
static inline int64_t decodePPC64LocalEntryOffset(unsigned Other) {
  unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT;
  return ((1 << Val) >> 2) << 2;
}
static inline unsigned encodePPC64LocalEntryOffset(int64_t Offset) {
  unsigned Val =
      (Offset >= 4 * 4 ? (Offset >= 8 * 4 ? (Offset >= 16 * 4 ? 6 : 5) : 4)
                       : (Offset >= 2 * 4 ? 3 : (Offset >= 1 * 4 ? 2 : 0)));
  return Val << STO_PPC64_LOCAL_BIT;
}

So handling st_value as a set of flags is technically not 100% correct for this particular case.
But perhaps we can just try to isolate this corner case (that is inline with my patches at the current step I think).

I need to investigate the possible solutions for obj2yaml a bit deeper to suggest a good approach. Seems it is a subject for a different patch though?

931 ↗(On Diff #216809)

Done.

test/tools/yaml2obj/elf-symbol-stother.yaml
81 ↗(On Diff #216809)

Done.

MaskRay added inline comments.Aug 26 2019, 7:53 AM
lib/ObjectYAML/ELFYAML.cpp
914–915 ↗(On Diff #216809)

I agree that dumping raw StOther is probably the best for PPC64 (its ELFv2 ABI uses the high bits)...

jhenderson accepted this revision.Aug 27 2019, 2:14 AM

LGTM.

lib/ObjectYAML/ELFYAML.cpp
914–915 ↗(On Diff #216809)

Okay, I agree that it's a possible future extension to obj2yaml to handle that case, as long as it's not going to produce incorrect ELF objects (e.g. with a value other than requested) in the case where it doesn't work (I'm okay with it emitting an error in this case for now). Using a raw StOther seems like the right thing to do longer term when things don't work.

A slightly more radical solution could be to only have one field "Other" (i.e. no Visibility or StOther), which simply takes a list of named parameters or an arbitrary integer. STV_HIDDEN etc could be allowed via the named parameters. I don't know if this is a good idea or not though.

This revision is now accepted and ready to land.Aug 27 2019, 2:14 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptAug 27 2019, 3:02 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
MaskRay added inline comments.Aug 27 2019, 3:12 AM
lib/ObjectYAML/ELFYAML.cpp
914–915 ↗(On Diff #216809)

Allow all of the following?

Other: [ STV_HIDDEN, STO_MIPS_OPTIONAL ] # MIPS
Other: [ STV_HIDDEN, 192 ] # PPC64 ELFv2
Other: 2

I think that will be great.

grimar marked an inline comment as done.Aug 27 2019, 3:29 AM
grimar added inline comments.
lib/ObjectYAML/ELFYAML.cpp
914–915 ↗(On Diff #216809)

It looks good. I am not sure which/how much changes needs to be done to achieve that though,
but it perhaps worth investigating. (Hopefully this might help to simplify the code, the current approach with MappingNormalization and NormalizedOther is a bit too complex for my eyes).

Perhaps there are other places which can switch to such approach too.

I'll try to investigate.

This was reverted by rL370198

This was reverted by rL370198

Yes. Seems there is an uninitialized variable, I do not see it though (http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap-msan/builds/14395/steps/check-llvm%20msan/logs/stdio)
I am going to post a patch that suggests to eliminate the 'Visibility' and 'StOther' soon. So we probably will not need this.

I also can't understand how this could trigger MachO test failtures:

Failing Tests (3):

LLVM :: ObjectYAML/MachO/DWARF-debug_info.yaml
LLVM :: ObjectYAML/MachO/DWARF-debug_line.yaml
LLVM :: ObjectYAML/MachO/DWARF5-debug_info.yaml

I do not see how my changes can affect this.

It was reverted by a mistake and relanded in r370206