diff options
author | Puyan Lotfi <puyan@puyan.org> | 2018-09-03 22:25:56 +0000 |
---|---|---|
committer | Puyan Lotfi <puyan@puyan.org> | 2018-09-03 22:25:56 +0000 |
commit | 5a40cd5b50e15ea5125904a1d389dadf8ac8647d (patch) | |
tree | 07ed326b9b4b746a35468a62130680f73f0aced9 /llvm/tools/llvm-objcopy/llvm-objcopy.cpp | |
parent | 0945959869dfc7c8ef13c2eecc55c6d5f260c1d2 (diff) | |
download | llvm-5a40cd5b50e15ea5125904a1d389dadf8ac8647d.zip llvm-5a40cd5b50e15ea5125904a1d389dadf8ac8647d.tar.gz llvm-5a40cd5b50e15ea5125904a1d389dadf8ac8647d.tar.bz2 |
[llvm-objcopy] Dwarf .debug section compression support (zlib, zlib-gnu).
Usage:
llvm-objcopy --compress-debug-sections=zlib foo.o
llvm-objcopy --compress-debug-sections=zlib-gnu foo.o
In both cases the debug section contents is compressed with zlib. In the GNU
style case the header is the "ZLIB" magic string followed by the uint64 big-
endian decompressed size. In the non-GNU mode the header is the
Elf(32|64)_Chdr.
Decompression support is coming soon.
Differential Revision: https://reviews.llvm.org/D49678
llvm-svn: 341342
Diffstat (limited to 'llvm/tools/llvm-objcopy/llvm-objcopy.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/llvm-objcopy.cpp | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp index 72501f3..f0d6b44 100644 --- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/Binary.h" @@ -175,6 +176,7 @@ struct CopyConfig { bool StripSections = false; bool StripUnneeded = false; bool Weaken = false; + DebugCompressionType CompressionType = DebugCompressionType::None; }; using SectionPred = std::function<bool(const SectionBase &Sec)>; @@ -290,12 +292,12 @@ static SectionRename parseRenameSectionValue(StringRef FlagValue) { } static bool isDebugSection(const SectionBase &Sec) { - return Sec.Name.startswith(".debug") || Sec.Name.startswith(".zdebug") || - Sec.Name == ".gdb_index"; + return StringRef(Sec.Name).startswith(".debug") || + StringRef(Sec.Name).startswith(".zdebug") || Sec.Name == ".gdb_index"; } static bool isDWOSection(const SectionBase &Sec) { - return Sec.Name.endswith(".dwo"); + return StringRef(Sec.Name).endswith(".dwo"); } static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) { @@ -405,6 +407,49 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename, object_error::parse_failed); } +static bool isCompressed(const SectionBase &Section) { + ArrayRef<uint8_t> GnuPrefix = {'Z', 'L', 'I', 'B'}; + return StringRef(Section.Name).startswith(".zdebug") || + (Section.OriginalData.size() > strlen("ZLIB") && + std::equal(GnuPrefix.begin(), GnuPrefix.end(), + Section.OriginalData.data())) || + (Section.Flags & ELF::SHF_COMPRESSED); +} + +static bool isCompressable(const SectionBase &Section) { + return !isCompressed(Section) && isDebugSection(Section) && + Section.Name != ".gdb_index"; +} + +static void compressSections(const CopyConfig &Config, Object &Obj, + SectionPred &RemovePred) { + SmallVector<SectionBase *, 13> ToCompress; + SmallVector<RelocationSection *, 13> RelocationSections; + for (auto &Sec : Obj.sections()) { + if (RelocationSection *R = dyn_cast<RelocationSection>(&Sec)) { + if (isCompressable(*R->getSection())) + RelocationSections.push_back(R); + continue; + } + + if (isCompressable(Sec)) + ToCompress.push_back(&Sec); + } + + for (SectionBase *S : ToCompress) { + CompressedSection &CS = + Obj.addSection<CompressedSection>(*S, Config.CompressionType); + + for (RelocationSection *RS : RelocationSections) { + if (RS->getSection() == S) + RS->setSection(&CS); + } + } + + RemovePred = [RemovePred](const SectionBase &Sec) { + return isCompressable(Sec) || RemovePred(Sec); + }; +} // This function handles the high level operations of GNU objcopy including // handling command line options. It's important to outline certain properties // we expect to hold of the command line operations. Any operation that "keeps" @@ -564,7 +609,7 @@ static void handleArgs(const CopyConfig &Config, Object &Obj, return true; if (&Sec == Obj.SectionNames) return false; - if (Sec.Name.startswith(".gnu.warning")) + if (StringRef(Sec.Name).startswith(".gnu.warning")) return false; return (Sec.Flags & SHF_ALLOC) == 0; }; @@ -616,6 +661,9 @@ static void handleArgs(const CopyConfig &Config, Object &Obj, }; } + if (Config.CompressionType != DebugCompressionType::None) + compressSections(Config, Obj, RemovePred); + Obj.removeSections(RemovePred); if (!Config.SectionsToRename.empty()) { @@ -860,6 +908,23 @@ static CopyConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) { Config.BinaryArch = getMachineInfo(BinaryArch); } + if (auto Arg = InputArgs.getLastArg(OBJCOPY_compress_debug_sections, + OBJCOPY_compress_debug_sections_eq)) { + Config.CompressionType = DebugCompressionType::Z; + + if (Arg->getOption().getID() == OBJCOPY_compress_debug_sections_eq) { + Config.CompressionType = + StringSwitch<DebugCompressionType>( + InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)) + .Case("zlib-gnu", DebugCompressionType::GNU) + .Case("zlib", DebugCompressionType::Z) + .Default(DebugCompressionType::None); + if (Config.CompressionType == DebugCompressionType::None) + error("Invalid or unsupported --compress-debug-sections format: " + + InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)); + } + } + Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo); Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols); |