summaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/COFF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/tools/llvm-objcopy/COFF
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'llvm/tools/llvm-objcopy/COFF')
-rw-r--r--llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp53
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Reader.cpp19
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Writer.cpp25
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Writer.h1
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() {}