LLVM: lib/ObjCopy/ELF/ELFObjcopy.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

32#include

33#include

34#include

35#include

36#include

37#include

38#include <system_error>

39#include

40

41using namespace llvm;

46

48

51}

52

55}

56

58

60 return false;

61

62

64}

65

69 if (AllFlags & SectionFlag::SecAlloc)

71 if (!(AllFlags & SectionFlag::SecReadonly))

73 if (AllFlags & SectionFlag::SecCode)

75 if (AllFlags & SectionFlag::SecMerge)

77 if (AllFlags & SectionFlag::SecStrings)

79 if (AllFlags & SectionFlag::SecExclude)

81 if (AllFlags & SectionFlag::SecLarge) {

84 "section flag SHF_X86_64_LARGE can only be used "

85 "with x86_64 architecture");

87 }

88 return NewFlags;

89}

90

94

95

102 return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);

103}

104

106

107

111}

112

116 if (!NewFlags)

119

120

121

122

125 Flags & (SectionFlag::SecContents | SectionFlag::SecLoad)))

127

129}

130

132

142}

143

145

146 if (MI.Is64Bit)

148 else

150}

151

155

156 switch (OutputElfType) {

158 return std::make_unique<ELFWriter>(Obj, Out, Config.StripSections,

159 Config.OnlyKeepDebug);

161 return std::make_unique<ELFWriter>(Obj, Out, Config.StripSections,

162 Config.OnlyKeepDebug);

164 return std::make_unique<ELFWriter>(Obj, Out, Config.StripSections,

165 Config.OnlyKeepDebug);

167 return std::make_unique<ELFWriter>(Obj, Out, Config.StripSections,

168 Config.OnlyKeepDebug);

169 }

171}

172

176 switch (Config.OutputFormat) {

177 case FileFormat::Binary:

178 return std::make_unique(Obj, Out, Config);

179 case FileFormat::IHex:

180 return std::make_unique(Obj, Out, Config.OutputFilename);

181 case FileFormat::SREC:

182 return std::make_unique(Obj, Out, Config.OutputFilename);

183 default:

185 }

186}

187

190 for (auto &Sec : Obj.sections()) {

191 if (Sec.Name == SecName) {

194 "cannot dump section '%s': it has no contents",

195 SecName.str().c_str());

198 if (!BufferOrErr)

200 std::unique_ptr Buf = std::move(*BufferOrErr);

201 std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),

202 Buf->getBufferStart());

203 if (Error E = Buf->commit())

204 return E;

206 }

207 }

208 return createStringError(object_error::parse_failed, "section '%s' not found",

209 SecName.str().c_str());

210}

211

213

214

215

217 ToReplace;

219 std::optional CType;

220 for (auto &[Matcher, T] : Config.compressSections)

221 if (Matcher.matches(Sec.Name))

222 CType = T;

223

224

227 CType = Config.CompressionType;

228 else if (Config.DecompressDebugSections)

230 }

231 if (!CType)

232 continue;

233

234 if (Sec.ParentSegment)

237 "section '" + Sec.Name +

238 "' within a segment cannot be (de)compressed");

239

240 if (auto *CS = dyn_cast(&Sec)) {

242 ToReplace.emplace_back(

243 &Sec, [=] { return &addSection(*CS); });

245 ToReplace.emplace_back(&Sec, [=, S = &Sec] {

246 return &addSection(

248 });

249 }

250 }

251

253 for (auto [S, Func] : ToReplace)

254 FromTo[S] = Func();

256}

257

261 return false;

263 if (Name.consume_front("$x") && Name.consume_front("$d"))

264 return false;

265 return Name.empty() || Name.starts_with(".");

266}

267

271 return false;

273 if (Name.consume_front("$a") && Name.consume_front("$d") &&

274 Name.consume_front("$t"))

275 return false;

276 return Name.empty() || Name.starts_with(".");

277}

278

279

283

286

288 default:

289 return false;

290 }

291}

292

297}

298

301

302

305

308 return;

309

310

311

317

321

322

323

324

325

326

327

328

329

330

331

332 if (Config.SymbolsToKeepGlobal.empty() &&

336

340

341

344

348

349 const auto I = Config.SymbolsToRename.find(Sym.Name);

350 if (I != Config.SymbolsToRename.end())

351 Sym.Name = std::string(I->getValue());

352

354 if (Sym.Name.compare(0, Config.SymbolsPrefixRemove.size(),

355 Config.SymbolsPrefixRemove) == 0)

357

360 });

361

362

363

364

