Created
February 25, 2019 10:50
-
-
Save santagada/b6f5c42a3c83cd52fc663094f34bcc8d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/llvm/tools/llvm-objcopy/CMakeLists.txt b/llvm/tools/llvm-objcopy/CMakeLists.txt | |
index 8406786e9e4..0a9e33e568a 100644 | |
--- a/llvm/tools/llvm-objcopy/CMakeLists.txt | |
+++ b/llvm/tools/llvm-objcopy/CMakeLists.txt | |
@@ -1,4 +1,5 @@ | |
set(LLVM_LINK_COMPONENTS | |
+ DebugInfoCodeView | |
Object | |
Option | |
Support | |
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp | |
index 72161e1c4d7..fd801764f61 100644 | |
--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp | |
+++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp | |
@@ -19,6 +19,8 @@ | |
#include "llvm/Support/Errc.h" | |
#include "llvm/Support/JamCRC.h" | |
#include "llvm/Support/Path.h" | |
+#include "llvm/DebugInfo/CodeView/TypeHashing.h" | |
+#include "llvm/Support/BinaryStreamWriter.h" | |
#include <cassert> | |
namespace llvm { | |
@@ -27,6 +29,7 @@ namespace coff { | |
using namespace object; | |
using namespace COFF; | |
+using namespace codeview; | |
static bool isDebugSection(const Section &Sec) { | |
return Sec.Name.startswith(".debug"); | |
@@ -87,6 +90,129 @@ static void addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) { | |
Obj.addSections(Sections); | |
} | |
+static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> Data, | |
+ StringRef SecName) { | |
+ // First 4 bytes are section magic. | |
+ if (Data.size() < 4) | |
+ error(SecName + " too short"); | |
+ if (support::endian::read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) | |
+ error(SecName + " has an invalid magic"); | |
+ return Data.slice(4); | |
+} | |
+ | |
+const std::vector<GloballyHashedType> mergeDebugT(const Section *Sec) { | |
+ std::vector<GloballyHashedType> OwnedHashes; | |
+ | |
+ ArrayRef<uint8_t> Data = Sec->getContents(); | |
+ Data = consumeDebugMagic(Data, ".debug$T"); | |
+ if (Data.empty()) | |
+ return OwnedHashes; | |
+ | |
+ BinaryByteStream Stream(Data, support::little); | |
+ CVTypeArray Types; | |
+ BinaryStreamReader Reader(Stream); | |
+ if (auto EC = Reader.readArray(Types, Reader.getLength())) | |
+ error("Reader::readArray failed: " + toString(std::move(EC))); | |
+ | |
+ OwnedHashes = GloballyHashedType::hashTypes(Types); | |
+ return OwnedHashes; | |
+} | |
+ | |
+//void CodeViewDebug::emitTypeGlobalHashes() { | |
+// if (TypeTable.empty()) | |
+// return; | |
+// | |
+// // Start the .debug$H section with the version and hash algorithm, currently | |
+// // hardcoded to version 0, SHA1. | |
+// OS.SwitchSection(Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection()); | |
+// | |
+// OS.EmitValueToAlignment(4); | |
+// OS.AddComment("Magic"); | |
+// OS.EmitIntValue(COFF::DEBUG_HASHES_SECTION_MAGIC, 4); | |
+// OS.AddComment("Section Version"); | |
+// OS.EmitIntValue(0, 2); | |
+// OS.AddComment("Hash Algorithm"); | |
+// OS.EmitIntValue(uint16_t(GlobalTypeHashAlg::SHA1_8), 2); | |
+// | |
+// TypeIndex TI(TypeIndex::FirstNonSimpleIndex); | |
+// for (const auto &GHR : TypeTable.hashes()) { | |
+// if (OS.isVerboseAsm()) { | |
+// // Emit an EOL-comment describing which TypeIndex this hash corresponds | |
+// // to, as well as the stringified SHA1 hash. | |
+// SmallString<32> Comment; | |
+// raw_svector_ostream CommentOS(Comment); | |
+// CommentOS << formatv("{0:X+} [{1}]", TI.getIndex(), GHR); | |
+// OS.AddComment(Comment); | |
+// ++TI; | |
+// } | |
+// assert(GHR.Hash.size() == 8); | |
+// StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()), | |
+// GHR.Hash.size()); | |
+// OS.EmitBinaryData(S); | |
+// } | |
+//} | |
+ | |
+ArrayRef<uint8_t> toDebugH(const std::vector<GloballyHashedType> hashes, | |
+ BumpPtrAllocator &Alloc) { | |
+ uint32_t Size = 8 + 8 * hashes.size(); | |
+ uint8_t *Data = Alloc.Allocate<uint8_t>(Size); | |
+ MutableArrayRef<uint8_t> Buffer(Data, Size); | |
+ BinaryStreamWriter Writer(Buffer, llvm::support::little); | |
+ uint32_t magic = COFF::DEBUG_HASHES_SECTION_MAGIC; | |
+ cantFail(Writer.writeInteger(magic)); | |
+ cantFail(Writer.writeInteger(uint16_t(0))); | |
+ cantFail(Writer.writeInteger(uint16_t(GlobalTypeHashAlg::SHA1_8))); | |
+ for (const auto &H : hashes) { | |
+ Writer.writeBytes(H.Hash); | |
+ } | |
+ assert(Writer.bytesRemaining() == 0); | |
+ return Buffer; | |
+} | |
+ | |
+static void addGHashes(Object &Obj) { | |
+ std::vector<GloballyHashedType> hashes; | |
+ | |
+ for (Section section: Obj.getSections()) { | |
+ if (section.Name == ".debug$H") | |
+ error("Already has .debug$H"); | |
+ | |
+ if (section.Name == ".debug$T") { | |
+ hashes = mergeDebugT(§ion); | |
+ break; | |
+ } | |
+ } | |
+ | |
+ | |
+ std::vector<Section> Sections; | |
+ Section Sec; | |
+ BumpPtrAllocator Allocator; | |
+ Sec.setOwnedContents(toDebugH(hashes, Allocator)); | |
+ Sec.Name = ".debug$H"; | |
+ Sec.Header.VirtualSize = 0; // Sec.getContents().size(); | |
+ Sec.Header.VirtualAddress = 0; | |
+ Sec.Header.SizeOfRawData = Sec.getContents().size(); | |
+ // Sec.Header.PointerToRawData is filled in by the writer. | |
+ Sec.Header.PointerToRelocations = 0; | |
+ Sec.Header.PointerToLinenumbers = 0; | |
+ // Sec.Header.NumberOfRelocations is filled in by the writer. | |
+ Sec.Header.NumberOfLinenumbers = 0; | |
+ Sec.Header.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | | |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_ALIGN_4BYTES; | |
+ std::vector<Symbol> Symbols; | |
+ Symbol Sym; | |
+ Sym.Name = ".debug$H"; | |
+ Sym.Sym.Value = 0; | |
+ Sym.Sym.StorageClass = IMAGE_SYM_CLASS_STATIC; | |
+ Sym.Sym.NumberOfAuxSymbols = 1; | |
+ | |
+ | |
+ Sections.push_back(Sec); | |
+ Obj.addSections(Sections); | |
+ Sym.Sym.SectionNumber = Sec.Index; | |
+ Symbols.push_back(Sym); | |
+ //Obj.addSymbols(Sym); | |
+} | |
+ | |
static Error handleArgs(const CopyConfig &Config, Object &Obj) { | |
// Perform the actual section removals. | |
Obj.removeSections([&Config](const Section &Sec) { | |
@@ -171,6 +297,10 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) { | |
if (!Config.AddGnuDebugLink.empty()) | |
addGnuDebugLink(Obj, Config.AddGnuDebugLink); | |
+ if (Config.AddGHashes) | |
+ addGHashes(Obj); | |
+ | |
+ | |
if (!Config.BuildIdLinkDir.empty() || Config.BuildIdLinkInput || | |
Config.BuildIdLinkOutput || !Config.SplitDWO.empty() || | |
!Config.SymbolsPrefix.empty() || !Config.AddSection.empty() || | |
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp | |
index 91721962503..0e59f75b034 100644 | |
--- a/llvm/tools/llvm-objcopy/CopyConfig.cpp | |
+++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp | |
@@ -328,6 +328,7 @@ DriverConfig parseObjcopyOptions(ArrayRef<const char *> ArgsArr) { | |
} | |
Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); | |
+ Config.AddGHashes = InputArgs.hasArg(OBJCOPY_add_ghashes); | |
Config.BuildIdLinkDir = InputArgs.getLastArgValue(OBJCOPY_build_id_link_dir); | |
if (InputArgs.hasArg(OBJCOPY_build_id_link_input)) | |
Config.BuildIdLinkInput = | |
diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h | |
index 9d16c7b4582..6480a87b6d5 100644 | |
--- a/llvm/tools/llvm-objcopy/CopyConfig.h | |
+++ b/llvm/tools/llvm-objcopy/CopyConfig.h | |
@@ -89,6 +89,7 @@ struct CopyConfig { | |
StringMap<StringRef> SymbolsToRename; | |
// Boolean options | |
+ bool AddGHashes = false; | |
bool DeterministicArchives = true; | |
bool ExtractDWO = false; | |
bool KeepFileSymbols = false; | |
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td | |
index a25d1f3b515..e8b41132961 100644 | |
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td | |
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td | |
@@ -63,6 +63,9 @@ defm add_gnu_debuglink | |
: Eq<"add-gnu-debuglink", "Add a .gnu_debuglink for <debug-file>">, | |
MetaVarName<"debug-file">; | |
+def add_ghashes : Flag<["-", "--"], "add-ghashes">, | |
+ HelpText<"Add .h global hashes">; | |
+ | |
defm remove_section : Eq<"remove-section", "Remove <section>">, | |
MetaVarName<"section">; | |
def R : JoinedOrSeparate<["-"], "R">, Alias<remove_section>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment