diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/tools/llvm-objcopy/COFF | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/tools/llvm-objcopy/COFF')
-rw-r--r-- | llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp | 53 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/COFF/Reader.cpp | 19 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/COFF/Writer.cpp | 25 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/COFF/Writer.h | 1 |
4 files changed, 82 insertions, 16 deletions
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp index b172fae527eb5..43ec2b1fa82f2 100644 --- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -89,6 +89,43 @@ static void addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) { IMAGE_SCN_MEM_DISCARDABLE); } +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) { @@ -178,6 +215,13 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) { return false; }); + 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("="); @@ -205,10 +249,11 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) { !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || - !Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() || - Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden || - Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc || - Config.StripSections || Config.Weaken || Config.DecompressDebugSections || + !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, diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp index 7be9cce2be3d9..d1beacb3bd67e 100644 --- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp +++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp @@ -45,9 +45,9 @@ Error COFFReader::readExecutableHeaders(Object &Obj) const { } for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) { - const data_directory *Dir; - if (auto EC = COFFObj.getDataDirectory(I, Dir)) - return errorCodeToError(EC); + const data_directory *Dir = COFFObj.getDataDirectory(I); + if (!Dir) + return errorCodeToError(object_error::parse_failed); Obj.DataDirectories.emplace_back(*Dir); } return Error::success(); @@ -57,9 +57,10 @@ 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++) { - const coff_section *Sec; - if (auto EC = COFFObj.getSection(I, Sec)) - return errorCodeToError(EC); + 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; @@ -99,8 +100,10 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const { else copySymbol(Sym.Sym, *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr())); - if (auto EC = COFFObj.getSymbolName(SymRef, Sym.Name)) - return errorCodeToError(EC); + 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); diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp index e35e0474a36d5..6b560890a4c16 100644 --- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp +++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp @@ -383,6 +383,16 @@ Error COFFWriter::write(bool IsBigObj) { 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. @@ -406,10 +416,17 @@ Error COFFWriter::patchDebugDirectory() { uint8_t *End = Ptr + Dir->Size; while (Ptr < End) { debug_directory *Debug = reinterpret_cast<debug_directory *>(Ptr); - Debug->PointerToRawData = - S.Header.PointerToRawData + Offset + sizeof(debug_directory); - Ptr += sizeof(debug_directory) + Debug->SizeOfData; - Offset += sizeof(debug_directory) + Debug->SizeOfData; + 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(); diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h index 681a8d5e4a66c..3c0bdcbd5d6f6 100644 --- a/llvm/tools/llvm-objcopy/COFF/Writer.h +++ b/llvm/tools/llvm-objcopy/COFF/Writer.h @@ -45,6 +45,7 @@ class COFFWriter { Error write(bool IsBigObj); Error patchDebugDirectory(); + Expected<uint32_t> virtualAddressToFileAddress(uint32_t RVA); public: virtual ~COFFWriter() {} |