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

&Sec)>;

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

&Sec) {

63 };

64 }

65

67

68 RemovePred = [RemovePred](const std::unique_ptr

&Sec) {

69 if (Sec->Segname == "__DWARF")

70 return true;

71

72 return RemovePred(Sec);

73 };

74 }

75

77

78 RemovePred = [&Config](const std::unique_ptr

&Sec) {

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

&Sec : LC.Sections) {

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

&S : LC.Sections)

344 Addr = std::max(Addr, S->Addr + S->Size);

345 LC.Sections.push_back(std::make_unique

(Sec));

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

(Sec));

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

&Sec) {

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

&Sec : LC.Sections)

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