LLVM: lib/Object/MachOUniversalWriter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

30

31using namespace llvm;

32using namespace object;

33

34

35

36

40 const bool Is64Bit = O.is64Bit();

41

42 for (const auto &LC : O.load_commands()) {

43 if (LC.C.cmd != (Is64Bit ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT))

44 continue;

46 unsigned NumberOfSections =

47 (Is64Bit ? O.getSegment64LoadCommand(LC).nsects

48 : O.getSegmentLoadCommand(LC).nsects);

49 P2CurrentAlignment = NumberOfSections ? 2 : P2MinAlignment;

50 for (unsigned SI = 0; SI < NumberOfSections; ++SI) {

51 P2CurrentAlignment = std::max(P2CurrentAlignment,

52 (Is64Bit ? O.getSection64(LC, SI).align

53 : O.getSection(LC, SI).align));

54 }

55 } else {

56 P2CurrentAlignment =

58 : O.getSegmentLoadCommand(LC).vmaddr);

59 }

60 P2MinAlignment = std::min(P2MinAlignment, P2CurrentAlignment);

61 }

62

63 return std::max(

65 std::min(P2MinAlignment, static_cast<uint32_t>(

67}

68

70 switch (ObjectFile.getHeader().cputype) {

75 return 12;

79 return 14;

80 default:

82 }

83}

84

87 : B(&A), CPUType(CPUType), CPUSubType(CPUSubType),

88 ArchName(std::move(ArchName)), P2Alignment(Align) {}

89

91 : B(&O), CPUType(O.getHeader().cputype),

92 CPUSubType(O.getHeader().cpusubtype),

93 ArchName(std::string(O.getArchTriple().getArchName())),

94 P2Alignment(Align) {}

95

98 : B(&IRO), CPUType(CPUType), CPUSubType(CPUSubType),

99 ArchName(std::move(ArchName)), P2Alignment(Align) {}

100

102

104

107 if (!CPU.first) {

108 return CPU.first.takeError();

109 }

110 if (!CPU.second) {

111 return CPU.second.takeError();

112 }

113 return std::make_pair(*CPU.first, *CPU.second);

114}

115

118}

119

121 return std::make_pair(O.getHeader().cputype, O.getHeader().cpusubtype);

122}

123

126 std::unique_ptr MFO = nullptr;

127 std::unique_ptr IRFO = nullptr;

128 std::optional CPU = std::nullopt;

131 if (!ChildOrErr)

134 if (Bin->isMachOUniversalBinary())

136 ("archive member " + Bin->getFileName() +

137 " is a fat file (not allowed in an archive)")

138 .str()

139 .c_str());

140 if (Bin->isMachO()) {

143

144 if (CPU && CPU != ObjectCPU) {

145

146 StringRef PreviousName = MFO ? MFO->getFileName() : IRFO->getFileName();

148 std::errc::invalid_argument,

149 ("archive member " + O->getFileName() + " cputype (" +

150 Twine(ObjectCPU.first) + ") and cpusubtype(" +

151 Twine(ObjectCPU.second) +

152 ") does not match previous archive members cputype (" +

153 Twine(CPU->first) + ") and cpusubtype(" + Twine(CPU->second) +

154 ") (all members must match) " + PreviousName)

155 .str()

156 .c_str());

157 }

158 if (!MFO) {

159 ChildOrErr.get().release();

160 MFO.reset(O);

161 if (!CPU)

162 CPU.emplace(ObjectCPU);

163 }

164 } else if (Bin->isIR()) {

168 if (!ObjectCPU)

170

171 if (CPU && CPU != *ObjectCPU) {

172

174 IRFO ? IRFO->getFileName() : MFO->getFileName();

176 std::errc::invalid_argument,

177 ("archive member " + O->getFileName() + " cputype (" +

178 Twine(ObjectCPU->first) + ") and cpusubtype(" +

179 Twine(ObjectCPU->second) +

180 ") does not match previous archive members cputype (" +

181 Twine(CPU->first) + ") and cpusubtype(" + Twine(CPU->second) +

182 ") (all members must match) " + PreviousName)

183 .str()

184 .c_str());

185 }

186

187 if (!IRFO) {

188 ChildOrErr.get().release();

189 IRFO.reset(O);

190 if (!CPU)

191 CPU.emplace(*ObjectCPU);

192 }

193 } else

195 ("archive member " + Bin->getFileName() +

196 " is neither a MachO file or an LLVM IR file "

197 "(not allowed in an archive)")

198 .str()

199 .c_str());

200 }

201 if (Err)

203 if (!MFO && !IRFO)

205 std::errc::invalid_argument,

206 ("empty archive with no architecture specification: " +

207 A.getFileName() + " (can't determine architecture for it)")

208 .str()

209 .c_str());

210

211 if (MFO) {

212 Slice ArchiveSlice(*(MFO), MFO->is64Bit() ? 3 : 2);

213 ArchiveSlice.B = &A;

214 return ArchiveSlice;

215 }

216

217

219 if (!ArchiveSliceOrErr)

221 auto &ArchiveSlice = ArchiveSliceOrErr.get();

222 ArchiveSlice.B = &A;

223 return std::move(ArchiveSlice);

224}

225

228 if (!CPUOrErr)

230 unsigned CPUType, CPUSubType;

231 std::tie(CPUType, CPUSubType) = CPUOrErr.get();

