patchfinder64.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. //
  2. // patchfinder64.c
  3. // extra_recipe
  4. //
  5. // Created by xerub on 06/06/2017.
  6. // Copyright © 2017 xerub. All rights reserved.
  7. //
  8. #include <assert.h>
  9. #include <stdint.h>
  10. #include <string.h>
  11. #include "kernel.h"
  12. typedef unsigned long long addr_t;
  13. #define IS64(image) (*(uint8_t *)(image) & 1)
  14. #define MACHO(p) ((*(unsigned int *)(p) & ~1) == 0xfeedface)
  15. /* generic stuff *************************************************************/
  16. #define UCHAR_MAX 255
  17. static unsigned char *
  18. boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,
  19. const unsigned char* needle, size_t nlen)
  20. {
  21. size_t last, scan = 0;
  22. size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:
  23. * bad character shift */
  24. /* Sanity checks on the parameters */
  25. if (nlen <= 0 || !haystack || !needle)
  26. return NULL;
  27. /* ---- Preprocess ---- */
  28. /* Initialize the table to default value */
  29. /* When a character is encountered that does not occur
  30. * in the needle, we can safely skip ahead for the whole
  31. * length of the needle.
  32. */
  33. for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)
  34. bad_char_skip[scan] = nlen;
  35. /* C arrays have the first byte at [0], therefore:
  36. * [nlen - 1] is the last byte of the array. */
  37. last = nlen - 1;
  38. /* Then populate it with the analysis of the needle */
  39. for (scan = 0; scan < last; scan = scan + 1)
  40. bad_char_skip[needle[scan]] = last - scan;
  41. /* ---- Do the matching ---- */
  42. /* Search the haystack, while the needle can still be within it. */
  43. while (hlen >= nlen)
  44. {
  45. /* scan from the end of the needle */
  46. for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)
  47. if (scan == 0) /* If the first byte matches, we've found it. */
  48. return (void *)haystack;
  49. /* otherwise, we need to skip some bytes and start again.
  50. Note that here we are getting the skip value based on the last byte
  51. of needle, no matter where we didn't match. So if needle is: "abcd"
  52. then we are skipping based on 'd' and that value will be 4, and
  53. for "abcdd" we again skip on 'd' but the value will be only 1.
  54. The alternative of pretending that the mismatched character was
  55. the last character is slower in the normal case (E.g. finding
  56. "abcd" in "...azcd..." gives 4 by using 'd' but only
  57. 4-2==2 using 'z'. */
  58. hlen -= bad_char_skip[haystack[last]];
  59. haystack += bad_char_skip[haystack[last]];
  60. }
  61. return NULL;
  62. }
  63. /* disassembler **************************************************************/
  64. static int HighestSetBit(int N, uint32_t imm)
  65. {
  66. int i;
  67. for (i = N - 1; i >= 0; i--) {
  68. if (imm & (1 << i)) {
  69. return i;
  70. }
  71. }
  72. return -1;
  73. }
  74. static uint64_t ZeroExtendOnes(unsigned M, unsigned N) // zero extend M ones to N width
  75. {
  76. (void)N;
  77. return ((uint64_t)1 << M) - 1;
  78. }
  79. static uint64_t RORZeroExtendOnes(unsigned M, unsigned N, unsigned R)
  80. {
  81. uint64_t val = ZeroExtendOnes(M, N);
  82. if (R == 0) {
  83. return val;
  84. }
  85. return ((val >> R) & (((uint64_t)1 << (N - R)) - 1)) | ((val & (((uint64_t)1 << R) - 1)) << (N - R));
  86. }
  87. static uint64_t Replicate(uint64_t val, unsigned bits)
  88. {
  89. uint64_t ret = val;
  90. unsigned shift;
  91. for (shift = bits; shift < 64; shift += bits) { // XXX actually, it is either 32 or 64
  92. ret |= (val << shift);
  93. }
  94. return ret;
  95. }
  96. static int DecodeBitMasks(unsigned immN, unsigned imms, unsigned immr, int immediate, uint64_t *newval)
  97. {
  98. unsigned levels, S, R, esize;
  99. int len = HighestSetBit(7, (immN << 6) | (~imms & 0x3F));
  100. if (len < 1) {
  101. return -1;
  102. }
  103. levels = ZeroExtendOnes(len, 6);
  104. if (immediate && (imms & levels) == levels) {
  105. return -1;
  106. }
  107. S = imms & levels;
  108. R = immr & levels;
  109. esize = 1 << len;
  110. *newval = Replicate(RORZeroExtendOnes(S + 1, esize, R), esize);
  111. return 0;
  112. }
  113. static int DecodeMov(uint32_t opcode, uint64_t total, int first, uint64_t *newval)
  114. {
  115. unsigned o = (opcode >> 29) & 3;
  116. unsigned k = (opcode >> 23) & 0x3F;
  117. unsigned rn, rd;
  118. uint64_t i;
  119. if (k == 0x24 && o == 1) { // MOV (bitmask imm) <=> ORR (immediate)
  120. unsigned s = (opcode >> 31) & 1;
  121. unsigned N = (opcode >> 22) & 1;
  122. if (s == 0 && N != 0) {
  123. return -1;
  124. }
  125. rn = (opcode >> 5) & 0x1F;
  126. if (rn == 31) {
  127. unsigned imms = (opcode >> 10) & 0x3F;
  128. unsigned immr = (opcode >> 16) & 0x3F;
  129. return DecodeBitMasks(N, imms, immr, 1, newval);
  130. }
  131. } else if (k == 0x25) { // MOVN/MOVZ/MOVK
  132. unsigned s = (opcode >> 31) & 1;
  133. unsigned h = (opcode >> 21) & 3;
  134. if (s == 0 && h > 1) {
  135. return -1;
  136. }
  137. i = (opcode >> 5) & 0xFFFF;
  138. h *= 16;
  139. i <<= h;
  140. if (o == 0) { // MOVN
  141. *newval = ~i;
  142. return 0;
  143. } else if (o == 2) { // MOVZ
  144. *newval = i;
  145. return 0;
  146. } else if (o == 3 && !first) { // MOVK
  147. *newval = (total & ~((uint64_t)0xFFFF << h)) | i;
  148. return 0;
  149. }
  150. } else if ((k | 1) == 0x23 && !first) { // ADD (immediate)
  151. unsigned h = (opcode >> 22) & 3;
  152. if (h > 1) {
  153. return -1;
  154. }
  155. rd = opcode & 0x1F;
  156. rn = (opcode >> 5) & 0x1F;
  157. if (rd != rn) {
  158. return -1;
  159. }
  160. i = (opcode >> 10) & 0xFFF;
  161. h *= 12;
  162. i <<= h;
  163. if (o & 2) { // SUB
  164. *newval = total - i;
  165. return 0;
  166. } else { // ADD
  167. *newval = total + i;
  168. return 0;
  169. }
  170. }
  171. return -1;
  172. }
  173. /* patchfinder ***************************************************************/
  174. static addr_t
  175. step64(const uint8_t *buf, addr_t start, size_t length, uint32_t what, uint32_t mask)
  176. {
  177. addr_t end = start + length;
  178. while (start < end) {
  179. uint32_t x = *(uint32_t *)(buf + start);
  180. if ((x & mask) == what) {
  181. return start;
  182. }
  183. start += 4;
  184. }
  185. return 0;
  186. }
  187. static addr_t
  188. step64_back(const uint8_t *buf, addr_t start, size_t length, uint32_t what, uint32_t mask)
  189. {
  190. addr_t end = start - length;
  191. while (start >= end) {
  192. uint32_t x = *(uint32_t *)(buf + start);
  193. if ((x & mask) == what) {
  194. return start;
  195. }
  196. start -= 4;
  197. }
  198. return 0;
  199. }
  200. static addr_t
  201. bof64(const uint8_t *buf, addr_t start, addr_t where)
  202. {
  203. for (; where >= start; where -= 4) {
  204. uint32_t op = *(uint32_t *)(buf + where);
  205. if ((op & 0xFFC003FF) == 0x910003FD) {
  206. unsigned delta = (op >> 10) & 0xFFF;
  207. //printf("%x: ADD X29, SP, #0x%x\n", where, delta);
  208. if ((delta & 0xF) == 0) {
  209. addr_t prev = where - ((delta >> 4) + 1) * 4;
  210. uint32_t au = *(uint32_t *)(buf + prev);
  211. if ((au & 0xFFC003E0) == 0xA98003E0) {
  212. //printf("%x: STP x, y, [SP,#-imm]!\n", prev);
  213. return prev;
  214. }
  215. }
  216. }
  217. }
  218. return 0;
  219. }
  220. static addr_t
  221. xref64(const uint8_t *buf, addr_t start, addr_t end, addr_t what)
  222. {
  223. addr_t i;
  224. uint64_t value[32];
  225. memset(value, 0, sizeof(value));
  226. end &= ~3;
  227. for (i = start & ~3; i < end; i += 4) {
  228. uint32_t op = *(uint32_t *)(buf + i);
  229. unsigned reg = op & 0x1F;
  230. if ((op & 0x9F000000) == 0x90000000) {
  231. signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);
  232. //printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF));
  233. value[reg] = ((long long)adr << 1) + (i & ~0xFFF);
  234. /*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) {
  235. unsigned rd = op & 0x1F;
  236. unsigned rm = (op >> 16) & 0x1F;
  237. //printf("%llx: MOV X%d, X%d\n", i, rd, rm);
  238. value[rd] = value[rm];*/
  239. } else if ((op & 0xFF000000) == 0x91000000) {
  240. unsigned rn = (op >> 5) & 0x1F;
  241. unsigned shift = (op >> 22) & 3;
  242. unsigned imm = (op >> 10) & 0xFFF;
  243. if (shift == 1) {
  244. imm <<= 12;
  245. } else {
  246. //assert(shift == 0);
  247. if (shift > 1) continue;
  248. }
  249. //printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm);
  250. value[reg] = value[rn] + imm;
  251. } else if ((op & 0xF9C00000) == 0xF9400000) {
  252. unsigned rn = (op >> 5) & 0x1F;
  253. unsigned imm = ((op >> 10) & 0xFFF) << 3;
  254. //printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);
  255. if (!imm) continue; // XXX not counted as true xref
  256. value[reg] = value[rn] + imm; // XXX address, not actual value
  257. /*} else if ((op & 0xF9C00000) == 0xF9000000) {
  258. unsigned rn = (op >> 5) & 0x1F;
  259. unsigned imm = ((op >> 10) & 0xFFF) << 3;
  260. //printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);
  261. if (!imm) continue; // XXX not counted as true xref
  262. value[rn] = value[rn] + imm; // XXX address, not actual value*/
  263. } else if ((op & 0x9F000000) == 0x10000000) {
  264. signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);
  265. //printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i);
  266. value[reg] = ((long long)adr >> 11) + i;
  267. } else if ((op & 0xFF000000) == 0x58000000) {
  268. unsigned adr = (op & 0xFFFFE0) >> 3;
  269. //printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i);
  270. value[reg] = adr + i; // XXX address, not actual value
  271. }
  272. if (value[reg] == what) {
  273. return i;
  274. }
  275. }
  276. return 0;
  277. }
  278. static addr_t
  279. calc64(const uint8_t *buf, addr_t start, addr_t end, int which)
  280. {
  281. addr_t i;
  282. uint64_t value[32];
  283. memset(value, 0, sizeof(value));
  284. end &= ~3;
  285. for (i = start & ~3; i < end; i += 4) {
  286. uint32_t op = *(uint32_t *)(buf + i);
  287. unsigned reg = op & 0x1F;
  288. if ((op & 0x9F000000) == 0x90000000) {
  289. signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);
  290. //printf("%llx: ADRP X%d, 0x%llx\n", i, reg, ((long long)adr << 1) + (i & ~0xFFF));
  291. value[reg] = ((long long)adr << 1) + (i & ~0xFFF);
  292. /*} else if ((op & 0xFFE0FFE0) == 0xAA0003E0) {
  293. unsigned rd = op & 0x1F;
  294. unsigned rm = (op >> 16) & 0x1F;
  295. //printf("%llx: MOV X%d, X%d\n", i, rd, rm);
  296. value[rd] = value[rm];*/
  297. } else if ((op & 0xFF000000) == 0x91000000) {
  298. unsigned rn = (op >> 5) & 0x1F;
  299. unsigned shift = (op >> 22) & 3;
  300. unsigned imm = (op >> 10) & 0xFFF;
  301. if (shift == 1) {
  302. imm <<= 12;
  303. } else {
  304. //assert(shift == 0);
  305. if (shift > 1) continue;
  306. }
  307. //printf("%llx: ADD X%d, X%d, 0x%x\n", i, reg, rn, imm);
  308. value[reg] = value[rn] + imm;
  309. } else if ((op & 0xF9C00000) == 0xF9400000) {
  310. unsigned rn = (op >> 5) & 0x1F;
  311. unsigned imm = ((op >> 10) & 0xFFF) << 3;
  312. //printf("%llx: LDR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);
  313. if (!imm) continue; // XXX not counted as true xref
  314. value[reg] = value[rn] + imm; // XXX address, not actual value
  315. } else if ((op & 0xF9C00000) == 0xF9000000) {
  316. unsigned rn = (op >> 5) & 0x1F;
  317. unsigned imm = ((op >> 10) & 0xFFF) << 3;
  318. //printf("%llx: STR X%d, [X%d, 0x%x]\n", i, reg, rn, imm);
  319. if (!imm) continue; // XXX not counted as true xref
  320. value[rn] = value[rn] + imm; // XXX address, not actual value
  321. } else if ((op & 0x9F000000) == 0x10000000) {
  322. signed adr = ((op & 0x60000000) >> 18) | ((op & 0xFFFFE0) << 8);
  323. //printf("%llx: ADR X%d, 0x%llx\n", i, reg, ((long long)adr >> 11) + i);
  324. value[reg] = ((long long)adr >> 11) + i;
  325. } else if ((op & 0xFF000000) == 0x58000000) {
  326. unsigned adr = (op & 0xFFFFE0) >> 3;
  327. //printf("%llx: LDR X%d, =0x%llx\n", i, reg, adr + i);
  328. value[reg] = adr + i; // XXX address, not actual value
  329. }
  330. }
  331. return value[which];
  332. }
  333. static addr_t
  334. calc64mov(const uint8_t *buf, addr_t start, addr_t end, int which)
  335. {
  336. addr_t i;
  337. uint64_t value[32];
  338. memset(value, 0, sizeof(value));
  339. end &= ~3;
  340. for (i = start & ~3; i < end; i += 4) {
  341. uint32_t op = *(uint32_t *)(buf + i);
  342. unsigned reg = op & 0x1F;
  343. uint64_t newval;
  344. int rv = DecodeMov(op, value[reg], 0, &newval);
  345. if (rv == 0) {
  346. if (((op >> 31) & 1) == 0) {
  347. newval &= 0xFFFFFFFF;
  348. }
  349. value[reg] = newval;
  350. }
  351. }
  352. return value[which];
  353. }
  354. static addr_t
  355. find_call64(const uint8_t *buf, addr_t start, size_t length)
  356. {
  357. return step64(buf, start, length, 0x94000000, 0xFC000000);
  358. }
  359. static addr_t
  360. follow_call64(const uint8_t *buf, addr_t call)
  361. {
  362. long long w;
  363. w = *(uint32_t *)(buf + call) & 0x3FFFFFF;
  364. w <<= 64 - 26;
  365. w >>= 64 - 26 - 2;
  366. return call + w;
  367. }
  368. static addr_t
  369. follow_cbz(const uint8_t *buf, addr_t cbz)
  370. {
  371. return cbz + ((*(int *)(buf + cbz) & 0x3FFFFE0) << 10 >> 13);
  372. }
  373. /* kernel iOS10 **************************************************************/
  374. #include <fcntl.h>
  375. #include <stdio.h>
  376. #include <stdlib.h>
  377. #include <unistd.h>
  378. #include <mach-o/loader.h>
  379. #ifdef __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
  380. #include <mach/mach.h>
  381. size_t kread(uint64_t where, void *p, size_t size);
  382. #endif
  383. static uint8_t *kernel = NULL;
  384. static size_t kernel_size = 0;
  385. static addr_t xnucore_base = 0;
  386. static addr_t xnucore_size = 0;
  387. static addr_t prelink_base = 0;
  388. static addr_t prelink_size = 0;
  389. static addr_t cstring_base = 0;
  390. static addr_t cstring_size = 0;
  391. static addr_t pstring_base = 0;
  392. static addr_t pstring_size = 0;
  393. static addr_t kerndumpbase = -1;
  394. static addr_t kernel_entry = 0;
  395. static void *kernel_mh = 0;
  396. static addr_t kernel_delta = 0;
  397. int
  398. init_patchfinder(const char *filename)
  399. {
  400. size_t rv;
  401. uint8_t buf[0x4000];
  402. unsigned i, j;
  403. const struct mach_header *hdr = (struct mach_header *)buf;
  404. const uint8_t *q;
  405. addr_t min = -1;
  406. addr_t max = 0;
  407. int is64 = 0;
  408. #ifdef __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
  409. #define close(f)
  410. rv = kread(kernel_base, buf, sizeof(buf));
  411. if (rv != sizeof(buf)) {
  412. printf("failed kread, got size: %zu \n", rv);
  413. return -1;
  414. }
  415. #else /* __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ */
  416. printf("this code right here has run ............. \n");
  417. int fd = open(filename, O_RDONLY);
  418. if (fd < 0) {
  419. printf("failed at open, got fd: %s \n", fd);
  420. return -1;
  421. }
  422. rv = rk32_via_tfp0(tfp0, fd);
  423. //rv = read(fd, buf, sizeof(buf));
  424. if (rv != sizeof(buf)) {
  425. close(fd);
  426. printf("failed at buf read, got rv: %d \n", rv);
  427. return -1;
  428. }
  429. #endif /* __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ */
  430. if (!MACHO(buf)) {
  431. close(fd);
  432. printf("failed macho, buf: %s \n", buf);
  433. return -1;
  434. }
  435. if (IS64(buf)) {
  436. is64 = 4;
  437. }
  438. q = buf + sizeof(struct mach_header) + is64;
  439. for (i = 0; i < hdr->ncmds; i++) {
  440. const struct load_command *cmd = (struct load_command *)q;
  441. if (cmd->cmd == LC_SEGMENT_64) {
  442. const struct segment_command_64 *seg = (struct segment_command_64 *)q;
  443. if (min > seg->vmaddr) {
  444. min = seg->vmaddr;
  445. }
  446. if (max < seg->vmaddr + seg->vmsize) {
  447. max = seg->vmaddr + seg->vmsize;
  448. }
  449. if (!strcmp(seg->segname, "__TEXT_EXEC")) {
  450. xnucore_base = seg->vmaddr;
  451. xnucore_size = seg->filesize;
  452. }
  453. if (!strcmp(seg->segname, "__PLK_TEXT_EXEC")) {
  454. prelink_base = seg->vmaddr;
  455. prelink_size = seg->filesize;
  456. }
  457. if (!strcmp(seg->segname, "__TEXT")) {
  458. const struct section_64 *sec = (struct section_64 *)(seg + 1);
  459. for (j = 0; j < seg->nsects; j++) {
  460. if (!strcmp(sec[j].sectname, "__cstring")) {
  461. cstring_base = sec[j].addr;
  462. cstring_size = sec[j].size;
  463. }
  464. }
  465. }
  466. if (!strcmp(seg->segname, "__PRELINK_TEXT")) {
  467. const struct section_64 *sec = (struct section_64 *)(seg + 1);
  468. for (j = 0; j < seg->nsects; j++) {
  469. if (!strcmp(sec[j].sectname, "__text")) {
  470. pstring_base = sec[j].addr;
  471. pstring_size = sec[j].size;
  472. }
  473. }
  474. }
  475. }
  476. if (cmd->cmd == LC_UNIXTHREAD) {
  477. uint32_t *ptr = (uint32_t *)(cmd + 1);
  478. uint32_t flavor = ptr[0];
  479. struct {
  480. uint64_t x[29]; /* General purpose registers x0-x28 */
  481. uint64_t fp; /* Frame pointer x29 */
  482. uint64_t lr; /* Link register x30 */
  483. uint64_t sp; /* Stack pointer x31 */
  484. uint64_t pc; /* Program counter */
  485. uint32_t cpsr; /* Current program status register */
  486. } *thread = (void *)(ptr + 2);
  487. if (flavor == 6) {
  488. kernel_entry = thread->pc;
  489. }
  490. }
  491. q = q + cmd->cmdsize;
  492. }
  493. kerndumpbase = min;
  494. xnucore_base -= kerndumpbase;
  495. prelink_base -= kerndumpbase;
  496. cstring_base -= kerndumpbase;
  497. pstring_base -= kerndumpbase;
  498. kernel_size = max - min;
  499. #ifdef __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__
  500. kernel = malloc(kernel_size);
  501. if (!kernel) {
  502. printf("failed to malloc kern \n");
  503. return -1;
  504. }
  505. rv = kread(kerndumpbase, kernel, kernel_size);
  506. // rv = kread(kerndumpbase, kernel, kernel_size);
  507. if (rv != kernel_size) {
  508. free(kernel);
  509. printf("failed to kread kern, rv: %zu \n", rv);
  510. return -1;
  511. }
  512. kernel_mh = kernel + kernel_base - min;
  513. (void)filename;
  514. #undef close
  515. #else /* __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ */
  516. kernel = calloc(1, kernel_size);
  517. if (!kernel) {
  518. close(fd);
  519. printf("failed to calloc kern, kernel: %d \n", kernel);
  520. return -1;
  521. }
  522. q = buf + sizeof(struct mach_header) + is64;
  523. for (i = 0; i < hdr->ncmds; i++) {
  524. const struct load_command *cmd = (struct load_command *)q;
  525. if (cmd->cmd == LC_SEGMENT_64) {
  526. const struct segment_command_64 *seg = (struct segment_command_64 *)q;
  527. size_t sz = pread(fd, kernel + seg->vmaddr - min, seg->filesize, seg->fileoff);
  528. if (sz != seg->filesize) {
  529. close(fd);
  530. free(kernel);
  531. printf("sz != seg->filesize, sz: %zu", sz);
  532. return -1;
  533. }
  534. if (!kernel_mh) {
  535. kernel_mh = kernel + seg->vmaddr - min;
  536. }
  537. if (!strcmp(seg->segname, "__LINKEDIT")) {
  538. kernel_delta = seg->vmaddr - min - seg->fileoff;
  539. }
  540. }
  541. q = q + cmd->cmdsize;
  542. }
  543. close(fd);
  544. (void)base;
  545. #endif /* __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ */
  546. return 0;
  547. }
  548. void
  549. term_kernel(void)
  550. {
  551. free(kernel);
  552. }
  553. /* these operate on VA ******************************************************/
  554. #define INSN_RET 0xD65F03C0, 0xFFFFFFFF
  555. #define INSN_CALL 0x94000000, 0xFC000000
  556. #define INSN_B 0x14000000, 0xFC000000
  557. #define INSN_CBZ 0x34000000, 0xFC000000
  558. addr_t
  559. find_register_value(addr_t where, int reg)
  560. {
  561. addr_t val;
  562. addr_t bof = 0;
  563. where -= kerndumpbase;
  564. if (where > xnucore_base) {
  565. bof = bof64(kernel, xnucore_base, where);
  566. if (!bof) {
  567. bof = xnucore_base;
  568. }
  569. } else if (where > prelink_base) {
  570. bof = bof64(kernel, prelink_base, where);
  571. if (!bof) {
  572. bof = prelink_base;
  573. }
  574. }
  575. val = calc64(kernel, bof, where, reg);
  576. if (!val) {
  577. return 0;
  578. }
  579. return val + kerndumpbase;
  580. }
  581. addr_t
  582. find_reference(addr_t to, int n, int prelink)
  583. {
  584. addr_t ref, end;
  585. addr_t base = xnucore_base;
  586. addr_t size = xnucore_size;
  587. if (prelink) {
  588. base = prelink_base;
  589. size = prelink_size;
  590. }
  591. if (n <= 0) {
  592. n = 1;
  593. }
  594. end = base + size;
  595. to -= kerndumpbase;
  596. do {
  597. ref = xref64(kernel, base, end, to);
  598. if (!ref) {
  599. return 0;
  600. }
  601. base = ref + 4;
  602. } while (--n > 0);
  603. return ref + kerndumpbase;
  604. }
  605. addr_t
  606. find_strref(const char *string, int n, int prelink)
  607. {
  608. uint8_t *str;
  609. addr_t base = cstring_base;
  610. addr_t size = cstring_size;
  611. if (prelink) {
  612. base = pstring_base;
  613. size = pstring_size;
  614. }
  615. str = boyermoore_horspool_memmem(kernel + base, size, (uint8_t *)string, strlen(string));
  616. if (!str) {
  617. return 0;
  618. }
  619. return find_reference(str - kernel + kerndumpbase, n, prelink);
  620. }
  621. addr_t
  622. find_gPhysBase(void)
  623. {
  624. addr_t ret, val;
  625. addr_t ref = find_strref("\"pmap_map_high_window_bd: insufficient pages", 1, 0);
  626. if (!ref) {
  627. return 0;
  628. }
  629. ref -= kerndumpbase;
  630. ret = step64(kernel, ref, 64, INSN_RET);
  631. if (!ret) {
  632. return 0;
  633. }
  634. val = calc64(kernel, ref, ret, 8);
  635. if (!val) {
  636. return 0;
  637. }
  638. return val + kerndumpbase;
  639. }
  640. addr_t
  641. find_kernel_pmap(void)
  642. {
  643. addr_t call, bof, val;
  644. addr_t ref = find_strref("\"pmap_map_bd\"", 1, 0);
  645. if (!ref) {
  646. return 0;
  647. }
  648. ref -= kerndumpbase;
  649. call = step64_back(kernel, ref, 64, INSN_CALL);
  650. if (!call) {
  651. return 0;
  652. }
  653. bof = bof64(kernel, xnucore_base, call);
  654. if (!bof) {
  655. return 0;
  656. }
  657. val = calc64(kernel, bof, call, 2);
  658. if (!val) {
  659. return 0;
  660. }
  661. return val + kerndumpbase;
  662. }
  663. addr_t
  664. find_amfiret(void)
  665. {
  666. addr_t ret;
  667. addr_t ref = find_strref("AMFI: hook..execve() killing pid %u: %s\n", 1, 1);
  668. if (!ref) {
  669. return 0;
  670. }
  671. ref -= kerndumpbase;
  672. ret = step64(kernel, ref, 512, INSN_RET);
  673. if (!ret) {
  674. return 0;
  675. }
  676. return ret + kerndumpbase;
  677. }
  678. addr_t
  679. find_ret_0(void)
  680. {
  681. addr_t off;
  682. uint32_t *k;
  683. k = (uint32_t *)(kernel + xnucore_base);
  684. for (off = 0; off < xnucore_size - 4; off += 4, k++) {
  685. if (k[0] == 0xAA1F03E0 && k[1] == 0xD65F03C0) {
  686. return off + xnucore_base + kerndumpbase;
  687. }
  688. }
  689. k = (uint32_t *)(kernel + prelink_base);
  690. for (off = 0; off < prelink_size - 4; off += 4, k++) {
  691. if (k[0] == 0xAA1F03E0 && k[1] == 0xD65F03C0) {
  692. return off + prelink_base + kerndumpbase;
  693. }
  694. }
  695. return 0;
  696. }
  697. addr_t
  698. find_amfi_memcmpstub(void)
  699. {
  700. addr_t call, dest, reg;
  701. addr_t ref = find_strref("%s: Possible race detected. Rejecting.", 1, 1);
  702. if (!ref) {
  703. return 0;
  704. }
  705. ref -= kerndumpbase;
  706. call = step64_back(kernel, ref, 64, INSN_CALL);
  707. if (!call) {
  708. return 0;
  709. }
  710. dest = follow_call64(kernel, call);
  711. if (!dest) {
  712. return 0;
  713. }
  714. reg = calc64(kernel, dest, dest + 8, 16);
  715. if (!reg) {
  716. return 0;
  717. }
  718. return reg + kerndumpbase;
  719. }
  720. addr_t
  721. find_sbops(void)
  722. {
  723. addr_t off, what;
  724. uint8_t *str = boyermoore_horspool_memmem(kernel + pstring_base, pstring_size, (uint8_t *)"Seatbelt sandbox policy", sizeof("Seatbelt sandbox policy") - 1);
  725. if (!str) {
  726. return 0;
  727. }
  728. what = str - kernel + kerndumpbase;
  729. for (off = 0; off < kernel_size - prelink_base; off += 8) {
  730. if (*(uint64_t *)(kernel + prelink_base + off) == what) {
  731. return *(uint64_t *)(kernel + prelink_base + off + 24);
  732. }
  733. }
  734. return 0;
  735. }
  736. addr_t
  737. find_lwvm_mapio_patch(void)
  738. {
  739. addr_t call, dest, reg;
  740. addr_t ref = find_strref("_mapForIO", 1, 1);
  741. if (!ref) {
  742. return 0;
  743. }
  744. ref -= kerndumpbase;
  745. call = step64(kernel, ref, 64, INSN_CALL);
  746. if (!call) {
  747. return 0;
  748. }
  749. call = step64(kernel, call + 4, 64, INSN_CALL);
  750. if (!call) {
  751. return 0;
  752. }
  753. dest = follow_call64(kernel, call);
  754. if (!dest) {
  755. return 0;
  756. }
  757. reg = calc64(kernel, dest, dest + 8, 16);
  758. if (!reg) {
  759. return 0;
  760. }
  761. return reg + kerndumpbase;
  762. }
  763. addr_t
  764. find_lwvm_mapio_newj(void)
  765. {
  766. addr_t call;
  767. addr_t ref = find_strref("_mapForIO", 1, 1);
  768. if (!ref) {
  769. return 0;
  770. }
  771. ref -= kerndumpbase;
  772. call = step64(kernel, ref, 64, INSN_CALL);
  773. if (!call) {
  774. return 0;
  775. }
  776. call = step64(kernel, call + 4, 64, INSN_CALL);
  777. if (!call) {
  778. return 0;
  779. }
  780. call = step64(kernel, call + 4, 64, INSN_CALL);
  781. if (!call) {
  782. return 0;
  783. }
  784. call = step64_back(kernel, call, 64, INSN_B);
  785. if (!call) {
  786. return 0;
  787. }
  788. return call + 4 + kerndumpbase;
  789. }
  790. addr_t
  791. find_cpacr_write(void)
  792. {
  793. addr_t off;
  794. uint32_t *k;
  795. k = (uint32_t *)(kernel + xnucore_base);
  796. for (off = 0; off < xnucore_size - 4; off += 4, k++) {
  797. if (k[0] == 0xd5181040) {
  798. return off + xnucore_base + kerndumpbase;
  799. }
  800. }
  801. return 0;
  802. }
  803. addr_t
  804. find_str(const char *string)
  805. {
  806. uint8_t *str = boyermoore_horspool_memmem(kernel, kernel_size, (uint8_t *)string, strlen(string));
  807. if (!str) {
  808. return 0;
  809. }
  810. return str - kernel + kerndumpbase;
  811. }
  812. addr_t
  813. find_entry(void)
  814. {
  815. /* XXX returns an unslid address */
  816. return kernel_entry;
  817. }
  818. const unsigned char *
  819. find_mh(void)
  820. {
  821. return kernel_mh;
  822. }
  823. addr_t
  824. find_amfiops(void)
  825. {
  826. addr_t off, what;
  827. uint8_t *str = boyermoore_horspool_memmem(kernel + pstring_base, pstring_size, (uint8_t *)"Apple Mobile File Integrity", sizeof("Apple Mobile File Integrity") - 1);
  828. if (!str) {
  829. return 0;
  830. }
  831. what = str - kernel + kerndumpbase;
  832. /* XXX will only work on a dumped kernel */
  833. for (off = 0; off < kernel_size - prelink_base; off += 8) {
  834. if (*(uint64_t *)(kernel + prelink_base + off) == what) {
  835. return *(uint64_t *)(kernel + prelink_base + off + 0x18);
  836. }
  837. }
  838. return 0;
  839. }
  840. addr_t
  841. find_sysbootnonce(void)
  842. {
  843. addr_t off, what;
  844. uint8_t *str = boyermoore_horspool_memmem(kernel + cstring_base, cstring_size, (uint8_t *)"com.apple.System.boot-nonce", sizeof("com.apple.System.boot-nonce") - 1);
  845. if (!str) {
  846. return 0;
  847. }
  848. what = str - kernel + kerndumpbase;
  849. for (off = 0; off < kernel_size - xnucore_base; off += 8) {
  850. if (*(uint64_t *)(kernel + xnucore_base + off) == what) {
  851. return xnucore_base + off + 8 + 4 + kerndumpbase;
  852. }
  853. }
  854. return 0;
  855. }
  856. uint64_t find_copyout(void) {
  857. // Find the first reference to the string
  858. addr_t ref = find_strref("\"%s(%p, %p, %lu) - transfer too large\"", 2, 0);
  859. if (!ref) {
  860. return 0;
  861. }
  862. ref -= kerndumpbase;
  863. uint64_t start = 0;
  864. for (int i = 4; i < 0x100*4; i+=4) {
  865. uint32_t op = *(uint32_t*)(kernel+ref-i);
  866. if (op == 0xd10143ff) { // SUB SP, SP, #0x50
  867. start = ref-i;
  868. break;
  869. }
  870. }
  871. if (!start) {
  872. return 0;
  873. }
  874. return start + kerndumpbase;
  875. }
  876. uint64_t find_bzero(void) {
  877. // Just find SYS #3, c7, c4, #1, X3, then get the start of that function
  878. addr_t off;
  879. uint32_t *k;
  880. k = (uint32_t *)(kernel + xnucore_base);
  881. for (off = 0; off < xnucore_size - 4; off += 4, k++) {
  882. if (k[0] == 0xd50b7423) {
  883. off += xnucore_base;
  884. break;
  885. }
  886. }
  887. uint64_t start = bof64(kernel, xnucore_base, off);
  888. if (!start) {
  889. return 0;
  890. }
  891. return start + kerndumpbase;
  892. }
  893. addr_t find_bcopy(void) {
  894. // Jumps straight into memmove after switching x0 and x1 around
  895. // Guess we just find the switch and that's it
  896. addr_t off;
  897. uint32_t *k;
  898. k = (uint32_t *)(kernel + xnucore_base);
  899. for (off = 0; off < xnucore_size - 4; off += 4, k++) {
  900. if (k[0] == 0xAA0003E3 && k[1] == 0xAA0103E0 && k[2] == 0xAA0303E1 && k[3] == 0xd503201F) {
  901. return off + xnucore_base + kerndumpbase;
  902. }
  903. }
  904. k = (uint32_t *)(kernel + prelink_base);
  905. for (off = 0; off < prelink_size - 4; off += 4, k++) {
  906. if (k[0] == 0xAA0003E3 && k[1] == 0xAA0103E0 && k[2] == 0xAA0303E1 && k[3] == 0xd503201F) {
  907. return off + prelink_base + kerndumpbase;
  908. }
  909. }
  910. return 0;
  911. }
  912. addr_t find_trustcache(void) {
  913. addr_t call, func, val;
  914. addr_t ref = find_strref("amfi_prevent_old_entitled_platform_binaries", 1, 1);
  915. if (!ref) {
  916. ref = find_strref("com.apple.MobileFileIntegrity", 1, 1);
  917. }
  918. if (!ref) {
  919. printf("didnt find string ref\n");
  920. return 0;
  921. }
  922. ref -= kerndumpbase;
  923. call = step64(kernel, ref, 32, INSN_CALL);
  924. if (!call) {
  925. printf("couldn't find the call\n");
  926. return 0;
  927. }
  928. call = step64(kernel, call+4, 32, INSN_CALL);
  929. func = follow_call64(kernel, call);
  930. if (!func) {
  931. printf("couldn't follow the call\n");
  932. return 0;
  933. }
  934. val = calc64(kernel, func, func + 16, 8);
  935. if (!val) {
  936. return 0;
  937. }
  938. return val + kerndumpbase;
  939. }
  940. addr_t find_amficache(void) {
  941. addr_t call, func, bof, val;
  942. addr_t ref = find_strref("amfi_prevent_old_entitled_platform_binaries", 1, 1);
  943. if (!ref) {
  944. ref = find_strref("com.apple.MobileFileIntegrity", 1, 1);
  945. }
  946. if (!ref) {
  947. printf("didnt find string ref\n");
  948. return 0;
  949. }
  950. ref -= kerndumpbase;
  951. call = step64(kernel, ref, 32, INSN_CALL);
  952. if (!call) {
  953. printf("couldn't find the call\n");
  954. return 0;
  955. }
  956. call = step64(kernel, call+4, 32, INSN_CALL);
  957. func = follow_call64(kernel, call);
  958. if (!func) {
  959. printf("couldn't follow the call\n");
  960. return 0;
  961. }
  962. bof = bof64(kernel, func - 256, func);
  963. if (!bof) {
  964. printf("couldn't find the start of the function\n");
  965. return 0;
  966. }
  967. val = calc64(kernel, bof, func, 9);
  968. if (!val) {
  969. printf("couldn't find x9\n");
  970. return 0;
  971. }
  972. return val + kerndumpbase;
  973. }
  974. // #ifdef HAVE_MAIN
  975. /* extra_recipe **************************************************************/
  976. #define INSN_STR8 0xF9000000 | 8, 0xFFC00000 | 0x1F
  977. addr_t
  978. find_AGXCommandQueue_vtable(void)
  979. {
  980. addr_t val, str8;
  981. addr_t ref = find_strref("AGXCommandQueue", 1, 1);
  982. if (!ref) {
  983. return 0;
  984. }
  985. val = find_register_value(ref, 0);
  986. if (!val) {
  987. return 0;
  988. }
  989. ref = find_reference(val, 1, 1);
  990. if (!ref) {
  991. return 0;
  992. }
  993. ref -= kerndumpbase;
  994. str8 = step64(kernel, ref, 32, INSN_STR8);
  995. if (!str8) {
  996. return 0;
  997. }
  998. val = calc64(kernel, ref, str8, 8);
  999. if (!val) {
  1000. return 0;
  1001. }
  1002. return val + kerndumpbase;
  1003. }
  1004. addr_t
  1005. find_allproc(void)
  1006. {
  1007. addr_t val, bof, str8;
  1008. addr_t ref = find_strref("\"pgrp_add : pgrp is dead adding process\"", 1, 0);
  1009. if (!ref) {
  1010. return 0;
  1011. }
  1012. ref -= kerndumpbase;
  1013. bof = bof64(kernel, xnucore_base, ref);
  1014. if (!bof) {
  1015. return 0;
  1016. }
  1017. str8 = step64_back(kernel, ref, ref - bof, INSN_STR8);
  1018. if (!str8) {
  1019. return 0;
  1020. }
  1021. val = calc64(kernel, bof, str8, 8);
  1022. if (!val) {
  1023. return 0;
  1024. }
  1025. return val + kerndumpbase;
  1026. }
  1027. addr_t
  1028. find_call5(void)
  1029. {
  1030. addr_t bof;
  1031. uint8_t gadget[] = { 0x95, 0x5A, 0x40, 0xF9, 0x68, 0x02, 0x40, 0xF9, 0x88, 0x5A, 0x00, 0xF9, 0x60, 0xA2, 0x40, 0xA9 };
  1032. uint8_t *str = boyermoore_horspool_memmem(kernel + prelink_base, prelink_size, gadget, sizeof(gadget));
  1033. if (!str) {
  1034. return 0;
  1035. }
  1036. bof = bof64(kernel, prelink_base, str - kernel);
  1037. if (!bof) {
  1038. return 0;
  1039. }
  1040. return bof + kerndumpbase;
  1041. }
  1042. addr_t
  1043. find_realhost(addr_t priv)
  1044. {
  1045. addr_t val;
  1046. if (!priv) {
  1047. return 0;
  1048. }
  1049. priv -= kerndumpbase;
  1050. val = calc64(kernel, priv, priv + 12, 0);
  1051. if (!val) {
  1052. return 0;
  1053. }
  1054. return val + kerndumpbase;
  1055. }
  1056. uint64_t find_boot_args(unsigned* cmdline_offset) {
  1057. /*
  1058. ADRP X8, #_PE_state@PAGE
  1059. ADD X8, X8, #_PE_state@PAGEOFF
  1060. LDR X8, [X8,#(PE_state__boot_args - 0xFFFFFFF0078BF098)]
  1061. ADD X8, X8, #0x6C
  1062. STR X8, [SP,#0x550+var_550]
  1063. ADRP X0, #aBsdInitCannotF@PAGE ; "\"bsd_init: cannot find root vnode: %s"...
  1064. ADD X0, X0, #aBsdInitCannotF@PAGEOFF ; "\"bsd_init: cannot find root vnode: %s"...
  1065. BL _panic
  1066. */
  1067. addr_t ref = find_strref("\"bsd_init: cannot find root vnode: %s\"", 1, 0);
  1068. if (ref == 0) {
  1069. return 0;
  1070. }
  1071. ref -= kerndumpbase;
  1072. // skip add & adrp for panic str
  1073. ref -= 8;
  1074. uint32_t *insn = (uint32_t*)(kernel+ref);
  1075. // skip str
  1076. --insn;
  1077. // add xX, xX, #cmdline_offset
  1078. uint8_t xm = *insn&0x1f;
  1079. if (((*insn>>5)&0x1f) != xm || ((*insn>>22)&3) != 0) {
  1080. return 0;
  1081. }
  1082. *cmdline_offset = (*insn>>10) & 0xfff;
  1083. uint64_t val = kerndumpbase;
  1084. --insn;
  1085. // ldr xX, [xX, #(PE_state__boot_args - PE_state)]
  1086. if ((*insn & 0xF9C00000) != 0xF9400000) {
  1087. return 0;
  1088. }
  1089. // xd == xX, xn == xX,
  1090. if ((*insn&0x1f) != xm || ((*insn>>5)&0x1f) != xm) {
  1091. return 0;
  1092. }
  1093. val += ((*insn >> 10) & 0xFFF) << 3;
  1094. --insn;
  1095. // add xX, xX, #_PE_state@PAGEOFF
  1096. if ((*insn&0x1f) != xm || ((*insn>>5)&0x1f) != xm || ((*insn>>22)&3) != 0) {
  1097. return 0;
  1098. }
  1099. val += (*insn>>10) & 0xfff;
  1100. --insn;
  1101. if ((*insn & 0x1f) != xm) {
  1102. return 0;
  1103. }
  1104. // pc
  1105. val += ((uint8_t*)(insn) - kernel) & ~0xfff;
  1106. // don't ask, I wrote this at 5am
  1107. val += (*insn<<9 & 0x1ffffc000) | (*insn>>17 & 0x3000);
  1108. return val;
  1109. }
  1110. #include <mach-o/nlist.h>
  1111. addr_t
  1112. find_symbol(const char *symbol)
  1113. {
  1114. unsigned i;
  1115. const struct mach_header *hdr = kernel_mh;
  1116. const uint8_t *q;
  1117. int is64 = 0;
  1118. if (IS64(hdr)) {
  1119. is64 = 4;
  1120. }
  1121. /* XXX will only work on a decrypted kernel */
  1122. if (!kernel_delta) {
  1123. return 0;
  1124. }
  1125. /* XXX I should cache these. ohwell... */
  1126. q = (uint8_t *)(hdr + 1) + is64;
  1127. for (i = 0; i < hdr->ncmds; i++) {
  1128. const struct load_command *cmd = (struct load_command *)q;
  1129. if (cmd->cmd == LC_SYMTAB) {
  1130. const struct symtab_command *sym = (struct symtab_command *)q;
  1131. const char *stroff = (const char *)kernel + sym->stroff + kernel_delta;
  1132. if (is64) {
  1133. uint32_t k;
  1134. const struct nlist_64 *s = (struct nlist_64 *)(kernel + sym->symoff + kernel_delta);
  1135. for (k = 0; k < sym->nsyms; k++) {
  1136. if (s[k].n_type & N_STAB) {
  1137. continue;
  1138. }
  1139. if (s[k].n_value && (s[k].n_type & N_TYPE) != N_INDR) {
  1140. if (!strcmp(symbol, stroff + s[k].n_un.n_strx)) {
  1141. /* XXX this is an unslid address */
  1142. return s[k].n_value;
  1143. }
  1144. }
  1145. }
  1146. }
  1147. }
  1148. q = q + cmd->cmdsize;
  1149. }
  1150. return 0;
  1151. }
  1152. /* test **********************************************************************/
  1153. /*
  1154. int
  1155. main(int argc, char **argv)
  1156. {
  1157. int rv;
  1158. addr_t base = 0;
  1159. const addr_t vm_kernel_slide = 0;
  1160. rv = init_kernel(base, (argc > 1) ? argv[1] : "krnl");
  1161. assert(rv == 0);
  1162. addr_t AGXCommandQueue_vtable = find_AGXCommandQueue_vtable();
  1163. printf("\t\t\t<string>0x%llx</string>\n", AGXCommandQueue_vtable - vm_kernel_slide);
  1164. addr_t OSData_getMetaClass = find_symbol("__ZNK6OSData12getMetaClassEv");
  1165. printf("\t\t\t<string>0x%llx</string>\n", OSData_getMetaClass);
  1166. addr_t OSSerializer_serialize = find_symbol("__ZNK12OSSerializer9serializeEP11OSSerialize");
  1167. printf("\t\t\t<string>0x%llx</string>\n", OSSerializer_serialize);
  1168. addr_t k_uuid_copy = find_symbol("_uuid_copy");
  1169. printf("\t\t\t<string>0x%llx</string>\n", k_uuid_copy);
  1170. addr_t allproc = find_allproc();
  1171. printf("\t\t\t<string>0x%llx</string>\n", allproc);
  1172. addr_t realhost = find_realhost(find_symbol("_host_priv_self") + vm_kernel_slide);
  1173. printf("\t\t\t<string>0x%llx</string>\n", realhost - vm_kernel_slide);
  1174. addr_t call5 = find_call5();
  1175. printf("\t\t\t<string>0x%llx</string>\n", call5 - vm_kernel_slide);
  1176. assert(find_symbol("_rootvnode") == find_gPhysBase() + 0x38 - vm_kernel_slide);
  1177. term_kernel();
  1178. return 0;
  1179. }*/
  1180. // #endif /* HAVE_MAIN */