LLVM  15.0.0git
MachOObject.cpp
Go to the documentation of this file.
1 //===- MachOObject.cpp - Mach-O object file model ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MachOObject.h"
10 #include "llvm/ADT/SmallPtrSet.h"
11 #include <unordered_set>
12 
13 using namespace llvm;
14 using namespace llvm::objcopy::macho;
15 
17  assert(Index < Symbols.size() && "invalid symbol index");
18  return Symbols[Index].get();
19 }
20 
22  return const_cast<SymbolEntry *>(
23  static_cast<const SymbolTable *>(this)->getSymbolByIndex(Index));
24 }
25 
27  function_ref<bool(const std::unique_ptr<SymbolEntry> &)> ToRemove) {
29 }
30 
32  static constexpr char TextSegmentName[] = "__TEXT";
33  // Update indices of special load commands
34  for (size_t Index = 0, Size = LoadCommands.size(); Index < Size; ++Index) {
36  switch (LC.MachOLoadCommand.load_command_data.cmd) {
37  case MachO::LC_CODE_SIGNATURE:
39  break;
40  case MachO::LC_SEGMENT:
41  if (StringRef(LC.MachOLoadCommand.segment_command_data.segname) ==
42  TextSegmentName)
44  break;
45  case MachO::LC_SEGMENT_64:
46  if (StringRef(LC.MachOLoadCommand.segment_command_64_data.segname) ==
47  TextSegmentName)
49  break;
50  case MachO::LC_SYMTAB:
52  break;
53  case MachO::LC_DYSYMTAB:
55  break;
56  case MachO::LC_DYLD_INFO:
57  case MachO::LC_DYLD_INFO_ONLY:
59  break;
60  case MachO::LC_DATA_IN_CODE:
62  break;
63  case MachO::LC_LINKER_OPTIMIZATION_HINT:
65  break;
66  case MachO::LC_FUNCTION_STARTS:
68  break;
69  case MachO::LC_DYLD_CHAINED_FIXUPS:
71  break;
72  case MachO::LC_DYLD_EXPORTS_TRIE:
74  break;
75  }
76  }
77 }
78 
80  function_ref<bool(const LoadCommand &)> ToRemove) {
81  auto It = std::stable_partition(
82  LoadCommands.begin(), LoadCommands.end(),
83  [&](const LoadCommand &LC) { return !ToRemove(LC); });
84  LoadCommands.erase(It, LoadCommands.end());
85 
87  return Error::success();
88 }
89 
91  function_ref<bool(const std::unique_ptr<Section> &)> ToRemove) {
92  DenseMap<uint32_t, const Section *> OldIndexToSection;
93  uint32_t NextSectionIndex = 1;
94  for (LoadCommand &LC : LoadCommands) {
95  auto It = std::stable_partition(
96  std::begin(LC.Sections), std::end(LC.Sections),
97  [&](const std::unique_ptr<Section> &Sec) { return !ToRemove(Sec); });
98  for (auto I = LC.Sections.begin(), End = It; I != End; ++I) {
99  OldIndexToSection[(*I)->Index] = I->get();
100  (*I)->Index = NextSectionIndex++;
101  }
102  LC.Sections.erase(It, LC.Sections.end());
103  }
104 
105  auto IsDead = [&](const std::unique_ptr<SymbolEntry> &S) -> bool {
106  Optional<uint32_t> Section = S->section();
107  return (Section && !OldIndexToSection.count(*Section));
108  };
109 
111  for (const std::unique_ptr<SymbolEntry> &Sym : SymTable.Symbols)
112  if (IsDead(Sym))
113  DeadSymbols.insert(Sym.get());
114 
115  for (const LoadCommand &LC : LoadCommands)
116  for (const std::unique_ptr<Section> &Sec : LC.Sections)
117  for (const RelocationInfo &R : Sec->Relocations)
118  if (R.Symbol && *R.Symbol && DeadSymbols.count(*R.Symbol))
119  return createStringError(std::errc::invalid_argument,
120  "symbol '%s' defined in section with index "
121  "'%u' cannot be removed because it is "
122  "referenced by a relocation in section '%s'",
123  (*R.Symbol)->Name.c_str(),
124  *((*R.Symbol)->section()),
125  Sec->CanonicalName.c_str());
127  for (std::unique_ptr<SymbolEntry> &S : SymTable.Symbols)
128  if (S->section())
129  S->n_sect = OldIndexToSection[S->n_sect]->Index;
130  return Error::success();
131 }
132 
135  is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
137  for (const LoadCommand &LC : LoadCommands) {
138  const MachO::macho_load_command &MLC = LC.MachOLoadCommand;
139  switch (MLC.load_command_data.cmd) {
140  case MachO::LC_SEGMENT:
141  Addr = std::max(Addr,
142  static_cast<uint64_t>(MLC.segment_command_data.vmaddr) +
143  MLC.segment_command_data.vmsize);
144  break;
145  case MachO::LC_SEGMENT_64:
146  Addr = std::max(Addr, MLC.segment_command_64_data.vmaddr +
147  MLC.segment_command_64_data.vmsize);
148  break;
149  default:
150  continue;
151  }
152  }
153  return Addr;
154 }
155 
156 template <typename SegmentType>
157 static void
159  StringRef SegName, uint64_t SegVMAddr, uint64_t SegVMSize) {
160  assert(SegName.size() <= sizeof(Seg.segname) && "too long segment name");
161  memset(&Seg, 0, sizeof(SegmentType));
162  Seg.cmd = CmdType;
163  strncpy(Seg.segname, SegName.data(), SegName.size());
164  Seg.maxprot |=
166  Seg.initprot |=
168  Seg.vmaddr = SegVMAddr;
169  Seg.vmsize = SegVMSize;
170 }
171 
173  LoadCommand LC;
174  const uint64_t SegVMAddr = nextAvailableSegmentAddress();
175  if (is64Bit())
176  constructSegment(LC.MachOLoadCommand.segment_command_64_data,
177  MachO::LC_SEGMENT_64, SegName, SegVMAddr, SegVMSize);
178  else
179  constructSegment(LC.MachOLoadCommand.segment_command_data,
180  MachO::LC_SEGMENT, SegName, SegVMAddr, SegVMSize);
181 
182  LoadCommands.push_back(std::move(LC));
183  return LoadCommands.back();
184 }
185 
186 /// Extracts a segment name from a string which is possibly non-null-terminated.
187 static StringRef extractSegmentName(const char *SegName) {
188  return StringRef(SegName,
189  strnlen(SegName, sizeof(MachO::segment_command::segname)));
190 }
191 
194  switch (MLC.load_command_data.cmd) {
195  case MachO::LC_SEGMENT:
196  return extractSegmentName(MLC.segment_command_data.segname);
197  case MachO::LC_SEGMENT_64:
198  return extractSegmentName(MLC.segment_command_64_data.segname);
199  default:
200  return None;
201  }
202 }
203 
206  switch (MLC.load_command_data.cmd) {
207  case MachO::LC_SEGMENT:
208  return MLC.segment_command_data.vmaddr;
209  case MachO::LC_SEGMENT_64:
210  return MLC.segment_command_64_data.vmaddr;
211  default:
212  return None;
213  }
214 }
llvm::objcopy::macho::Object::SymTabCommandIndex
Optional< size_t > SymTabCommandIndex
The index of LC_SYMTAB load command if present.
Definition: MachOObject.h:326
IsDead
bool IsDead
Definition: SILowerControlFlow.cpp:168
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::objcopy::macho::Object::LinkerOptimizationHintCommandIndex
Optional< size_t > LinkerOptimizationHintCommandIndex
The index of LC_LINKER_OPTIMIZATIN_HINT load command if present.
Definition: MachOObject.h:334
llvm::BTF::HeaderSize
@ HeaderSize
Definition: BTF.h:60
constructSegment
static void constructSegment(SegmentType &Seg, llvm::MachO::LoadCommandType CmdType, StringRef SegName, uint64_t SegVMAddr, uint64_t SegVMSize)
Definition: MachOObject.cpp:158
llvm::objcopy::macho::SymbolTable
The location of the symbol table inside the binary is described by LC_SYMTAB load command.
Definition: MachOObject.h:139
ToRemove
ReachingDefAnalysis InstSet & ToRemove
Definition: ARMLowOverheadLoops.cpp:542
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::erase_if
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:1807
llvm::objcopy::macho::SymbolTable::removeSymbols
void removeSymbols(function_ref< bool(const std::unique_ptr< SymbolEntry > &)> ToRemove)
Definition: MachOObject.cpp:26
llvm::MachO::VM_PROT_WRITE
@ VM_PROT_WRITE
Definition: MachO.h:489
llvm::objcopy::macho::RelocationInfo
Definition: MachOObject.h:176
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:235
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
llvm::objcopy::macho::Object::DataInCodeCommandIndex
Optional< size_t > DataInCodeCommandIndex
The index LC_DATA_IN_CODE load command if present.
Definition: MachOObject.h:332
llvm::objcopy::macho::Object::FunctionStartsCommandIndex
Optional< size_t > FunctionStartsCommandIndex
The index LC_FUNCTION_STARTS load command if present.
Definition: MachOObject.h:336
llvm::objcopy::macho::Object::ChainedFixupsCommandIndex
Optional< size_t > ChainedFixupsCommandIndex
The index LC_DYLD_CHAINED_FIXUPS load command if present.
Definition: MachOObject.h:338
llvm::Optional< uint32_t >
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::count
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:147
llvm::MachO::LoadCommandType
LoadCommandType
Definition: MachO.h:97
llvm::SmallPtrSet
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:450
llvm::objcopy::macho
Definition: MachOObjcopy.h:26
llvm::max
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:337
llvm::objcopy::macho::MachHeader::SizeOfCmds
uint32_t SizeOfCmds
Definition: MachOObject.h:33
llvm::objcopy::macho::LoadCommand::getSegmentName
Optional< StringRef > getSegmentName() const
Definition: MachOObject.cpp:192
llvm::objcopy::macho::Object::nextAvailableSegmentAddress
uint64_t nextAvailableSegmentAddress() const
Definition: MachOObject.cpp:133
llvm::objcopy::macho::Object::removeLoadCommands
Error removeLoadCommands(function_ref< bool(const LoadCommand &)> ToRemove)
Definition: MachOObject.cpp:79
llvm::objcopy::macho::LoadCommand
Definition: MachOObject.h:84
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::MachO::segment_command::segname
char segname[16]
Definition: MachO.h:540
SmallPtrSet.h
llvm::objcopy::macho::Object::updateLoadCommandIndexes
void updateLoadCommandIndexes()
Definition: MachOObject.cpp:31
llvm::None
const NoneType None
Definition: None.h:24
llvm::objcopy::macho::Object::SymTable
SymbolTable SymTable
Definition: MachOObject.h:306
llvm::objcopy::macho::LoadCommand::getSegmentVMAddr
Optional< uint64_t > getSegmentVMAddr() const
Definition: MachOObject.cpp:204
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
llvm::MachO::mach_header_64
Definition: MachO.h:521
llvm::MachO::VM_PROT_EXECUTE
@ VM_PROT_EXECUTE
Definition: MachO.h:489
uint64_t
llvm::objcopy::macho::Object::removeSections
Error removeSections(function_ref< bool(const std::unique_ptr< Section > &)> ToRemove)
Definition: MachOObject.cpp:90
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
llvm::objcopy::macho::Object::LoadCommands
std::vector< LoadCommand > LoadCommands
Definition: MachOObject.h:304
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:716
llvm::objcopy::macho::LoadCommand::MachOLoadCommand
MachO::macho_load_command MachOLoadCommand
Definition: MachOObject.h:88
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::objcopy::macho::Object::addSegment
LoadCommand & addSegment(StringRef SegName, uint64_t SegVMSize)
Creates a new segment load command in the object and returns a reference to the newly created load co...
Definition: MachOObject.cpp:172
llvm::objcopy::macho::Object::DyLdInfoCommandIndex
Optional< size_t > DyLdInfoCommandIndex
The index of LC_DYLD_INFO or LC_DYLD_INFO_ONLY load command if present.
Definition: MachOObject.h:328
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::objcopy::macho::SymbolTable::getSymbolByIndex
const SymbolEntry * getSymbolByIndex(uint32_t Index) const
Definition: MachOObject.cpp:16
llvm::SmallPtrSetImpl::count
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:383
llvm::objcopy::macho::SymbolEntry
Definition: MachOObject.h:110
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
llvm::MachO::VM_PROT_READ
@ VM_PROT_READ
Definition: MachO.h:489
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::objcopy::macho::Object::DySymTabCommandIndex
Optional< size_t > DySymTabCommandIndex
The index LC_DYSYMTAB load command if present.
Definition: MachOObject.h:330
llvm::objcopy::macho::Object::TextSegmentCommandIndex
Optional< size_t > TextSegmentCommandIndex
The index of the LC_SEGMENT or LC_SEGMENT_64 load command corresponding to the __TEXT segment.
Definition: MachOObject.h:343
MachOObject.h
extractSegmentName
static StringRef extractSegmentName(const char *SegName)
Extracts a segment name from a string which is possibly non-null-terminated.
Definition: MachOObject.cpp:187
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1239
llvm::objcopy::macho::Object::Header
MachHeader Header
Definition: MachOObject.h:303
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::MachO::mach_header
Definition: MachO.h:511
llvm::objcopy::macho::SymbolTable::Symbols
std::vector< std::unique_ptr< SymbolEntry > > Symbols
Definition: MachOObject.h:140
llvm::objcopy::macho::Section
Definition: MachOObject.h:39
llvm::objcopy::macho::Object::ExportsTrieCommandIndex
Optional< size_t > ExportsTrieCommandIndex
The index LC_DYLD_EXPORTS_TRIE load command if present.
Definition: MachOObject.h:340
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:149
llvm::objcopy::macho::Object::is64Bit
bool is64Bit() const
Definition: MachOObject.h:362
llvm::objcopy::macho::Object::CodeSignatureCommandIndex
Optional< size_t > CodeSignatureCommandIndex
The index of LC_CODE_SIGNATURE load command if present.
Definition: MachOObject.h:324
llvm::SmallPtrSetImpl::insert
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:365
llvm::MachO::macho_load_command
Definition: MachO.h:2028