diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/tools/llvm-objcopy/COFF | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-objcopy/COFF')
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 538 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.h | 62 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.cpp | 200 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.h | 418 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.cpp | 452 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.h | 84 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.cpp | 898 | ||||
-rw-r--r-- | contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.h | 124 |
8 files changed, 1388 insertions, 1388 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.cpp index b5de8a45a8..3c058e4785 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -1,292 +1,292 @@ -//===- COFFObjcopy.cpp ----------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "COFFObjcopy.h" -#include "Buffer.h" -#include "CopyConfig.h" -#include "Object.h" -#include "Reader.h" -#include "Writer.h" - -#include "llvm/Object/Binary.h" -#include "llvm/Object/COFF.h" -#include "llvm/Support/CRC.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/Path.h" -#include <cassert> - -namespace llvm { -namespace objcopy { -namespace coff { - -using namespace object; -using namespace COFF; - -static bool isDebugSection(const Section &Sec) { - return Sec.Name.startswith(".debug"); -} - -static uint64_t getNextRVA(const Object &Obj) { - if (Obj.getSections().empty()) - return 0; - const Section &Last = Obj.getSections().back(); - return alignTo(Last.Header.VirtualAddress + Last.Header.VirtualSize, - Obj.IsPE ? Obj.PeHeader.SectionAlignment : 1); -} - +//===- COFFObjcopy.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "COFFObjcopy.h" +#include "Buffer.h" +#include "CopyConfig.h" +#include "Object.h" +#include "Reader.h" +#include "Writer.h" + +#include "llvm/Object/Binary.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/CRC.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/Path.h" +#include <cassert> + +namespace llvm { +namespace objcopy { +namespace coff { + +using namespace object; +using namespace COFF; + +static bool isDebugSection(const Section &Sec) { + return Sec.Name.startswith(".debug"); +} + +static uint64_t getNextRVA(const Object &Obj) { + if (Obj.getSections().empty()) + return 0; + const Section &Last = Obj.getSections().back(); + return alignTo(Last.Header.VirtualAddress + Last.Header.VirtualSize, + Obj.IsPE ? Obj.PeHeader.SectionAlignment : 1); +} + static Expected<std::vector<uint8_t>> createGnuDebugLinkSectionContents(StringRef File) { - ErrorOr<std::unique_ptr<MemoryBuffer>> LinkTargetOrErr = - MemoryBuffer::getFile(File); - if (!LinkTargetOrErr) + ErrorOr<std::unique_ptr<MemoryBuffer>> LinkTargetOrErr = + MemoryBuffer::getFile(File); + if (!LinkTargetOrErr) return createFileError(File, LinkTargetOrErr.getError()); - auto LinkTarget = std::move(*LinkTargetOrErr); - uint32_t CRC32 = llvm::crc32(arrayRefFromStringRef(LinkTarget->getBuffer())); - - StringRef FileName = sys::path::filename(File); - size_t CRCPos = alignTo(FileName.size() + 1, 4); - std::vector<uint8_t> Data(CRCPos + 4); - memcpy(Data.data(), FileName.data(), FileName.size()); - support::endian::write32le(Data.data() + CRCPos, CRC32); - return Data; -} - -// Adds named section with given contents to the object. -static void addSection(Object &Obj, StringRef Name, ArrayRef<uint8_t> Contents, - uint32_t Characteristics) { - bool NeedVA = Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | - IMAGE_SCN_MEM_WRITE); - - Section Sec; - Sec.setOwnedContents(Contents); - Sec.Name = Name; - Sec.Header.VirtualSize = NeedVA ? Sec.getContents().size() : 0u; - Sec.Header.VirtualAddress = NeedVA ? getNextRVA(Obj) : 0u; - Sec.Header.SizeOfRawData = - NeedVA ? alignTo(Sec.Header.VirtualSize, - Obj.IsPE ? Obj.PeHeader.FileAlignment : 1) - : 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 = Characteristics; - - Obj.addSections(Sec); -} - + auto LinkTarget = std::move(*LinkTargetOrErr); + uint32_t CRC32 = llvm::crc32(arrayRefFromStringRef(LinkTarget->getBuffer())); + + StringRef FileName = sys::path::filename(File); + size_t CRCPos = alignTo(FileName.size() + 1, 4); + std::vector<uint8_t> Data(CRCPos + 4); + memcpy(Data.data(), FileName.data(), FileName.size()); + support::endian::write32le(Data.data() + CRCPos, CRC32); + return Data; +} + +// Adds named section with given contents to the object. +static void addSection(Object &Obj, StringRef Name, ArrayRef<uint8_t> Contents, + uint32_t Characteristics) { + bool NeedVA = Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_WRITE); + + Section Sec; + Sec.setOwnedContents(Contents); + Sec.Name = Name; + Sec.Header.VirtualSize = NeedVA ? Sec.getContents().size() : 0u; + Sec.Header.VirtualAddress = NeedVA ? getNextRVA(Obj) : 0u; + Sec.Header.SizeOfRawData = + NeedVA ? alignTo(Sec.Header.VirtualSize, + Obj.IsPE ? Obj.PeHeader.FileAlignment : 1) + : 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 = Characteristics; + + Obj.addSections(Sec); +} + static Error addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) { Expected<std::vector<uint8_t>> Contents = - createGnuDebugLinkSectionContents(DebugLinkFile); + createGnuDebugLinkSectionContents(DebugLinkFile); if (!Contents) return Contents.takeError(); addSection(Obj, ".gnu_debuglink", *Contents, - IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | - IMAGE_SCN_MEM_DISCARDABLE); + IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | + IMAGE_SCN_MEM_DISCARDABLE); return Error::success(); -} - -static void setSectionFlags(Section &Sec, SectionFlag AllFlags) { - // Need to preserve alignment flags. - const uint32_t PreserveMask = - IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_ALIGN_4BYTES | - IMAGE_SCN_ALIGN_8BYTES | IMAGE_SCN_ALIGN_16BYTES | - IMAGE_SCN_ALIGN_32BYTES | IMAGE_SCN_ALIGN_64BYTES | - IMAGE_SCN_ALIGN_128BYTES | IMAGE_SCN_ALIGN_256BYTES | - IMAGE_SCN_ALIGN_512BYTES | IMAGE_SCN_ALIGN_1024BYTES | - IMAGE_SCN_ALIGN_2048BYTES | IMAGE_SCN_ALIGN_4096BYTES | - IMAGE_SCN_ALIGN_8192BYTES; - - // Setup new section characteristics based on the flags provided in command - // line. - uint32_t NewCharacteristics = - (Sec.Header.Characteristics & PreserveMask) | IMAGE_SCN_MEM_READ; - - if ((AllFlags & SectionFlag::SecAlloc) && !(AllFlags & SectionFlag::SecLoad)) - NewCharacteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA; - if (AllFlags & SectionFlag::SecNoload) - NewCharacteristics |= IMAGE_SCN_LNK_REMOVE; - if (!(AllFlags & SectionFlag::SecReadonly)) - NewCharacteristics |= IMAGE_SCN_MEM_WRITE; - if (AllFlags & SectionFlag::SecDebug) - NewCharacteristics |= - IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE; - if (AllFlags & SectionFlag::SecCode) - NewCharacteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; - if (AllFlags & SectionFlag::SecData) - NewCharacteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; - if (AllFlags & SectionFlag::SecShare) - NewCharacteristics |= IMAGE_SCN_MEM_SHARED; - if (AllFlags & SectionFlag::SecExclude) - NewCharacteristics |= IMAGE_SCN_LNK_REMOVE; - - Sec.Header.Characteristics = NewCharacteristics; -} - -static Error handleArgs(const CopyConfig &Config, Object &Obj) { - // Perform the actual section removals. - Obj.removeSections([&Config](const Section &Sec) { - // Contrary to --only-keep-debug, --only-section fully removes sections that - // aren't mentioned. - if (!Config.OnlySection.empty() && !Config.OnlySection.matches(Sec.Name)) - return true; - - if (Config.StripDebug || Config.StripAll || Config.StripAllGNU || - Config.DiscardMode == DiscardType::All || Config.StripUnneeded) { - if (isDebugSection(Sec) && - (Sec.Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0) - return true; - } - - if (Config.ToRemove.matches(Sec.Name)) - return true; - - return false; - }); - - if (Config.OnlyKeepDebug) { - // For --only-keep-debug, we keep all other sections, but remove their - // content. The VirtualSize field in the section header is kept intact. - Obj.truncateSections([](const Section &Sec) { - return !isDebugSection(Sec) && Sec.Name != ".buildid" && - ((Sec.Header.Characteristics & - (IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA)) != 0); - }); - } - - // StripAll removes all symbols and thus also removes all relocations. - if (Config.StripAll || Config.StripAllGNU) - for (Section &Sec : Obj.getMutableSections()) - Sec.Relocs.clear(); - - // If we need to do per-symbol removals, initialize the Referenced field. - if (Config.StripUnneeded || Config.DiscardMode == DiscardType::All || - !Config.SymbolsToRemove.empty()) - if (Error E = Obj.markSymbols()) - return E; - - for (Symbol &Sym : Obj.getMutableSymbols()) { - auto I = Config.SymbolsToRename.find(Sym.Name); - if (I != Config.SymbolsToRename.end()) - Sym.Name = I->getValue(); - } - +} + +static void setSectionFlags(Section &Sec, SectionFlag AllFlags) { + // Need to preserve alignment flags. + const uint32_t PreserveMask = + IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_ALIGN_4BYTES | + IMAGE_SCN_ALIGN_8BYTES | IMAGE_SCN_ALIGN_16BYTES | + IMAGE_SCN_ALIGN_32BYTES | IMAGE_SCN_ALIGN_64BYTES | + IMAGE_SCN_ALIGN_128BYTES | IMAGE_SCN_ALIGN_256BYTES | + IMAGE_SCN_ALIGN_512BYTES | IMAGE_SCN_ALIGN_1024BYTES | + IMAGE_SCN_ALIGN_2048BYTES | IMAGE_SCN_ALIGN_4096BYTES | + IMAGE_SCN_ALIGN_8192BYTES; + + // Setup new section characteristics based on the flags provided in command + // line. + uint32_t NewCharacteristics = + (Sec.Header.Characteristics & PreserveMask) | IMAGE_SCN_MEM_READ; + + if ((AllFlags & SectionFlag::SecAlloc) && !(AllFlags & SectionFlag::SecLoad)) + NewCharacteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA; + if (AllFlags & SectionFlag::SecNoload) + NewCharacteristics |= IMAGE_SCN_LNK_REMOVE; + if (!(AllFlags & SectionFlag::SecReadonly)) + NewCharacteristics |= IMAGE_SCN_MEM_WRITE; + if (AllFlags & SectionFlag::SecDebug) + NewCharacteristics |= + IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE; + if (AllFlags & SectionFlag::SecCode) + NewCharacteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; + if (AllFlags & SectionFlag::SecData) + NewCharacteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; + if (AllFlags & SectionFlag::SecShare) + NewCharacteristics |= IMAGE_SCN_MEM_SHARED; + if (AllFlags & SectionFlag::SecExclude) + NewCharacteristics |= IMAGE_SCN_LNK_REMOVE; + + Sec.Header.Characteristics = NewCharacteristics; +} + +static Error handleArgs(const CopyConfig &Config, Object &Obj) { + // Perform the actual section removals. + Obj.removeSections([&Config](const Section &Sec) { + // Contrary to --only-keep-debug, --only-section fully removes sections that + // aren't mentioned. + if (!Config.OnlySection.empty() && !Config.OnlySection.matches(Sec.Name)) + return true; + + if (Config.StripDebug || Config.StripAll || Config.StripAllGNU || + Config.DiscardMode == DiscardType::All || Config.StripUnneeded) { + if (isDebugSection(Sec) && + (Sec.Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0) + return true; + } + + if (Config.ToRemove.matches(Sec.Name)) + return true; + + return false; + }); + + if (Config.OnlyKeepDebug) { + // For --only-keep-debug, we keep all other sections, but remove their + // content. The VirtualSize field in the section header is kept intact. + Obj.truncateSections([](const Section &Sec) { + return !isDebugSection(Sec) && Sec.Name != ".buildid" && + ((Sec.Header.Characteristics & + (IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA)) != 0); + }); + } + + // StripAll removes all symbols and thus also removes all relocations. + if (Config.StripAll || Config.StripAllGNU) + for (Section &Sec : Obj.getMutableSections()) + Sec.Relocs.clear(); + + // If we need to do per-symbol removals, initialize the Referenced field. + if (Config.StripUnneeded || Config.DiscardMode == DiscardType::All || + !Config.SymbolsToRemove.empty()) + if (Error E = Obj.markSymbols()) + return E; + + for (Symbol &Sym : Obj.getMutableSymbols()) { + auto I = Config.SymbolsToRename.find(Sym.Name); + if (I != Config.SymbolsToRename.end()) + Sym.Name = I->getValue(); + } + auto ToRemove = [&](const Symbol &Sym) -> Expected<bool> { - // For StripAll, all relocations have been stripped and we remove all - // symbols. - if (Config.StripAll || Config.StripAllGNU) - return true; - - if (Config.SymbolsToRemove.matches(Sym.Name)) { - // Explicitly removing a referenced symbol is an error. - if (Sym.Referenced) + // For StripAll, all relocations have been stripped and we remove all + // symbols. + if (Config.StripAll || Config.StripAllGNU) + return true; + + if (Config.SymbolsToRemove.matches(Sym.Name)) { + // Explicitly removing a referenced symbol is an error. + if (Sym.Referenced) return createStringError( llvm::errc::invalid_argument, "'" + Config.OutputFilename + "': not stripping symbol '" + Sym.Name.str() + "' because it is named in a relocation"); - return true; - } - - if (!Sym.Referenced) { - // With --strip-unneeded, GNU objcopy removes all unreferenced local - // symbols, and any unreferenced undefined external. - // With --strip-unneeded-symbol we strip only specific unreferenced - // local symbol instead of removing all of such. - if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC || - Sym.Sym.SectionNumber == 0) - if (Config.StripUnneeded || - Config.UnneededSymbolsToRemove.matches(Sym.Name)) - return true; - - // GNU objcopy keeps referenced local symbols and external symbols - // if --discard-all is set, similar to what --strip-unneeded does, - // but undefined local symbols are kept when --discard-all is set. - if (Config.DiscardMode == DiscardType::All && - Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC && - Sym.Sym.SectionNumber != 0) - return true; - } - - return false; + return true; + } + + if (!Sym.Referenced) { + // With --strip-unneeded, GNU objcopy removes all unreferenced local + // symbols, and any unreferenced undefined external. + // With --strip-unneeded-symbol we strip only specific unreferenced + // local symbol instead of removing all of such. + if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC || + Sym.Sym.SectionNumber == 0) + if (Config.StripUnneeded || + Config.UnneededSymbolsToRemove.matches(Sym.Name)) + return true; + + // GNU objcopy keeps referenced local symbols and external symbols + // if --discard-all is set, similar to what --strip-unneeded does, + // but undefined local symbols are kept when --discard-all is set. + if (Config.DiscardMode == DiscardType::All && + Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC && + Sym.Sym.SectionNumber != 0) + return true; + } + + return false; }; - + // Actually do removals of symbols. if (Error Err = Obj.removeSymbols(ToRemove)) return Err; - if (!Config.SetSectionFlags.empty()) - for (Section &Sec : Obj.getMutableSections()) { - const auto It = Config.SetSectionFlags.find(Sec.Name); - if (It != Config.SetSectionFlags.end()) - setSectionFlags(Sec, It->second.NewFlags); - } - - for (const auto &Flag : Config.AddSection) { - StringRef SecName, FileName; - std::tie(SecName, FileName) = Flag.split("="); - - auto BufOrErr = MemoryBuffer::getFile(FileName); - if (!BufOrErr) - return createFileError(FileName, errorCodeToError(BufOrErr.getError())); - auto Buf = std::move(*BufOrErr); - - addSection( - Obj, SecName, - makeArrayRef(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), - Buf->getBufferSize()), - IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES); - } - - if (!Config.AddGnuDebugLink.empty()) + if (!Config.SetSectionFlags.empty()) + for (Section &Sec : Obj.getMutableSections()) { + const auto It = Config.SetSectionFlags.find(Sec.Name); + if (It != Config.SetSectionFlags.end()) + setSectionFlags(Sec, It->second.NewFlags); + } + + for (const auto &Flag : Config.AddSection) { + StringRef SecName, FileName; + std::tie(SecName, FileName) = Flag.split("="); + + auto BufOrErr = MemoryBuffer::getFile(FileName); + if (!BufOrErr) + return createFileError(FileName, errorCodeToError(BufOrErr.getError())); + auto Buf = std::move(*BufOrErr); + + addSection( + Obj, SecName, + makeArrayRef(reinterpret_cast<const uint8_t *>(Buf->getBufferStart()), + Buf->getBufferSize()), + IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES); + } + + if (!Config.AddGnuDebugLink.empty()) if (Error E = addGnuDebugLink(Obj, Config.AddGnuDebugLink)) return E; - - if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() || - Config.BuildIdLinkInput || Config.BuildIdLinkOutput || - !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || - !Config.AllocSectionsPrefix.empty() || !Config.DumpSection.empty() || - !Config.KeepSection.empty() || Config.NewSymbolVisibility || - !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || - !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || - !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || - !Config.SetSectionAlignment.empty() || Config.ExtractDWO || - Config.LocalizeHidden || Config.PreserveDates || Config.StripDWO || - Config.StripNonAlloc || Config.StripSections || - Config.StripSwiftSymbols || Config.Weaken || - Config.DecompressDebugSections || - Config.DiscardMode == DiscardType::Locals || - !Config.SymbolsToAdd.empty() || Config.EntryExpr) { - return createStringError(llvm::errc::invalid_argument, - "option not supported by llvm-objcopy for COFF"); - } - - return Error::success(); -} - -Error executeObjcopyOnBinary(const CopyConfig &Config, COFFObjectFile &In, - Buffer &Out) { - COFFReader Reader(In); - Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create(); - if (!ObjOrErr) - return createFileError(Config.InputFilename, ObjOrErr.takeError()); - Object *Obj = ObjOrErr->get(); - assert(Obj && "Unable to deserialize COFF object"); - if (Error E = handleArgs(Config, *Obj)) - return createFileError(Config.InputFilename, std::move(E)); - COFFWriter Writer(*Obj, Out); - if (Error E = Writer.write()) - return createFileError(Config.OutputFilename, std::move(E)); - return Error::success(); -} - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm + + if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() || + Config.BuildIdLinkInput || Config.BuildIdLinkOutput || + !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || + !Config.AllocSectionsPrefix.empty() || !Config.DumpSection.empty() || + !Config.KeepSection.empty() || Config.NewSymbolVisibility || + !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || + !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || + !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || + !Config.SetSectionAlignment.empty() || Config.ExtractDWO || + Config.LocalizeHidden || Config.PreserveDates || Config.StripDWO || + Config.StripNonAlloc || Config.StripSections || + Config.StripSwiftSymbols || Config.Weaken || + Config.DecompressDebugSections || + Config.DiscardMode == DiscardType::Locals || + !Config.SymbolsToAdd.empty() || Config.EntryExpr) { + return createStringError(llvm::errc::invalid_argument, + "option not supported by llvm-objcopy for COFF"); + } + + return Error::success(); +} + +Error executeObjcopyOnBinary(const CopyConfig &Config, COFFObjectFile &In, + Buffer &Out) { + COFFReader Reader(In); + Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create(); + if (!ObjOrErr) + return createFileError(Config.InputFilename, ObjOrErr.takeError()); + Object *Obj = ObjOrErr->get(); + assert(Obj && "Unable to deserialize COFF object"); + if (Error E = handleArgs(Config, *Obj)) + return createFileError(Config.InputFilename, std::move(E)); + COFFWriter Writer(*Obj, Out); + if (Error E = Writer.write()) + return createFileError(Config.OutputFilename, std::move(E)); + return Error::success(); +} + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.h b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.h index 858759e52c..6b59f44946 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.h +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/COFFObjcopy.h @@ -1,31 +1,31 @@ -//===- COFFObjcopy.h --------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H -#define LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H - -namespace llvm { -class Error; - -namespace object { -class COFFObjectFile; -} // end namespace object - -namespace objcopy { -struct CopyConfig; -class Buffer; - -namespace coff { -Error executeObjcopyOnBinary(const CopyConfig &Config, - object::COFFObjectFile &In, Buffer &Out); - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm - -#endif // LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H +//===- COFFObjcopy.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H +#define LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H + +namespace llvm { +class Error; + +namespace object { +class COFFObjectFile; +} // end namespace object + +namespace objcopy { +struct CopyConfig; +class Buffer; + +namespace coff { +Error executeObjcopyOnBinary(const CopyConfig &Config, + object::COFFObjectFile &In, Buffer &Out); + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm + +#endif // LLVM_TOOLS_OBJCOPY_COFFOBJCOPY_H diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.cpp index 1c17b8408e..fc67f1cb4d 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.cpp +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.cpp @@ -1,39 +1,39 @@ -//===- Object.cpp ---------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Object.h" -#include "llvm/ADT/DenseSet.h" -#include <algorithm> - -namespace llvm { -namespace objcopy { -namespace coff { - -using namespace object; - -void Object::addSymbols(ArrayRef<Symbol> NewSymbols) { - for (Symbol S : NewSymbols) { - S.UniqueId = NextSymbolUniqueId++; - Symbols.emplace_back(S); - } - updateSymbols(); -} - -void Object::updateSymbols() { - SymbolMap = DenseMap<size_t, Symbol *>(Symbols.size()); - for (Symbol &Sym : Symbols) - SymbolMap[Sym.UniqueId] = &Sym; -} - -const Symbol *Object::findSymbol(size_t UniqueId) const { +//===- Object.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Object.h" +#include "llvm/ADT/DenseSet.h" +#include <algorithm> + +namespace llvm { +namespace objcopy { +namespace coff { + +using namespace object; + +void Object::addSymbols(ArrayRef<Symbol> NewSymbols) { + for (Symbol S : NewSymbols) { + S.UniqueId = NextSymbolUniqueId++; + Symbols.emplace_back(S); + } + updateSymbols(); +} + +void Object::updateSymbols() { + SymbolMap = DenseMap<size_t, Symbol *>(Symbols.size()); + for (Symbol &Sym : Symbols) + SymbolMap[Sym.UniqueId] = &Sym; +} + +const Symbol *Object::findSymbol(size_t UniqueId) const { return SymbolMap.lookup(UniqueId); -} - +} + Error Object::removeSymbols( function_ref<Expected<bool>(const Symbol &)> ToRemove) { Error Errs = Error::success(); @@ -46,61 +46,61 @@ Error Object::removeSymbols( return *ShouldRemove; }); - updateSymbols(); + updateSymbols(); return Errs; -} - -Error Object::markSymbols() { - for (Symbol &Sym : Symbols) - Sym.Referenced = false; - for (const Section &Sec : Sections) { - for (const Relocation &R : Sec.Relocs) { - auto It = SymbolMap.find(R.Target); - if (It == SymbolMap.end()) - return createStringError(object_error::invalid_symbol_index, - "relocation target %zu not found", R.Target); - It->second->Referenced = true; - } - } - return Error::success(); -} - -void Object::addSections(ArrayRef<Section> NewSections) { - for (Section S : NewSections) { - S.UniqueId = NextSectionUniqueId++; - Sections.emplace_back(S); - } - updateSections(); -} - -void Object::updateSections() { - SectionMap = DenseMap<ssize_t, Section *>(Sections.size()); - size_t Index = 1; - for (Section &S : Sections) { - SectionMap[S.UniqueId] = &S; - S.Index = Index++; - } -} - -const Section *Object::findSection(ssize_t UniqueId) const { +} + +Error Object::markSymbols() { + for (Symbol &Sym : Symbols) + Sym.Referenced = false; + for (const Section &Sec : Sections) { + for (const Relocation &R : Sec.Relocs) { + auto It = SymbolMap.find(R.Target); + if (It == SymbolMap.end()) + return createStringError(object_error::invalid_symbol_index, + "relocation target %zu not found", R.Target); + It->second->Referenced = true; + } + } + return Error::success(); +} + +void Object::addSections(ArrayRef<Section> NewSections) { + for (Section S : NewSections) { + S.UniqueId = NextSectionUniqueId++; + Sections.emplace_back(S); + } + updateSections(); +} + +void Object::updateSections() { + SectionMap = DenseMap<ssize_t, Section *>(Sections.size()); + size_t Index = 1; + for (Section &S : Sections) { + SectionMap[S.UniqueId] = &S; + S.Index = Index++; + } +} + +const Section *Object::findSection(ssize_t UniqueId) const { return SectionMap.lookup(UniqueId); -} - -void Object::removeSections(function_ref<bool(const Section &)> ToRemove) { - DenseSet<ssize_t> AssociatedSections; - auto RemoveAssociated = [&AssociatedSections](const Section &Sec) { +} + +void Object::removeSections(function_ref<bool(const Section &)> ToRemove) { + DenseSet<ssize_t> AssociatedSections; + auto RemoveAssociated = [&AssociatedSections](const Section &Sec) { return AssociatedSections.contains(Sec.UniqueId); - }; - do { - DenseSet<ssize_t> RemovedSections; + }; + do { + DenseSet<ssize_t> RemovedSections; llvm::erase_if(Sections, [ToRemove, &RemovedSections](const Section &Sec) { bool Remove = ToRemove(Sec); if (Remove) RemovedSections.insert(Sec.UniqueId); return Remove; }); - // Remove all symbols referring to the removed sections. - AssociatedSections.clear(); + // Remove all symbols referring to the removed sections. + AssociatedSections.clear(); llvm::erase_if( Symbols, [&RemovedSections, &AssociatedSections](const Symbol &Sym) { // If there are sections that are associative to a removed @@ -111,22 +111,22 @@ void Object::removeSections(function_ref<bool(const Section &)> ToRemove) { AssociatedSections.insert(Sym.TargetSectionId); return RemovedSections.contains(Sym.TargetSectionId); }); - ToRemove = RemoveAssociated; - } while (!AssociatedSections.empty()); - updateSections(); - updateSymbols(); -} - -void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) { - for (Section &Sec : Sections) { - if (ToTruncate(Sec)) { - Sec.clearContents(); - Sec.Relocs.clear(); - Sec.Header.SizeOfRawData = 0; - } - } -} - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm + ToRemove = RemoveAssociated; + } while (!AssociatedSections.empty()); + updateSections(); + updateSymbols(); +} + +void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) { + for (Section &Sec : Sections) { + if (ToTruncate(Sec)) { + Sec.clearContents(); + Sec.Relocs.clear(); + Sec.Header.SizeOfRawData = 0; + } + } +} + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.h b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.h index 0e854b58cb..9602f56e63 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.h +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Object.h @@ -1,211 +1,211 @@ -//===- Object.h -------------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H -#define LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Object/COFF.h" -#include <cstddef> -#include <cstdint> -#include <vector> - -namespace llvm { -namespace objcopy { -namespace coff { - -struct Relocation { - Relocation() = default; +//===- Object.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H +#define LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFF.h" +#include <cstddef> +#include <cstdint> +#include <vector> + +namespace llvm { +namespace objcopy { +namespace coff { + +struct Relocation { + Relocation() = default; Relocation(const object::coff_relocation &R) : Reloc(R) {} - - object::coff_relocation Reloc; - size_t Target = 0; - StringRef TargetName; // Used for diagnostics only -}; - -struct Section { - object::coff_section Header; - std::vector<Relocation> Relocs; - StringRef Name; - ssize_t UniqueId; - size_t Index; - - ArrayRef<uint8_t> getContents() const { - if (!OwnedContents.empty()) - return OwnedContents; - return ContentsRef; - } - - void setContentsRef(ArrayRef<uint8_t> Data) { - OwnedContents.clear(); - ContentsRef = Data; - } - - void setOwnedContents(std::vector<uint8_t> &&Data) { - ContentsRef = ArrayRef<uint8_t>(); - OwnedContents = std::move(Data); - } - - void clearContents() { - ContentsRef = ArrayRef<uint8_t>(); - OwnedContents.clear(); - } - -private: - ArrayRef<uint8_t> ContentsRef; - std::vector<uint8_t> OwnedContents; -}; - -struct AuxSymbol { - AuxSymbol(ArrayRef<uint8_t> In) { - assert(In.size() == sizeof(Opaque)); - std::copy(In.begin(), In.end(), Opaque); - } - - ArrayRef<uint8_t> getRef() const { - return ArrayRef<uint8_t>(Opaque, sizeof(Opaque)); - } - - uint8_t Opaque[sizeof(object::coff_symbol16)]; -}; - -struct Symbol { - object::coff_symbol32 Sym; - StringRef Name; - std::vector<AuxSymbol> AuxData; - StringRef AuxFile; - ssize_t TargetSectionId; - ssize_t AssociativeComdatTargetSectionId = 0; - Optional<size_t> WeakTargetSymbolId; - size_t UniqueId; - size_t RawIndex; - bool Referenced; -}; - -struct Object { - bool IsPE = false; - - object::dos_header DosHeader; - ArrayRef<uint8_t> DosStub; - - object::coff_file_header CoffFileHeader; - - bool Is64 = false; - object::pe32plus_header PeHeader; - uint32_t BaseOfData = 0; // pe32plus_header lacks this field. - - std::vector<object::data_directory> DataDirectories; - - ArrayRef<Symbol> getSymbols() const { return Symbols; } - // This allows mutating individual Symbols, but not mutating the list - // of symbols itself. - iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() { - return make_range(Symbols.begin(), Symbols.end()); - } - - const Symbol *findSymbol(size_t UniqueId) const; - - void addSymbols(ArrayRef<Symbol> NewSymbols); + + object::coff_relocation Reloc; + size_t Target = 0; + StringRef TargetName; // Used for diagnostics only +}; + +struct Section { + object::coff_section Header; + std::vector<Relocation> Relocs; + StringRef Name; + ssize_t UniqueId; + size_t Index; + + ArrayRef<uint8_t> getContents() const { + if (!OwnedContents.empty()) + return OwnedContents; + return ContentsRef; + } + + void setContentsRef(ArrayRef<uint8_t> Data) { + OwnedContents.clear(); + ContentsRef = Data; + } + + void setOwnedContents(std::vector<uint8_t> &&Data) { + ContentsRef = ArrayRef<uint8_t>(); + OwnedContents = std::move(Data); + } + + void clearContents() { + ContentsRef = ArrayRef<uint8_t>(); + OwnedContents.clear(); + } + +private: + ArrayRef<uint8_t> ContentsRef; + std::vector<uint8_t> OwnedContents; +}; + +struct AuxSymbol { + AuxSymbol(ArrayRef<uint8_t> In) { + assert(In.size() == sizeof(Opaque)); + std::copy(In.begin(), In.end(), Opaque); + } + + ArrayRef<uint8_t> getRef() const { + return ArrayRef<uint8_t>(Opaque, sizeof(Opaque)); + } + + uint8_t Opaque[sizeof(object::coff_symbol16)]; +}; + +struct Symbol { + object::coff_symbol32 Sym; + StringRef Name; + std::vector<AuxSymbol> AuxData; + StringRef AuxFile; + ssize_t TargetSectionId; + ssize_t AssociativeComdatTargetSectionId = 0; + Optional<size_t> WeakTargetSymbolId; + size_t UniqueId; + size_t RawIndex; + bool Referenced; +}; + +struct Object { + bool IsPE = false; + + object::dos_header DosHeader; + ArrayRef<uint8_t> DosStub; + + object::coff_file_header CoffFileHeader; + + bool Is64 = false; + object::pe32plus_header PeHeader; + uint32_t BaseOfData = 0; // pe32plus_header lacks this field. + + std::vector<object::data_directory> DataDirectories; + + ArrayRef<Symbol> getSymbols() const { return Symbols; } + // This allows mutating individual Symbols, but not mutating the list + // of symbols itself. + iterator_range<std::vector<Symbol>::iterator> getMutableSymbols() { + return make_range(Symbols.begin(), Symbols.end()); + } + + const Symbol *findSymbol(size_t UniqueId) const; + + void addSymbols(ArrayRef<Symbol> NewSymbols); Error removeSymbols(function_ref<Expected<bool>(const Symbol &)> ToRemove); - - // Set the Referenced field on all Symbols, based on relocations in - // all sections. - Error markSymbols(); - - ArrayRef<Section> getSections() const { return Sections; } - // This allows mutating individual Sections, but not mutating the list - // of sections itself. - iterator_range<std::vector<Section>::iterator> getMutableSections() { - return make_range(Sections.begin(), Sections.end()); - } - - const Section *findSection(ssize_t UniqueId) const; - - void addSections(ArrayRef<Section> NewSections); - void removeSections(function_ref<bool(const Section &)> ToRemove); - void truncateSections(function_ref<bool(const Section &)> ToTruncate); - -private: - std::vector<Symbol> Symbols; - DenseMap<size_t, Symbol *> SymbolMap; - - size_t NextSymbolUniqueId = 0; - - std::vector<Section> Sections; - DenseMap<ssize_t, Section *> SectionMap; - - ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined. - - // Update SymbolMap. - void updateSymbols(); - - // Update SectionMap and Index in each Section. - void updateSections(); -}; - -// Copy between coff_symbol16 and coff_symbol32. -// The source and destination files can use either coff_symbol16 or -// coff_symbol32, while we always store them as coff_symbol32 in the -// intermediate data structure. -template <class Symbol1Ty, class Symbol2Ty> -void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) { - static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName), - "Mismatched name sizes"); - memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName)); - Dest.Value = Src.Value; - Dest.SectionNumber = Src.SectionNumber; - Dest.Type = Src.Type; - Dest.StorageClass = Src.StorageClass; - Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols; -} - -// Copy between pe32_header and pe32plus_header. -// We store the intermediate state in a pe32plus_header. -template <class PeHeader1Ty, class PeHeader2Ty> -void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) { - Dest.Magic = Src.Magic; - Dest.MajorLinkerVersion = Src.MajorLinkerVersion; - Dest.MinorLinkerVersion = Src.MinorLinkerVersion; - Dest.SizeOfCode = Src.SizeOfCode; - Dest.SizeOfInitializedData = Src.SizeOfInitializedData; - Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData; - Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint; - Dest.BaseOfCode = Src.BaseOfCode; - Dest.ImageBase = Src.ImageBase; - Dest.SectionAlignment = Src.SectionAlignment; - Dest.FileAlignment = Src.FileAlignment; - Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion; - Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion; - Dest.MajorImageVersion = Src.MajorImageVersion; - Dest.MinorImageVersion = Src.MinorImageVersion; - Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion; - Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion; - Dest.Win32VersionValue = Src.Win32VersionValue; - Dest.SizeOfImage = Src.SizeOfImage; - Dest.SizeOfHeaders = Src.SizeOfHeaders; - Dest.CheckSum = Src.CheckSum; - Dest.Subsystem = Src.Subsystem; - Dest.DLLCharacteristics = Src.DLLCharacteristics; - Dest.SizeOfStackReserve = Src.SizeOfStackReserve; - Dest.SizeOfStackCommit = Src.SizeOfStackCommit; - Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve; - Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit; - Dest.LoaderFlags = Src.LoaderFlags; - Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize; -} - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm - -#endif // LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H + + // Set the Referenced field on all Symbols, based on relocations in + // all sections. + Error markSymbols(); + + ArrayRef<Section> getSections() const { return Sections; } + // This allows mutating individual Sections, but not mutating the list + // of sections itself. + iterator_range<std::vector<Section>::iterator> getMutableSections() { + return make_range(Sections.begin(), Sections.end()); + } + + const Section *findSection(ssize_t UniqueId) const; + + void addSections(ArrayRef<Section> NewSections); + void removeSections(function_ref<bool(const Section &)> ToRemove); + void truncateSections(function_ref<bool(const Section &)> ToTruncate); + +private: + std::vector<Symbol> Symbols; + DenseMap<size_t, Symbol *> SymbolMap; + + size_t NextSymbolUniqueId = 0; + + std::vector<Section> Sections; + DenseMap<ssize_t, Section *> SectionMap; + + ssize_t NextSectionUniqueId = 1; // Allow a UniqueId 0 to mean undefined. + + // Update SymbolMap. + void updateSymbols(); + + // Update SectionMap and Index in each Section. + void updateSections(); +}; + +// Copy between coff_symbol16 and coff_symbol32. +// The source and destination files can use either coff_symbol16 or +// coff_symbol32, while we always store them as coff_symbol32 in the +// intermediate data structure. +template <class Symbol1Ty, class Symbol2Ty> +void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src) { + static_assert(sizeof(Dest.Name.ShortName) == sizeof(Src.Name.ShortName), + "Mismatched name sizes"); + memcpy(Dest.Name.ShortName, Src.Name.ShortName, sizeof(Dest.Name.ShortName)); + Dest.Value = Src.Value; + Dest.SectionNumber = Src.SectionNumber; + Dest.Type = Src.Type; + Dest.StorageClass = Src.StorageClass; + Dest.NumberOfAuxSymbols = Src.NumberOfAuxSymbols; +} + +// Copy between pe32_header and pe32plus_header. +// We store the intermediate state in a pe32plus_header. +template <class PeHeader1Ty, class PeHeader2Ty> +void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src) { + Dest.Magic = Src.Magic; + Dest.MajorLinkerVersion = Src.MajorLinkerVersion; + Dest.MinorLinkerVersion = Src.MinorLinkerVersion; + Dest.SizeOfCode = Src.SizeOfCode; + Dest.SizeOfInitializedData = Src.SizeOfInitializedData; + Dest.SizeOfUninitializedData = Src.SizeOfUninitializedData; + Dest.AddressOfEntryPoint = Src.AddressOfEntryPoint; + Dest.BaseOfCode = Src.BaseOfCode; + Dest.ImageBase = Src.ImageBase; + Dest.SectionAlignment = Src.SectionAlignment; + Dest.FileAlignment = Src.FileAlignment; + Dest.MajorOperatingSystemVersion = Src.MajorOperatingSystemVersion; + Dest.MinorOperatingSystemVersion = Src.MinorOperatingSystemVersion; + Dest.MajorImageVersion = Src.MajorImageVersion; + Dest.MinorImageVersion = Src.MinorImageVersion; + Dest.MajorSubsystemVersion = Src.MajorSubsystemVersion; + Dest.MinorSubsystemVersion = Src.MinorSubsystemVersion; + Dest.Win32VersionValue = Src.Win32VersionValue; + Dest.SizeOfImage = Src.SizeOfImage; + Dest.SizeOfHeaders = Src.SizeOfHeaders; + Dest.CheckSum = Src.CheckSum; + Dest.Subsystem = Src.Subsystem; + Dest.DLLCharacteristics = Src.DLLCharacteristics; + Dest.SizeOfStackReserve = Src.SizeOfStackReserve; + Dest.SizeOfStackCommit = Src.SizeOfStackCommit; + Dest.SizeOfHeapReserve = Src.SizeOfHeapReserve; + Dest.SizeOfHeapCommit = Src.SizeOfHeapCommit; + Dest.LoaderFlags = Src.LoaderFlags; + Dest.NumberOfRvaAndSize = Src.NumberOfRvaAndSize; +} + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm + +#endif // LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.cpp index d1beacb3bd..aafdc0f728 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.cpp +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.cpp @@ -1,226 +1,226 @@ -//===- Reader.cpp ---------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Reader.h" -#include "Object.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Object/COFF.h" -#include "llvm/Support/ErrorHandling.h" -#include <cstddef> -#include <cstdint> - -namespace llvm { -namespace objcopy { -namespace coff { - -using namespace object; -using namespace COFF; - -Error COFFReader::readExecutableHeaders(Object &Obj) const { - const dos_header *DH = COFFObj.getDOSHeader(); - Obj.Is64 = COFFObj.is64(); - if (!DH) - return Error::success(); - - Obj.IsPE = true; - Obj.DosHeader = *DH; - if (DH->AddressOfNewExeHeader > sizeof(*DH)) - Obj.DosStub = ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&DH[1]), - DH->AddressOfNewExeHeader - sizeof(*DH)); - - if (COFFObj.is64()) { - Obj.PeHeader = *COFFObj.getPE32PlusHeader(); - } else { - const pe32_header *PE32 = COFFObj.getPE32Header(); - copyPeHeader(Obj.PeHeader, *PE32); - // The pe32plus_header (stored in Object) lacks the BaseOfData field. - Obj.BaseOfData = PE32->BaseOfData; - } - - for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) { - const data_directory *Dir = COFFObj.getDataDirectory(I); - if (!Dir) - return errorCodeToError(object_error::parse_failed); - Obj.DataDirectories.emplace_back(*Dir); - } - return Error::success(); -} - -Error COFFReader::readSections(Object &Obj) const { - std::vector<Section> Sections; - // Section indexing starts from 1. - for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) { - Expected<const coff_section *> SecOrErr = COFFObj.getSection(I); - if (!SecOrErr) - return SecOrErr.takeError(); - const coff_section *Sec = *SecOrErr; - Sections.push_back(Section()); - Section &S = Sections.back(); - S.Header = *Sec; - S.Header.Characteristics &= ~COFF::IMAGE_SCN_LNK_NRELOC_OVFL; - ArrayRef<uint8_t> Contents; - if (Error E = COFFObj.getSectionContents(Sec, Contents)) - return E; - S.setContentsRef(Contents); - ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec); - for (const coff_relocation &R : Relocs) - S.Relocs.push_back(R); - if (Expected<StringRef> NameOrErr = COFFObj.getSectionName(Sec)) - S.Name = *NameOrErr; - else - return NameOrErr.takeError(); - } - Obj.addSections(Sections); - return Error::success(); -} - -Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const { - std::vector<Symbol> Symbols; - Symbols.reserve(COFFObj.getRawNumberOfSymbols()); - ArrayRef<Section> Sections = Obj.getSections(); - for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) { - Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I); - if (!SymOrErr) - return SymOrErr.takeError(); - COFFSymbolRef SymRef = *SymOrErr; - - Symbols.push_back(Symbol()); - Symbol &Sym = Symbols.back(); - // Copy symbols from the original form into an intermediate coff_symbol32. - if (IsBigObj) - copySymbol(Sym.Sym, - *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr())); - else - copySymbol(Sym.Sym, - *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr())); - auto NameOrErr = COFFObj.getSymbolName(SymRef); - if (!NameOrErr) - return NameOrErr.takeError(); - Sym.Name = *NameOrErr; - - ArrayRef<uint8_t> AuxData = COFFObj.getSymbolAuxData(SymRef); - size_t SymSize = IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16); - assert(AuxData.size() == SymSize * SymRef.getNumberOfAuxSymbols()); - // The auxillary symbols are structs of sizeof(coff_symbol16) each. - // In the big object format (where symbols are coff_symbol32), each - // auxillary symbol is padded with 2 bytes at the end. Copy each - // auxillary symbol to the Sym.AuxData vector. For file symbols, - // the whole range of aux symbols are interpreted as one null padded - // string instead. - if (SymRef.isFileRecord()) - Sym.AuxFile = StringRef(reinterpret_cast<const char *>(AuxData.data()), - AuxData.size()) - .rtrim('\0'); - else - for (size_t I = 0; I < SymRef.getNumberOfAuxSymbols(); I++) - Sym.AuxData.push_back(AuxData.slice(I * SymSize, sizeof(AuxSymbol))); - - // Find the unique id of the section - if (SymRef.getSectionNumber() <= - 0) // Special symbol (undefined/absolute/debug) - Sym.TargetSectionId = SymRef.getSectionNumber(); - else if (static_cast<uint32_t>(SymRef.getSectionNumber() - 1) < - Sections.size()) - Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId; - else - return createStringError(object_error::parse_failed, - "section number out of range"); - // For section definitions, check if it is comdat associative, and if - // it is, find the target section unique id. - const coff_aux_section_definition *SD = SymRef.getSectionDefinition(); - const coff_aux_weak_external *WE = SymRef.getWeakExternal(); - if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) { - int32_t Index = SD->getNumber(IsBigObj); - if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size()) - return createStringError(object_error::parse_failed, - "unexpected associative section index"); - Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId; - } else if (WE) { - // This is a raw symbol index for now, but store it in the Symbol - // until we've added them to the Object, which assigns the final - // unique ids. - Sym.WeakTargetSymbolId = WE->TagIndex; - } - I += 1 + SymRef.getNumberOfAuxSymbols(); - } - Obj.addSymbols(Symbols); - return Error::success(); -} - -Error COFFReader::setSymbolTargets(Object &Obj) const { - std::vector<const Symbol *> RawSymbolTable; - for (const Symbol &Sym : Obj.getSymbols()) { - RawSymbolTable.push_back(&Sym); - for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++) - RawSymbolTable.push_back(nullptr); - } - for (Symbol &Sym : Obj.getMutableSymbols()) { - // Convert WeakTargetSymbolId from the original raw symbol index to - // a proper unique id. - if (Sym.WeakTargetSymbolId) { - if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size()) - return createStringError(object_error::parse_failed, - "weak external reference out of range"); - const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId]; - if (Target == nullptr) - return createStringError(object_error::parse_failed, - "invalid SymbolTableIndex"); - Sym.WeakTargetSymbolId = Target->UniqueId; - } - } - for (Section &Sec : Obj.getMutableSections()) { - for (Relocation &R : Sec.Relocs) { - if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size()) - return createStringError(object_error::parse_failed, - "SymbolTableIndex out of range"); - const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex]; - if (Sym == nullptr) - return createStringError(object_error::parse_failed, - "invalid SymbolTableIndex"); - R.Target = Sym->UniqueId; - R.TargetName = Sym->Name; - } - } - return Error::success(); -} - -Expected<std::unique_ptr<Object>> COFFReader::create() const { - auto Obj = std::make_unique<Object>(); - - bool IsBigObj = false; - if (const coff_file_header *CFH = COFFObj.getCOFFHeader()) { - Obj->CoffFileHeader = *CFH; - } else { - const coff_bigobj_file_header *CBFH = COFFObj.getCOFFBigObjHeader(); - if (!CBFH) - return createStringError(object_error::parse_failed, - "no COFF file header returned"); - // Only copying the few fields from the bigobj header that we need - // and won't recreate in the end. - Obj->CoffFileHeader.Machine = CBFH->Machine; - Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp; - IsBigObj = true; - } - - if (Error E = readExecutableHeaders(*Obj)) - return std::move(E); - if (Error E = readSections(*Obj)) - return std::move(E); - if (Error E = readSymbols(*Obj, IsBigObj)) - return std::move(E); - if (Error E = setSymbolTargets(*Obj)) - return std::move(E); - - return std::move(Obj); -} - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm +//===- Reader.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Reader.h" +#include "Object.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstddef> +#include <cstdint> + +namespace llvm { +namespace objcopy { +namespace coff { + +using namespace object; +using namespace COFF; + +Error COFFReader::readExecutableHeaders(Object &Obj) const { + const dos_header *DH = COFFObj.getDOSHeader(); + Obj.Is64 = COFFObj.is64(); + if (!DH) + return Error::success(); + + Obj.IsPE = true; + Obj.DosHeader = *DH; + if (DH->AddressOfNewExeHeader > sizeof(*DH)) + Obj.DosStub = ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&DH[1]), + DH->AddressOfNewExeHeader - sizeof(*DH)); + + if (COFFObj.is64()) { + Obj.PeHeader = *COFFObj.getPE32PlusHeader(); + } else { + const pe32_header *PE32 = COFFObj.getPE32Header(); + copyPeHeader(Obj.PeHeader, *PE32); + // The pe32plus_header (stored in Object) lacks the BaseOfData field. + Obj.BaseOfData = PE32->BaseOfData; + } + + for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) { + const data_directory *Dir = COFFObj.getDataDirectory(I); + if (!Dir) + return errorCodeToError(object_error::parse_failed); + Obj.DataDirectories.emplace_back(*Dir); + } + return Error::success(); +} + +Error COFFReader::readSections(Object &Obj) const { + std::vector<Section> Sections; + // Section indexing starts from 1. + for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) { + Expected<const coff_section *> SecOrErr = COFFObj.getSection(I); + if (!SecOrErr) + return SecOrErr.takeError(); + const coff_section *Sec = *SecOrErr; + Sections.push_back(Section()); + Section &S = Sections.back(); + S.Header = *Sec; + S.Header.Characteristics &= ~COFF::IMAGE_SCN_LNK_NRELOC_OVFL; + ArrayRef<uint8_t> Contents; + if (Error E = COFFObj.getSectionContents(Sec, Contents)) + return E; + S.setContentsRef(Contents); + ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec); + for (const coff_relocation &R : Relocs) + S.Relocs.push_back(R); + if (Expected<StringRef> NameOrErr = COFFObj.getSectionName(Sec)) + S.Name = *NameOrErr; + else + return NameOrErr.takeError(); + } + Obj.addSections(Sections); + return Error::success(); +} + +Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const { + std::vector<Symbol> Symbols; + Symbols.reserve(COFFObj.getRawNumberOfSymbols()); + ArrayRef<Section> Sections = Obj.getSections(); + for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) { + Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I); + if (!SymOrErr) + return SymOrErr.takeError(); + COFFSymbolRef SymRef = *SymOrErr; + + Symbols.push_back(Symbol()); + Symbol &Sym = Symbols.back(); + // Copy symbols from the original form into an intermediate coff_symbol32. + if (IsBigObj) + copySymbol(Sym.Sym, + *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr())); + else + copySymbol(Sym.Sym, + *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr())); + auto NameOrErr = COFFObj.getSymbolName(SymRef); + if (!NameOrErr) + return NameOrErr.takeError(); + Sym.Name = *NameOrErr; + + ArrayRef<uint8_t> AuxData = COFFObj.getSymbolAuxData(SymRef); + size_t SymSize = IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16); + assert(AuxData.size() == SymSize * SymRef.getNumberOfAuxSymbols()); + // The auxillary symbols are structs of sizeof(coff_symbol16) each. + // In the big object format (where symbols are coff_symbol32), each + // auxillary symbol is padded with 2 bytes at the end. Copy each + // auxillary symbol to the Sym.AuxData vector. For file symbols, + // the whole range of aux symbols are interpreted as one null padded + // string instead. + if (SymRef.isFileRecord()) + Sym.AuxFile = StringRef(reinterpret_cast<const char *>(AuxData.data()), + AuxData.size()) + .rtrim('\0'); + else + for (size_t I = 0; I < SymRef.getNumberOfAuxSymbols(); I++) + Sym.AuxData.push_back(AuxData.slice(I * SymSize, sizeof(AuxSymbol))); + + // Find the unique id of the section + if (SymRef.getSectionNumber() <= + 0) // Special symbol (undefined/absolute/debug) + Sym.TargetSectionId = SymRef.getSectionNumber(); + else if (static_cast<uint32_t>(SymRef.getSectionNumber() - 1) < + Sections.size()) + Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId; + else + return createStringError(object_error::parse_failed, + "section number out of range"); + // For section definitions, check if it is comdat associative, and if + // it is, find the target section unique id. + const coff_aux_section_definition *SD = SymRef.getSectionDefinition(); + const coff_aux_weak_external *WE = SymRef.getWeakExternal(); + if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + int32_t Index = SD->getNumber(IsBigObj); + if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size()) + return createStringError(object_error::parse_failed, + "unexpected associative section index"); + Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId; + } else if (WE) { + // This is a raw symbol index for now, but store it in the Symbol + // until we've added them to the Object, which assigns the final + // unique ids. + Sym.WeakTargetSymbolId = WE->TagIndex; + } + I += 1 + SymRef.getNumberOfAuxSymbols(); + } + Obj.addSymbols(Symbols); + return Error::success(); +} + +Error COFFReader::setSymbolTargets(Object &Obj) const { + std::vector<const Symbol *> RawSymbolTable; + for (const Symbol &Sym : Obj.getSymbols()) { + RawSymbolTable.push_back(&Sym); + for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++) + RawSymbolTable.push_back(nullptr); + } + for (Symbol &Sym : Obj.getMutableSymbols()) { + // Convert WeakTargetSymbolId from the original raw symbol index to + // a proper unique id. + if (Sym.WeakTargetSymbolId) { + if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size()) + return createStringError(object_error::parse_failed, + "weak external reference out of range"); + const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId]; + if (Target == nullptr) + return createStringError(object_error::parse_failed, + "invalid SymbolTableIndex"); + Sym.WeakTargetSymbolId = Target->UniqueId; + } + } + for (Section &Sec : Obj.getMutableSections()) { + for (Relocation &R : Sec.Relocs) { + if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size()) + return createStringError(object_error::parse_failed, + "SymbolTableIndex out of range"); + const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex]; + if (Sym == nullptr) + return createStringError(object_error::parse_failed, + "invalid SymbolTableIndex"); + R.Target = Sym->UniqueId; + R.TargetName = Sym->Name; + } + } + return Error::success(); +} + +Expected<std::unique_ptr<Object>> COFFReader::create() const { + auto Obj = std::make_unique<Object>(); + + bool IsBigObj = false; + if (const coff_file_header *CFH = COFFObj.getCOFFHeader()) { + Obj->CoffFileHeader = *CFH; + } else { + const coff_bigobj_file_header *CBFH = COFFObj.getCOFFBigObjHeader(); + if (!CBFH) + return createStringError(object_error::parse_failed, + "no COFF file header returned"); + // Only copying the few fields from the bigobj header that we need + // and won't recreate in the end. + Obj->CoffFileHeader.Machine = CBFH->Machine; + Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp; + IsBigObj = true; + } + + if (Error E = readExecutableHeaders(*Obj)) + return std::move(E); + if (Error E = readSections(*Obj)) + return std::move(E); + if (Error E = readSymbols(*Obj, IsBigObj)) + return std::move(E); + if (Error E = setSymbolTargets(*Obj)) + return std::move(E); + + return std::move(Obj); +} + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.h b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.h index ec15369db0..573b768c06 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.h +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Reader.h @@ -1,42 +1,42 @@ -//===- Reader.h -------------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_OBJCOPY_COFF_READER_H -#define LLVM_TOOLS_OBJCOPY_COFF_READER_H - -#include "Buffer.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Object/COFF.h" -#include "llvm/Support/Error.h" - -namespace llvm { -namespace objcopy { -namespace coff { - -struct Object; - -using object::COFFObjectFile; - -class COFFReader { - const COFFObjectFile &COFFObj; - - Error readExecutableHeaders(Object &Obj) const; - Error readSections(Object &Obj) const; - Error readSymbols(Object &Obj, bool IsBigObj) const; - Error setSymbolTargets(Object &Obj) const; - -public: - explicit COFFReader(const COFFObjectFile &O) : COFFObj(O) {} - Expected<std::unique_ptr<Object>> create() const; -}; - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm - -#endif // LLVM_TOOLS_OBJCOPY_COFF_READER_H +//===- Reader.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_OBJCOPY_COFF_READER_H +#define LLVM_TOOLS_OBJCOPY_COFF_READER_H + +#include "Buffer.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace objcopy { +namespace coff { + +struct Object; + +using object::COFFObjectFile; + +class COFFReader { + const COFFObjectFile &COFFObj; + + Error readExecutableHeaders(Object &Obj) const; + Error readSections(Object &Obj) const; + Error readSymbols(Object &Obj, bool IsBigObj) const; + Error setSymbolTargets(Object &Obj) const; + +public: + explicit COFFReader(const COFFObjectFile &O) : COFFObj(O) {} + Expected<std::unique_ptr<Object>> create() const; +}; + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm + +#endif // LLVM_TOOLS_OBJCOPY_COFF_READER_H diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.cpp index 6b560890a4..3fff721dcb 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.cpp +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.cpp @@ -1,449 +1,449 @@ -//===- Writer.cpp ---------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Writer.h" -#include "Object.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Object/COFF.h" -#include "llvm/Support/ErrorHandling.h" -#include <cstddef> -#include <cstdint> - -namespace llvm { -namespace objcopy { -namespace coff { - -using namespace object; -using namespace COFF; - -Error COFFWriter::finalizeRelocTargets() { - for (Section &Sec : Obj.getMutableSections()) { - for (Relocation &R : Sec.Relocs) { - const Symbol *Sym = Obj.findSymbol(R.Target); - if (Sym == nullptr) - return createStringError(object_error::invalid_symbol_index, - "relocation target '%s' (%zu) not found", - R.TargetName.str().c_str(), R.Target); - R.Reloc.SymbolTableIndex = Sym->RawIndex; - } - } - return Error::success(); -} - -Error COFFWriter::finalizeSymbolContents() { - for (Symbol &Sym : Obj.getMutableSymbols()) { - if (Sym.TargetSectionId <= 0) { - // Undefined, or a special kind of symbol. These negative values - // are stored in the SectionNumber field which is unsigned. - Sym.Sym.SectionNumber = static_cast<uint32_t>(Sym.TargetSectionId); - } else { - const Section *Sec = Obj.findSection(Sym.TargetSectionId); - if (Sec == nullptr) - return createStringError(object_error::invalid_symbol_index, - "symbol '%s' points to a removed section", - Sym.Name.str().c_str()); - Sym.Sym.SectionNumber = Sec->Index; - - if (Sym.Sym.NumberOfAuxSymbols == 1 && - Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) { - coff_aux_section_definition *SD = - reinterpret_cast<coff_aux_section_definition *>( - Sym.AuxData[0].Opaque); - uint32_t SDSectionNumber; - if (Sym.AssociativeComdatTargetSectionId == 0) { - // Not a comdat associative section; just set the Number field to - // the number of the section itself. - SDSectionNumber = Sec->Index; - } else { - Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId); - if (Sec == nullptr) - return createStringError( - object_error::invalid_symbol_index, - "symbol '%s' is associative to a removed section", - Sym.Name.str().c_str()); - SDSectionNumber = Sec->Index; - } - // Update the section definition with the new section number. - SD->NumberLowPart = static_cast<uint16_t>(SDSectionNumber); - SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16); - } - } - // Check that we actually have got AuxData to match the weak symbol target - // we want to set. Only >= 1 would be required, but only == 1 makes sense. - if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) { - coff_aux_weak_external *WE = - reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData[0].Opaque); - const Symbol *Target = Obj.findSymbol(*Sym.WeakTargetSymbolId); - if (Target == nullptr) - return createStringError(object_error::invalid_symbol_index, - "symbol '%s' is missing its weak target", - Sym.Name.str().c_str()); - WE->TagIndex = Target->RawIndex; - } - } - return Error::success(); -} - -void COFFWriter::layoutSections() { - for (auto &S : Obj.getMutableSections()) { - if (S.Header.SizeOfRawData > 0) - S.Header.PointerToRawData = FileSize; - FileSize += S.Header.SizeOfRawData; // For executables, this is already - // aligned to FileAlignment. - if (S.Relocs.size() >= 0xffff) { - S.Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; - S.Header.NumberOfRelocations = 0xffff; - S.Header.PointerToRelocations = FileSize; - FileSize += sizeof(coff_relocation); - } else { - S.Header.NumberOfRelocations = S.Relocs.size(); - S.Header.PointerToRelocations = S.Relocs.size() ? FileSize : 0; - } - - FileSize += S.Relocs.size() * sizeof(coff_relocation); - FileSize = alignTo(FileSize, FileAlignment); - - if (S.Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) - SizeOfInitializedData += S.Header.SizeOfRawData; - } -} - -size_t COFFWriter::finalizeStringTable() { - for (const auto &S : Obj.getSections()) - if (S.Name.size() > COFF::NameSize) - StrTabBuilder.add(S.Name); - - for (const auto &S : Obj.getSymbols()) - if (S.Name.size() > COFF::NameSize) - StrTabBuilder.add(S.Name); - - StrTabBuilder.finalize(); - - for (auto &S : Obj.getMutableSections()) { - memset(S.Header.Name, 0, sizeof(S.Header.Name)); - if (S.Name.size() > COFF::NameSize) { - snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d", - (int)StrTabBuilder.getOffset(S.Name)); - } else { - memcpy(S.Header.Name, S.Name.data(), S.Name.size()); - } - } - for (auto &S : Obj.getMutableSymbols()) { - if (S.Name.size() > COFF::NameSize) { - S.Sym.Name.Offset.Zeroes = 0; - S.Sym.Name.Offset.Offset = StrTabBuilder.getOffset(S.Name); - } else { - strncpy(S.Sym.Name.ShortName, S.Name.data(), COFF::NameSize); - } - } - return StrTabBuilder.getSize(); -} - -template <class SymbolTy> -std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() { - size_t RawSymIndex = 0; - for (auto &S : Obj.getMutableSymbols()) { - // Symbols normally have NumberOfAuxSymbols set correctly all the time. - // For file symbols, we need to know the output file's symbol size to be - // able to calculate the number of slots it occupies. - if (!S.AuxFile.empty()) - S.Sym.NumberOfAuxSymbols = - alignTo(S.AuxFile.size(), sizeof(SymbolTy)) / sizeof(SymbolTy); - S.RawIndex = RawSymIndex; - RawSymIndex += 1 + S.Sym.NumberOfAuxSymbols; - } - return std::make_pair(RawSymIndex * sizeof(SymbolTy), sizeof(SymbolTy)); -} - -Error COFFWriter::finalize(bool IsBigObj) { - size_t SymTabSize, SymbolSize; - std::tie(SymTabSize, SymbolSize) = IsBigObj - ? finalizeSymbolTable<coff_symbol32>() - : finalizeSymbolTable<coff_symbol16>(); - - if (Error E = finalizeRelocTargets()) - return E; - if (Error E = finalizeSymbolContents()) - return E; - - size_t SizeOfHeaders = 0; - FileAlignment = 1; - size_t PeHeaderSize = 0; - if (Obj.IsPE) { - Obj.DosHeader.AddressOfNewExeHeader = - sizeof(Obj.DosHeader) + Obj.DosStub.size(); - SizeOfHeaders += Obj.DosHeader.AddressOfNewExeHeader + sizeof(PEMagic); - - FileAlignment = Obj.PeHeader.FileAlignment; - Obj.PeHeader.NumberOfRvaAndSize = Obj.DataDirectories.size(); - - PeHeaderSize = Obj.Is64 ? sizeof(pe32plus_header) : sizeof(pe32_header); - SizeOfHeaders += - PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size(); - } - Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size(); - SizeOfHeaders += - IsBigObj ? sizeof(coff_bigobj_file_header) : sizeof(coff_file_header); - SizeOfHeaders += sizeof(coff_section) * Obj.getSections().size(); - SizeOfHeaders = alignTo(SizeOfHeaders, FileAlignment); - - Obj.CoffFileHeader.SizeOfOptionalHeader = - PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size(); - - FileSize = SizeOfHeaders; - SizeOfInitializedData = 0; - - layoutSections(); - - if (Obj.IsPE) { - Obj.PeHeader.SizeOfHeaders = SizeOfHeaders; - Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData; - - if (!Obj.getSections().empty()) { - const Section &S = Obj.getSections().back(); - Obj.PeHeader.SizeOfImage = - alignTo(S.Header.VirtualAddress + S.Header.VirtualSize, - Obj.PeHeader.SectionAlignment); - } - - // If the PE header had a checksum, clear it, since it isn't valid - // any longer. (We don't calculate a new one.) - Obj.PeHeader.CheckSum = 0; - } - - size_t StrTabSize = finalizeStringTable(); - - size_t PointerToSymbolTable = FileSize; - // StrTabSize <= 4 is the size of an empty string table, only consisting - // of the length field. - if (SymTabSize == 0 && StrTabSize <= 4 && Obj.IsPE) { - // For executables, don't point to the symbol table and skip writing - // the length field, if both the symbol and string tables are empty. - PointerToSymbolTable = 0; - StrTabSize = 0; - } - - size_t NumRawSymbols = SymTabSize / SymbolSize; - Obj.CoffFileHeader.PointerToSymbolTable = PointerToSymbolTable; - Obj.CoffFileHeader.NumberOfSymbols = NumRawSymbols; - FileSize += SymTabSize + StrTabSize; - FileSize = alignTo(FileSize, FileAlignment); - - return Error::success(); -} - -void COFFWriter::writeHeaders(bool IsBigObj) { - uint8_t *Ptr = Buf.getBufferStart(); - if (Obj.IsPE) { - memcpy(Ptr, &Obj.DosHeader, sizeof(Obj.DosHeader)); - Ptr += sizeof(Obj.DosHeader); - memcpy(Ptr, Obj.DosStub.data(), Obj.DosStub.size()); - Ptr += Obj.DosStub.size(); - memcpy(Ptr, PEMagic, sizeof(PEMagic)); - Ptr += sizeof(PEMagic); - } - if (!IsBigObj) { - memcpy(Ptr, &Obj.CoffFileHeader, sizeof(Obj.CoffFileHeader)); - Ptr += sizeof(Obj.CoffFileHeader); - } else { - // Generate a coff_bigobj_file_header, filling it in with the values - // from Obj.CoffFileHeader. All extra fields that don't exist in - // coff_file_header can be set to hardcoded values. - coff_bigobj_file_header BigObjHeader; - BigObjHeader.Sig1 = IMAGE_FILE_MACHINE_UNKNOWN; - BigObjHeader.Sig2 = 0xffff; - BigObjHeader.Version = BigObjHeader::MinBigObjectVersion; - BigObjHeader.Machine = Obj.CoffFileHeader.Machine; - BigObjHeader.TimeDateStamp = Obj.CoffFileHeader.TimeDateStamp; - memcpy(BigObjHeader.UUID, BigObjMagic, sizeof(BigObjMagic)); - BigObjHeader.unused1 = 0; - BigObjHeader.unused2 = 0; - BigObjHeader.unused3 = 0; - BigObjHeader.unused4 = 0; - // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus - // get the original one instead. - BigObjHeader.NumberOfSections = Obj.getSections().size(); - BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable; - BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols; - - memcpy(Ptr, &BigObjHeader, sizeof(BigObjHeader)); - Ptr += sizeof(BigObjHeader); - } - if (Obj.IsPE) { - if (Obj.Is64) { - memcpy(Ptr, &Obj.PeHeader, sizeof(Obj.PeHeader)); - Ptr += sizeof(Obj.PeHeader); - } else { - pe32_header PeHeader; - copyPeHeader(PeHeader, Obj.PeHeader); - // The pe32plus_header (stored in Object) lacks the BaseOfData field. - PeHeader.BaseOfData = Obj.BaseOfData; - - memcpy(Ptr, &PeHeader, sizeof(PeHeader)); - Ptr += sizeof(PeHeader); - } - for (const auto &DD : Obj.DataDirectories) { - memcpy(Ptr, &DD, sizeof(DD)); - Ptr += sizeof(DD); - } - } - for (const auto &S : Obj.getSections()) { - memcpy(Ptr, &S.Header, sizeof(S.Header)); - Ptr += sizeof(S.Header); - } -} - -void COFFWriter::writeSections() { - for (const auto &S : Obj.getSections()) { - uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData; - ArrayRef<uint8_t> Contents = S.getContents(); - std::copy(Contents.begin(), Contents.end(), Ptr); - - // For executable sections, pad the remainder of the raw data size with - // 0xcc, which is int3 on x86. - if ((S.Header.Characteristics & IMAGE_SCN_CNT_CODE) && - S.Header.SizeOfRawData > Contents.size()) - memset(Ptr + Contents.size(), 0xcc, - S.Header.SizeOfRawData - Contents.size()); - - Ptr += S.Header.SizeOfRawData; - - if (S.Relocs.size() >= 0xffff) { - object::coff_relocation R; - R.VirtualAddress = S.Relocs.size() + 1; - R.SymbolTableIndex = 0; - R.Type = 0; - memcpy(Ptr, &R, sizeof(R)); - Ptr += sizeof(R); - } - for (const auto &R : S.Relocs) { - memcpy(Ptr, &R.Reloc, sizeof(R.Reloc)); - Ptr += sizeof(R.Reloc); - } - } -} - -template <class SymbolTy> void COFFWriter::writeSymbolStringTables() { - uint8_t *Ptr = Buf.getBufferStart() + Obj.CoffFileHeader.PointerToSymbolTable; - for (const auto &S : Obj.getSymbols()) { - // Convert symbols back to the right size, from coff_symbol32. - copySymbol<SymbolTy, coff_symbol32>(*reinterpret_cast<SymbolTy *>(Ptr), - S.Sym); - Ptr += sizeof(SymbolTy); - if (!S.AuxFile.empty()) { - // For file symbols, just write the string into the aux symbol slots, - // assuming that the unwritten parts are initialized to zero in the memory - // mapped file. - std::copy(S.AuxFile.begin(), S.AuxFile.end(), Ptr); - Ptr += S.Sym.NumberOfAuxSymbols * sizeof(SymbolTy); - } else { - // For other auxillary symbols, write their opaque payload into one symbol - // table slot each. For big object files, the symbols are larger than the - // opaque auxillary symbol struct and we leave padding at the end of each - // entry. - for (const AuxSymbol &AuxSym : S.AuxData) { - ArrayRef<uint8_t> Ref = AuxSym.getRef(); - std::copy(Ref.begin(), Ref.end(), Ptr); - Ptr += sizeof(SymbolTy); - } - } - } - if (StrTabBuilder.getSize() > 4 || !Obj.IsPE) { - // Always write a string table in object files, even an empty one. - StrTabBuilder.write(Ptr); - Ptr += StrTabBuilder.getSize(); - } -} - -Error COFFWriter::write(bool IsBigObj) { - if (Error E = finalize(IsBigObj)) - return E; - - if (Error E = Buf.allocate(FileSize)) - return E; - - writeHeaders(IsBigObj); - writeSections(); - if (IsBigObj) - writeSymbolStringTables<coff_symbol32>(); - else - writeSymbolStringTables<coff_symbol16>(); - - if (Obj.IsPE) - if (Error E = patchDebugDirectory()) - return E; - - return Buf.commit(); -} - -Expected<uint32_t> COFFWriter::virtualAddressToFileAddress(uint32_t RVA) { - for (const auto &S : Obj.getSections()) { - if (RVA >= S.Header.VirtualAddress && - RVA < S.Header.VirtualAddress + S.Header.SizeOfRawData) - return S.Header.PointerToRawData + RVA - S.Header.VirtualAddress; - } - return createStringError(object_error::parse_failed, - "debug directory payload not found"); -} - -// Locate which sections contain the debug directories, iterate over all -// the debug_directory structs in there, and set the PointerToRawData field -// in all of them, according to their new physical location in the file. -Error COFFWriter::patchDebugDirectory() { - if (Obj.DataDirectories.size() < DEBUG_DIRECTORY) - return Error::success(); - const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY]; - if (Dir->Size <= 0) - return Error::success(); - for (const auto &S : Obj.getSections()) { - if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress && - Dir->RelativeVirtualAddress < - S.Header.VirtualAddress + S.Header.SizeOfRawData) { - if (Dir->RelativeVirtualAddress + Dir->Size > - S.Header.VirtualAddress + S.Header.SizeOfRawData) - return createStringError(object_error::parse_failed, - "debug directory extends past end of section"); - - size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress; - uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData + Offset; - uint8_t *End = Ptr + Dir->Size; - while (Ptr < End) { - debug_directory *Debug = reinterpret_cast<debug_directory *>(Ptr); - if (!Debug->AddressOfRawData) - return createStringError(object_error::parse_failed, - "debug directory payload outside of " - "mapped sections not supported"); - if (Expected<uint32_t> FilePosOrErr = - virtualAddressToFileAddress(Debug->AddressOfRawData)) - Debug->PointerToRawData = *FilePosOrErr; - else - return FilePosOrErr.takeError(); - Ptr += sizeof(debug_directory); - Offset += sizeof(debug_directory); - } - // Debug directory found and patched, all done. - return Error::success(); - } - } - return createStringError(object_error::parse_failed, - "debug directory not found"); -} - -Error COFFWriter::write() { - bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16; - if (IsBigObj && Obj.IsPE) - return createStringError(object_error::parse_failed, - "too many sections for executable"); - return write(IsBigObj); -} - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm +//===- Writer.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Writer.h" +#include "Object.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstddef> +#include <cstdint> + +namespace llvm { +namespace objcopy { +namespace coff { + +using namespace object; +using namespace COFF; + +Error COFFWriter::finalizeRelocTargets() { + for (Section &Sec : Obj.getMutableSections()) { + for (Relocation &R : Sec.Relocs) { + const Symbol *Sym = Obj.findSymbol(R.Target); + if (Sym == nullptr) + return createStringError(object_error::invalid_symbol_index, + "relocation target '%s' (%zu) not found", + R.TargetName.str().c_str(), R.Target); + R.Reloc.SymbolTableIndex = Sym->RawIndex; + } + } + return Error::success(); +} + +Error COFFWriter::finalizeSymbolContents() { + for (Symbol &Sym : Obj.getMutableSymbols()) { + if (Sym.TargetSectionId <= 0) { + // Undefined, or a special kind of symbol. These negative values + // are stored in the SectionNumber field which is unsigned. + Sym.Sym.SectionNumber = static_cast<uint32_t>(Sym.TargetSectionId); + } else { + const Section *Sec = Obj.findSection(Sym.TargetSectionId); + if (Sec == nullptr) + return createStringError(object_error::invalid_symbol_index, + "symbol '%s' points to a removed section", + Sym.Name.str().c_str()); + Sym.Sym.SectionNumber = Sec->Index; + + if (Sym.Sym.NumberOfAuxSymbols == 1 && + Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC) { + coff_aux_section_definition *SD = + reinterpret_cast<coff_aux_section_definition *>( + Sym.AuxData[0].Opaque); + uint32_t SDSectionNumber; + if (Sym.AssociativeComdatTargetSectionId == 0) { + // Not a comdat associative section; just set the Number field to + // the number of the section itself. + SDSectionNumber = Sec->Index; + } else { + Sec = Obj.findSection(Sym.AssociativeComdatTargetSectionId); + if (Sec == nullptr) + return createStringError( + object_error::invalid_symbol_index, + "symbol '%s' is associative to a removed section", + Sym.Name.str().c_str()); + SDSectionNumber = Sec->Index; + } + // Update the section definition with the new section number. + SD->NumberLowPart = static_cast<uint16_t>(SDSectionNumber); + SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16); + } + } + // Check that we actually have got AuxData to match the weak symbol target + // we want to set. Only >= 1 would be required, but only == 1 makes sense. + if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) { + coff_aux_weak_external *WE = + reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData[0].Opaque); + const Symbol *Target = Obj.findSymbol(*Sym.WeakTargetSymbolId); + if (Target == nullptr) + return createStringError(object_error::invalid_symbol_index, + "symbol '%s' is missing its weak target", + Sym.Name.str().c_str()); + WE->TagIndex = Target->RawIndex; + } + } + return Error::success(); +} + +void COFFWriter::layoutSections() { + for (auto &S : Obj.getMutableSections()) { + if (S.Header.SizeOfRawData > 0) + S.Header.PointerToRawData = FileSize; + FileSize += S.Header.SizeOfRawData; // For executables, this is already + // aligned to FileAlignment. + if (S.Relocs.size() >= 0xffff) { + S.Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; + S.Header.NumberOfRelocations = 0xffff; + S.Header.PointerToRelocations = FileSize; + FileSize += sizeof(coff_relocation); + } else { + S.Header.NumberOfRelocations = S.Relocs.size(); + S.Header.PointerToRelocations = S.Relocs.size() ? FileSize : 0; + } + + FileSize += S.Relocs.size() * sizeof(coff_relocation); + FileSize = alignTo(FileSize, FileAlignment); + + if (S.Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) + SizeOfInitializedData += S.Header.SizeOfRawData; + } +} + +size_t COFFWriter::finalizeStringTable() { + for (const auto &S : Obj.getSections()) + if (S.Name.size() > COFF::NameSize) + StrTabBuilder.add(S.Name); + + for (const auto &S : Obj.getSymbols()) + if (S.Name.size() > COFF::NameSize) + StrTabBuilder.add(S.Name); + + StrTabBuilder.finalize(); + + for (auto &S : Obj.getMutableSections()) { + memset(S.Header.Name, 0, sizeof(S.Header.Name)); + if (S.Name.size() > COFF::NameSize) { + snprintf(S.Header.Name, sizeof(S.Header.Name), "/%d", + (int)StrTabBuilder.getOffset(S.Name)); + } else { + memcpy(S.Header.Name, S.Name.data(), S.Name.size()); + } + } + for (auto &S : Obj.getMutableSymbols()) { + if (S.Name.size() > COFF::NameSize) { + S.Sym.Name.Offset.Zeroes = 0; + S.Sym.Name.Offset.Offset = StrTabBuilder.getOffset(S.Name); + } else { + strncpy(S.Sym.Name.ShortName, S.Name.data(), COFF::NameSize); + } + } + return StrTabBuilder.getSize(); +} + +template <class SymbolTy> +std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() { + size_t RawSymIndex = 0; + for (auto &S : Obj.getMutableSymbols()) { + // Symbols normally have NumberOfAuxSymbols set correctly all the time. + // For file symbols, we need to know the output file's symbol size to be + // able to calculate the number of slots it occupies. + if (!S.AuxFile.empty()) + S.Sym.NumberOfAuxSymbols = + alignTo(S.AuxFile.size(), sizeof(SymbolTy)) / sizeof(SymbolTy); + S.RawIndex = RawSymIndex; + RawSymIndex += 1 + S.Sym.NumberOfAuxSymbols; + } + return std::make_pair(RawSymIndex * sizeof(SymbolTy), sizeof(SymbolTy)); +} + +Error COFFWriter::finalize(bool IsBigObj) { + size_t SymTabSize, SymbolSize; + std::tie(SymTabSize, SymbolSize) = IsBigObj + ? finalizeSymbolTable<coff_symbol32>() + : finalizeSymbolTable<coff_symbol16>(); + + if (Error E = finalizeRelocTargets()) + return E; + if (Error E = finalizeSymbolContents()) + return E; + + size_t SizeOfHeaders = 0; + FileAlignment = 1; + size_t PeHeaderSize = 0; + if (Obj.IsPE) { + Obj.DosHeader.AddressOfNewExeHeader = + sizeof(Obj.DosHeader) + Obj.DosStub.size(); + SizeOfHeaders += Obj.DosHeader.AddressOfNewExeHeader + sizeof(PEMagic); + + FileAlignment = Obj.PeHeader.FileAlignment; + Obj.PeHeader.NumberOfRvaAndSize = Obj.DataDirectories.size(); + + PeHeaderSize = Obj.Is64 ? sizeof(pe32plus_header) : sizeof(pe32_header); + SizeOfHeaders += + PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size(); + } + Obj.CoffFileHeader.NumberOfSections = Obj.getSections().size(); + SizeOfHeaders += + IsBigObj ? sizeof(coff_bigobj_file_header) : sizeof(coff_file_header); + SizeOfHeaders += sizeof(coff_section) * Obj.getSections().size(); + SizeOfHeaders = alignTo(SizeOfHeaders, FileAlignment); + + Obj.CoffFileHeader.SizeOfOptionalHeader = + PeHeaderSize + sizeof(data_directory) * Obj.DataDirectories.size(); + + FileSize = SizeOfHeaders; + SizeOfInitializedData = 0; + + layoutSections(); + + if (Obj.IsPE) { + Obj.PeHeader.SizeOfHeaders = SizeOfHeaders; + Obj.PeHeader.SizeOfInitializedData = SizeOfInitializedData; + + if (!Obj.getSections().empty()) { + const Section &S = Obj.getSections().back(); + Obj.PeHeader.SizeOfImage = + alignTo(S.Header.VirtualAddress + S.Header.VirtualSize, + Obj.PeHeader.SectionAlignment); + } + + // If the PE header had a checksum, clear it, since it isn't valid + // any longer. (We don't calculate a new one.) + Obj.PeHeader.CheckSum = 0; + } + + size_t StrTabSize = finalizeStringTable(); + + size_t PointerToSymbolTable = FileSize; + // StrTabSize <= 4 is the size of an empty string table, only consisting + // of the length field. + if (SymTabSize == 0 && StrTabSize <= 4 && Obj.IsPE) { + // For executables, don't point to the symbol table and skip writing + // the length field, if both the symbol and string tables are empty. + PointerToSymbolTable = 0; + StrTabSize = 0; + } + + size_t NumRawSymbols = SymTabSize / SymbolSize; + Obj.CoffFileHeader.PointerToSymbolTable = PointerToSymbolTable; + Obj.CoffFileHeader.NumberOfSymbols = NumRawSymbols; + FileSize += SymTabSize + StrTabSize; + FileSize = alignTo(FileSize, FileAlignment); + + return Error::success(); +} + +void COFFWriter::writeHeaders(bool IsBigObj) { + uint8_t *Ptr = Buf.getBufferStart(); + if (Obj.IsPE) { + memcpy(Ptr, &Obj.DosHeader, sizeof(Obj.DosHeader)); + Ptr += sizeof(Obj.DosHeader); + memcpy(Ptr, Obj.DosStub.data(), Obj.DosStub.size()); + Ptr += Obj.DosStub.size(); + memcpy(Ptr, PEMagic, sizeof(PEMagic)); + Ptr += sizeof(PEMagic); + } + if (!IsBigObj) { + memcpy(Ptr, &Obj.CoffFileHeader, sizeof(Obj.CoffFileHeader)); + Ptr += sizeof(Obj.CoffFileHeader); + } else { + // Generate a coff_bigobj_file_header, filling it in with the values + // from Obj.CoffFileHeader. All extra fields that don't exist in + // coff_file_header can be set to hardcoded values. + coff_bigobj_file_header BigObjHeader; + BigObjHeader.Sig1 = IMAGE_FILE_MACHINE_UNKNOWN; + BigObjHeader.Sig2 = 0xffff; + BigObjHeader.Version = BigObjHeader::MinBigObjectVersion; + BigObjHeader.Machine = Obj.CoffFileHeader.Machine; + BigObjHeader.TimeDateStamp = Obj.CoffFileHeader.TimeDateStamp; + memcpy(BigObjHeader.UUID, BigObjMagic, sizeof(BigObjMagic)); + BigObjHeader.unused1 = 0; + BigObjHeader.unused2 = 0; + BigObjHeader.unused3 = 0; + BigObjHeader.unused4 = 0; + // The value in Obj.CoffFileHeader.NumberOfSections is truncated, thus + // get the original one instead. + BigObjHeader.NumberOfSections = Obj.getSections().size(); + BigObjHeader.PointerToSymbolTable = Obj.CoffFileHeader.PointerToSymbolTable; + BigObjHeader.NumberOfSymbols = Obj.CoffFileHeader.NumberOfSymbols; + + memcpy(Ptr, &BigObjHeader, sizeof(BigObjHeader)); + Ptr += sizeof(BigObjHeader); + } + if (Obj.IsPE) { + if (Obj.Is64) { + memcpy(Ptr, &Obj.PeHeader, sizeof(Obj.PeHeader)); + Ptr += sizeof(Obj.PeHeader); + } else { + pe32_header PeHeader; + copyPeHeader(PeHeader, Obj.PeHeader); + // The pe32plus_header (stored in Object) lacks the BaseOfData field. + PeHeader.BaseOfData = Obj.BaseOfData; + + memcpy(Ptr, &PeHeader, sizeof(PeHeader)); + Ptr += sizeof(PeHeader); + } + for (const auto &DD : Obj.DataDirectories) { + memcpy(Ptr, &DD, sizeof(DD)); + Ptr += sizeof(DD); + } + } + for (const auto &S : Obj.getSections()) { + memcpy(Ptr, &S.Header, sizeof(S.Header)); + Ptr += sizeof(S.Header); + } +} + +void COFFWriter::writeSections() { + for (const auto &S : Obj.getSections()) { + uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData; + ArrayRef<uint8_t> Contents = S.getContents(); + std::copy(Contents.begin(), Contents.end(), Ptr); + + // For executable sections, pad the remainder of the raw data size with + // 0xcc, which is int3 on x86. + if ((S.Header.Characteristics & IMAGE_SCN_CNT_CODE) && + S.Header.SizeOfRawData > Contents.size()) + memset(Ptr + Contents.size(), 0xcc, + S.Header.SizeOfRawData - Contents.size()); + + Ptr += S.Header.SizeOfRawData; + + if (S.Relocs.size() >= 0xffff) { + object::coff_relocation R; + R.VirtualAddress = S.Relocs.size() + 1; + R.SymbolTableIndex = 0; + R.Type = 0; + memcpy(Ptr, &R, sizeof(R)); + Ptr += sizeof(R); + } + for (const auto &R : S.Relocs) { + memcpy(Ptr, &R.Reloc, sizeof(R.Reloc)); + Ptr += sizeof(R.Reloc); + } + } +} + +template <class SymbolTy> void COFFWriter::writeSymbolStringTables() { + uint8_t *Ptr = Buf.getBufferStart() + Obj.CoffFileHeader.PointerToSymbolTable; + for (const auto &S : Obj.getSymbols()) { + // Convert symbols back to the right size, from coff_symbol32. + copySymbol<SymbolTy, coff_symbol32>(*reinterpret_cast<SymbolTy *>(Ptr), + S.Sym); + Ptr += sizeof(SymbolTy); + if (!S.AuxFile.empty()) { + // For file symbols, just write the string into the aux symbol slots, + // assuming that the unwritten parts are initialized to zero in the memory + // mapped file. + std::copy(S.AuxFile.begin(), S.AuxFile.end(), Ptr); + Ptr += S.Sym.NumberOfAuxSymbols * sizeof(SymbolTy); + } else { + // For other auxillary symbols, write their opaque payload into one symbol + // table slot each. For big object files, the symbols are larger than the + // opaque auxillary symbol struct and we leave padding at the end of each + // entry. + for (const AuxSymbol &AuxSym : S.AuxData) { + ArrayRef<uint8_t> Ref = AuxSym.getRef(); + std::copy(Ref.begin(), Ref.end(), Ptr); + Ptr += sizeof(SymbolTy); + } + } + } + if (StrTabBuilder.getSize() > 4 || !Obj.IsPE) { + // Always write a string table in object files, even an empty one. + StrTabBuilder.write(Ptr); + Ptr += StrTabBuilder.getSize(); + } +} + +Error COFFWriter::write(bool IsBigObj) { + if (Error E = finalize(IsBigObj)) + return E; + + if (Error E = Buf.allocate(FileSize)) + return E; + + writeHeaders(IsBigObj); + writeSections(); + if (IsBigObj) + writeSymbolStringTables<coff_symbol32>(); + else + writeSymbolStringTables<coff_symbol16>(); + + if (Obj.IsPE) + if (Error E = patchDebugDirectory()) + return E; + + return Buf.commit(); +} + +Expected<uint32_t> COFFWriter::virtualAddressToFileAddress(uint32_t RVA) { + for (const auto &S : Obj.getSections()) { + if (RVA >= S.Header.VirtualAddress && + RVA < S.Header.VirtualAddress + S.Header.SizeOfRawData) + return S.Header.PointerToRawData + RVA - S.Header.VirtualAddress; + } + return createStringError(object_error::parse_failed, + "debug directory payload not found"); +} + +// Locate which sections contain the debug directories, iterate over all +// the debug_directory structs in there, and set the PointerToRawData field +// in all of them, according to their new physical location in the file. +Error COFFWriter::patchDebugDirectory() { + if (Obj.DataDirectories.size() < DEBUG_DIRECTORY) + return Error::success(); + const data_directory *Dir = &Obj.DataDirectories[DEBUG_DIRECTORY]; + if (Dir->Size <= 0) + return Error::success(); + for (const auto &S : Obj.getSections()) { + if (Dir->RelativeVirtualAddress >= S.Header.VirtualAddress && + Dir->RelativeVirtualAddress < + S.Header.VirtualAddress + S.Header.SizeOfRawData) { + if (Dir->RelativeVirtualAddress + Dir->Size > + S.Header.VirtualAddress + S.Header.SizeOfRawData) + return createStringError(object_error::parse_failed, + "debug directory extends past end of section"); + + size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress; + uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData + Offset; + uint8_t *End = Ptr + Dir->Size; + while (Ptr < End) { + debug_directory *Debug = reinterpret_cast<debug_directory *>(Ptr); + if (!Debug->AddressOfRawData) + return createStringError(object_error::parse_failed, + "debug directory payload outside of " + "mapped sections not supported"); + if (Expected<uint32_t> FilePosOrErr = + virtualAddressToFileAddress(Debug->AddressOfRawData)) + Debug->PointerToRawData = *FilePosOrErr; + else + return FilePosOrErr.takeError(); + Ptr += sizeof(debug_directory); + Offset += sizeof(debug_directory); + } + // Debug directory found and patched, all done. + return Error::success(); + } + } + return createStringError(object_error::parse_failed, + "debug directory not found"); +} + +Error COFFWriter::write() { + bool IsBigObj = Obj.getSections().size() > MaxNumberOfSections16; + if (IsBigObj && Obj.IsPE) + return createStringError(object_error::parse_failed, + "too many sections for executable"); + return write(IsBigObj); +} + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.h b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.h index 3c0bdcbd5d..cd6a17984c 100644 --- a/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.h +++ b/contrib/libs/llvm12/tools/llvm-objcopy/COFF/Writer.h @@ -1,62 +1,62 @@ -//===- Writer.h -------------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_OBJCOPY_COFF_WRITER_H -#define LLVM_TOOLS_OBJCOPY_COFF_WRITER_H - -#include "Buffer.h" -#include "llvm/MC/StringTableBuilder.h" -#include "llvm/Support/Error.h" -#include <cstddef> -#include <utility> - -namespace llvm { -namespace objcopy { -namespace coff { - -struct Object; - -class COFFWriter { - Object &Obj; - Buffer &Buf; - - size_t FileSize; - size_t FileAlignment; - size_t SizeOfInitializedData; - StringTableBuilder StrTabBuilder; - - template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable(); - Error finalizeRelocTargets(); - Error finalizeSymbolContents(); - void layoutSections(); - size_t finalizeStringTable(); - - Error finalize(bool IsBigObj); - - void writeHeaders(bool IsBigObj); - void writeSections(); - template <class SymbolTy> void writeSymbolStringTables(); - - Error write(bool IsBigObj); - - Error patchDebugDirectory(); - Expected<uint32_t> virtualAddressToFileAddress(uint32_t RVA); - -public: - virtual ~COFFWriter() {} - Error write(); - - COFFWriter(Object &Obj, Buffer &Buf) - : Obj(Obj), Buf(Buf), StrTabBuilder(StringTableBuilder::WinCOFF) {} -}; - -} // end namespace coff -} // end namespace objcopy -} // end namespace llvm - -#endif // LLVM_TOOLS_OBJCOPY_COFF_WRITER_H +//===- Writer.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_OBJCOPY_COFF_WRITER_H +#define LLVM_TOOLS_OBJCOPY_COFF_WRITER_H + +#include "Buffer.h" +#include "llvm/MC/StringTableBuilder.h" +#include "llvm/Support/Error.h" +#include <cstddef> +#include <utility> + +namespace llvm { +namespace objcopy { +namespace coff { + +struct Object; + +class COFFWriter { + Object &Obj; + Buffer &Buf; + + size_t FileSize; + size_t FileAlignment; + size_t SizeOfInitializedData; + StringTableBuilder StrTabBuilder; + + template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable(); + Error finalizeRelocTargets(); + Error finalizeSymbolContents(); + void layoutSections(); + size_t finalizeStringTable(); + + Error finalize(bool IsBigObj); + + void writeHeaders(bool IsBigObj); + void writeSections(); + template <class SymbolTy> void writeSymbolStringTables(); + + Error write(bool IsBigObj); + + Error patchDebugDirectory(); + Expected<uint32_t> virtualAddressToFileAddress(uint32_t RVA); + +public: + virtual ~COFFWriter() {} + Error write(); + + COFFWriter(Object &Obj, Buffer &Buf) + : Obj(Obj), Buf(Buf), StrTabBuilder(StringTableBuilder::WinCOFF) {} +}; + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm + +#endif // LLVM_TOOLS_OBJCOPY_COFF_WRITER_H |