summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
authorGeorgii Rymar <grimar@accesssoftek.com>2019-12-13 15:48:09 +0300
committerGeorgii Rymar <grimar@accesssoftek.com>2019-12-18 10:44:40 +0300
commit541daa5e6b9bc38986e09612a9bd6f0f148fdfcf (patch)
tree65262352632b9c71872b294803bf2ae3227969d2 /llvm/tools
parent8cc0b586738157728a93af145c8f8dec1bf59ee1 (diff)
downloadbcm5719-llvm-541daa5e6b9bc38986e09612a9bd6f0f148fdfcf.tar.gz
bcm5719-llvm-541daa5e6b9bc38986e09612a9bd6f0f148fdfcf.zip
[llvm-readelf][llvm-readobj] - Reimplement the logic of section flags dumping.
Our logic that dumped the flags was buggy. For LLVM style it dumped SHF_MASKPROC/SHF_MASKOS named constants, though they are not flags, but masks. For GNU style it was just very inconsistent with GNU which has logic that is not straightforward. Imagine we have sh_flags == 0x90000000. SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000. GNU readelf will not print "E" or "Ep" in this case, but will print just "p". It only will print "E" when no other processor flag is set. I had to investigate the GNU source to find the algorithm and now our logic should match it. Differential revision: https://reviews.llvm.org/D71462
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp69
1 files changed, 42 insertions, 27 deletions
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 531ca351e21..7d648da41ea 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -1444,8 +1444,6 @@ static const EnumEntry<unsigned> ElfSectionFlags[] = {
ENUM_ENT(SHF_TLS, "T"),
ENUM_ENT(SHF_COMPRESSED, "C"),
ENUM_ENT(SHF_EXCLUDE, "E"),
- ENUM_ENT(SHF_MASKOS, "o"),
- ENUM_ENT(SHF_MASKPROC, "p"),
};
static const EnumEntry<unsigned> ElfXCoreSectionFlags[] = {
@@ -1477,34 +1475,51 @@ static const EnumEntry<unsigned> ElfX86_64SectionFlags[] = {
};
static std::string getGNUFlags(uint64_t Flags) {
+ // Here we are trying to build the flags string in the same way as GNU does.
+ // It is not that straightforward. Imagine we have sh_flags == 0x90000000.
+ // SHF_EXCLUDE ("E") has a value of 0x80000000 and SHF_MASKPROC is 0xf0000000.
+ // GNU readelf will not print "E" or "Ep" in this case, but will print just
+ // "p". It only will print "E" when no other processor flag is set.
std::string Str;
- for (auto Entry : ElfSectionFlags) {
- uint64_t Flag = Entry.Value & Flags;
- Flags &= ~Entry.Value;
- switch (Flag) {
- case ELF::SHF_WRITE:
- case ELF::SHF_ALLOC:
- case ELF::SHF_EXECINSTR:
- case ELF::SHF_MERGE:
- case ELF::SHF_STRINGS:
- case ELF::SHF_INFO_LINK:
- case ELF::SHF_LINK_ORDER:
- case ELF::SHF_OS_NONCONFORMING:
- case ELF::SHF_GROUP:
- case ELF::SHF_TLS:
- case ELF::SHF_COMPRESSED:
- case ELF::SHF_EXCLUDE:
- Str += Entry.AltName;
- break;
- default:
- if (Flag & ELF::SHF_MASKOS)
- Str += "o";
- else if (Flag & ELF::SHF_MASKPROC)
- Str += "p";
- else if (Flag)
- Str += "x";
+ bool HasUnknownFlag = false;
+ bool HasOSFlag = false;
+ bool HasProcFlag = false;
+ while (Flags) {
+ // Take the least significant bit as a flag.
+ uint64_t Flag = Flags & -Flags;
+ Flags -= Flag;
+
+ // Find the flag in the known flags list.
+ auto I = llvm::find_if(ElfSectionFlags, [=](const EnumEntry<unsigned> &E) {
+ return E.Value == Flag;
+ });
+ if (I != std::end(ElfSectionFlags)) {
+ Str += I->AltName;
+ continue;
+ }
+
+ // If we did not find a matching regular flag, then we deal with an OS
+ // specific flag, processor specific flag or an unknown flag.
+ if (Flag & ELF::SHF_MASKOS) {
+ HasOSFlag = true;
+ Flags &= ~ELF::SHF_MASKOS;
+ } else if (Flag & ELF::SHF_MASKPROC) {
+ HasProcFlag = true;
+ // Mask off all the processor-specific bits. This removes the SHF_EXCLUDE
+ // bit if set so that it doesn't also get printed.
+ Flags &= ~ELF::SHF_MASKPROC;
+ } else {
+ HasUnknownFlag = true;
}
}
+
+ // "o", "p" and "x" are printed last.
+ if (HasOSFlag)
+ Str += "o";
+ if (HasProcFlag)
+ Str += "p";
+ if (HasUnknownFlag)
+ Str += "x";
return Str;
}
OpenPOWER on IntegriCloud