LLVM: lib/ObjCopy/MachO/MachOObjcopy.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10#include "Archive.h"
26
27using namespace llvm;
31
32using SectionPred = std::function<bool(const std::unique_ptr
34
35#ifndef NDEBUG
44#endif
45
48 "unsupported load command encountered");
49
50 return StringRef(reinterpret_cast<const char *>(LC.Payload.data()),
53}
54
56 SectionPred RemovePred = [](const std::unique_ptr
57 return false;
58 };
59
61 RemovePred = [&Config, RemovePred](const std::unique_ptr
63 };
64 }
65
67
68 RemovePred = [RemovePred](const std::unique_ptr
69 if (Sec->Segname == "__DWARF")
70 return true;
71
72 return RemovePred(Sec);
73 };
74 }
75
77
78 RemovePred = [&Config](const std::unique_ptr
80 };
81 }
82
83 return Obj.removeSections(RemovePred);
84}
85
87
90 (*ISE.Symbol)->Referenced = true;
91}
92
96 Obj.SymTable.updateSymbols([&](SymbolEntry &Sym) {
98 return;
99
102
103
104
105
106
107
108
109
110
111
112
116
119
123
126 Sym.Name = std::string(I->getValue());
127 });
128
129 auto RemovePred = [&Config, &MachOConfig,
130 &Obj](const std::unique_ptr &N) {
131 if (N->Referenced)
132 return false;
134 return false;
136 return false;
138 return true;
140 return true;
141
143 return true;
144
147 *Obj.SwiftVersion && N->isSwiftSymbol())
148 return true;
149 return false;
150 };
151
152 Obj.SymTable.removeSymbols(RemovePred);
153}
154
155template
158 "unsupported load command encountered");
159
161
163 LC.Payload.assign(NewCmdsize - sizeof(LCType), 0);
165}
166
170 RPathLC.cmd = MachO::LC_RPATH;
176 return LC;
177}
178
180
183
186 if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH) {
187
188
190 return true;
191
193 if (RPathsToRemove.count(RPath)) {
194 RPathsToRemove.erase(RPath);
195 return true;
196 }
197 }
198 return false;
199 };
200
201 if (Error E = Obj.removeLoadCommands(RemovePred))
202 return E;
203
204
205
207 if (RPathsToRemove.count(RPath))
209 "no LC_RPATH load command with path: %s",
210 RPath.str().c_str());
211 }
212
214
215
216 for (LoadCommand &LC : Obj.LoadCommands) {
217 if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH)
219 }
220
221
223 StringRef Old = OldNew.getFirst();
224 StringRef New = OldNew.getSecond();
227 "no LC_RPATH load command with path: " + Old);
230 "rpath '" + New +
231 "' would create a duplicate load command");
232 }
233
234
235 for (LoadCommand &LC : Obj.LoadCommands) {
237 case MachO::LC_ID_DYLIB:
241 break;
242
243 case MachO::LC_RPATH: {
246 if (!NewRPath.empty())
248 break;
249 }
250
251
252
253 case MachO::LC_LOAD_DYLIB:
254 case MachO::LC_LOAD_WEAK_DYLIB:
258 if (!NewInstallName.empty())
260 NewInstallName);
261 break;
262 }
263 }
264
265
269 "rpath '" + RPath +
270 "' would create a duplicate load command");
271 RPaths.insert(RPath);
273 }
274
278 "rpath '" + RPath +
279 "' would create a duplicate load command");
280
281 RPaths.insert(RPath);
282 Obj.LoadCommands.insert(Obj.LoadCommands.begin(),
284 }
285
286
287
289 Obj.updateLoadCommandIndexes();
290
291
294 if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_SEGMENT_64 ||
295 LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_SEGMENT) {
296 return LC.Sections.empty() &&
298 }
299 return false;
300 };
301 if (Error E = Obj.removeLoadCommands(RemovePred))
302 return E;
303 }
304
306}
307
311 for (const std::unique_ptr
312 if (Sec->CanonicalName == SecName) {
315 if (!BufferOrErr)
317 std::unique_ptr Buf = std::move(*BufferOrErr);
318 llvm::copy(Sec->Content, Buf->getBufferStart());
319
320 if (Error E = Buf->commit())
323 }
324 }
325
327 "section '%s' not found", SecName.str().c_str());
328}
329
331 std::pair<StringRef, StringRef> Pair = NewSection.SectionName.split(',');
332 StringRef TargetSegName = Pair.first;
333 Section Sec(TargetSegName, Pair.second);
335 Obj.NewSectionsContents.save(NewSection.SectionData->getBuffer());
337
338
339 for (LoadCommand &LC : Obj.LoadCommands) {
340 std::optional SegName = LC.getSegmentName();
341 if (SegName && SegName == TargetSegName) {
343 for (const std::unique_ptr
344 Addr = std::max(Addr, S->Addr + S->Size);
345 LC.Sections.push_back(std::make_unique
346 LC.Sections.back()->Addr = Addr;
348 }
349 }
350
351
352
354 Obj.addSegment(TargetSegName, alignTo(Sec.Size, 16384));
355 NewSegment.Sections.push_back(std::make_unique
358}
359
362 std::tie(SegName, SecName) = SecName.split(",");
363
364
365
366
367
368
369
370
372 for (const auto& LC : O.LoadCommands)
373 for (const auto& Sec : LC.Sections)
374 if (Sec->Segname == SegName && Sec->Sectname == SecName)
375 return *Sec;
376
377 StringRef ErrMsg = "could not find section with name '%s' in '%s' segment";
379 SecName.str().c_str(), SegName.str().c_str());
380 }
381 auto FoundSeg =
383 return LC.getSegmentName() == SegName;
384 });
385 if (FoundSeg == O.LoadCommands.end())
387 "could not find segment with name '%s'",
388 SegName.str().c_str());
389 auto FoundSec = llvm::find_if(FoundSeg->Sections,
390 [SecName](const std::unique_ptr
391 return Sec->Sectname == SecName;
392 });
393 if (FoundSec == FoundSeg->Sections.end())
395 "could not find section with name '%s'",
396 SecName.str().c_str());
397
398 assert(FoundSec->get()->CanonicalName == (SegName + "," + SecName).str());
399 return **FoundSec;
400}
401
404
405 if (!SecToUpdateOrErr)
406 return SecToUpdateOrErr.takeError();
407 Section &Sec = *SecToUpdateOrErr;
408
412 "new section cannot be larger than previous section");
413 Sec.Content = O.NewSectionsContents.save(NewSection.SectionData->getBuffer());
416}
417
418
419
420
422 if (Name.count(',') != 1)
424 "invalid section name '%s' (should be formatted "
425 "as ',
426 Name.str().c_str());
427
428 std::pair<StringRef, StringRef> Pair = Name.split(',');
429 if (Pair.first.size() > 16)
431 "too long segment name: '%s'",
432 Pair.first.str().c_str());
433 if (Pair.second.size() > 16)
435 "too long section name: '%s'",
436 Pair.second.str().c_str());
438}
439
442
446 std::tie(SectionName, FileName) = Flag.split('=');
449 return E;
450 }
451
454
455
458
460
463 for (std::unique_ptr
464 Sec->Relocations.clear();
465
471 }
472
478 }
479
482
484}
485
492 if (!O)
494
497 "%s: MH_PRELOAD files are not supported",
499
501 return E;
502
503
504
506 switch (In.getArch()) {
511 break;
512 default:
514 }
515
516 MachOWriter Writer(**O, In.is64Bit(), In.isLittleEndian(),
518 if (auto E = Writer.finalize())
519 return E;
520 return Writer.write();
521}
522
528 for (const auto &O : In.objects()) {
530 if (ArOrErr) {
533 if (!NewArchiveMembersOrErr)
534 return NewArchiveMembersOrErr.takeError();
535 auto Kind = (*ArOrErr)->kind();
540 *NewArchiveMembersOrErr,
544 (*ArOrErr)->isThin());
545 if (!OutputBufferOrErr)
546 return OutputBufferOrErr.takeError();
549 if (!BinaryOrErr)
551 Binaries.emplace_back(std::move(*BinaryOrErr),
552 std::move(*OutputBufferOrErr));
554 O.getCPUType(), O.getCPUSubType(),
555 O.getArchFlagName(), O.getAlign());
556 continue;
557 }
558
559
560
561
563
565 if (!ObjOrErr) {
568 std::errc::invalid_argument,
569 "slice for '%s' of the universal Mach-O binary "
570 "'%s' is not a Mach-O object or an archive",
571 O.getArchFlagName().c_str(),
573 }
574 std::string ArchFlagName = O.getArchFlagName();
575
578
581 return MachO.takeError();
582
584 **ObjOrErr, MemStream))
585 return E;
586
587 auto MB = std::make_unique(
588 std::move(Buffer), ArchFlagName, false);
590 if (!BinaryOrErr)
592 Binaries.emplace_back(std::move(*BinaryOrErr), std::move(MB));
594 O.getAlign());
595 }
596
598 return Err;
599
601}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseSet and SmallDenseSet classes.
std::function< bool(const SectionBase &Sec)> SectionPred
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
static Error processLoadCommands(const MachOConfig &MachOConfig, Object &Obj)
Definition MachOObjcopy.cpp:179
static Expected< Section & > findSection(StringRef SecName, Object &O)
Definition MachOObjcopy.cpp:360
static Error isValidMachOCannonicalName(StringRef Name)
Definition MachOObjcopy.cpp:421
static void updateLoadCommandPayloadString(LoadCommand &LC, StringRef S)
Definition MachOObjcopy.cpp:156
static LoadCommand buildRPathLoadCommand(StringRef Path)
Definition MachOObjcopy.cpp:167
static bool isLoadCommandWithPayloadString(const LoadCommand &LC)
Definition MachOObjcopy.cpp:36
static void markSymbols(const CommonConfig &, Object &Obj)
Definition MachOObjcopy.cpp:86
static Error handleArgs(const CommonConfig &Config, const MachOConfig &MachOConfig, Object &Obj)
Definition MachOObjcopy.cpp:440
static Error removeSections(const CommonConfig &Config, Object &Obj)
Definition MachOObjcopy.cpp:55
std::function< bool(const LoadCommand &LC)> LoadCommandPred
Definition MachOObjcopy.cpp:33
static Error dumpSectionToFile(StringRef SecName, StringRef Filename, StringRef InputFilename, Object &Obj)
Definition MachOObjcopy.cpp:308
static Error addSection(const NewSectionInfo &NewSection, Object &Obj)
Definition MachOObjcopy.cpp:330
static StringRef getPayloadString(const LoadCommand &LC)
Definition MachOObjcopy.cpp:46
static void updateAndRemoveSymbols(const CommonConfig &Config, const MachOConfig &MachOConfig, Object &Obj)
Definition MachOObjcopy.cpp:93
static Error updateSection(const NewSectionInfo &NewSection, Object &O)
Definition MachOObjcopy.cpp:402
static cl::opt< std::string > InputFilename(cl::Positional, cl::desc(""), cl::init("-"))
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static LLVM_ABI Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
StringRef rtrim(char Char) const
Return string with consecutive Char characters starting from the right removed.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
bool erase(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
virtual Expected< const MachOConfig & > getMachOConfig() const =0
virtual const CommonConfig & getCommonConfig() const =0
bool matches(StringRef S) const
virtual Expected< std::unique_ptr< Object > > create() const =0
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
LLVM_ABI Error executeObjcopyOnBinary(const CommonConfig &Config, const MachOConfig &MachOConfig, object::MachOObjectFile &In, raw_ostream &Out)
Apply the transformations described by Config and MachOConfig to In and writes the result into Out.
Definition MachOObjcopy.cpp:486
LLVM_ABI Error executeObjcopyOnMachOUniversalBinary(const MultiFormatConfig &Config, const object::MachOUniversalBinary &In, raw_ostream &Out)
Apply the transformations described by Config and MachOConfig to In and writes the result into Out.
Definition MachOObjcopy.cpp:523
Expected< std::vector< NewArchiveMember > > createNewArchiveMembers(const MultiFormatConfig &Config, const object::Archive &Ar)
Applies the transformations described by Config to each member in archive Ar.
LLVM_ABI Error writeUniversalBinaryToStream(ArrayRef< Slice > Slices, raw_ostream &Out, FatHeaderType FatHeader=FatHeaderType::FatHeader)
LLVM_ABI Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI Expected< std::unique_ptr< MemoryBuffer > > writeArchiveToBuffer(ArrayRef< NewArchiveMember > NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, function_ref< void(Error)> Warn=warnToStderr)
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt copy(R &&Range, OutputIt Out)
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void consumeError(Error Err)
Consume a Error without doing anything.
SmallVector< NewSectionInfo, 0 > UpdateSection
NameMatcher SymbolsToGlobalize
SmallVector< StringRef, 0 > DumpSection
NameMatcher SymbolsToWeaken
NameMatcher SymbolsToKeepGlobal
bool DeterministicArchives
NameMatcher SymbolsToSkip
SmallVector< NewSectionInfo, 0 > AddSection
StringMap< StringRef > SymbolsToRename
NameMatcher SymbolsToLocalize
std::vector< StringRef > RPathToPrepend
DenseMap< StringRef, StringRef > InstallNamesToUpdate
std::optional< StringRef > SharedLibId
DenseSet< StringRef > EmptySegmentsToRemove
DenseSet< StringRef > RPathsToRemove
DenseMap< StringRef, StringRef > RPathsToUpdate
std::vector< StringRef > RPathToAdd
std::shared_ptr< MemoryBuffer > SectionData
std::optional< SymbolEntry * > Symbol
The Symbol referenced by this entry.
MachO::macho_load_command MachOLoadCommand
std::optional< StringRef > getSegmentName() const
std::vector< std::unique_ptr< Section > > Sections
std::optional< uint64_t > getSegmentVMAddr() const
std::vector< uint8_t > Payload
bool isExternalSymbol() const
bool isUndefinedSymbol() const