MachONormalizedFileToAtoms.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. //===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
  2. //
  3. // The LLVM Linker
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. ///
  10. /// \file Converts from in-memory normalized mach-o to in-memory Atoms.
  11. ///
  12. /// +------------+
  13. /// | normalized |
  14. /// +------------+
  15. /// |
  16. /// |
  17. /// v
  18. /// +-------+
  19. /// | Atoms |
  20. /// +-------+
  21. #include "MachONormalizedFile.h"
  22. #include "MachONormalizedFileBinaryUtils.h"
  23. #include "File.h"
  24. #include "Atoms.h"
  25. #include "ReferenceKinds.h"
  26. #include "lld/Core/Error.h"
  27. #include "lld/Core/LLVM.h"
  28. #include "llvm/Support/MachO.h"
  29. #include "llvm/Support/Format.h"
  30. using namespace llvm::MachO;
  31. using namespace lld::mach_o::normalized;
  32. namespace lld {
  33. namespace mach_o {
  34. namespace { // anonymous
  35. #define ENTRY(seg, sect, type, atomType) \
  36. {seg, sect, type, DefinedAtom::atomType }
  37. struct MachORelocatableSectionToAtomType {
  38. StringRef segmentName;
  39. StringRef sectionName;
  40. SectionType sectionType;
  41. DefinedAtom::ContentType atomType;
  42. };
  43. const MachORelocatableSectionToAtomType sectsToAtomType[] = {
  44. ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
  45. ENTRY("__TEXT", "__text", S_REGULAR, typeResolver),
  46. ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
  47. ENTRY("", "", S_CSTRING_LITERALS, typeCString),
  48. ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
  49. ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
  50. ENTRY("__TEXT", "__const_coal", S_COALESCED, typeConstant),
  51. ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
  52. ENTRY("__TEXT", "__literal4", S_4BYTE_LITERALS, typeLiteral4),
  53. ENTRY("__TEXT", "__literal8", S_8BYTE_LITERALS, typeLiteral8),
  54. ENTRY("__TEXT", "__literal16", S_16BYTE_LITERALS, typeLiteral16),
  55. ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA),
  56. ENTRY("__DATA", "__data", S_REGULAR, typeData),
  57. ENTRY("__DATA", "__datacoal_nt", S_COALESCED, typeData),
  58. ENTRY("__DATA", "__const", S_REGULAR, typeConstData),
  59. ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString),
  60. ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS,
  61. typeInitializerPtr),
  62. ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS,
  63. typeTerminatorPtr),
  64. ENTRY("__DATA", "___got", S_NON_LAZY_SYMBOL_POINTERS,
  65. typeGOT),
  66. ENTRY("__DATA", "___bss", S_ZEROFILL, typeZeroFill),
  67. ENTRY("", "", S_NON_LAZY_SYMBOL_POINTERS,
  68. typeGOT),
  69. ENTRY("__LD", "__compact_unwind", S_REGULAR,
  70. typeCompactUnwindInfo),
  71. ENTRY("", "", S_REGULAR, typeUnknown)
  72. };
  73. #undef ENTRY
  74. /// Figures out ContentType of a mach-o section.
  75. DefinedAtom::ContentType atomTypeFromSection(const Section &section) {
  76. // First look for match of name and type. Empty names in table are wildcards.
  77. for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
  78. p->atomType != DefinedAtom::typeUnknown; ++p) {
  79. if (p->sectionType != section.type)
  80. continue;
  81. if (!p->segmentName.equals(section.segmentName) && !p->segmentName.empty())
  82. continue;
  83. if (!p->sectionName.equals(section.sectionName) && !p->sectionName.empty())
  84. continue;
  85. return p->atomType;
  86. }
  87. // Look for code denoted by section attributes
  88. if (section.attributes & S_ATTR_PURE_INSTRUCTIONS)
  89. return DefinedAtom::typeCode;
  90. return DefinedAtom::typeUnknown;
  91. }
  92. enum AtomizeModel {
  93. atomizeAtSymbols,
  94. atomizeFixedSize,
  95. atomizePointerSize,
  96. atomizeUTF8,
  97. atomizeUTF16,
  98. atomizeCFI,
  99. atomizeCU,
  100. atomizeCFString
  101. };
  102. /// Returns info on how to atomize a section of the specified ContentType.
  103. void sectionParseInfo(DefinedAtom::ContentType atomType,
  104. unsigned int &sizeMultiple,
  105. DefinedAtom::Scope &scope,
  106. DefinedAtom::Merge &merge,
  107. AtomizeModel &atomizeModel) {
  108. struct ParseInfo {
  109. DefinedAtom::ContentType atomType;
  110. unsigned int sizeMultiple;
  111. DefinedAtom::Scope scope;
  112. DefinedAtom::Merge merge;
  113. AtomizeModel atomizeModel;
  114. };
  115. #define ENTRY(type, size, scope, merge, model) \
  116. {DefinedAtom::type, size, DefinedAtom::scope, DefinedAtom::merge, model }
  117. static const ParseInfo parseInfo[] = {
  118. ENTRY(typeCode, 1, scopeGlobal, mergeNo,
  119. atomizeAtSymbols),
  120. ENTRY(typeData, 1, scopeGlobal, mergeNo,
  121. atomizeAtSymbols),
  122. ENTRY(typeConstData, 1, scopeGlobal, mergeNo,
  123. atomizeAtSymbols),
  124. ENTRY(typeZeroFill, 1, scopeGlobal, mergeNo,
  125. atomizeAtSymbols),
  126. ENTRY(typeConstant, 1, scopeGlobal, mergeNo,
  127. atomizeAtSymbols),
  128. ENTRY(typeCString, 1, scopeLinkageUnit, mergeByContent,
  129. atomizeUTF8),
  130. ENTRY(typeUTF16String, 1, scopeLinkageUnit, mergeByContent,
  131. atomizeUTF16),
  132. ENTRY(typeCFI, 1, scopeTranslationUnit, mergeNo,
  133. atomizeCFI),
  134. ENTRY(typeLiteral4, 4, scopeLinkageUnit, mergeByContent,
  135. atomizeFixedSize),
  136. ENTRY(typeLiteral8, 8, scopeLinkageUnit, mergeByContent,
  137. atomizeFixedSize),
  138. ENTRY(typeLiteral16, 16, scopeLinkageUnit, mergeByContent,
  139. atomizeFixedSize),
  140. ENTRY(typeCFString, 4, scopeLinkageUnit, mergeByContent,
  141. atomizeCFString),
  142. ENTRY(typeInitializerPtr, 4, scopeTranslationUnit, mergeNo,
  143. atomizePointerSize),
  144. ENTRY(typeTerminatorPtr, 4, scopeTranslationUnit, mergeNo,
  145. atomizePointerSize),
  146. ENTRY(typeCompactUnwindInfo, 4, scopeTranslationUnit, mergeNo,
  147. atomizeCU),
  148. ENTRY(typeCFI, 4, scopeTranslationUnit, mergeNo,
  149. atomizeFixedSize),
  150. ENTRY(typeGOT, 4, scopeLinkageUnit, mergeByContent,
  151. atomizePointerSize),
  152. ENTRY(typeUnknown, 1, scopeGlobal, mergeNo,
  153. atomizeAtSymbols)
  154. };
  155. #undef ENTRY
  156. const int tableLen = sizeof(parseInfo) / sizeof(ParseInfo);
  157. for (int i=0; i < tableLen; ++i) {
  158. if (parseInfo[i].atomType == atomType) {
  159. sizeMultiple = parseInfo[i].sizeMultiple;
  160. scope = parseInfo[i].scope;
  161. merge = parseInfo[i].merge;
  162. atomizeModel = parseInfo[i].atomizeModel;
  163. return;
  164. }
  165. }
  166. // Unknown type is atomized by symbols.
  167. sizeMultiple = 1;
  168. scope = DefinedAtom::scopeGlobal;
  169. merge = DefinedAtom::mergeNo;
  170. atomizeModel = atomizeAtSymbols;
  171. }
  172. Atom::Scope atomScope(uint8_t scope) {
  173. switch (scope) {
  174. case N_EXT:
  175. return Atom::scopeGlobal;
  176. case N_PEXT:
  177. case N_PEXT | N_EXT:
  178. return Atom::scopeLinkageUnit;
  179. case 0:
  180. return Atom::scopeTranslationUnit;
  181. }
  182. llvm_unreachable("unknown scope value!");
  183. }
  184. void appendSymbolsInSection(const std::vector<Symbol> &inSymbols,
  185. uint32_t sectionIndex,
  186. SmallVector<const Symbol *, 64> &outSyms) {
  187. for (const Symbol &sym : inSymbols) {
  188. // Only look at definition symbols.
  189. if ((sym.type & N_TYPE) != N_SECT)
  190. continue;
  191. if (sym.sect != sectionIndex)
  192. continue;
  193. outSyms.push_back(&sym);
  194. }
  195. }
  196. void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
  197. MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
  198. uint16_t symbolDescFlags, Atom::Scope symbolScope,
  199. uint64_t nextSymbolAddr, bool copyRefs) {
  200. // Mach-O symbol table does have size in it. Instead the size is the
  201. // difference between this and the next symbol.
  202. uint64_t size = nextSymbolAddr - symbolAddr;
  203. uint64_t offset = symbolAddr - section.address;
  204. if (section.type == llvm::MachO::S_ZEROFILL) {
  205. file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size, copyRefs,
  206. &section);
  207. } else {
  208. DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
  209. ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
  210. bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF);
  211. if (atomType == DefinedAtom::typeUnknown) {
  212. // Mach-O needs a segment and section name. Concatentate those two
  213. // with a / seperator (e.g. "seg/sect") to fit into the lld model
  214. // of just a section name.
  215. std::string segSectName = section.segmentName.str()
  216. + "/" + section.sectionName.str();
  217. file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
  218. merge, thumb,offset, size, segSectName,
  219. true, &section);
  220. } else {
  221. if ((atomType == lld::DefinedAtom::typeCode) &&
  222. (symbolDescFlags & N_SYMBOL_RESOLVER)) {
  223. atomType = lld::DefinedAtom::typeResolver;
  224. }
  225. file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
  226. offset, size, thumb, copyRefs, &section);
  227. }
  228. }
  229. }
  230. std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
  231. const Section &section,
  232. const NormalizedFile &normalizedFile,
  233. MachOFile &file, bool copyRefs) {
  234. // Find section's index.
  235. uint32_t sectIndex = 1;
  236. for (auto &sect : normalizedFile.sections) {
  237. if (&sect == &section)
  238. break;
  239. ++sectIndex;
  240. }
  241. // Find all symbols in this section.
  242. SmallVector<const Symbol *, 64> symbols;
  243. appendSymbolsInSection(normalizedFile.globalSymbols, sectIndex, symbols);
  244. appendSymbolsInSection(normalizedFile.localSymbols, sectIndex, symbols);
  245. // Sort symbols.
  246. std::sort(symbols.begin(), symbols.end(),
  247. [](const Symbol *lhs, const Symbol *rhs) -> bool {
  248. if (lhs == rhs)
  249. return false;
  250. // First by address.
  251. uint64_t lhsAddr = lhs->value;
  252. uint64_t rhsAddr = rhs->value;
  253. if (lhsAddr != rhsAddr)
  254. return lhsAddr < rhsAddr;
  255. // If same address, one is an alias so sort by scope.
  256. Atom::Scope lScope = atomScope(lhs->scope);
  257. Atom::Scope rScope = atomScope(rhs->scope);
  258. if (lScope != rScope)
  259. return lScope < rScope;
  260. // If same address and scope, sort by name.
  261. return lhs->name < rhs->name;
  262. });
  263. // Debug logging of symbols.
  264. //for (const Symbol *sym : symbols)
  265. // llvm::errs() << " sym: "
  266. // << llvm::format("0x%08llx ", (uint64_t)sym->value)
  267. // << ", " << sym->name << "\n";
  268. // If section has no symbols and no content, there are no atoms.
  269. if (symbols.empty() && section.content.empty())
  270. return std::error_code();
  271. if (symbols.empty()) {
  272. // Section has no symbols, put all content in one anoymous atom.
  273. atomFromSymbol(atomType, section, file, section.address, StringRef(),
  274. 0, Atom::scopeTranslationUnit,
  275. section.address + section.content.size(), copyRefs);
  276. }
  277. else if (symbols.front()->value != section.address) {
  278. // Section has anonymous content before first symbol.
  279. atomFromSymbol(atomType, section, file, section.address, StringRef(),
  280. 0, Atom::scopeTranslationUnit, symbols.front()->value,
  281. copyRefs);
  282. }
  283. const Symbol *lastSym = nullptr;
  284. for (const Symbol *sym : symbols) {
  285. if (lastSym != nullptr) {
  286. atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
  287. lastSym->desc, atomScope(lastSym->scope), sym->value, copyRefs);
  288. }
  289. lastSym = sym;
  290. }
  291. if (lastSym != nullptr) {
  292. atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
  293. lastSym->desc, atomScope(lastSym->scope),
  294. section.address + section.content.size(), copyRefs);
  295. }
  296. return std::error_code();
  297. }
  298. std::error_code processSection(DefinedAtom::ContentType atomType,
  299. const Section &section,
  300. const NormalizedFile &normalizedFile,
  301. MachOFile &file, bool copyRefs) {
  302. const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
  303. const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
  304. // Get info on how to atomize section.
  305. unsigned int sizeMultiple;
  306. DefinedAtom::Scope scope;
  307. DefinedAtom::Merge merge;
  308. AtomizeModel atomizeModel;
  309. sectionParseInfo(atomType, sizeMultiple, scope, merge, atomizeModel);
  310. // Validate section size.
  311. if ((section.content.size() % sizeMultiple) != 0)
  312. return make_dynamic_error_code(Twine("Section ") + section.segmentName
  313. + "/" + section.sectionName
  314. + " has size ("
  315. + Twine(section.content.size())
  316. + ") which is not a multiple of "
  317. + Twine(sizeMultiple) );
  318. if (atomizeModel == atomizeAtSymbols) {
  319. // Break section up into atoms each with a fixed size.
  320. return processSymboledSection(atomType, section, normalizedFile, file,
  321. copyRefs);
  322. } else {
  323. const uint32_t *cfi;
  324. unsigned int size;
  325. for (unsigned int offset = 0, e = section.content.size(); offset != e;) {
  326. switch (atomizeModel) {
  327. case atomizeFixedSize:
  328. // Break section up into atoms each with a fixed size.
  329. size = sizeMultiple;
  330. break;
  331. case atomizePointerSize:
  332. // Break section up into atoms each the size of a pointer.
  333. size = is64 ? 8 : 4;
  334. break;
  335. case atomizeUTF8:
  336. // Break section up into zero terminated c-strings.
  337. size = 0;
  338. for (unsigned int i = offset; i < e; ++i) {
  339. if (section.content[i] == 0) {
  340. size = i + 1 - offset;
  341. break;
  342. }
  343. }
  344. break;
  345. case atomizeUTF16:
  346. // Break section up into zero terminated UTF16 strings.
  347. size = 0;
  348. for (unsigned int i = offset; i < e; i += 2) {
  349. if ((section.content[i] == 0) && (section.content[i + 1] == 0)) {
  350. size = i + 2 - offset;
  351. break;
  352. }
  353. }
  354. break;
  355. case atomizeCFI:
  356. // Break section up into dwarf unwind CFIs (FDE or CIE).
  357. cfi = reinterpret_cast<const uint32_t *>(&section.content[offset]);
  358. size = read32(swap, *cfi) + 4;
  359. if (offset+size > section.content.size()) {
  360. return make_dynamic_error_code(Twine(Twine("Section ")
  361. + section.segmentName
  362. + "/" + section.sectionName
  363. + " is malformed. Size of CFI "
  364. "starting at offset ("
  365. + Twine(offset)
  366. + ") is past end of section."));
  367. }
  368. break;
  369. case atomizeCU:
  370. // Break section up into compact unwind entries.
  371. size = is64 ? 32 : 20;
  372. break;
  373. case atomizeCFString:
  374. // Break section up into NS/CFString objects.
  375. size = is64 ? 32 : 16;
  376. break;
  377. case atomizeAtSymbols:
  378. break;
  379. }
  380. if (size == 0) {
  381. return make_dynamic_error_code(Twine("Section ") + section.segmentName
  382. + "/" + section.sectionName
  383. + " is malformed. The last atom is "
  384. "not zero terminated.");
  385. }
  386. file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
  387. false, copyRefs, &section);
  388. offset += size;
  389. }
  390. }
  391. return std::error_code();
  392. }
  393. // Walks all relocations for a section in a normalized .o file and
  394. // creates corresponding lld::Reference objects.
  395. std::error_code convertRelocs(const Section &section,
  396. const NormalizedFile &normalizedFile,
  397. MachOFile &file,
  398. KindHandler &handler) {
  399. // Utility function for KindHandler to find atom by its address.
  400. auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
  401. const lld::Atom **atom, Reference::Addend *addend)
  402. -> std::error_code {
  403. if (sectIndex > normalizedFile.sections.size())
  404. return make_dynamic_error_code(Twine("out of range section "
  405. "index (") + Twine(sectIndex) + ")");
  406. const Section *sect = nullptr;
  407. if (sectIndex == 0) {
  408. for (const Section &s : normalizedFile.sections) {
  409. uint64_t sAddr = s.address;
  410. if ((sAddr <= addr) && (addr < sAddr+s.content.size())) {
  411. sect = &s;
  412. break;
  413. }
  414. }
  415. if (!sect) {
  416. return make_dynamic_error_code(Twine("address (" + Twine(addr)
  417. + ") is not in any section"));
  418. }
  419. } else {
  420. sect = &normalizedFile.sections[sectIndex-1];
  421. }
  422. uint32_t offsetInTarget;
  423. uint64_t offsetInSect = addr - sect->address;
  424. *atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
  425. *addend = offsetInTarget;
  426. return std::error_code();
  427. };
  428. // Utility function for KindHandler to find atom by its symbol index.
  429. auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
  430. -> std::error_code {
  431. // Find symbol from index.
  432. const Symbol *sym = nullptr;
  433. uint32_t numLocal = normalizedFile.localSymbols.size();
  434. uint32_t numGlobal = normalizedFile.globalSymbols.size();
  435. uint32_t numUndef = normalizedFile.undefinedSymbols.size();
  436. if (symbolIndex < numLocal) {
  437. sym = &normalizedFile.localSymbols[symbolIndex];
  438. } else if (symbolIndex < numLocal+numGlobal) {
  439. sym = &normalizedFile.globalSymbols[symbolIndex-numLocal];
  440. } else if (symbolIndex < numLocal+numGlobal+numUndef) {
  441. sym = &normalizedFile.undefinedSymbols[symbolIndex-numLocal-numGlobal];
  442. } else {
  443. return make_dynamic_error_code(Twine("symbol index (")
  444. + Twine(symbolIndex) + ") out of range");
  445. }
  446. // Find atom from symbol.
  447. if ((sym->type & N_TYPE) == N_SECT) {
  448. if (sym->sect > normalizedFile.sections.size())
  449. return make_dynamic_error_code(Twine("symbol section index (")
  450. + Twine(sym->sect) + ") out of range ");
  451. const Section &symSection = normalizedFile.sections[sym->sect-1];
  452. uint64_t targetOffsetInSect = sym->value - symSection.address;
  453. MachODefinedAtom *target = file.findAtomCoveringAddress(symSection,
  454. targetOffsetInSect);
  455. if (target) {
  456. *result = target;
  457. return std::error_code();
  458. }
  459. return make_dynamic_error_code(Twine("no atom found for defined symbol"));
  460. } else if ((sym->type & N_TYPE) == N_UNDF) {
  461. const lld::Atom *target = file.findUndefAtom(sym->name);
  462. if (target) {
  463. *result = target;
  464. return std::error_code();
  465. }
  466. return make_dynamic_error_code(Twine("no undefined atom found for sym"));
  467. } else {
  468. // Search undefs
  469. return make_dynamic_error_code(Twine("no atom found for symbol"));
  470. }
  471. };
  472. const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
  473. // Use old-school iterator so that paired relocations can be grouped.
  474. for (auto it=section.relocations.begin(), e=section.relocations.end();
  475. it != e; ++it) {
  476. const Relocation &reloc = *it;
  477. // Find atom this relocation is in.
  478. if (reloc.offset > section.content.size())
  479. return make_dynamic_error_code(Twine("r_address (") + Twine(reloc.offset)
  480. + ") is larger than section size ("
  481. + Twine(section.content.size()) + ")");
  482. uint32_t offsetInAtom;
  483. MachODefinedAtom *inAtom = file.findAtomCoveringAddress(section,
  484. reloc.offset,
  485. &offsetInAtom);
  486. assert(inAtom && "r_address in range, should have found atom");
  487. uint64_t fixupAddress = section.address + reloc.offset;
  488. const lld::Atom *target = nullptr;
  489. Reference::Addend addend = 0;
  490. Reference::KindValue kind;
  491. std::error_code relocErr;
  492. if (handler.isPairedReloc(reloc)) {
  493. // Handle paired relocations together.
  494. relocErr = handler.getPairReferenceInfo(reloc, *++it, inAtom,
  495. offsetInAtom, fixupAddress, swap,
  496. atomByAddr, atomBySymbol, &kind,
  497. &target, &addend);
  498. }
  499. else {
  500. // Use KindHandler to convert relocation record into information
  501. // needed to instantiate an lld::Reference object.
  502. relocErr = handler.getReferenceInfo(reloc, inAtom, offsetInAtom,
  503. fixupAddress,swap, atomByAddr,
  504. atomBySymbol, &kind, &target, &addend);
  505. }
  506. if (relocErr) {
  507. return make_dynamic_error_code(
  508. Twine("bad relocation (") + relocErr.message()
  509. + ") in section "
  510. + section.segmentName + "/" + section.sectionName
  511. + " (r_address=" + Twine::utohexstr(reloc.offset)
  512. + ", r_type=" + Twine(reloc.type)
  513. + ", r_extern=" + Twine(reloc.isExtern)
  514. + ", r_length=" + Twine((int)reloc.length)
  515. + ", r_pcrel=" + Twine(reloc.pcRel)
  516. + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
  517. : (Twine(", r_scattered=1, r_value=")
  518. + Twine(reloc.value)))
  519. + ")" );
  520. } else {
  521. // Instantiate an lld::Reference object and add to its atom.
  522. Reference::KindArch arch = Reference::KindArch::all;
  523. switch (normalizedFile.arch ) {
  524. case lld::MachOLinkingContext::arch_x86_64:
  525. arch = Reference::KindArch::x86_64;
  526. break;
  527. case lld::MachOLinkingContext::arch_x86:
  528. arch = Reference::KindArch::x86;
  529. break;
  530. case lld::MachOLinkingContext::arch_ppc:
  531. arch = Reference::KindArch::PowerPC;
  532. break;
  533. case lld::MachOLinkingContext::arch_armv6:
  534. case lld::MachOLinkingContext::arch_armv7:
  535. case lld::MachOLinkingContext::arch_armv7s:
  536. arch = Reference::KindArch::ARM;
  537. break;
  538. case lld::MachOLinkingContext::arch_unknown:
  539. return make_dynamic_error_code(Twine("unknown architecture"));
  540. }
  541. inAtom->addReference(offsetInAtom, kind, target, addend, arch);
  542. }
  543. }
  544. return std::error_code();
  545. }
  546. bool isDebugInfoSection(const Section &section) {
  547. if ((section.attributes & S_ATTR_DEBUG) == 0)
  548. return false;
  549. return section.segmentName.equals("__DWARF");
  550. }
  551. /// Converts normalized mach-o file into an lld::File and lld::Atoms.
  552. ErrorOr<std::unique_ptr<lld::File>>
  553. normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
  554. bool copyRefs) {
  555. std::unique_ptr<MachOFile> file(new MachOFile(path));
  556. // Create atoms from each section.
  557. for (auto &sect : normalizedFile.sections) {
  558. if (isDebugInfoSection(sect))
  559. continue;
  560. DefinedAtom::ContentType atomType = atomTypeFromSection(sect);
  561. if (std::error_code ec =
  562. processSection(atomType, sect, normalizedFile, *file, copyRefs))
  563. return ec;
  564. }
  565. // Create atoms from undefined symbols.
  566. for (auto &sym : normalizedFile.undefinedSymbols) {
  567. // Undefinded symbols with n_value != 0 are actually tentative definitions.
  568. if (sym.value == Hex64(0)) {
  569. file->addUndefinedAtom(sym.name, copyRefs);
  570. } else {
  571. file->addTentativeDefAtom(sym.name, atomScope(sym.scope), sym.value,
  572. DefinedAtom::Alignment(sym.desc >> 8), copyRefs);
  573. }
  574. }
  575. // Convert mach-o relocations to References
  576. std::unique_ptr<mach_o::KindHandler> handler
  577. = KindHandler::create(normalizedFile.arch);
  578. for (auto &sect : normalizedFile.sections) {
  579. if (isDebugInfoSection(sect))
  580. continue;
  581. if (std::error_code ec = convertRelocs(sect, normalizedFile, *file, *handler))
  582. return ec;
  583. }
  584. // Sort references in each atom to their canonical order.
  585. for (const DefinedAtom* defAtom : file->defined()) {
  586. reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
  587. }
  588. return std::unique_ptr<File>(std::move(file));
  589. }
  590. ErrorOr<std::unique_ptr<lld::File>>
  591. normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
  592. bool copyRefs) {
  593. std::unique_ptr<MachODylibFile> file(
  594. new MachODylibFile(normalizedFile.installName));
  595. for (auto &sym : normalizedFile.globalSymbols) {
  596. assert((sym.scope & N_EXT) && "only expect external symbols here");
  597. file->addSharedLibraryAtom(sym.name, copyRefs);
  598. }
  599. return std::unique_ptr<File>(std::move(file));
  600. }
  601. } // anonymous namespace
  602. namespace normalized {
  603. void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
  604. StringRef &segmentName,
  605. StringRef &sectionName,
  606. SectionType &sectionType,
  607. SectionAttr &sectionAttrs) {
  608. for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
  609. p->atomType != DefinedAtom::typeUnknown; ++p) {
  610. if (p->atomType != atomType)
  611. continue;
  612. // Wild carded entries are ignored for reverse lookups.
  613. if (p->segmentName.empty() || p->sectionName.empty())
  614. continue;
  615. segmentName = p->segmentName;
  616. sectionName = p->sectionName;
  617. sectionType = p->sectionType;
  618. sectionAttrs = 0;
  619. if (atomType == DefinedAtom::typeCode)
  620. sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
  621. return;
  622. }
  623. llvm_unreachable("content type not yet supported");
  624. }
  625. ErrorOr<std::unique_ptr<lld::File>>
  626. normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
  627. bool copyRefs) {
  628. switch (normalizedFile.fileType) {
  629. case MH_DYLIB:
  630. return normalizedDylibToAtoms(normalizedFile, path, copyRefs);
  631. case MH_OBJECT:
  632. return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
  633. default:
  634. llvm_unreachable("unhandled MachO file type!");
  635. }
  636. }
  637. } // namespace normalized
  638. } // namespace mach_o
  639. } // namespace lld