MachOObjectFile.cpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the MachOObjectFile class, which binds the MachOObject
  11. // class to the generic ObjectFile wrapper.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/ADT/Triple.h"
  15. #include "llvm/Object/MachO.h"
  16. #include "llvm/Object/MachOFormat.h"
  17. #include "llvm/Support/MemoryBuffer.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. #include <cctype>
  20. #include <cstring>
  21. #include <limits>
  22. using namespace llvm;
  23. using namespace object;
  24. namespace llvm {
  25. namespace object {
  26. MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
  27. error_code &ec)
  28. : ObjectFile(Binary::isMachO, Object, ec),
  29. MachOObj(MOO),
  30. RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
  31. DataRefImpl DRI;
  32. DRI.d.a = DRI.d.b = 0;
  33. moveToNextSection(DRI);
  34. uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
  35. while (DRI.d.a < LoadCommandCount) {
  36. Sections.push_back(DRI);
  37. DRI.d.b++;
  38. moveToNextSection(DRI);
  39. }
  40. }
  41. ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
  42. error_code ec;
  43. std::string Err;
  44. MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err);
  45. if (!MachOObj)
  46. return NULL;
  47. return new MachOObjectFile(Buffer, MachOObj, ec);
  48. }
  49. /*===-- Symbols -----------------------------------------------------------===*/
  50. void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const {
  51. uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
  52. while (DRI.d.a < LoadCommandCount) {
  53. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  54. if (LCI.Command.Type == macho::LCT_Symtab) {
  55. InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
  56. MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
  57. if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries)
  58. return;
  59. }
  60. DRI.d.a++;
  61. DRI.d.b = 0;
  62. }
  63. }
  64. void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI,
  65. InMemoryStruct<macho::SymbolTableEntry> &Res) const {
  66. InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
  67. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  68. MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
  69. if (RegisteredStringTable != DRI.d.a) {
  70. MachOObj->RegisterStringTable(*SymtabLoadCmd);
  71. RegisteredStringTable = DRI.d.a;
  72. }
  73. MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
  74. Res);
  75. }
  76. void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI,
  77. InMemoryStruct<macho::Symbol64TableEntry> &Res) const {
  78. InMemoryStruct<macho::SymtabLoadCommand> SymtabLoadCmd;
  79. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  80. MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd);
  81. if (RegisteredStringTable != DRI.d.a) {
  82. MachOObj->RegisterStringTable(*SymtabLoadCmd);
  83. RegisteredStringTable = DRI.d.a;
  84. }
  85. MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b,
  86. Res);
  87. }
  88. error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI,
  89. SymbolRef &Result) const {
  90. DRI.d.b++;
  91. moveToNextSymbol(DRI);
  92. Result = SymbolRef(DRI, this);
  93. return object_error::success;
  94. }
  95. error_code MachOObjectFile::getSymbolName(DataRefImpl DRI,
  96. StringRef &Result) const {
  97. if (MachOObj->is64Bit()) {
  98. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  99. getSymbol64TableEntry(DRI, Entry);
  100. Result = MachOObj->getStringAtIndex(Entry->StringIndex);
  101. } else {
  102. InMemoryStruct<macho::SymbolTableEntry> Entry;
  103. getSymbolTableEntry(DRI, Entry);
  104. Result = MachOObj->getStringAtIndex(Entry->StringIndex);
  105. }
  106. return object_error::success;
  107. }
  108. error_code MachOObjectFile::getSymbolOffset(DataRefImpl DRI,
  109. uint64_t &Result) const {
  110. uint64_t SectionOffset;
  111. uint8_t SectionIndex;
  112. if (MachOObj->is64Bit()) {
  113. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  114. getSymbol64TableEntry(DRI, Entry);
  115. Result = Entry->Value;
  116. SectionIndex = Entry->SectionIndex;
  117. } else {
  118. InMemoryStruct<macho::SymbolTableEntry> Entry;
  119. getSymbolTableEntry(DRI, Entry);
  120. Result = Entry->Value;
  121. SectionIndex = Entry->SectionIndex;
  122. }
  123. getSectionAddress(Sections[SectionIndex-1], SectionOffset);
  124. Result -= SectionOffset;
  125. return object_error::success;
  126. }
  127. error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI,
  128. uint64_t &Result) const {
  129. if (MachOObj->is64Bit()) {
  130. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  131. getSymbol64TableEntry(DRI, Entry);
  132. Result = Entry->Value;
  133. } else {
  134. InMemoryStruct<macho::SymbolTableEntry> Entry;
  135. getSymbolTableEntry(DRI, Entry);
  136. Result = Entry->Value;
  137. }
  138. return object_error::success;
  139. }
  140. error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,
  141. uint64_t &Result) const {
  142. Result = UnknownAddressOrSize;
  143. return object_error::success;
  144. }
  145. error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI,
  146. char &Result) const {
  147. uint8_t Type, Flags;
  148. if (MachOObj->is64Bit()) {
  149. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  150. getSymbol64TableEntry(DRI, Entry);
  151. Type = Entry->Type;
  152. Flags = Entry->Flags;
  153. } else {
  154. InMemoryStruct<macho::SymbolTableEntry> Entry;
  155. getSymbolTableEntry(DRI, Entry);
  156. Type = Entry->Type;
  157. Flags = Entry->Flags;
  158. }
  159. char Char;
  160. switch (Type & macho::STF_TypeMask) {
  161. case macho::STT_Undefined:
  162. Char = 'u';
  163. break;
  164. case macho::STT_Absolute:
  165. case macho::STT_Section:
  166. Char = 's';
  167. break;
  168. default:
  169. Char = '?';
  170. break;
  171. }
  172. if (Flags & (macho::STF_External | macho::STF_PrivateExtern))
  173. Char = toupper(Char);
  174. Result = Char;
  175. return object_error::success;
  176. }
  177. error_code MachOObjectFile::isSymbolInternal(DataRefImpl DRI,
  178. bool &Result) const {
  179. if (MachOObj->is64Bit()) {
  180. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  181. getSymbol64TableEntry(DRI, Entry);
  182. Result = Entry->Flags & macho::STF_StabsEntryMask;
  183. } else {
  184. InMemoryStruct<macho::SymbolTableEntry> Entry;
  185. getSymbolTableEntry(DRI, Entry);
  186. Result = Entry->Flags & macho::STF_StabsEntryMask;
  187. }
  188. return object_error::success;
  189. }
  190. error_code MachOObjectFile::isSymbolGlobal(DataRefImpl Symb, bool &Res) const {
  191. if (MachOObj->is64Bit()) {
  192. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  193. getSymbol64TableEntry(Symb, Entry);
  194. Res = Entry->Type & MachO::NlistMaskExternal;
  195. } else {
  196. InMemoryStruct<macho::SymbolTableEntry> Entry;
  197. getSymbolTableEntry(Symb, Entry);
  198. Res = Entry->Type & MachO::NlistMaskExternal;
  199. }
  200. return object_error::success;
  201. }
  202. error_code MachOObjectFile::isSymbolWeak(DataRefImpl Symb, bool &Res) const {
  203. if (MachOObj->is64Bit()) {
  204. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  205. getSymbol64TableEntry(Symb, Entry);
  206. Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
  207. } else {
  208. InMemoryStruct<macho::SymbolTableEntry> Entry;
  209. getSymbolTableEntry(Symb, Entry);
  210. Res = Entry->Flags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef);
  211. }
  212. return object_error::success;
  213. }
  214. error_code MachOObjectFile::isSymbolAbsolute(DataRefImpl Symb, bool &Res) const{
  215. uint8_t n_type;
  216. if (MachOObj->is64Bit()) {
  217. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  218. getSymbol64TableEntry(Symb, Entry);
  219. n_type = Entry->Type;
  220. } else {
  221. InMemoryStruct<macho::SymbolTableEntry> Entry;
  222. getSymbolTableEntry(Symb, Entry);
  223. n_type = Entry->Type;
  224. }
  225. Res = (n_type & MachO::NlistMaskType) == MachO::NListTypeAbsolute;
  226. return object_error::success;
  227. }
  228. error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb,
  229. section_iterator &Res) const {
  230. uint8_t index;
  231. if (MachOObj->is64Bit()) {
  232. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  233. getSymbol64TableEntry(Symb, Entry);
  234. index = Entry->SectionIndex;
  235. } else {
  236. InMemoryStruct<macho::SymbolTableEntry> Entry;
  237. getSymbolTableEntry(Symb, Entry);
  238. index = Entry->SectionIndex;
  239. }
  240. if (index == 0)
  241. Res = end_sections();
  242. else
  243. Res = section_iterator(SectionRef(Sections[index], this));
  244. return object_error::success;
  245. }
  246. error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,
  247. SymbolRef::Type &Res) const {
  248. uint8_t n_type;
  249. if (MachOObj->is64Bit()) {
  250. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  251. getSymbol64TableEntry(Symb, Entry);
  252. n_type = Entry->Type;
  253. } else {
  254. InMemoryStruct<macho::SymbolTableEntry> Entry;
  255. getSymbolTableEntry(Symb, Entry);
  256. n_type = Entry->Type;
  257. }
  258. Res = SymbolRef::ST_Other;
  259. // If this is a STAB debugging symbol, we can do nothing more.
  260. if (n_type & MachO::NlistMaskStab) {
  261. Res = SymbolRef::ST_Debug;
  262. return object_error::success;
  263. }
  264. switch (n_type & MachO::NlistMaskType) {
  265. case MachO::NListTypeUndefined :
  266. Res = SymbolRef::ST_External;
  267. break;
  268. case MachO::NListTypeSection :
  269. Res = SymbolRef::ST_Function;
  270. break;
  271. }
  272. return object_error::success;
  273. }
  274. symbol_iterator MachOObjectFile::begin_symbols() const {
  275. // DRI.d.a = segment number; DRI.d.b = symbol index.
  276. DataRefImpl DRI;
  277. DRI.d.a = DRI.d.b = 0;
  278. moveToNextSymbol(DRI);
  279. return symbol_iterator(SymbolRef(DRI, this));
  280. }
  281. symbol_iterator MachOObjectFile::end_symbols() const {
  282. DataRefImpl DRI;
  283. DRI.d.a = MachOObj->getHeader().NumLoadCommands;
  284. DRI.d.b = 0;
  285. return symbol_iterator(SymbolRef(DRI, this));
  286. }
  287. /*===-- Sections ----------------------------------------------------------===*/
  288. void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const {
  289. uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
  290. while (DRI.d.a < LoadCommandCount) {
  291. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  292. if (LCI.Command.Type == macho::LCT_Segment) {
  293. InMemoryStruct<macho::SegmentLoadCommand> SegmentLoadCmd;
  294. MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd);
  295. if (DRI.d.b < SegmentLoadCmd->NumSections)
  296. return;
  297. } else if (LCI.Command.Type == macho::LCT_Segment64) {
  298. InMemoryStruct<macho::Segment64LoadCommand> Segment64LoadCmd;
  299. MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd);
  300. if (DRI.d.b < Segment64LoadCmd->NumSections)
  301. return;
  302. }
  303. DRI.d.a++;
  304. DRI.d.b = 0;
  305. }
  306. }
  307. error_code MachOObjectFile::getSectionNext(DataRefImpl DRI,
  308. SectionRef &Result) const {
  309. DRI.d.b++;
  310. moveToNextSection(DRI);
  311. Result = SectionRef(DRI, this);
  312. return object_error::success;
  313. }
  314. void
  315. MachOObjectFile::getSection(DataRefImpl DRI,
  316. InMemoryStruct<macho::Section> &Res) const {
  317. InMemoryStruct<macho::SegmentLoadCommand> SLC;
  318. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  319. MachOObj->ReadSegmentLoadCommand(LCI, SLC);
  320. MachOObj->ReadSection(LCI, DRI.d.b, Res);
  321. }
  322. std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
  323. SectionList::const_iterator loc =
  324. std::find(Sections.begin(), Sections.end(), Sec);
  325. assert(loc != Sections.end() && "Sec is not a valid section!");
  326. return std::distance(Sections.begin(), loc);
  327. }
  328. void
  329. MachOObjectFile::getSection64(DataRefImpl DRI,
  330. InMemoryStruct<macho::Section64> &Res) const {
  331. InMemoryStruct<macho::Segment64LoadCommand> SLC;
  332. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  333. MachOObj->ReadSegment64LoadCommand(LCI, SLC);
  334. MachOObj->ReadSection64(LCI, DRI.d.b, Res);
  335. }
  336. static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) {
  337. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  338. if (LCI.Command.Type == macho::LCT_Segment64)
  339. return true;
  340. assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type.");
  341. return false;
  342. }
  343. error_code MachOObjectFile::getSectionName(DataRefImpl DRI,
  344. StringRef &Result) const {
  345. // FIXME: thread safety.
  346. static char result[34];
  347. if (is64BitLoadCommand(MachOObj, DRI)) {
  348. InMemoryStruct<macho::Segment64LoadCommand> SLC;
  349. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  350. MachOObj->ReadSegment64LoadCommand(LCI, SLC);
  351. InMemoryStruct<macho::Section64> Sect;
  352. MachOObj->ReadSection64(LCI, DRI.d.b, Sect);
  353. strcpy(result, Sect->SegmentName);
  354. strcat(result, ",");
  355. strcat(result, Sect->Name);
  356. } else {
  357. InMemoryStruct<macho::SegmentLoadCommand> SLC;
  358. LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a);
  359. MachOObj->ReadSegmentLoadCommand(LCI, SLC);
  360. InMemoryStruct<macho::Section> Sect;
  361. MachOObj->ReadSection(LCI, DRI.d.b, Sect);
  362. strcpy(result, Sect->SegmentName);
  363. strcat(result, ",");
  364. strcat(result, Sect->Name);
  365. }
  366. Result = StringRef(result);
  367. return object_error::success;
  368. }
  369. error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI,
  370. uint64_t &Result) const {
  371. if (is64BitLoadCommand(MachOObj, DRI)) {
  372. InMemoryStruct<macho::Section64> Sect;
  373. getSection64(DRI, Sect);
  374. Result = Sect->Address;
  375. } else {
  376. InMemoryStruct<macho::Section> Sect;
  377. getSection(DRI, Sect);
  378. Result = Sect->Address;
  379. }
  380. return object_error::success;
  381. }
  382. error_code MachOObjectFile::getSectionSize(DataRefImpl DRI,
  383. uint64_t &Result) const {
  384. if (is64BitLoadCommand(MachOObj, DRI)) {
  385. InMemoryStruct<macho::Section64> Sect;
  386. getSection64(DRI, Sect);
  387. Result = Sect->Size;
  388. } else {
  389. InMemoryStruct<macho::Section> Sect;
  390. getSection(DRI, Sect);
  391. Result = Sect->Size;
  392. }
  393. return object_error::success;
  394. }
  395. error_code MachOObjectFile::getSectionContents(DataRefImpl DRI,
  396. StringRef &Result) const {
  397. if (is64BitLoadCommand(MachOObj, DRI)) {
  398. InMemoryStruct<macho::Section64> Sect;
  399. getSection64(DRI, Sect);
  400. Result = MachOObj->getData(Sect->Offset, Sect->Size);
  401. } else {
  402. InMemoryStruct<macho::Section> Sect;
  403. getSection(DRI, Sect);
  404. Result = MachOObj->getData(Sect->Offset, Sect->Size);
  405. }
  406. return object_error::success;
  407. }
  408. error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI,
  409. uint64_t &Result) const {
  410. if (is64BitLoadCommand(MachOObj, DRI)) {
  411. InMemoryStruct<macho::Section64> Sect;
  412. getSection64(DRI, Sect);
  413. Result = uint64_t(1) << Sect->Align;
  414. } else {
  415. InMemoryStruct<macho::Section> Sect;
  416. getSection(DRI, Sect);
  417. Result = uint64_t(1) << Sect->Align;
  418. }
  419. return object_error::success;
  420. }
  421. error_code MachOObjectFile::isSectionText(DataRefImpl DRI,
  422. bool &Result) const {
  423. if (is64BitLoadCommand(MachOObj, DRI)) {
  424. InMemoryStruct<macho::Section64> Sect;
  425. getSection64(DRI, Sect);
  426. Result = !strcmp(Sect->Name, "__text");
  427. } else {
  428. InMemoryStruct<macho::Section> Sect;
  429. getSection(DRI, Sect);
  430. Result = !strcmp(Sect->Name, "__text");
  431. }
  432. return object_error::success;
  433. }
  434. error_code MachOObjectFile::isSectionData(DataRefImpl DRI,
  435. bool &Result) const {
  436. // FIXME: Unimplemented.
  437. Result = false;
  438. return object_error::success;
  439. }
  440. error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI,
  441. bool &Result) const {
  442. // FIXME: Unimplemented.
  443. Result = false;
  444. return object_error::success;
  445. }
  446. error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec,
  447. DataRefImpl Symb,
  448. bool &Result) const {
  449. SymbolRef::Type ST;
  450. getSymbolType(Symb, ST);
  451. if (ST == SymbolRef::ST_External) {
  452. Result = false;
  453. return object_error::success;
  454. }
  455. uint64_t SectBegin, SectEnd;
  456. getSectionAddress(Sec, SectBegin);
  457. getSectionSize(Sec, SectEnd);
  458. SectEnd += SectBegin;
  459. if (MachOObj->is64Bit()) {
  460. InMemoryStruct<macho::Symbol64TableEntry> Entry;
  461. getSymbol64TableEntry(Symb, Entry);
  462. uint64_t SymAddr= Entry->Value;
  463. Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
  464. } else {
  465. InMemoryStruct<macho::SymbolTableEntry> Entry;
  466. getSymbolTableEntry(Symb, Entry);
  467. uint64_t SymAddr= Entry->Value;
  468. Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd);
  469. }
  470. return object_error::success;
  471. }
  472. relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
  473. DataRefImpl ret;
  474. ret.d.a = 0;
  475. ret.d.b = getSectionIndex(Sec);
  476. return relocation_iterator(RelocationRef(ret, this));
  477. }
  478. relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
  479. uint32_t last_reloc;
  480. if (is64BitLoadCommand(MachOObj, Sec)) {
  481. InMemoryStruct<macho::Section64> Sect;
  482. getSection64(Sec, Sect);
  483. last_reloc = Sect->NumRelocationTableEntries;
  484. } else {
  485. InMemoryStruct<macho::Section> Sect;
  486. getSection(Sec, Sect);
  487. last_reloc = Sect->NumRelocationTableEntries;
  488. }
  489. DataRefImpl ret;
  490. ret.d.a = last_reloc;
  491. ret.d.b = getSectionIndex(Sec);
  492. return relocation_iterator(RelocationRef(ret, this));
  493. }
  494. section_iterator MachOObjectFile::begin_sections() const {
  495. DataRefImpl DRI;
  496. DRI.d.a = DRI.d.b = 0;
  497. moveToNextSection(DRI);
  498. return section_iterator(SectionRef(DRI, this));
  499. }
  500. section_iterator MachOObjectFile::end_sections() const {
  501. DataRefImpl DRI;
  502. DRI.d.a = MachOObj->getHeader().NumLoadCommands;
  503. DRI.d.b = 0;
  504. return section_iterator(SectionRef(DRI, this));
  505. }
  506. /*===-- Relocations -------------------------------------------------------===*/
  507. void MachOObjectFile::
  508. getRelocation(DataRefImpl Rel,
  509. InMemoryStruct<macho::RelocationEntry> &Res) const {
  510. uint32_t relOffset;
  511. if (MachOObj->is64Bit()) {
  512. InMemoryStruct<macho::Section64> Sect;
  513. getSection64(Sections[Rel.d.b], Sect);
  514. relOffset = Sect->RelocationTableOffset;
  515. } else {
  516. InMemoryStruct<macho::Section> Sect;
  517. getSection(Sections[Rel.d.b], Sect);
  518. relOffset = Sect->RelocationTableOffset;
  519. }
  520. MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
  521. }
  522. error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
  523. RelocationRef &Res) const {
  524. ++Rel.d.a;
  525. Res = RelocationRef(Rel, this);
  526. return object_error::success;
  527. }
  528. error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
  529. uint64_t &Res) const {
  530. const uint8_t* sectAddress = 0;
  531. if (MachOObj->is64Bit()) {
  532. InMemoryStruct<macho::Section64> Sect;
  533. getSection64(Sections[Rel.d.b], Sect);
  534. sectAddress += Sect->Address;
  535. } else {
  536. InMemoryStruct<macho::Section> Sect;
  537. getSection(Sections[Rel.d.b], Sect);
  538. sectAddress += Sect->Address;
  539. }
  540. InMemoryStruct<macho::RelocationEntry> RE;
  541. getRelocation(Rel, RE);
  542. Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
  543. return object_error::success;
  544. }
  545. error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
  546. SymbolRef &Res) const {
  547. InMemoryStruct<macho::RelocationEntry> RE;
  548. getRelocation(Rel, RE);
  549. uint32_t SymbolIdx = RE->Word1 & 0xffffff;
  550. bool isExtern = (RE->Word1 >> 27) & 1;
  551. DataRefImpl Sym;
  552. Sym.d.a = Sym.d.b = 0;
  553. moveToNextSymbol(Sym);
  554. if (isExtern) {
  555. for (unsigned i = 0; i < SymbolIdx; i++) {
  556. Sym.d.b++;
  557. moveToNextSymbol(Sym);
  558. assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands &&
  559. "Relocation symbol index out of range!");
  560. }
  561. }
  562. Res = SymbolRef(Sym, this);
  563. return object_error::success;
  564. }
  565. error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
  566. uint32_t &Res) const {
  567. InMemoryStruct<macho::RelocationEntry> RE;
  568. getRelocation(Rel, RE);
  569. Res = RE->Word1;
  570. return object_error::success;
  571. }
  572. error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,
  573. SmallVectorImpl<char> &Result) const {
  574. // TODO: Support scattered relocations.
  575. StringRef res;
  576. InMemoryStruct<macho::RelocationEntry> RE;
  577. getRelocation(Rel, RE);
  578. unsigned r_type = (RE->Word1 >> 28) & 0xF;
  579. unsigned Arch = getArch();
  580. switch (Arch) {
  581. case Triple::x86: {
  582. const char* Table[] = {
  583. "GENERIC_RELOC_VANILLA",
  584. "GENERIC_RELOC_PAIR",
  585. "GENERIC_RELOC_SECTDIFF",
  586. "GENERIC_RELOC_LOCAL_SECTDIFF",
  587. "GENERIC_RELOC_PB_LA_PTR" };
  588. if (r_type > 4)
  589. res = "Unknown";
  590. else
  591. res = Table[r_type];
  592. break;
  593. }
  594. case Triple::x86_64: {
  595. const char* Table[] = {
  596. "X86_64_RELOC_UNSIGNED",
  597. "X86_64_RELOC_SIGNED",
  598. "X86_64_RELOC_BRANCH",
  599. "X86_64_RELOC_GOT_LOAD",
  600. "X86_64_RELOC_GOT",
  601. "X86_64_RELOC_SUBTRACTOR",
  602. "X86_64_RELOC_SIGNED_1",
  603. "X86_64_RELOC_SIGNED_2",
  604. "X86_64_RELOC_SIGNED_4",
  605. "X86_64_RELOC_TLV" };
  606. if (r_type > 9)
  607. res = "Unknown";
  608. else
  609. res = Table[r_type];
  610. break;
  611. }
  612. case Triple::arm: {
  613. const char* Table[] = {
  614. "ARM_RELOC_VANILLA",
  615. "ARM_RELOC_PAIR",
  616. "ARM_RELOC_SECTDIFF",
  617. "ARM_RELOC_LOCAL_SECTDIFF",
  618. "ARM_RELOC_PB_LA_PTR",
  619. "ARM_RELOC_BR24",
  620. "ARM_THUMB_RELOC_BR22",
  621. "ARM_THUMB_32BIT_BRANCH",
  622. "ARM_RELOC_HALF",
  623. "ARM_RELOC_HALF_SECTDIFF" };
  624. if (r_type > 9)
  625. res = "Unknown";
  626. else
  627. res = Table[r_type];
  628. break;
  629. }
  630. case Triple::ppc: {
  631. const char* Table[] = {
  632. "PPC_RELOC_VANILLA",
  633. "PPC_RELOC_PAIR",
  634. "PPC_RELOC_BR14",
  635. "PPC_RELOC_BR24",
  636. "PPC_RELOC_HI16",
  637. "PPC_RELOC_LO16",
  638. "PPC_RELOC_HA16",
  639. "PPC_RELOC_LO14",
  640. "PPC_RELOC_SECTDIFF",
  641. "PPC_RELOC_PB_LA_PTR",
  642. "PPC_RELOC_HI16_SECTDIFF",
  643. "PPC_RELOC_LO16_SECTDIFF",
  644. "PPC_RELOC_HA16_SECTDIFF",
  645. "PPC_RELOC_JBSR",
  646. "PPC_RELOC_LO14_SECTDIFF",
  647. "PPC_RELOC_LOCAL_SECTDIFF" };
  648. res = Table[r_type];
  649. break;
  650. }
  651. case Triple::UnknownArch:
  652. res = "Unknown";
  653. break;
  654. }
  655. Result.append(res.begin(), res.end());
  656. return object_error::success;
  657. }
  658. error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
  659. int64_t &Res) const {
  660. InMemoryStruct<macho::RelocationEntry> RE;
  661. getRelocation(Rel, RE);
  662. bool isExtern = (RE->Word1 >> 27) & 1;
  663. Res = 0;
  664. if (!isExtern) {
  665. const uint8_t* sectAddress = base();
  666. if (MachOObj->is64Bit()) {
  667. InMemoryStruct<macho::Section64> Sect;
  668. getSection64(Sections[Rel.d.b], Sect);
  669. sectAddress += Sect->Offset;
  670. } else {
  671. InMemoryStruct<macho::Section> Sect;
  672. getSection(Sections[Rel.d.b], Sect);
  673. sectAddress += Sect->Offset;
  674. }
  675. Res = reinterpret_cast<uintptr_t>(sectAddress);
  676. }
  677. return object_error::success;
  678. }
  679. // Helper to advance a section or symbol iterator multiple increments at a time.
  680. template<class T>
  681. error_code advance(T &it, size_t Val) {
  682. error_code ec;
  683. while (Val--) {
  684. it.increment(ec);
  685. }
  686. return ec;
  687. }
  688. template<class T>
  689. void advanceTo(T &it, size_t Val) {
  690. if (error_code ec = advance(it, Val))
  691. report_fatal_error(ec.message());
  692. }
  693. error_code
  694. MachOObjectFile::getRelocationTargetName(uint32_t Idx, StringRef &S) const {
  695. bool isExtern = (Idx >> 27) & 1;
  696. uint32_t Val = Idx & 0xFFFFFF;
  697. error_code ec;
  698. if (isExtern) {
  699. symbol_iterator SI = begin_symbols();
  700. advanceTo(SI, Val);
  701. ec = SI->getName(S);
  702. } else {
  703. section_iterator SI = begin_sections();
  704. advanceTo(SI, Val);
  705. ec = SI->getName(S);
  706. }
  707. return ec;
  708. }
  709. error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel,
  710. SmallVectorImpl<char> &Result) const {
  711. InMemoryStruct<macho::RelocationEntry> RE;
  712. getRelocation(Rel, RE);
  713. bool isPCRel = (RE->Word1 >> 25) & 1;
  714. unsigned Type = (RE->Word1 >> 28) & 0xF;
  715. std::string fmtbuf;
  716. raw_string_ostream fmt(fmtbuf);
  717. // Determine any addends that should be displayed with the relocation.
  718. // These require decoding the relocation type, which is triple-specific.
  719. unsigned Arch = getArch();
  720. // X86_64 has entirely custom relocation types.
  721. if (Arch == Triple::x86_64) {
  722. StringRef Name;
  723. if (error_code ec = getRelocationTargetName(RE->Word1, Name))
  724. report_fatal_error(ec.message());
  725. switch (Type) {
  726. case 5: { // X86_64_RELOC_SUBTRACTOR
  727. InMemoryStruct<macho::RelocationEntry> RENext;
  728. DataRefImpl RelNext = Rel;
  729. RelNext.d.a++;
  730. getRelocation(RelNext, RENext);
  731. // X86_64_SUBTRACTOR must be followed by a relocation of type
  732. // X86_64_RELOC_UNSIGNED.
  733. unsigned RType = (RENext->Word1 >> 28) & 0xF;
  734. if (RType != 0)
  735. report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
  736. "X86_64_RELOC_SUBTRACTOR.");
  737. StringRef SucName;
  738. if (error_code ec = getRelocationTargetName(RENext->Word1, SucName))
  739. report_fatal_error(ec.message());
  740. fmt << Name << "-" << SucName;
  741. if (isPCRel) fmt << "-PC";
  742. }
  743. case 6: // X86_64_RELOC_SIGNED1
  744. fmt << Name << "-1";
  745. break;
  746. case 7: // X86_64_RELOC_SIGNED2
  747. fmt << Name << "-2";
  748. break;
  749. case 8: // X86_64_RELOC_SIGNED4
  750. fmt << Name << "-4";
  751. break;
  752. default:
  753. fmt << Name;
  754. break;
  755. }
  756. // X86 and ARM share some relocation types in common.
  757. } else if (Arch == Triple::x86 || Arch == Triple::arm) {
  758. // Generic relocation types...
  759. switch (Type) {
  760. case 1: // GENERIC_RELOC_PAIR - prints no info
  761. return object_error::success;
  762. case 2: // GENERIC_RELOC_SECTDIFF
  763. case 4: { // GENERIC_RELOC_LOCAL_SECTDIFF
  764. InMemoryStruct<macho::RelocationEntry> RENext;
  765. DataRefImpl RelNext = Rel;
  766. RelNext.d.a++;
  767. getRelocation(RelNext, RENext);
  768. // X86 sect diff's must be followed by a relocation of type
  769. // GENERIC_RELOC_PAIR.
  770. unsigned RType = (RENext->Word1 >> 28) & 0xF;
  771. if (RType != 1)
  772. report_fatal_error("Expected GENERIC_RELOC_PAIR after "
  773. "GENERIC_RELOC_SECTDIFF or "
  774. "GENERIC_RELOC_LOCAL_SECTDIFF.");
  775. StringRef SucName;
  776. if (error_code ec = getRelocationTargetName(RENext->Word1, SucName))
  777. report_fatal_error(ec.message());
  778. StringRef Name;
  779. if (error_code ec = getRelocationTargetName(RE->Word1, Name))
  780. report_fatal_error(ec.message());
  781. fmt << Name << "-" << SucName;
  782. break;
  783. }
  784. }
  785. if (Arch == Triple::x86 && Type != 1) {
  786. // All X86 relocations that need special printing were already
  787. // handled in the generic code.
  788. StringRef Name;
  789. if (error_code ec = getRelocationTargetName(RE->Word1, Name))
  790. report_fatal_error(ec.message());
  791. fmt << Name;
  792. } else { // ARM-specific relocations
  793. switch (Type) {
  794. case 8: // ARM_RELOC_HALF
  795. case 9: { // ARM_RELOC_HALF_SECTDIFF
  796. StringRef Name;
  797. if (error_code ec = getRelocationTargetName(RE->Word1, Name))
  798. report_fatal_error(ec.message());
  799. // Half relocations steal a bit from the length field to encode
  800. // whether this is an upper16 or a lower16 relocation.
  801. bool isUpper = (RE->Word1 >> 25) & 1;
  802. if (isUpper)
  803. fmt << ":upper16:(" << Name;
  804. else
  805. fmt << ":lower16:(" << Name;
  806. InMemoryStruct<macho::RelocationEntry> RENext;
  807. DataRefImpl RelNext = Rel;
  808. RelNext.d.a++;
  809. getRelocation(RelNext, RENext);
  810. // ARM half relocs must be followed by a relocation of type
  811. // ARM_RELOC_PAIR.
  812. unsigned RType = (RENext->Word1 >> 28) & 0xF;
  813. if (RType != 1)
  814. report_fatal_error("Expected ARM_RELOC_PAIR after "
  815. "GENERIC_RELOC_HALF");
  816. // A constant addend for the relocation is stored in the address
  817. // field of the follow-on relocation. If this is a lower16 relocation
  818. // we need to shift it left by 16 before using it.
  819. int32_t Addend = RENext->Word0;
  820. if (!isUpper) Addend <<= 16;
  821. // ARM_RELOC_HALF_SECTDIFF encodes the second section in the
  822. // symbol/section pointer of the follow-on relocation.
  823. StringRef SucName;
  824. if (Type == 9) { // ARM_RELOC_HALF_SECTDIFF
  825. if (error_code ec = getRelocationTargetName(RENext->Word1, SucName))
  826. report_fatal_error(ec.message());
  827. }
  828. if (SucName.size()) fmt << "-" << SucName;
  829. if (Addend > 0) fmt << "+" << Addend;
  830. else if (Addend < 0) fmt << Addend;
  831. fmt << ")";
  832. break;
  833. }
  834. default: {
  835. StringRef Name;
  836. if (error_code ec = getRelocationTargetName(RE->Word1, Name))
  837. report_fatal_error(ec.message());
  838. fmt << Name;
  839. }
  840. }
  841. }
  842. } else {
  843. StringRef Name;
  844. if (error_code ec = getRelocationTargetName(RE->Word1, Name))
  845. report_fatal_error(ec.message());
  846. fmt << Name;
  847. }
  848. fmt.flush();
  849. Result.append(fmtbuf.begin(), fmtbuf.end());
  850. return object_error::success;
  851. }
  852. error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel,
  853. bool &Result) const {
  854. InMemoryStruct<macho::RelocationEntry> RE;
  855. getRelocation(Rel, RE);
  856. unsigned Type = (RE->Word1 >> 28) & 0xF;
  857. unsigned Arch = getArch();
  858. Result = false;
  859. // On arches that use the generic relocations, GENERIC_RELOC_PAIR
  860. // is always hidden.
  861. if (Arch == Triple::x86 || Arch == Triple::arm) {
  862. if (Type == 1) Result = true;
  863. } else if (Arch == Triple::x86_64) {
  864. // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows
  865. // an X864_64_RELOC_SUBTRACTOR.
  866. if (Type == 0 && Rel.d.a > 0) {
  867. DataRefImpl RelPrev = Rel;
  868. RelPrev.d.a--;
  869. InMemoryStruct<macho::RelocationEntry> REPrev;
  870. getRelocation(RelPrev, REPrev);
  871. unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
  872. if (PrevType == 5) Result = true;
  873. }
  874. }
  875. return object_error::success;
  876. }
  877. /*===-- Miscellaneous -----------------------------------------------------===*/
  878. uint8_t MachOObjectFile::getBytesInAddress() const {
  879. return MachOObj->is64Bit() ? 8 : 4;
  880. }
  881. StringRef MachOObjectFile::getFileFormatName() const {
  882. if (!MachOObj->is64Bit()) {
  883. switch (MachOObj->getHeader().CPUType) {
  884. case llvm::MachO::CPUTypeI386:
  885. return "Mach-O 32-bit i386";
  886. case llvm::MachO::CPUTypeARM:
  887. return "Mach-O arm";
  888. case llvm::MachO::CPUTypePowerPC:
  889. return "Mach-O 32-bit ppc";
  890. default:
  891. assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 &&
  892. "64-bit object file when we're not 64-bit?");
  893. return "Mach-O 32-bit unknown";
  894. }
  895. }
  896. switch (MachOObj->getHeader().CPUType) {
  897. case llvm::MachO::CPUTypeX86_64:
  898. return "Mach-O 64-bit x86-64";
  899. case llvm::MachO::CPUTypePowerPC64:
  900. return "Mach-O 64-bit ppc64";
  901. default:
  902. assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 &&
  903. "32-bit object file when we're 64-bit?");
  904. return "Mach-O 64-bit unknown";
  905. }
  906. }
  907. unsigned MachOObjectFile::getArch() const {
  908. switch (MachOObj->getHeader().CPUType) {
  909. case llvm::MachO::CPUTypeI386:
  910. return Triple::x86;
  911. case llvm::MachO::CPUTypeX86_64:
  912. return Triple::x86_64;
  913. case llvm::MachO::CPUTypeARM:
  914. return Triple::arm;
  915. case llvm::MachO::CPUTypePowerPC:
  916. return Triple::ppc;
  917. case llvm::MachO::CPUTypePowerPC64:
  918. return Triple::ppc64;
  919. default:
  920. return Triple::UnknownArch;
  921. }
  922. }
  923. } // end namespace object
  924. } // end namespace llvm