365 if (Config.StripUnneeded || Config.UnneededSymbolsToRemove.empty() ||

366 Config.OnlySection.empty()) {

368 Sec.markSymbols();

369 }

370

371 auto RemoveSymbolsPred = [&](const Symbol &Sym) {

374 return false;

375

377 return true;

378

380 return true;

381

383 return false;

384

386 return true;

387

393 return true;

394

395 if ((Config.StripUnneeded ||

396 Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&

398 return true;

399

400

403 return true;

404

405 return false;

406 };

407

409}

410

414

415

416 if (Config.ToRemove.empty()) {

418 return Config.ToRemove.matches(Sec.Name);

419 };

420 }

421

423 RemovePred = [RemovePred](const SectionBase &Sec) {

425 };

426

427 if (Config.ExtractDWO)

428 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

430 };

431

432 if (Config.StripAllGNU)

433 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

434 if (RemovePred(Sec))

435 return true;

436 if ((Sec.Flags & SHF_ALLOC) != 0)

437 return false;

439 return false;

440 switch (Sec.Type) {

445 return true;

446 }

448 };

449

450 if (Config.StripSections) {

451 RemovePred = [RemovePred](const SectionBase &Sec) {

452 return RemovePred(Sec) || Sec.ParentSegment == nullptr;

453 };

454 }

455

456 if (Config.StripDebug || Config.StripUnneeded) {

457 RemovePred = [RemovePred](const SectionBase &Sec) {

459 };

460 }

461

462 if (Config.StripNonAlloc)

463 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

464 if (RemovePred(Sec))

465 return true;

467 return false;

468 return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;

469 };

470

472 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {

473 if (RemovePred(Sec))

474 return true;

476 return false;

478 return false;

480 return false;

481

482

483

484

486 return false;

487 if (Sec.ParentSegment != nullptr)

488 return false;

489 return (Sec.Flags & SHF_ALLOC) == 0;

490 };

491

492 if (Config.ExtractPartition || Config.ExtractMainPartition) {

493 RemovePred = [RemovePred](const SectionBase &Sec) {

494 if (RemovePred(Sec))

495 return true;

497 return true;

498 return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;

499 };

500 }

501

502

503 if (Config.OnlySection.empty()) {

504 RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {

505

506 if (Config.OnlySection.matches(Sec.Name))

507 return false;

508

509

510 if (RemovePred(Sec))

511 return true;

512

513

515 return false;

518 return false;

519

520

521 return true;

522 };

523 }

524

525 if (Config.KeepSection.empty()) {

527

528 if (Config.KeepSection.matches(Sec.Name))

529 return false;

530

531 return RemovePred(Sec);

532 };

533 }

534

535

536

537

538

539

542 RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {

544 return false;

545 return RemovePred(Sec);

546 };

547 }

548

550 return E;

551

553 return E;

554

556}

557

558

560 uint8_t DefaultVisibility) {

563

566 uint8_t Visibility = DefaultVisibility;

567

569 switch (FlagValue) {

572 break;

575 break;

578 break;

581 break;

584 break;

587 break;

590 break;

593 break;

596 break;

599 break;

602 break;

603 default:

604 break;

605 };

606

610}

611

616 NewSection.SectionData->getBufferStart()),

617 NewSection.SectionData->getBufferSize());

619}

620

623

624

625

626

627

628

629

630 if (Data.empty())

632

633 if (Data.size() < 12) {

634 std::string msg;

636 << Name << " data must be either empty or at least 12 bytes long";

638 }

639 if (Data.size() % 4 != 0) {

640 std::string msg;

642 << Name << " data size must be a multiple of 4 bytes";

644 }

647

650

652 4 + 4 + 4 +

653 alignTo(NameSizeValue, 4) +

654 alignTo(DescSizeValue, 4);

656 if (ActualDataSize != ExpectedDataSize) {

657 std::string msg;

660 << " data size is incompatible with the content of "

661 "the name and description size fields:"

662 << " expecting " << ExpectedDataSize << ", found " << ActualDataSize;

664 }

665

667}

668

669

670

671

672

673

674

675

678 if (Config.OutputArch) {

681 }

682

683 if (Config.SplitDWO.empty() && Config.ExtractDWO) {

686 [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });

687 }

688

689

693 std::tie(SectionName, FileName) = Flag.split('=');

695 return E;

696 }

697

698

699

700

701

703 return E;

704

706 return E;

707

708 if (Config.SetSectionAlignment.empty()) {

710 auto I = Config.SetSectionAlignment.find(Sec.Name);

711 if (I != Config.SetSectionAlignment.end())

712 Sec.Align = I->second;

713 }