232

233

234 std::string ArchName(

236 return Slice{IRO, CPUType, CPUSubType, std::move(ArchName), Align};

237}

238

243};

244

246 static const uint64_t OffsetLimit = UINT32_MAX;

249};

251

256};

258

259template

265

266 for (const auto &S : Slices) {

270 std::errc::invalid_argument,

271 ("fat file too large to be created because the offset field in the "

272 "struct " +

275 Twine(Offset) + " for " + S.getBinary()->getFileName() +

276 " for architecture " + S.getArchString() + "exceeds that.")

277 .str()

278 .c_str());

279

280 FatArchTy FatArch = {};

281 FatArch.cputype = S.getCPUType();

282 FatArch.cpusubtype = S.getCPUSubType();

283 FatArch.offset = Offset;

284 FatArch.size = S.getBinary()->getMemoryBufferRef().getBufferSize();

285 FatArch.align = S.getP2Alignment();

286 Offset += FatArch.size;

288 }

289 return FatArchList;

290}

291

292template

297 buildFatArchList(Slices);

298 if (!FatArchListOrErr)

299 return FatArchListOrErr.takeError();

301

304 Out.write(reinterpret_cast<const char *>(&FatHeader),

306

308 for (FatArchTy &FA : FatArchList)

310 Out.write(reinterpret_cast<const char *>(FatArchList.data()),

311 sizeof(FatArchTy) * FatArchList.size());

312

314 for (FatArchTy &FA : FatArchList)

316

319 for (size_t Index = 0, Size = Slices.size(); Index < Size; ++Index) {

320 MemoryBufferRef BufferRef = Slices[Index].getBinary()->getMemoryBufferRef();

321 assert((Offset <= FatArchList[Index].offset) && "Incorrect slice offset");

325 }

326

329}

330

336

337 switch (HeaderType) {

340 return writeUniversalArchsToStreamMachO::fat\_arch\_64(FatHeader, Slices,

341 Out);

342 break;

345 return writeUniversalArchsToStreamMachO::fat\_arch(FatHeader, Slices, Out);

346 break;

347 }

348

350}

351

355 const bool IsExecutable = any_of(Slices, [](Slice S) {

357 });

359 if (IsExecutable)

362 OutputFileName + ".temp-universal-%%%%%%", Mode);

363 if (!Temp)

367 if (Error DiscardError = Temp->discard())

368 return joinErrors(std::move(E), std::move(DiscardError));

369 return E;

370 }

371 return Temp->keep(OutputFileName);

372}

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static uint32_t calculateFileAlignment(const MachOObjectFile &O)

std::pair< uint32_t, uint32_t > MachoCPUTy

static Expected< MachoCPUTy > getMachoCPUFromTriple(Triple TT)

static MachoCPUTy getMachoCPUFromObjectFile(const MachOObjectFile &O)

static Error writeUniversalArchsToStream(MachO::fat_header FatHeader, ArrayRef< Slice > Slices, raw_ostream &Out)

static Expected< SmallVector< FatArchTy, 2 > > buildFatArchList(ArrayRef< Slice > Slices)

static uint32_t calculateAlignment(const MachOObjectFile &ObjectFile)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallVector class.

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

size_t size() const

size - Get the array size.

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.

reference get()

Returns a reference to the stored T value.

This is an important class for using LLVM in a threaded context.

size_t getBufferSize() const

const char * getBufferStart() const

void push_back(const T &Elt)

pointer data()

Return a pointer to the vector's buffer, even if empty().

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.

Triple - Helper class for working with autoconf configuration names.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

StringRef getFileName() const

StringRef getTargetTriple() const

Triple getArchTriple(const char **McpuDefault=nullptr) const

static constexpr uint32_t MaxSectionAlignment

This class is the base class for all object file types.

const Binary * getBinary() const

static Expected< Slice > create(const Archive &A, LLVMContext *LLVMCtx=nullptr)

A raw_ostream that writes to a file descriptor.

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

raw_ostream & write_zeros(unsigned NumZeros)

write_zeros - Insert 'NumZeros' nulls.

raw_ostream & write(unsigned char C)

static Expected< TempFile > create(const Twine &Model, unsigned Mode=all_read|all_write, OpenFlags ExtraFlags=OF_None)

This creates a temporary file with createUniqueFile and schedules it for deletion with sys::RemoveFil...

#define llvm_unreachable(msg)

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

Expected< uint32_t > getCPUSubType(const Triple &T)

void swapStruct(fat_header &mh)

Expected< uint32_t > getCPUType(const Triple &T)

Error writeUniversalBinary(ArrayRef< Slice > Slices, StringRef OutputFileName, FatHeaderType FatHeader=FatHeaderType::FatHeader)

Error writeUniversalBinaryToStream(ArrayRef< Slice > Slices, raw_ostream &Out, FatHeaderType FatHeader=FatHeaderType::FatHeader)

bool can_execute(const Twine &Path)

Can we execute this file?

static const bool IsLittleEndianHost

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.

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

Create formatted StringError object.

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

Error joinErrors(Error E1, Error E2)

Concatenate errors.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

Implement std::hash so that hash_code can be used in STL containers.

static const std::string StructName

static const std::string StructName

static const std::string StructName

static const uint64_t OffsetLimit

static const uint8_t BitCount

This struct is a compact representation of a valid (non-zero power of two) alignment.