summaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
index 915394b65b12..0f92ca516bef 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
@@ -317,6 +317,52 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) {
return Error::success();
}
+static Expected<Section &> findSection(StringRef SecName, Object &O) {
+ StringRef SegName;
+ std::tie(SegName, SecName) = SecName.split(",");
+ auto FoundSeg =
+ llvm::find_if(O.LoadCommands, [SegName](const LoadCommand &LC) {
+ return LC.getSegmentName() == SegName;
+ });
+ if (FoundSeg == O.LoadCommands.end())
+ return createStringError(errc::invalid_argument,
+ "could not find segment with name '%s'",
+ SegName.str().c_str());
+ auto FoundSec = llvm::find_if(FoundSeg->Sections,
+ [SecName](const std::unique_ptr<Section> &Sec) {
+ return Sec->Sectname == SecName;
+ });
+ if (FoundSec == FoundSeg->Sections.end())
+ return createStringError(errc::invalid_argument,
+ "could not find section with name '%s'",
+ SecName.str().c_str());
+
+ assert(FoundSec->get()->CanonicalName == (SegName + "," + SecName).str());
+ return *FoundSec->get();
+}
+
+static Error updateSection(StringRef SecName, StringRef Filename, Object &O) {
+ Expected<Section &> SecToUpdateOrErr = findSection(SecName, O);
+
+ if (!SecToUpdateOrErr)
+ return SecToUpdateOrErr.takeError();
+ Section &Sec = *SecToUpdateOrErr;
+
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+ MemoryBuffer::getFile(Filename);
+ if (!BufOrErr)
+ return createFileError(Filename, errorCodeToError(BufOrErr.getError()));
+ std::unique_ptr<MemoryBuffer> Buf = std::move(*BufOrErr);
+
+ if (Buf->getBufferSize() > Sec.Size)
+ return createStringError(
+ errc::invalid_argument,
+ "new section cannot be larger than previous section");
+ Sec.Content = O.NewSectionsContents.save(Buf->getBuffer());
+ Sec.Size = Sec.Content.size();
+ return Error::success();
+}
+
// isValidMachOCannonicalName returns success if Name is a MachO cannonical name
// ("<segment>,<section>") and lengths of both segment and section names are
// valid.
@@ -374,6 +420,16 @@ static Error handleArgs(const CommonConfig &Config,
return E;
}
+ for (const auto &Flag : Config.UpdateSection) {
+ StringRef SectionName;
+ StringRef FileName;
+ std::tie(SectionName, FileName) = Flag.split('=');
+ if (Error E = isValidMachOCannonicalName(SectionName))
+ return E;
+ if (Error E = updateSection(SectionName, FileName, Obj))
+ return E;
+ }
+
if (Error E = processLoadCommands(MachOConfig, Obj))
return E;