714 }

715

716 if (Config.ChangeSectionLMAValAll != 0) {

718 if (Seg.FileSize > 0) {

719 if (Config.ChangeSectionLMAValAll > 0 &&

720 Seg.PAddr > std::numeric_limits<uint64_t>::max() -

721 Config.ChangeSectionLMAValAll) {

725 " cannot be increased by 0x" +

727 ". The result would overflow");

728 } else if (Config.ChangeSectionLMAValAll < 0 &&

729 Seg.PAddr < std::numeric_limits<uint64_t>::min() -

730 Config.ChangeSectionLMAValAll) {

734 " cannot be decreased by 0x" +

736 ". The result would underflow");

737 }

738 Seg.PAddr += Config.ChangeSectionLMAValAll;

739 }

740 }

741 }

742

743 if (Config.ChangeSectionAddress.empty()) {

746 object_error::invalid_file_type,

747 "cannot change section address in a non-relocatable file");

748

752 Config.ChangeSectionAddress.rend())) {

754 if (PatternUpdate.SectionPattern.matches(Sec.Name) &&

755 SectionsToUpdateAddress.try_emplace(Sec.Name, PatternUpdate.Update)

756 .second) {

758 Sec.Addr < PatternUpdate.Update.Value) {

762 " cannot be decreased by 0x" +

764 ". The result would underflow");

765 }

767 Sec.Addr > std::numeric_limits<uint64_t>::max() -

768 PatternUpdate.Update.Value) {

772 " cannot be increased by 0x" +

774 ". The result would overflow");

775 }

776

777 switch (PatternUpdate.Update.Kind) {

779 Sec.Addr = PatternUpdate.Update.Value;

780 break;

782 Sec.Addr -= PatternUpdate.Update.Value;

783 break;

785 Sec.Addr += PatternUpdate.Update.Value;

786 break;

787 }

788 }

789 }

790 }

791 }

792

793 if (Config.OnlyKeepDebug)

794 for (auto &Sec : Obj.sections())

797

801

806 if (Name.starts_with(".note") && Name != ".note.GNU-stack") {

810 }

812 };

814 return E;

815 }

816

820 };

822 return E;

823 }

824

825 if (Config.AddGnuDebugLink.empty())

827 Config.GnuDebugLinkCRC32);

828

829

830

833 return E;

834

837

838

839 if (Config.SetSectionFlags.empty() || Config.SetSectionType.empty()) {

840 for (auto &Sec : Obj.sections()) {

841 const auto Iter = Config.SetSectionFlags.find(Sec.Name);

842 if (Iter != Config.SetSectionFlags.end()) {

845 return E;

846 }

847 auto It2 = Config.SetSectionType.find(Sec.Name);

848 if (It2 != Config.SetSectionType.end())

850 }

851 }

852

853 if (Config.SectionsToRename.empty()) {

854 std::vector<RelocationSectionBase *> RelocSections;

857 auto *RelocSec = dyn_cast(&Sec);

858 const auto Iter = Config.SectionsToRename.find(Sec.Name);

859 if (Iter != Config.SectionsToRename.end()) {

861 Sec.Name = std::string(SR.NewName);

864 return E;

865 }

866 RenamedSections.insert(&Sec);

867 } else if (RelocSec && !(Sec.Flags & SHF_ALLOC))

868

869

870

871

872

873

874 RelocSections.push_back(RelocSec);

875 }

876

877

879 auto Iter = RenamedSections.find(RelocSec->getSection());

880 if (Iter != RenamedSections.end())

881 RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str();

882 }

883 }

884

885

886

887

888 if (Config.AllocSectionsPrefix.empty()) {

892 Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();

893 PrefixedSections.insert(&Sec);

894 } else if (auto *RelocSec = dyn_cast(&Sec)) {

895

896

897

898

899

900

901

902 const SectionBase *TargetSec = RelocSec->getSection();

904

905

906

907

908 if (PrefixedSections.count(TargetSec))

909 Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str();

910 else

911 Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix +

912 TargetSec->Name)

913 .str();

914 }

915 }

916 }

917 }

918

922}

923

926 std::unique_ptr Writer =

929 return E;

931}

932

938 if (!Obj)

940

941 const ElfType OutputElfType =

944 return E;

946}

947

954 if (!Obj)

956

957

958

959 const ElfType OutputElfType =

962 return E;

964}

965

973 if (!Obj)

975

979

982

985

987}

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

This file defines the DenseSet and SmallDenseSet classes.

