machoutils.pas 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
  1. {
  2. Copyright (c) 2009-2010 by Dmitry Boyarintsev
  3. Contains utility routines and types for handling mach-o structure and types.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit machoutils;
  18. {$i fpcdefs.inc}
  19. {$h+}
  20. interface
  21. uses
  22. macho;
  23. type
  24. TRawWriter=class(TObject)
  25. public
  26. procedure WriteRaw(const data; datasize: Integer); virtual; abstract;
  27. end;
  28. TRawReader=class(TObject)
  29. public
  30. function ReadRaw(var data; datasize: Integer): Integer; virtual; abstract;
  31. function Seek(pos: qword): Boolean; virtual; abstract;
  32. function ReadPos: qword; virtual; abstract;
  33. end;
  34. TMachHeader=record
  35. cputype : cpu_type_t;
  36. cpusubtype : cpu_subtype_t;
  37. filetype : longword;
  38. ncmds : longword;
  39. sizeofcmds : longword;
  40. flags : longword;
  41. end;
  42. TSegmentName=string[16];
  43. TSectionName=TSegmentName;
  44. TMachoSegment=record
  45. segname : TSegmentName;
  46. vmaddr : qword;
  47. vmsize : qword;
  48. fileoff : qword;
  49. filesize : qword;
  50. maxprot : vm_prot_t;
  51. initprot : vm_prot_t;
  52. nsects : longword;
  53. flags : longword;
  54. end;
  55. TMachoSection=record
  56. sectname : TSectionName;
  57. segname : TSegmentName;
  58. addr : uint64_t;
  59. size : uint64_t;
  60. offset : uint32_t;
  61. align : uint32_t;
  62. reloff : uint32_t;
  63. nreloc : uint32_t;
  64. flags : uint32_t;
  65. indirectIndex : Integer; // reserved1 for LAZY and NON_LAZY pointers
  66. stubSize : Integer; // reserved2 for S_SYMBOL_STUBS
  67. end;
  68. TMachoRoutine=record
  69. init_address : uint64_t; { address of initialization routine }
  70. init_module : uint64_t; { index into the module table that }
  71. end;
  72. { TMachoWriter }
  73. TMachoWriter=class(TObject)
  74. private
  75. fwriter : TRawWriter;
  76. fown : Boolean;
  77. protected
  78. public
  79. constructor Create(ARawWriter: TRawWriter; AllowFreeWriter: Boolean);
  80. destructor Destroy; override;
  81. { non platform specific writer }
  82. procedure WriteData(const data; dataSize: Integer);
  83. procedure WriteUint8(i: uint8_t);
  84. { endian specific writer }
  85. procedure WriteUint16(i: uint16_t); virtual; abstract;
  86. procedure WriteUint32(i: uint32_t); virtual; abstract;
  87. procedure WriteUint64(i: uint64_t); virtual; abstract;
  88. { endian and ptr-size specific writer }
  89. procedure WritePtr(ofs: QWord); virtual; abstract; // ptr is 32 bit for 32-bit platforms
  90. { macro utility methods }
  91. procedure WriteHeader(const hdr: TMachHeader); virtual; abstract;
  92. procedure WriteSegmentCmd(const seg: TMachoSegment; cmdSize: LongWord); virtual; abstract;
  93. procedure WriteSection(const sec: TMachoSection); virtual; abstract;
  94. procedure WriteRoutineCmd(const rt: TMachoRoutine); virtual; abstract;
  95. procedure WriteLoadCommand(const cmd: load_command); virtual; abstract; overload;
  96. procedure WriteLoadCommand(cmd, cmdsize: Integer); overload;
  97. procedure WriteRelocation(const ri: relocation_info); virtual; abstract;
  98. procedure WriteScatterReloc(const ri: scattered_relocation_info); virtual; abstract;
  99. procedure WriteNList(const list: nlist_64); virtual; abstract;
  100. end;
  101. { TLE32MachoWriter }
  102. TLE32MachoWriter=class(TMachoWriter)
  103. public
  104. procedure WriteUint16(i: uint16_t); override;
  105. procedure WriteUint32(i: uint32_t); override;
  106. procedure WriteUint64(i: uint64_t); override;
  107. procedure WritePtr(ofs: QWord); override;
  108. procedure WriteHeader(const hdr: TMachHeader); override;
  109. procedure WriteSegmentCmd(const seg: TMachoSegment; ACmdSize: LongWord); override;
  110. procedure WriteSection(const sec: TMachoSection); override;
  111. procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
  112. procedure WriteLoadCommand(const cmd: load_command); override;
  113. procedure WriteRelocation(const ri: relocation_info); override;
  114. procedure WriteScatterReloc(const ri: scattered_relocation_info); override;
  115. procedure WriteNList(const list: nlist_64); override;
  116. end;
  117. { TLE64MachoWriter }
  118. TLE64MachoWriter=class(TLE32MachoWriter)
  119. public
  120. procedure WritePtr(ofs: QWord); override;
  121. procedure WriteHeader(const hdr: TMachHeader); override;
  122. procedure WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord); override;
  123. procedure WriteSection(const sec: TMachoSection); override;
  124. procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
  125. procedure WriteNList(const list: nlist_64); override;
  126. end;
  127. { TBE32MachoWriter }
  128. TBE32MachoWriter=class(TMachoWriter)
  129. public
  130. procedure WriteUint16(i: uint16_t); override;
  131. procedure WriteUint32(i: uint32_t); override;
  132. procedure WriteUint64(i: uint64_t); override;
  133. procedure WritePtr(ofs: QWord); override;
  134. procedure WriteHeader(const hdr: TMachHeader); override;
  135. procedure WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord); override;
  136. procedure WriteSection(const sec: TMachoSection); override;
  137. procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
  138. procedure WriteLoadCommand(const cmd: load_command); override;
  139. procedure WriteRelocation(const ri: relocation_info); override;
  140. procedure WriteScatterReloc(const ri: scattered_relocation_info); override;
  141. procedure WriteNList(const list: nlist_64); override;
  142. end;
  143. { TBE64MachoWriter }
  144. TBE64MachoWriter=class(TBE32MachoWriter)
  145. public
  146. procedure WritePtr(ofs: QWord); override;
  147. procedure WriteHeader(const hdr: TMachHeader); override;
  148. procedure WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord); override;
  149. procedure WriteSection(const sec: TMachoSection); override;
  150. procedure WriteRoutineCmd(const rt: TMachoRoutine); override;
  151. procedure WriteNList(const list: nlist_64); override;
  152. end;
  153. { TLEMachoStructConverter }
  154. { converter for Little-endian structures to Host }
  155. TLEMachoStructConverter = class(TObject)
  156. public
  157. procedure ConvertMachoHeader(const mh: mach_header; var hdr: TMachHeader); virtual;
  158. procedure ConvertMachoHeader64(const mh: mach_header_64; var hdr: TMachHeader); virtual;
  159. procedure ConvertLoadCommand(var cmd: load_command); virtual;
  160. procedure ConvertSegment(const segcmd: segment_command; var segment: TMachoSegment); virtual;
  161. procedure ConvertSegment64(const segcmd: segment_command_64; var segment: TMachoSegment); virtual;
  162. procedure ConvertSection(const sec: section; var section: TMachoSection); virtual;
  163. procedure ConvertSection64(const sec: section_64; var section: TMachoSection); virtual;
  164. procedure ConvertUInt16(var v: Word); virtual;
  165. procedure ConvertUInt32(var v: LongWord); virtual;
  166. procedure ConvertUInt64(var v: qWord); virtual;
  167. end;
  168. { converter for Big-endian structures to Host }
  169. TBEMachoStructConverter = class(TLEMachoStructConverter);
  170. {common}
  171. TMachoStructConverter = TLEMachoStructConverter;
  172. { TMachoReader }
  173. TMachoReader=class(TObject)
  174. private
  175. fReader : TRawReader;
  176. HdrOfs : qword;
  177. fCnv : TMachoStructConverter;
  178. fHdr : TMachHeader;
  179. is64 : Boolean;
  180. cmdofs : array of qword;
  181. cmds : array of load_command;
  182. protected
  183. function IntReadStruct: Boolean;
  184. public
  185. constructor Create(ARawReader: TRawReader; StartOfs: QWord=0);
  186. function ReadHeader(var hdr: TMachHeader): Boolean;
  187. function ReadCommandID(index: LongWord; var cmd: load_command): Boolean;
  188. function GetCmdOfs(index: LongWord): qword;
  189. function ReadSegmentCommand(cmdindex: LongWord; var segment: TMachoSegment): Boolean;
  190. function ReadSection(segindex, secindex: LongWord; var machsection: TMachoSection): Boolean;
  191. function ReadSymTabCmd(var symcmd: symtab_command): Boolean;
  192. function ReadUInt32(var v: LongWord): Boolean;
  193. function ReadData(var data; dataSize: Integer): Integer;
  194. {todo: ReadNList - using index of symbol, instead of file offset?}
  195. function GetNListSize: Integer;
  196. function ReadNList(fileofs: qword; var nsym: nlist_64): Boolean;
  197. procedure Seek(apos: qword);
  198. end;
  199. const
  200. seg_TEXT : TSegmentName = '__TEXT';
  201. seg_DATA : TSegmentName = '__DATA';
  202. seg_OBJC : TSegmentName = '__OBJC';
  203. seg_IMPORT : TSegmentName = '__IMPORT';
  204. seg_DWARF : TSegmentName = '__DWARF';
  205. function AllocMachoWriter(cputarget: cpu_type_t; ARawWriter: TRawWriter; AllowFreeWriter: Boolean): TMachoWriter;
  206. function sizeMachHeader(cputarget: cpu_type_t): integer;
  207. function sizeSegment(cputarget: cpu_type_t): integer;
  208. function sizeSection(cputarget: cpu_type_t): integer;
  209. function sizeNList(cputarget: cpu_type_t): integer;
  210. function AlignAddr(cputarget: cpu_type_t; addr: qword): qword;
  211. procedure InitSegment(var seg: TMachoSegment);
  212. function MakeSectionName(const segName, secName: shortstring): shortstring;
  213. function GetSegmentSectionName(const objSecName: shortstring; var segName, secName: shortstring): shortstring;
  214. function GetSectionFlags(const segName, secName: shortstring): LongWord;
  215. type
  216. TRelocInfoLength = (ril_byte = 0, ril_word = 1, ril_long = 2, ril_quad = 3);
  217. procedure RelocInfo(addr, symnum, reltype: integer; len: TRelocInfoLength; pcrel, extern: Boolean; var info: relocation_info);
  218. procedure ScatterRelocInfo(value, addr, reltype: integer; len: TRelocInfoLength; pcrel: Boolean; var info: scattered_relocation_info);
  219. function GetReserved1(const macho: TMachoSection): integer;
  220. function GetReserved2(const macho: TMachoSection): integer;
  221. function GetStubSize(cputarget: Integer; Pic: Boolean): Integer;
  222. function MachoAlign(al: integer): integer;
  223. implementation
  224. function MachoAlign(al: integer): integer;
  225. begin
  226. Result:=0;
  227. al:=al shr 1;
  228. while al>0 do
  229. begin
  230. inc(Result);
  231. al:=al shr 1;
  232. end;
  233. end;
  234. function AllocConverter(magic: LongWord): TMachoStructConverter;
  235. begin
  236. {$ifdef ENDIAN_BIG}
  237. if magic=MH_MAGIC then
  238. Result:=TBEMachoStructConverter.Create
  239. else
  240. Result:=TLEMachoStructConverter.Create;
  241. {$else}
  242. if magic=MH_MAGIC then
  243. Result:=TLEMachoStructConverter.Create
  244. else
  245. Result:=TBEMachoStructConverter.Create;
  246. {$endif}
  247. end;
  248. {result values are used from aggas.pas, see TGNUAssembler.WriteSection }
  249. function GetStubSize(cputarget: Integer; Pic: Boolean): Integer;
  250. begin
  251. case cputarget of
  252. CPU_TYPE_I386, CPU_TYPE_X86_64:
  253. Result:=5;
  254. CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64:
  255. if Pic then
  256. Result:=32
  257. else
  258. Result:=16;
  259. CPU_TYPE_ARM:
  260. if Pic then
  261. Result:=16
  262. else
  263. Result:=12;
  264. else
  265. Result:=-1;
  266. end;
  267. end;
  268. function GetReserved1(const macho: TMachoSection): integer;
  269. begin
  270. case macho.flags and SECTION_TYPE of
  271. S_NON_LAZY_SYMBOL_POINTERS, S_LAZY_SYMBOL_POINTERS:
  272. Result:=macho.indirectIndex;
  273. else
  274. Result:=0;
  275. end;
  276. end;
  277. function GetReserved2(const macho: TMachoSection): integer;
  278. begin
  279. case macho.flags and SECTION_TYPE of
  280. S_SYMBOL_STUBS:
  281. Result:=macho.stubSize
  282. else
  283. Result:=0;
  284. end;
  285. end;
  286. procedure RelocInfo(addr, symnum, reltype: integer; len: TRelocInfoLength; pcrel, extern: Boolean; var info: relocation_info);
  287. {$ifdef ENDIAN_BIG}
  288. const
  289. relbit : array [Boolean] of Integer = (0, 1 shl 7);
  290. extbit : array [Boolean] of Integer = (0, 1 shl 4);
  291. ri_len_mask : array [TRelocInfoLength] of Integer = (0 shl 5, 1 shl 5, 2 shl 5, 3 shl 5);
  292. begin
  293. info.r_address:=addr;
  294. info.r_info:=((symnum and $FFFFFF) shl 8) or // r_symbolnum:24
  295. relbit[pcrel] or // r_pcrel:1;
  296. ri_len_mask[len] or // r_length:2;
  297. extbit[extern] or // r_extern:1;
  298. (reltype and $F); // r_type:4;
  299. end;
  300. {$else}
  301. const
  302. relbit : array [Boolean] of Integer = (0, 1 shl 24);
  303. extbit : array [Boolean] of Integer = (0, 1 shl 27);
  304. ri_len_mask : array [TRelocInfoLength] of Integer = (0 shl 25, 1 shl 25, 2 shl 25, 3 shl 25);
  305. begin
  306. info.r_address:=addr;
  307. info.r_info:=(symnum and $FFFFFF) or // r_symbolnum:24
  308. relbit[pcrel] or // r_pcrel:1;
  309. extbit[extern] or // r_length:2;
  310. ri_len_mask[len] or // r_extern:1;
  311. (reltype shl 28); // r_type:4;
  312. end;
  313. {$endif}
  314. const
  315. si_len_mask: array [TRelocInfoLength] of Integer = (0 shl 28, 1 shl 28, 2 shl 28, 3 shl 28);
  316. si_type_ofs = 24;
  317. si_pcrel_bit = 1 shl 30;
  318. si_scatter_bit = 1 shl 31;
  319. si_addr_ofs = 0;
  320. procedure ScatterRelocInfo(value, addr, reltype: integer; len: TRelocInfoLength; pcrel: Boolean; var info: scattered_relocation_info);
  321. const
  322. relbit : array [Boolean] of Integer = (0, si_pcrel_bit);
  323. begin
  324. // big endian
  325. info.r_info:=si_scatter_bit or // r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */
  326. relbit[pcrel] or // r_pcrel:1, /* was relocated pc relative already */
  327. si_len_mask[len] or // r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
  328. ((reltype and $F) shl si_type_ofs) or // r_type:4, /* if not 0, machine specific relocation type */
  329. ((addr and $FFFFFF) shl si_addr_ofs); // r_address:24; /* offset in the section to what is being relocated */}
  330. info.r_value:=value;
  331. // little endian
  332. // r_address:24, /* offset in the section to what is being relocated */
  333. // r_type:4, /* if not 0, machine specific relocation type */
  334. // r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
  335. // r_pcrel:1, /* was relocated pc relative already */
  336. // r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ *}
  337. end;
  338. function GetSectionFlags(const segName, secName: shortstring): LongWord;
  339. begin
  340. Result:=0;
  341. if segName = seg_DATA then
  342. begin
  343. if secName = '__nl_symbol_ptr' then
  344. Result:=Result or S_NON_LAZY_SYMBOL_POINTERS
  345. else if secName = '__la_symbol_ptr' then
  346. Result:=Result or S_LAZY_SYMBOL_POINTERS
  347. else if secName = '__common' then
  348. Result:=Result or S_ZEROFILL
  349. end
  350. else if segName = seg_TEXT then
  351. begin
  352. if (secName = '__text') then
  353. Result:=Result or S_ATTR_PURE_INSTRUCTIONS or S_ATTR_SOME_INSTRUCTIONS
  354. else if secName = '__textcoal_nt' then
  355. Result:=Result or S_ATTR_PURE_INSTRUCTIONS or S_ATTR_SOME_INSTRUCTIONS or S_COALESCED
  356. else if secName = '.fpc' then
  357. Result:=Result or S_ATTR_NO_DEAD_STRIP
  358. else if secName = '__cstring' then
  359. Result:=Result or S_CSTRING_LITERALS;
  360. end
  361. else if (segName = seg_IMPORT) then
  362. begin
  363. if (secName = '__jump_table') then
  364. Result:=Result or S_SYMBOL_STUBS or S_ATTR_SELF_MODIFYING_CODE or S_ATTR_SOME_INSTRUCTIONS
  365. end
  366. else if (segName=seg_OBJC) then
  367. begin
  368. Result:=S_ATTR_NO_DEAD_STRIP;
  369. if secName='__message_refs' then
  370. Result:=Result or S_ATTR_NO_DEAD_STRIP or S_LITERAL_POINTERS
  371. else if secName='__cls_refs' then
  372. Result:=Result or S_ATTR_NO_DEAD_STRIP or S_LITERAL_POINTERS;
  373. end;
  374. end;
  375. function MakeSectionName(const segName, secName: shortstring): shortstring;
  376. begin
  377. if segName = '' then
  378. Result:=secName
  379. else
  380. Result:=segName+' '+secName;
  381. end;
  382. function GetSegmentSectionName(const objSecName: shortstring; var segName, secName: shortstring): shortstring;
  383. var
  384. i : integer;
  385. begin
  386. i:=Pos(' ', objSecName);
  387. if i>0 then
  388. begin
  389. segName:=copy(objsecName, 1, i-1);
  390. secName:=copy(objsecName, i+1, length(objsecName)-i);
  391. end
  392. else
  393. begin
  394. segName:='';
  395. secName:=objSecName;
  396. end;
  397. Result:=objSecName;
  398. end;
  399. procedure InitSegment(var seg: TMachoSegment);
  400. begin
  401. FillChar(seg, sizeof(seg), 0);
  402. seg.initprot:=VM_PROT_ALL;
  403. seg.maxprot:=VM_PROT_ALL;
  404. end;
  405. const
  406. is64MachHeaderSize : array [Boolean] of Integer = ( sizeof(mach_header), sizeof(mach_header_64));
  407. is64SectionSize : array [Boolean] of Integer = ( sizeof(section), sizeof(section_64));
  408. is64SegmentSize : array [Boolean] of Integer = ( sizeof(segment_command), sizeof(segment_command_64));
  409. is64NListSize : array [Boolean] of Integer = (sizeof(nlist), sizeof(nlist_64));
  410. function AlignAddr(cputarget: cpu_type_t; addr: qword): qword;
  411. var
  412. md : array [Boolean] of integer = (4, 8);
  413. p : PtrUInt;
  414. begin
  415. p:=addr;
  416. p:=align(p, md[cputarget and CPU_ARCH_ABI64 > 0]);
  417. Result:=qword(p);
  418. end;
  419. function sizeMachHeader(cputarget: cpu_type_t): integer;
  420. begin
  421. Result:=is64MachHeaderSize[ cputarget and CPU_ARCH_ABI64 > 0];
  422. end;
  423. function sizeSegment(cputarget: cpu_type_t): integer;
  424. begin
  425. Result:=is64SegmentSize[ cputarget and CPU_ARCH_ABI64 > 0];
  426. end;
  427. function sizeSection(cputarget: cpu_type_t): integer;
  428. begin
  429. Result:=is64SectionSize[ cputarget and CPU_ARCH_ABI64 > 0];
  430. end;
  431. function sizeNList(cputarget: cpu_type_t): integer;
  432. begin
  433. Result:=is64NlistSize[ cputarget and CPU_ARCH_ABI64 > 0];
  434. end;
  435. function AllocMachoWriter(cputarget: cpu_type_t; ARawWriter: TRawWriter; AllowFreeWriter: Boolean): TMachoWriter;
  436. begin
  437. case cputarget of
  438. CPU_TYPE_I386,
  439. CPU_TYPE_ARM: Result:=TLE32MachoWriter.Create(ARawWriter, AllowFreeWriter);
  440. CPU_TYPE_X86_64: Result:=TLE64MachoWriter.Create(ARawWriter, AllowFreeWriter);
  441. CPU_TYPE_POWERPC: Result:=TBE32MachoWriter.Create(ARawWriter, AllowFreeWriter);
  442. CPU_TYPE_POWERPC64: Result:=TBE64MachoWriter.Create(ARawWriter, AllowFreeWriter);
  443. else
  444. begin
  445. if AllowFreeWriter then
  446. ARawWriter.Free;
  447. ARawWriter := nil;
  448. Result:=nil;
  449. end;
  450. end;
  451. end;
  452. { TMachoWriter }
  453. procedure TMachoWriter.WriteData(const data; dataSize: Integer);
  454. begin
  455. if not assigned(fwriter) then
  456. Exit;
  457. fwriter.WriteRaw(data, dataSize);
  458. end;
  459. procedure TMachoWriter.WriteUint8(i: uint8_t);
  460. begin
  461. WriteData(i, sizeof(i));
  462. end;
  463. procedure TMachoWriter.WriteLoadCommand(cmd, cmdsize: Integer);
  464. var
  465. m : load_command;
  466. begin
  467. m.cmd:=cmd;
  468. m.cmdsize:=cmdsize;
  469. WriteLoadCommand(m);
  470. end;
  471. constructor TMachoWriter.Create(ARawWriter: TRawWriter; AllowFreeWriter: Boolean);
  472. begin
  473. inherited Create;
  474. fwriter:=ARawWriter;
  475. fown:=AllowFreeWriter;
  476. end;
  477. destructor TMachoWriter.Destroy;
  478. begin
  479. if fown then
  480. fwriter.Free;
  481. fwriter := nil;
  482. inherited Destroy;
  483. end;
  484. { TLE32MachoWriter }
  485. procedure TLE32MachoWriter.WriteHeader(const hdr: TMachHeader);
  486. var
  487. m : mach_header;
  488. begin
  489. with m do
  490. begin
  491. magic:=NtoLE(MH_MAGIC);
  492. cputype:=NtoLE(hdr.cputype);
  493. cpusubtype:=NtoLE(hdr.cpusubtype);
  494. filetype:=NtoLE(hdr.filetype);
  495. ncmds:=NtoLE(hdr.ncmds);
  496. sizeofcmds:=NtoLE(hdr.sizeofcmds);
  497. flags:=NtoLE(hdr.flags);
  498. end;
  499. WriteData(m, sizeof(m));
  500. end;
  501. procedure TLE32MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; ACmdSize: LongWord);
  502. var
  503. m : segment_command;
  504. begin
  505. with m do
  506. begin
  507. cmd:=NtoLE(LC_SEGMENT);
  508. cmdsize:=NtoLE(ACmdSize);
  509. segname:=seg.segname;
  510. vmaddr:=NtoLE(uint32_t(seg.vmaddr));
  511. vmsize:=NtoLE(uint32_t(seg.vmsize));
  512. fileoff:=NtoLE(uint32_t(seg.fileoff));
  513. filesize:=NtoLE(uint32_t(seg.filesize));
  514. maxprot:=NtoLE(seg.maxprot);
  515. initprot:=NtoLE(seg.initprot);
  516. nsects:=NtoLE(seg.nsects);
  517. flags:=NtoLE(seg.flags);
  518. end;
  519. WriteData(m, sizeof(m));
  520. end;
  521. procedure TLE32MachoWriter.WriteSection(const sec: TMachoSection);
  522. var
  523. m : section;
  524. begin
  525. FillChar(m, sizeof(m), 0);
  526. with m do
  527. begin
  528. sectname:=sec.sectname;
  529. segname:=sec.segname;
  530. addr:=NtoLE(sec.addr);
  531. size:=NtoLE(sec.size);
  532. offset:=NtoLE(sec.offset);
  533. align:=NtoLE(sec.align);
  534. reloff:=NtoLE(sec.reloff);
  535. nreloc:=NtoLE(sec.nreloc);
  536. flags:=NtoLE(sec.flags);
  537. reserved1:=NtoLE( GetReserved1(sec));
  538. reserved2:=NtoLE( GetReserved2(sec));
  539. end;
  540. WriteData(m, sizeof(m));
  541. end;
  542. procedure TLE32MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
  543. var
  544. m : routines_command;
  545. begin
  546. FillChar(m, sizeof(m), 0);
  547. with m do
  548. begin
  549. cmd:=NtoLE(LC_ROUTINES);
  550. cmdsize:=NtoLE(sizeof(m));
  551. init_address:=NtoLE(rt.init_address);
  552. init_module:=NtoLE(rt.init_module);
  553. end;
  554. WriteData(m, sizeof(m));
  555. end;
  556. procedure TLE32MachoWriter.WriteLoadCommand(const cmd: load_command);
  557. var
  558. m : load_command;
  559. begin
  560. m.cmd:=NtoLE(cmd.cmd);
  561. m.cmdsize:=NtoLE(cmd.cmdsize);
  562. WriteData(m, sizeof(m));
  563. end;
  564. procedure TLE32MachoWriter.WriteRelocation(const ri: relocation_info);
  565. var
  566. m : relocation_info;
  567. begin
  568. m.r_address:=NtoLE(ri.r_address);
  569. m.r_info:=NtoLE(ri.r_info);
  570. WriteData(m, sizeof(m));
  571. end;
  572. procedure TLE32MachoWriter.WriteScatterReloc(const ri: scattered_relocation_info);
  573. var
  574. m : LongWord;
  575. begin
  576. m:=LongWord(ri.r_info);
  577. WriteUint32(NtoLE(m));
  578. m:=LongWord(ri.r_value);
  579. WriteUint32(NtoLE(m));
  580. end;
  581. procedure TLE32MachoWriter.WriteNList(const list: nlist_64);
  582. var
  583. m : nlist;
  584. begin
  585. m.n_un.n_strx:=NtoLe(list.n_un.n_strx);
  586. m.n_type:=NtoLe(list.n_type);
  587. m.n_sect:=NtoLe(list.n_sect);
  588. m.n_desc:=NtoLe(list.n_desc);
  589. m.n_value:=NtoLe(list.n_value);
  590. WriteData(m, sizeof(m));
  591. end;
  592. procedure TLE32MachoWriter.WriteUint16(i: uint16_t);
  593. var
  594. m: uint16_t;
  595. begin
  596. m:=NtoLE(i);
  597. WriteData(m, sizeof(m));
  598. end;
  599. procedure TLE32MachoWriter.WriteUint32(i: uint32_t);
  600. var
  601. m: uint32_t;
  602. begin
  603. m:=NtoLE(i);
  604. WriteData(m, sizeof(m));
  605. end;
  606. procedure TLE32MachoWriter.WriteUint64(i: uint64_t);
  607. var
  608. m: uint64_t;
  609. begin
  610. m:=NtoLE(i);
  611. WriteData(m, sizeof(m));
  612. end;
  613. procedure TLE32MachoWriter.WritePtr(ofs: QWord);
  614. var
  615. m: uint32_t;
  616. begin
  617. m:=NtoLE(ofs);
  618. WriteData(m, sizeof(m));
  619. end;
  620. { TLE64MachoWriter }
  621. procedure TLE64MachoWriter.WritePtr(ofs: QWord);
  622. var
  623. m : uint64_t;
  624. begin
  625. m:=NtoLE(ofs);
  626. Writedata(m, sizeof(m));
  627. end;
  628. procedure TLE64MachoWriter.WriteHeader(const hdr: TMachHeader);
  629. var
  630. m : mach_header_64;
  631. begin
  632. with m do
  633. begin
  634. magic:=NtoLE(MH_MAGIC_64);
  635. cputype:=NtoLE(hdr.cputype);
  636. cpusubtype:=NtoLE(hdr.cpusubtype);
  637. filetype:=NtoLE(hdr.filetype);
  638. ncmds:=NtoLE(hdr.ncmds);
  639. sizeofcmds:=NtoLE(hdr.sizeofcmds);
  640. flags:=NtoLE(hdr.flags);
  641. reserved:=0;
  642. end;
  643. WriteData(m, sizeof(m));
  644. end;
  645. procedure TLE64MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord);
  646. var
  647. m : segment_command_64;
  648. begin
  649. with m do
  650. begin
  651. cmd:=NtoLE(LC_SEGMENT_64);
  652. cmdsize:=NtoLE(acmdSize);
  653. segname:=seg.segname;
  654. vmaddr:=NtoLE(seg.vmaddr);
  655. vmsize:=NtoLE(seg.vmsize);
  656. fileoff:=NtoLE(seg.fileoff);
  657. filesize:=NtoLE(seg.filesize);
  658. maxprot:=NtoLE(seg.maxprot);
  659. initprot:=NtoLE(seg.initprot);
  660. nsects:=NtoLE(seg.nsects);
  661. flags:=NtoLE(seg.flags);
  662. end;
  663. WriteData(m, sizeof(m));
  664. end;
  665. procedure TLE64MachoWriter.WriteSection(const sec: TMachoSection);
  666. var
  667. m : section_64;
  668. begin
  669. FillChar(m, sizeof(m), 0);
  670. with m do
  671. begin
  672. sectname:=sec.sectname;
  673. segname:=sec.segname;
  674. addr:=NtoLE(sec.addr);
  675. size:=NtoLE(sec.size);
  676. offset:=NtoLE(sec.offset);
  677. align:=NtoLE(sec.align);
  678. reloff:=NtoLE(sec.reloff);
  679. nreloc:=NtoLE(sec.nreloc);
  680. flags:=NtoLE(sec.flags);
  681. reserved1:=NtoLE( GetReserved1(sec));
  682. reserved2:=NtoLE( GetReserved2(sec));
  683. end;
  684. WriteData(m, sizeof(m));
  685. end;
  686. procedure TLE64MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
  687. var
  688. m : routines_command_64;
  689. begin
  690. FillChar(m, sizeof(m), 0);
  691. with m do
  692. begin
  693. cmd:=NtoLE(LC_ROUTINES);
  694. cmdsize:=NtoLE(sizeof(m));
  695. init_address:=NtoLE(rt.init_address);
  696. init_module:=NtoLE(rt.init_module);
  697. end;
  698. WriteData(m, sizeof(m));
  699. end;
  700. procedure TLE64MachoWriter.WriteNList(const list: nlist_64);
  701. var
  702. m : nlist_64;
  703. begin
  704. m.n_un.n_strx:=NtoLe(list.n_un.n_strx);
  705. m.n_type:=NtoLe(list.n_type);
  706. m.n_sect:=NtoLe(list.n_sect);
  707. m.n_desc:=NtoLe(list.n_desc);
  708. m.n_value:=NtoLe(list.n_value);
  709. WriteData(m, sizeof(m));
  710. end;
  711. { TBE32MachoWriter }
  712. procedure TBE32MachoWriter.WriteHeader(const hdr: TMachHeader);
  713. var
  714. m : mach_header;
  715. begin
  716. with m do
  717. begin
  718. magic:=NtoBE(MH_MAGIC);
  719. cputype:=NtoBE(hdr.cputype);
  720. cpusubtype:=NtoBE(hdr.cpusubtype);
  721. filetype:=NtoBE(hdr.filetype);
  722. ncmds:=NtoBE(hdr.ncmds);
  723. sizeofcmds:=NtoBE(hdr.sizeofcmds);
  724. flags:=NtoBE(hdr.flags);
  725. end;
  726. WriteData(m, sizeof(m));
  727. end;
  728. procedure TBE32MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord);
  729. var
  730. m : segment_command;
  731. begin
  732. with m do
  733. begin
  734. cmd:=NtoBE(LC_SEGMENT);
  735. cmdsize:=NtoBE(acmdSize);
  736. segname:=seg.segname;
  737. vmaddr:=NtoBE(uint32_t(seg.vmaddr));
  738. vmsize:=NtoBE(uint32_t(seg.vmsize));
  739. fileoff:=NtoBE(uint32_t(seg.fileoff));
  740. filesize:=NtoBE(uint32_t(seg.filesize));
  741. maxprot:=NtoBE(seg.maxprot);
  742. initprot:=NtoBE(seg.initprot);
  743. nsects:=NtoBE(seg.nsects);
  744. flags:=NtoBE(seg.flags);
  745. end;
  746. WriteData(m, sizeof(m));
  747. end;
  748. procedure TBE32MachoWriter.WriteSection(const sec: TMachoSection);
  749. var
  750. m : section;
  751. begin
  752. FillChar(m, sizeof(m), 0);
  753. with m do
  754. begin
  755. sectname:=sec.sectname;
  756. segname:=sec.segname;
  757. addr:=NtoBE(sec.addr);
  758. size:=NtoBE(sec.size);
  759. offset:=NtoBE(sec.offset);
  760. align:=NtoBE(sec.align);
  761. reloff:=NtoBE(sec.reloff);
  762. nreloc:=NtoBE(sec.nreloc);
  763. flags:=NtoBE(sec.flags);
  764. reserved1:=NtoBE( GetReserved1(sec));
  765. reserved2:=NtoBE( GetReserved2(sec));
  766. end;
  767. WriteData(m, sizeof(m));
  768. end;
  769. procedure TBE32MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
  770. var
  771. m : routines_command;
  772. begin
  773. FillChar(m, sizeof(m), 0);
  774. with m do
  775. begin
  776. cmd:=NtoBE(LC_ROUTINES);
  777. cmdsize:=NtoBE(sizeof(m));
  778. init_address:=NtoBE(rt.init_address);
  779. init_module:=NtoBE(rt.init_module);
  780. end;
  781. WriteData(m, sizeof(m));
  782. end;
  783. procedure TBE32MachoWriter.WriteLoadCommand(const cmd: load_command);
  784. var
  785. m : load_command;
  786. begin
  787. m.cmd:=NtoBE(cmd.cmd);
  788. m.cmdsize:=NtoBE(cmd.cmdsize);
  789. WriteData(m, sizeof(m));
  790. end;
  791. procedure TBE32MachoWriter.WriteRelocation(const ri: relocation_info);
  792. var
  793. m : relocation_info;
  794. begin
  795. m.r_address:=NtoBE(ri.r_address);
  796. m.r_info:=NtoBE(ri.r_info);
  797. WriteData(m, sizeof(m));
  798. end;
  799. procedure TBE32MachoWriter.WriteScatterReloc(const ri: scattered_relocation_info);
  800. var
  801. m : LongWord;
  802. begin
  803. m:=LongWord(ri.r_info);
  804. WriteUint32(NtoBE(m));
  805. m:=LongWord(ri.r_value);
  806. WriteUint32(NtoBE(m));
  807. end;
  808. procedure TBE32MachoWriter.WriteNList(const list: nlist_64);
  809. var
  810. m : nlist;
  811. begin
  812. m.n_un.n_strx:=NtoBe(list.n_un.n_strx);
  813. m.n_type:=NtoBe(list.n_type);
  814. m.n_sect:=NtoBe(list.n_sect);
  815. m.n_desc:=NtoBe(list.n_desc);
  816. m.n_value:=NtoBe(list.n_value);
  817. WriteData(m, sizeof(m));
  818. end;
  819. procedure TBE32MachoWriter.WriteUint16(i: uint16_t);
  820. var
  821. m: uint16_t;
  822. begin
  823. m:=NtoBE(i);
  824. WriteData(m, sizeof(m));
  825. end;
  826. procedure TBE32MachoWriter.WriteUint32(i: uint32_t);
  827. var
  828. m: uint32_t;
  829. begin
  830. m:=NtoBE(i);
  831. WriteData(m, sizeof(m));
  832. end;
  833. procedure TBE32MachoWriter.WriteUint64(i: uint64_t);
  834. var
  835. m: uint64_t;
  836. begin
  837. m:=NtoBE(i);
  838. WriteData(m, sizeof(m));
  839. end;
  840. procedure TBE32MachoWriter.WritePtr(ofs: QWord);
  841. var
  842. m: uint32_t;
  843. begin
  844. m:=NtoBE(ofs);
  845. WriteData(m, sizeof(m));
  846. end;
  847. { TBE64MachoWriter }
  848. procedure TBE64MachoWriter.WritePtr(ofs: QWord);
  849. var
  850. m : uint64_t;
  851. begin
  852. m:=NtoBE(ofs);
  853. Writedata(m, sizeof(m));
  854. end;
  855. procedure TBE64MachoWriter.WriteHeader(const hdr: TMachHeader);
  856. var
  857. m : mach_header_64;
  858. begin
  859. with m do
  860. begin
  861. magic:=NtoBE(MH_MAGIC_64);
  862. cputype:=NtoBE(hdr.cputype);
  863. cpusubtype:=NtoBE(hdr.cpusubtype);
  864. filetype:=NtoBE(hdr.filetype);
  865. ncmds:=NtoBE(hdr.ncmds);
  866. sizeofcmds:=NtoBE(hdr.sizeofcmds);
  867. flags:=NtoBE(hdr.flags);
  868. reserved:=0;
  869. end;
  870. WriteData(m, sizeof(m));
  871. end;
  872. procedure TBE64MachoWriter.WriteSegmentCmd(const seg: TMachoSegment; acmdSize: LongWord);
  873. var
  874. m : segment_command_64;
  875. begin
  876. with m do
  877. begin
  878. cmd:=NtoBE(LC_SEGMENT_64);
  879. cmdsize:=NtoBE(acmdSize);
  880. segname:=seg.segname;
  881. vmaddr:=NtoBE(seg.vmaddr);
  882. vmsize:=NtoBE(seg.vmsize);
  883. fileoff:=NtoBE(seg.fileoff);
  884. filesize:=NtoBE(seg.filesize);
  885. maxprot:=NtoBE(seg.maxprot);
  886. initprot:=NtoBE(seg.initprot);
  887. nsects:=NtoBE(seg.nsects);
  888. flags:=NtoBE(seg.flags);
  889. end;
  890. WriteData(m, sizeof(m));
  891. end;
  892. procedure TBE64MachoWriter.WriteSection(const sec: TMachoSection);
  893. var
  894. m : section_64;
  895. begin
  896. FillChar(m, sizeof(m), 0);
  897. with m do
  898. begin
  899. sectname:=sec.sectname;
  900. segname:=sec.segname;
  901. addr:=NtoBE(sec.addr);
  902. size:=NtoBE(sec.size);
  903. offset:=NtoBE(sec.offset);
  904. align:=NtoBE(sec.align);
  905. reloff:=NtoBE(sec.reloff);
  906. nreloc:=NtoBE(sec.nreloc);
  907. flags:=NtoBE(sec.flags);
  908. reserved1:=NtoBE( GetReserved1(sec));
  909. reserved2:=NtoBE( GetReserved2(sec));
  910. end;
  911. WriteData(m, sizeof(m));
  912. end;
  913. procedure TBE64MachoWriter.WriteRoutineCmd(const rt: TMachoRoutine);
  914. var
  915. m : routines_command_64;
  916. begin
  917. FillChar(m, sizeof(m), 0);
  918. with m do
  919. begin
  920. cmd:=NtoBE(LC_ROUTINES);
  921. cmdsize:=NtoBE(sizeof(m));
  922. init_address:=NtoBE(rt.init_address);
  923. init_module:=NtoBE(rt.init_module);
  924. end;
  925. WriteData(m, sizeof(m));
  926. end;
  927. procedure TBE64MachoWriter.WriteNList(const list: nlist_64);
  928. var
  929. m : nlist_64;
  930. begin
  931. m.n_un.n_strx:=NtoBe(list.n_un.n_strx);
  932. m.n_type:=NtoBe(list.n_type);
  933. m.n_sect:=NtoBe(list.n_sect);
  934. m.n_desc:=NtoBe(list.n_desc);
  935. m.n_value:=NtoBe(list.n_value);
  936. WriteData(m, sizeof(m));
  937. end;
  938. { TMachoReader }
  939. constructor TMachoReader.Create(ARawReader: TRawReader; StartOfs: QWord=0);
  940. begin
  941. inherited Create;
  942. fReader:=ARawReader;
  943. hdrofs:=StartOfs;
  944. end;
  945. function TMachoReader.IntReadStruct: Boolean;
  946. var
  947. m : mach_header_64;
  948. i : Integer;
  949. p : qword;
  950. begin
  951. Result:=false;
  952. if not fReader.Seek(hdrofs) then
  953. Exit;
  954. //todo:
  955. fReader.ReadRaw(m, sizeof(mach_header_64));
  956. fCnv:=AllocConverter(m.magic);
  957. fCnv.ConvertMachoHeader(pmach_header(@m)^, fhdr);
  958. is64:=fhdr.cputype and CPU_ARCH_ABI64>0;
  959. Result:=true;
  960. SetLength(cmds, fHdr.ncmds);
  961. if fHdr.ncmds>0 then
  962. begin
  963. if is64 then
  964. p:=sizeof(mach_header_64)
  965. else
  966. p:=sizeof(mach_header);
  967. SetLength(cmdofs, fHdr.ncmds);
  968. for i:=0 to fHdr.ncmds - 1 do
  969. begin
  970. cmdofs[i]:=p;
  971. fReader.Seek(p);
  972. fReader.ReadRaw(cmds[i], sizeof(cmds[i]));
  973. fCnv.ConvertLoadCommand(cmds[i]);
  974. inc(p, cmds[i].cmdsize);
  975. end;
  976. end;
  977. end;
  978. function TMachoReader.ReadHeader(var hdr: TMachHeader): Boolean;
  979. begin
  980. if not Assigned(fCnv) then
  981. Result:=IntReadStruct
  982. else
  983. Result:=true;
  984. hdr:=fhdr;
  985. end;
  986. function TMachoReader.ReadCommandID(index: LongWord; var cmd: load_command): Boolean;
  987. begin
  988. if not Assigned(fCnv) then
  989. IntReadStruct;
  990. Result:={(index>=0) and }(index<fHdr.ncmds);
  991. if not Result then
  992. Exit;
  993. Result:=true;
  994. cmd:=cmds[index];
  995. end;
  996. function TMachoReader.ReadSegmentCommand(cmdindex: LongWord; var segment: TMachoSegment): Boolean;
  997. var
  998. seg64 : segment_command_64;
  999. seg32 : segment_command;
  1000. begin
  1001. if not Assigned(fCnv) then
  1002. IntReadStruct;
  1003. Result:={(cmdindex>=0) and }
  1004. (cmdindex<fHdr.ncmds) and
  1005. (cmds[cmdindex].cmd in [LC_SEGMENT, LC_SEGMENT_64]);
  1006. if Result then
  1007. begin
  1008. fReader.Seek(cmdofs[cmdindex]);
  1009. if is64 then
  1010. begin
  1011. Result:=fReader.ReadRaw(seg64, sizeof(seg64))=sizeof(seg64);
  1012. if Result then
  1013. fCnv.ConvertSegment64(seg64, segment);
  1014. end
  1015. else
  1016. begin
  1017. Result:=fReader.ReadRaw(seg32, sizeof(seg32))=sizeof(seg32);
  1018. if Result then
  1019. fCnv.ConvertSegment(seg32, segment);
  1020. end;
  1021. end;
  1022. end;
  1023. function TMachoReader.GetCmdOfs(index: LongWord): qword;
  1024. begin
  1025. if not Assigned(fCnv) then
  1026. IntReadStruct;
  1027. if {(index<0) or}
  1028. (index>=longword(length(cmdofs))) then
  1029. Result:=0
  1030. else
  1031. Result:=cmdofs[index];
  1032. end;
  1033. function TMachoReader.ReadSection(segindex, secindex: LongWord; var machsection: TMachoSection): Boolean;
  1034. var
  1035. ofs : qword;
  1036. is64bit : Boolean;
  1037. buf : array [0..sizeof(section_64)-1] of byte;
  1038. const
  1039. sectsize : array[Boolean] of LongWord = ( sizeof(macho.section), sizeof(macho.section_64));
  1040. segsize : array[Boolean] of LongWord = ( sizeof(macho.segment_command), sizeof(macho.segment_command_64));
  1041. begin
  1042. if not Assigned(fCnv) then
  1043. IntReadStruct;
  1044. Result:={(secindex>=0) and (segindex>=0) and }(segindex<fHdr.ncmds) and (cmds[segindex].cmd in [LC_SEGMENT, LC_SEGMENT_64]);
  1045. if not Result then
  1046. Exit;
  1047. is64bit:=cmds[segindex].cmd=LC_SEGMENT_64;
  1048. Result:=secindex<(cmds[segindex].cmdsize-segsize[is64bit]) div sectsize[is64bit];
  1049. if not Result then
  1050. Exit;
  1051. ofs:=cmdofs[segindex]+segsize[is64bit]+sectsize[is64]*secindex;
  1052. fReader.Seek(ofs);
  1053. fReader.ReadRaw(buf, segsize[is64bit]);
  1054. if is64bit then
  1055. fCnv.ConvertSection64( psection_64(@buf)^, machsection)
  1056. else
  1057. fCnv.ConvertSection( psection(@buf)^, machsection);
  1058. end;
  1059. function TMachoReader.ReadUInt32(var v: LongWord): Boolean;
  1060. begin
  1061. if not Assigned(fCnv) then
  1062. IntReadStruct;
  1063. Result:=Assigned(fCnv) and (fReader.ReadRaw(v, sizeof(v))=sizeof(v));
  1064. if Result then
  1065. fCnv.ConvertUint32(v);
  1066. end;
  1067. function TMachoReader.ReadData(var data; dataSize: Integer): Integer;
  1068. begin
  1069. Result:=fReader.ReadRaw(data, dataSize);
  1070. end;
  1071. function TMachoReader.GetNListSize: Integer;
  1072. begin
  1073. if is64 then
  1074. Result:=sizeof(nlist_64)
  1075. else
  1076. Result:=sizeof(nlist);
  1077. end;
  1078. function TMachoReader.ReadNList(fileofs: qword; var nsym: nlist_64): Boolean;
  1079. var
  1080. n32 : nlist;
  1081. begin
  1082. fReader.Seek(fileofs);
  1083. if is64 then
  1084. Result:=fReader.ReadRaw(nsym, sizeof(nlist_64))=sizeof(nlist_64)
  1085. else
  1086. begin
  1087. Result:=fReader.ReadRaw(n32, sizeof(nlist))=sizeof(nlist);
  1088. nsym.n_un.n_strx:=n32.n_un.n_strx;
  1089. nsym.n_desc:=n32.n_desc;
  1090. nsym.n_sect:=n32.n_sect;
  1091. nsym.n_type:=n32.n_type;
  1092. nsym.n_value:=n32.n_value;
  1093. end;
  1094. fCnv.ConvertUInt32(nsym.n_un.n_strx);
  1095. fCnv.ConvertUInt16(nsym.n_desc);
  1096. fCnv.ConvertUInt64(nsym.n_value);
  1097. end;
  1098. function TMachoReader.ReadSymTabCmd(var symcmd: symtab_command): Boolean;
  1099. var
  1100. i : Integer;
  1101. p : qword;
  1102. begin
  1103. if not Assigned(fCnv) then
  1104. IntReadStruct;
  1105. for i:=0 to length(cmds)-1 do
  1106. if cmds[i].cmd=LC_SYMTAB then
  1107. begin
  1108. p:=fReader.ReadPos;
  1109. fReader.Seek(cmdofs[i]);
  1110. fReader.ReadRaw(symcmd, sizeof(symcmd));
  1111. fCnv.ConvertUInt32(symcmd.cmd);
  1112. fCnv.ConvertUInt32(symcmd.cmdsize);
  1113. fCnv.ConvertUInt32(symcmd.symoff);
  1114. fCnv.ConvertUInt32(symcmd.nsyms);
  1115. fCnv.ConvertUInt32(symcmd.stroff);
  1116. fCnv.ConvertUInt32(symcmd.strsize);
  1117. fReader.Seek(p);
  1118. Result:=true;
  1119. Exit;
  1120. end;
  1121. Result:=false;
  1122. end;
  1123. procedure TMachoReader.Seek(apos: qword);
  1124. begin
  1125. fReader.Seek(apos);
  1126. end;
  1127. { TLEMachoStructConverter }
  1128. procedure TLEMachoStructConverter.ConvertMachoHeader(const mh: mach_header; var hdr: TMachHeader);
  1129. begin
  1130. hdr.cputype:=LEToN(mh.cputype);
  1131. hdr.cpusubtype:=LEtoN(mh.cpusubtype);
  1132. hdr.filetype:=LEToN(mh.filetype);
  1133. hdr.ncmds:=LEToN(mh.ncmds);
  1134. hdr.sizeofcmds:=LEToN(mh.ncmds);
  1135. hdr.flags:=LEToN(mh.flags);
  1136. end;
  1137. procedure TLEMachoStructConverter.ConvertMachoHeader64(const mh: mach_header_64; var hdr: TMachHeader);
  1138. begin
  1139. hdr.cputype:=LEToN(mh.cputype);
  1140. hdr.cpusubtype:=LEtoN(mh.cpusubtype);
  1141. hdr.filetype:=LEToN(mh.filetype);
  1142. hdr.ncmds:=LEToN(mh.ncmds);
  1143. hdr.sizeofcmds:=LEToN(mh.ncmds);
  1144. hdr.flags:=LEToN(mh.flags);
  1145. end;
  1146. procedure TLEMachoStructConverter.ConvertLoadCommand(var cmd: load_command);
  1147. begin
  1148. cmd.cmd:=LEToN(cmd.cmd);
  1149. cmd.cmdsize:=LEToN(cmd.cmdsize);
  1150. end;
  1151. procedure TLEMachoStructConverter.ConvertSegment(const segcmd: segment_command; var segment: TMachoSegment);
  1152. begin
  1153. FillChar(segment, sizeof(segment), 0);
  1154. segment.segname:=segcmd.segname;
  1155. segment.vmaddr:=LEToN(segcmd.vmaddr);
  1156. segment.vmsize:=LEToN(segcmd.vmsize);
  1157. segment.fileoff:=LEToN(segcmd.fileoff);
  1158. segment.filesize:=LEToN(segcmd.filesize);
  1159. segment.maxprot:=LEToN(segcmd.maxprot);
  1160. segment.initprot:=LEToN(segcmd.initprot);
  1161. writelN('segcmd.nsects = ', segcmd.nsects);
  1162. segment.nsects:=LEToN(segcmd.nsects);
  1163. segment.flags:=LEToN(segcmd.flags);
  1164. //todo: reserved!?
  1165. end;
  1166. procedure TMachoStructConverter.ConvertSegment64(const segcmd: segment_command_64; var segment: TMachoSegment);
  1167. begin
  1168. FillChar(segment, sizeof(segment), 0);
  1169. segment.segname:=segcmd.segname;
  1170. segment.vmaddr:=LEToN(segcmd.vmaddr);
  1171. segment.vmsize:=LEToN(segcmd.vmsize);
  1172. segment.fileoff:=LEToN(segcmd.fileoff);
  1173. segment.filesize:=LEToN(segcmd.filesize);
  1174. segment.maxprot:=LEToN(segcmd.maxprot);
  1175. segment.initprot:=LEToN(segcmd.initprot);
  1176. segment.nsects:=LEToN(segcmd.nsects);
  1177. segment.flags:=LEToN(segcmd.flags);
  1178. //todo: reserved!?
  1179. end;
  1180. procedure TMachoStructConverter.ConvertSection(const sec: section; var section: TMachoSection);
  1181. begin
  1182. FillChar(section, sizeof(section), 0);
  1183. section.sectname:=sec.sectname;
  1184. section.segname:=sec.segname;
  1185. section.addr:=LEToN(sec.addr);
  1186. section.size:=LEToN(sec.size);
  1187. section.offset:=LEToN(sec.offset);
  1188. section.align:=LEToN(sec.align);
  1189. section.reloff:=LEToN(sec.reloff);
  1190. section.nreloc:=LEToN(sec.nreloc);
  1191. section.flags:=LEToN(sec.flags);
  1192. //todo:
  1193. //section.indirectIndex : Integer; // reserved1 for LAZY and NON_LAZY pointers
  1194. //section.stubSize : Integer; // reserved2 for S_SYMBOL_STUBS
  1195. end;
  1196. procedure TMachoStructConverter.ConvertSection64(const sec: section_64; var section: TMachoSection);
  1197. begin
  1198. FillChar(section, sizeof(section), 0);
  1199. section.sectname:=sec.sectname;
  1200. section.segname:=sec.segname;
  1201. section.addr:=LEToN(sec.addr);
  1202. section.size:=LEToN(sec.size);
  1203. section.offset:=LEToN(sec.offset);
  1204. section.align:=LEToN(sec.align);
  1205. section.reloff:=LEToN(sec.reloff);
  1206. section.nreloc:=LEToN(sec.nreloc);
  1207. section.flags:=LEToN(sec.flags);
  1208. //todo:
  1209. //section.indirectIndex : Integer; // reserved1 for LAZY and NON_LAZY pointers
  1210. //section.stubSize : Integer; // reserved2 for S_SYMBOL_STUBS
  1211. end;
  1212. procedure TMachoStructConverter.ConvertUInt32(var v: LongWord);
  1213. begin
  1214. v:=LEtoN(v);
  1215. end;
  1216. procedure TMachoStructConverter.ConvertUInt64(var v: qword);
  1217. begin
  1218. v:=LEtoN(v);
  1219. end;
  1220. procedure TMachoStructConverter.ConvertUInt16(var v: Word);
  1221. begin
  1222. v:=LEToN(v);
  1223. end;
  1224. end.