static Error replaceAndRemoveSections(const CommonConfig &Config, const ELFConfig &ELFConfig, Object &Obj)

static bool isArmMappingSymbol(const Symbol &Sym)

static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig, ElfType OutputElfType, Object &Obj)

static Error handleUserSection(const NewSectionInfo &NewSection, function_ref< Error(StringRef, ArrayRef< uint8_t >)> F)

static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, uint8_t DefaultVisibility)

static Error updateAndRemoveSymbols(const CommonConfig &Config, const ELFConfig &ELFConfig, Object &Obj)

std::function< bool(const SectionBase &Sec)> SectionPred

static Error verifyNoteSection(StringRef Name, endianness Endianness, ArrayRef< uint8_t > Data)

static bool isDWOSection(const SectionBase &Sec)

static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym)

static bool isDebugSection(const SectionBase &Sec)

static Error dumpSectionToFile(StringRef SecName, StringRef Filename, Object &Obj)

static Error writeOutput(const CommonConfig &Config, Object &Obj, raw_ostream &Out, ElfType OutputElfType)

static bool isUnneededSymbol(const Symbol &Sym)

static bool isAArch64MappingSymbol(const Symbol &Sym)

static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec)

static void setSectionType(SectionBase &Sec, uint64_t Type)

static Expected< uint64_t > getNewShfFlags(SectionFlag AllFlags, uint16_t EMachine)

static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags, uint16_t EMachine)

static std::unique_ptr< Writer > createELFWriter(const CommonConfig &Config, Object &Obj, raw_ostream &Out, ElfType OutputElfType)

static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, uint64_t NewFlags, uint16_t EMachine)

static std::unique_ptr< Writer > createWriter(const CommonConfig &Config, Object &Obj, raw_ostream &Out, ElfType OutputElfType)

static ElfType getOutputElfType(const Binary &Bin)

This file defines the SmallVector class.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

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 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...

This interface provides simple read-only access to a block of memory, and provides simple methods for...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)

Emplace a new element for the specified key into the map if the key isn't already in the map.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

bool ends_with(StringRef Suffix) const

Check if this string ends with the given Suffix.

static Twine utohexstr(const uint64_t &Val)

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

std::pair< iterator, bool > insert(const ValueT &V)

iterator find(const_arg_type_t< ValueT > V)

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

An efficient, type-erasing, non-owning reference to a callable.

SectionTableRef sections() const

StringTableSection * SectionNames

bool isRelocatable() const

Error updateSection(StringRef Name, ArrayRef< uint8_t > Data)

Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove)

T & addSection(Ts &&...Args)

Error removeSections(bool AllowBrokenLinks, std::function< bool(const SectionBase &)> ToRemove)

ConstRange< Segment > segments() const

SymbolTableSection * SymbolTable

Error compressOrDecompressSections(const CommonConfig &Config)

SectionBase * findSection(StringRef Name)

Error addNewSymbolTable()

Error replaceSections(const DenseMap< SectionBase *, SectionBase * > &FromTo)

virtual Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const =0

const SectionBase * getStrTab() const

void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, uint16_t Shndx, uint64_t SymbolSize)

void updateSymbols(function_ref< void(Symbol &)> Callable)

virtual Error finalize()=0

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr size_t NameSize

Error executeObjcopyOnIHex(const CommonConfig &Config, const ELFConfig &ELFConfig, MemoryBuffer &In, raw_ostream &Out)

Apply the transformations described by Config and ELFConfig to In, which must represent an IHex file,...

Error executeObjcopyOnBinary(const CommonConfig &Config, const ELFConfig &ELFConfig, object::ELFObjectFileBase &In, raw_ostream &Out)

Apply the transformations described by Config and ELFConfig to In and writes the result into Out.

Error executeObjcopyOnRawBinary(const CommonConfig &Config, const ELFConfig &ELFConfig, MemoryBuffer &In, raw_ostream &Out)

Apply the transformations described by Config and ELFConfig to In, which is treated as a raw binary i...

uint32_t read32(const void *P, endianness E)

This is an optimization pass for GlobalISel generic memory operations.

Error createFileError(const Twine &F, Error E)

Concatenate a source file path and/or name with an Error.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

SymInfo contains information about symbol: it's address and section index which is -1LL for absolute ...

std::vector< std::pair< NameMatcher, uint8_t > > SymbolsToSetVisibility

uint8_t NewSymbolVisibility

std::function< uint64_t(uint64_t)> EntryExpr

std::shared_ptr< MemoryBuffer > SectionData

std::optional< SectionFlag > NewFlags

uint16_t getShndx() const