hex2_linker_x86.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. ## This file was generated by running:
  2. ## cat functions/exit.c functions/file.c functions/file_print.c functions/malloc.c functions/calloc.c functions/match.c functions/numerate_number.c functions/stat.c test/test22/hex2_linker.c >| ../stage0/stage3/hex2_linker_x86.c
  3. ## inside of M2-Planet's source repo
  4. ## Copyright (C) 2016 Jeremiah Orians
  5. ## This file is part of stage0.
  6. ##
  7. ## stage0 is free software: you can redistribute it and/or modify
  8. ## it under the terms of the GNU General Public License as published by
  9. ## the Free Software Foundation, either version 3 of the License, or
  10. ## (at your option) any later version.
  11. ##
  12. ## stage0 is distributed in the hope that it will be useful,
  13. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ## GNU General Public License for more details.
  16. ##
  17. ## You should have received a copy of the GNU General Public License
  18. ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
  19. // CONSTANT EXIT_FAILURE 1
  20. // CONSTANT EXIT_SUCCESS 0
  21. void exit(int value)
  22. {
  23. asm("POP_ebx"
  24. "POP_ebx"
  25. "LOAD_IMMEDIATE_eax %1"
  26. "INT_80");
  27. }
  28. /* Copyright (C) 2016 Jeremiah Orians
  29. * This file is part of stage0.
  30. *
  31. * stage0 is free software: you can redistribute it and/or modify
  32. * it under the terms of the GNU General Public License as published by
  33. * the Free Software Foundation, either version 3 of the License, or
  34. * (at your option) any later version.
  35. *
  36. * stage0 is distributed in the hope that it will be useful,
  37. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  39. * GNU General Public License for more details.
  40. *
  41. * You should have received a copy of the GNU General Public License
  42. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  43. */
  44. // CONSTANT stdin 0
  45. // CONSTANT stdout 1
  46. // CONSTANT stderr 2
  47. // CONSTANT EOF 0xFFFFFFFF
  48. int fgetc(FILE* f)
  49. {
  50. asm("LOAD_IMMEDIATE_eax %3"
  51. "LOAD_EFFECTIVE_ADDRESS_ebx %4"
  52. "LOAD_INTEGER_ebx"
  53. "PUSH_ebx"
  54. "COPY_esp_to_ecx"
  55. "LOAD_IMMEDIATE_edx %1"
  56. "INT_80"
  57. "TEST"
  58. "POP_eax"
  59. "JUMP_NE8 !FUNCTION_fgetc_Done"
  60. "LOAD_IMMEDIATE_eax %-1"
  61. ":FUNCTION_fgetc_Done");
  62. }
  63. void fputc(char s, FILE* f)
  64. {
  65. asm("LOAD_IMMEDIATE_eax %4"
  66. "LOAD_EFFECTIVE_ADDRESS_ebx %4"
  67. "LOAD_INTEGER_ebx"
  68. "LOAD_EFFECTIVE_ADDRESS_ecx %8"
  69. "LOAD_IMMEDIATE_edx %1"
  70. "INT_80");
  71. }
  72. /* Important values needed for open
  73. * O_RDONLY => 0
  74. * O_WRONLY => 1
  75. * O_RDWR => 2
  76. * O_CREAT => 64
  77. * O_TRUNC => 512
  78. * S_IRWXU => 00700
  79. * S_IXUSR => 00100
  80. * S_IWUSR => 00200
  81. * S_IRUSR => 00400
  82. */
  83. FILE* open(char* name, int flag, int mode)
  84. {
  85. asm("LOAD_EFFECTIVE_ADDRESS_ebx %12"
  86. "LOAD_INTEGER_ebx"
  87. "LOAD_EFFECTIVE_ADDRESS_ecx %8"
  88. "LOAD_INTEGER_ecx"
  89. "LOAD_EFFECTIVE_ADDRESS_edx %4"
  90. "LOAD_INTEGER_edx"
  91. "LOAD_IMMEDIATE_eax %5"
  92. "INT_80");
  93. }
  94. FILE* fopen(char* filename, char* mode)
  95. {
  96. FILE* f;
  97. if('w' == mode[0])
  98. { /* 577 is O_WRONLY|O_CREAT|O_TRUNC, 384 is 600 in octal */
  99. f = open(filename, 577 , 384);
  100. }
  101. else
  102. { /* Everything else is a read */
  103. f = open(filename, 0, 0);
  104. }
  105. /* Negative numbers are error codes */
  106. if(0 > f)
  107. {
  108. return 0;
  109. }
  110. return f;
  111. }
  112. int close(int fd)
  113. {
  114. asm("LOAD_EFFECTIVE_ADDRESS_ebx %4"
  115. "LOAD_IMMEDIATE_eax %6"
  116. "INT_80");
  117. }
  118. int fclose(FILE* stream)
  119. {
  120. int error = close(stream);
  121. return error;
  122. }
  123. /* Copyright (C) 2016 Jeremiah Orians
  124. * This file is part of stage0.
  125. *
  126. * stage0 is free software: you can redistribute it and/or modify
  127. * it under the terms of the GNU General Public License as published by
  128. * the Free Software Foundation, either version 3 of the License, or
  129. * (at your option) any later version.
  130. *
  131. * stage0 is distributed in the hope that it will be useful,
  132. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  133. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  134. * GNU General Public License for more details.
  135. *
  136. * You should have received a copy of the GNU General Public License
  137. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  138. */
  139. #include<stdio.h>
  140. // void fputc(char s, FILE* f);
  141. void file_print(char* s, FILE* f)
  142. {
  143. while(0 != s[0])
  144. {
  145. fputc(s[0], f);
  146. s = s + 1;
  147. }
  148. }
  149. ## Copyright (C) 2016 Jeremiah Orians
  150. ## This file is part of stage0.
  151. ##
  152. ## stage0 is free software: you can redistribute it and/or modify
  153. ## it under the terms of the GNU General Public License as published by
  154. ## the Free Software Foundation, either version 3 of the License, or
  155. ## (at your option) any later version.
  156. ##
  157. ## stage0 is distributed in the hope that it will be useful,
  158. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  159. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  160. ## GNU General Public License for more details.
  161. ##
  162. ## You should have received a copy of the GNU General Public License
  163. ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
  164. // CONSTANT NULL 0
  165. void* malloc(int size)
  166. {
  167. asm("STORE_eax_into_ESP_IMMEDIATE8 !4"
  168. "PUSH_eax"
  169. "LOAD_IMMEDIATE_eax %45"
  170. "LOAD_IMMEDIATE_ebx %0"
  171. "INT_80"
  172. "POP_ebx"
  173. "ADD_eax_to_ebx"
  174. "PUSH_eax"
  175. "PUSH_ebx"
  176. "LOAD_IMMEDIATE_eax %45"
  177. "INT_80"
  178. "POP_ebx"
  179. "CMP"
  180. "POP_eax"
  181. "JUMP_EQ8 !FUNCTION_malloc_Done"
  182. "LOAD_IMMEDIATE_eax %-1"
  183. ":FUNCTION_malloc_Done");
  184. }
  185. /* Copyright (C) 2016 Jeremiah Orians
  186. * This file is part of stage0.
  187. *
  188. * stage0 is free software: you can redistribute it and/or modify
  189. * it under the terms of the GNU General Public License as published by
  190. * the Free Software Foundation, either version 3 of the License, or
  191. * (at your option) any later version.
  192. *
  193. * stage0 is distributed in the hope that it will be useful,
  194. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  195. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  196. * GNU General Public License for more details.
  197. *
  198. * You should have received a copy of the GNU General Public License
  199. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  200. */
  201. // void* malloc(int size);
  202. void* memset(void* ptr, int value, int num)
  203. {
  204. char* s;
  205. for(s = ptr; 0 < num; num = num - 1)
  206. {
  207. s[0] = value;
  208. s = s + 1;
  209. }
  210. }
  211. void* calloc(int count, int size)
  212. {
  213. void* ret = malloc(count * size);
  214. memset(ret, 0, (count * size));
  215. return ret;
  216. }
  217. void free(void* l)
  218. {
  219. return;
  220. }
  221. /* Copyright (C) 2016 Jeremiah Orians
  222. * This file is part of stage0.
  223. *
  224. * stage0 is free software: you can redistribute it and/or modify
  225. * it under the terms of the GNU General Public License as published by
  226. * the Free Software Foundation, either version 3 of the License, or
  227. * (at your option) any later version.
  228. *
  229. * stage0 is distributed in the hope that it will be useful,
  230. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  231. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  232. * GNU General Public License for more details.
  233. *
  234. * You should have received a copy of the GNU General Public License
  235. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  236. */
  237. #define FALSE 0
  238. // CONSTANT FALSE 0
  239. #define TRUE 1
  240. // CONSTANT TRUE 1
  241. int match(char* a, char* b)
  242. {
  243. int i = -1;
  244. do
  245. {
  246. i = i + 1;
  247. if(a[i] != b[i])
  248. {
  249. return FALSE;
  250. }
  251. } while((0 != a[i]) && (0 !=b[i]));
  252. return TRUE;
  253. }
  254. /* Copyright (C) 2016 Jeremiah Orians
  255. * This file is part of stage0.
  256. *
  257. * stage0 is free software: you can redistribute it and/or modify
  258. * it under the terms of the GNU General Public License as published by
  259. * the Free Software Foundation, either version 3 of the License, or
  260. * (at your option) any later version.
  261. *
  262. * stage0 is distributed in the hope that it will be useful,
  263. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  264. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  265. * GNU General Public License for more details.
  266. *
  267. * You should have received a copy of the GNU General Public License
  268. * along with stage0. If not, see <http://www.gnu.org/licenses/>.
  269. */
  270. #include<stdlib.h>
  271. #include<string.h>
  272. // void* calloc(int count, int size);
  273. #define TRUE 1
  274. //CONSTANT TRUE 1
  275. #define FALSE 0
  276. //CONSTANT FALSE 0
  277. char* numerate_number(int a)
  278. {
  279. char* result = calloc(16, sizeof(char));
  280. int i = 0;
  281. /* Deal with Zero case */
  282. if(0 == a)
  283. {
  284. result[0] = '0';
  285. return result;
  286. }
  287. /* Deal with negatives */
  288. if(0 > a)
  289. {
  290. result[0] = '-';
  291. i = 1;
  292. a = a * -1;
  293. }
  294. /* Using the largest 10^n number possible in 32bits */
  295. int divisor = 0x3B9ACA00;
  296. /* Skip leading Zeros */
  297. while(0 == (a / divisor)) divisor = divisor / 10;
  298. /* Now simply collect numbers until divisor is gone */
  299. while(0 < divisor)
  300. {
  301. result[i] = ((a / divisor) + 48);
  302. a = a % divisor;
  303. divisor = divisor / 10;
  304. i = i + 1;
  305. }
  306. return result;
  307. }
  308. int char2hex(int c)
  309. {
  310. if (c >= '0' && c <= '9') return (c - 48);
  311. else if (c >= 'a' && c <= 'f') return (c - 87);
  312. else if (c >= 'A' && c <= 'F') return (c - 55);
  313. else return -1;
  314. }
  315. int hex2char(int c)
  316. {
  317. if((c >= 0) && (c <= 9)) return (c + 48);
  318. else if((c >= 10) && (c <= 15)) return (c + 55);
  319. else return -1;
  320. }
  321. int char2dec(int c)
  322. {
  323. if (c >= '0' && c <= '9') return (c - 48);
  324. else return -1;
  325. }
  326. int dec2char(int c)
  327. {
  328. if((c >= 0) && (c <= 9)) return (c + 48);
  329. else return -1;
  330. }
  331. int numerate_string(char *a)
  332. {
  333. int count = 0;
  334. int index;
  335. int negative;
  336. /* If NULL string */
  337. if(0 == a[0])
  338. {
  339. return 0;
  340. }
  341. /* Deal with hex */
  342. else if (a[0] == '0' && a[1] == 'x')
  343. {
  344. if('-' == a[2])
  345. {
  346. negative = TRUE;
  347. index = 3;
  348. }
  349. else
  350. {
  351. negative = FALSE;
  352. index = 2;
  353. }
  354. while(0 != a[index])
  355. {
  356. if(-1 == char2hex(a[index])) return 0;
  357. count = (16 * count) + char2hex(a[index]);
  358. index = index + 1;
  359. }
  360. }
  361. /* Deal with decimal */
  362. else
  363. {
  364. if('-' == a[0])
  365. {
  366. negative = TRUE;
  367. index = 1;
  368. }
  369. else
  370. {
  371. negative = FALSE;
  372. index = 0;
  373. }
  374. while(0 != a[index])
  375. {
  376. if(-1 == char2dec(a[index])) return 0;
  377. count = (10 * count) + char2dec(a[index]);
  378. index = index + 1;
  379. }
  380. }
  381. if(negative)
  382. {
  383. count = count * -1;
  384. }
  385. return count;
  386. }
  387. ## Copyright (C) 2016 Jeremiah Orians
  388. ## This file is part of stage0.
  389. ##
  390. ## stage0 is free software: you can redistribute it and/or modify
  391. ## it under the terms of the GNU General Public License as published by
  392. ## the Free Software Foundation, either version 3 of the License, or
  393. ## (at your option) any later version.
  394. ##
  395. ## stage0 is distributed in the hope that it will be useful,
  396. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  397. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  398. ## GNU General Public License for more details.
  399. ##
  400. ## You should have received a copy of the GNU General Public License
  401. ## along with stage0. If not, see <http://www.gnu.org/licenses/>.
  402. /*
  403. * chmod() changes the mode of the file specified whose pathname is given in
  404. * pathname, which is dereferenced if it is a symbolic link.
  405. * fchmod() changes the mode of the file referred to by the open file
  406. * descriptor fd.
  407. * The new file mode is specified in mode, which is a bit mask created by
  408. * ORing together zero or more of the following:
  409. * S_ISUID (04000) set-user-ID (set process effective user ID on execve(2))
  410. * S_ISGID (02000) set-group-ID (set process effective group ID on execve(2)
  411. * mandatory locking, as described in fcntl(2); take a new file's group from
  412. * parent directory, as described in chown(2) and mkdir(2))
  413. * S_ISVTX (01000) sticky bit (restricted deletion flag, as described in
  414. * unlink(2))
  415. * S_IRUSR (00400) read by owner
  416. * S_IWUSR (00200) write by owner
  417. * S_IXUSR (00100) execute/search by owner ("search" applies for directories
  418. * , and means that entries within the directory can be accessed)
  419. * S_IRGRP (00040) read by group
  420. * S_IWGRP (00020) write by group
  421. * S_IXGRP (00010) execute/search by group
  422. * S_IROTH (00004) read by others
  423. * S_IWOTH (00002) write by others
  424. * S_IXOTH (00001) execute/search by others
  425. */
  426. int chmod(char *pathname, int mode)
  427. {
  428. asm("LOAD_EFFECTIVE_ADDRESS_ebx %8"
  429. "LOAD_INTEGER_ebx"
  430. "LOAD_EFFECTIVE_ADDRESS_ecx %4"
  431. "LOAD_INTEGER_ecx"
  432. "LOAD_IMMEDIATE_eax %15"
  433. "INT_80");
  434. }
  435. /* -*- c-file-style: "linux";indent-tabs-mode:t -*- */
  436. /* Copyright (C) 2017 Jeremiah Orians
  437. * Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
  438. * This file is part of mescc-tools
  439. *
  440. * mescc-tools is free software: you can redistribute it and/or modify
  441. * it under the terms of the GNU General Public License as published by
  442. * the Free Software Foundation, either version 3 of the License, or
  443. * (at your option) any later version.
  444. *
  445. * mescc-tools is distributed in the hope that it will be useful,
  446. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  447. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  448. * GNU General Public License for more details.
  449. *
  450. * You should have received a copy of the GNU General Public License
  451. * along with mescc-tools. If not, see <http://www.gnu.org/licenses/>.
  452. */
  453. #include <stdio.h>
  454. #include <stdlib.h>
  455. #include <string.h>
  456. #include <unistd.h>
  457. #include <sys/stat.h>
  458. #define max_string 4096
  459. //CONSTANT max_string 4096
  460. #define TRUE 1
  461. //CONSTANT TRUE 1
  462. #define FALSE 0
  463. //CONSTANT FALSE 0
  464. void file_print(char* s, FILE* f);
  465. int match(char* a, char* b);
  466. char* numerate_number(int a);
  467. int numerate_string(char *a);
  468. struct input_files
  469. {
  470. struct input_files* next;
  471. char* filename;
  472. };
  473. struct entry
  474. {
  475. struct entry* next;
  476. unsigned target;
  477. char* name;
  478. };
  479. FILE* output;
  480. struct entry* jump_table;
  481. int BigEndian;
  482. int Base_Address;
  483. int Architecture;
  484. int ByteMode;
  485. int exec_enable;
  486. int ip;
  487. char* scratch;
  488. char* scratch2;
  489. int consume_token(FILE* source_file, char* s)
  490. {
  491. int i = 0;
  492. int c = fgetc(source_file);
  493. do
  494. {
  495. if(NULL != s) s[i] = c;
  496. i = i + 1;
  497. c = fgetc(source_file);
  498. } while((' ' != c) && ('\t' != c) && ('\n' != c) && '>' != c);
  499. return c;
  500. }
  501. unsigned GetTarget(char* c)
  502. {
  503. struct entry* i;
  504. for(i = jump_table; NULL != i; i = i->next)
  505. {
  506. if(match(c, i->name))
  507. {
  508. return i->target;
  509. }
  510. }
  511. file_print("Target label ", stderr);
  512. file_print(c, stderr);
  513. file_print(" is not valid\n", stderr);
  514. exit(EXIT_FAILURE);
  515. }
  516. int storeLabel(FILE* source_file, int ip)
  517. {
  518. struct entry* entry = calloc(1, sizeof(struct entry));
  519. /* Prepend to list */
  520. entry->next = jump_table;
  521. jump_table = entry;
  522. /* Store string */
  523. entry->name = calloc(max_string + 1, sizeof(char));
  524. int c = consume_token(source_file, entry->name);
  525. /* Ensure we have target address */
  526. entry->target = ip;
  527. return c;
  528. }
  529. void range_check(int displacement, int number_of_bytes)
  530. {
  531. if(4 == number_of_bytes) return;
  532. else if (3 == number_of_bytes)
  533. {
  534. if((8388607 < displacement) || (displacement < -8388608))
  535. {
  536. file_print("A displacement of ", stderr);
  537. file_print(numerate_number(displacement), stderr);
  538. file_print(" does not fit in 3 bytes\n", stderr);
  539. exit(EXIT_FAILURE);
  540. }
  541. return;
  542. }
  543. else if (2 == number_of_bytes)
  544. {
  545. if((32767 < displacement) || (displacement < -32768))
  546. {
  547. file_print("A displacement of ", stderr);
  548. file_print(numerate_number(displacement), stderr);
  549. file_print(" does not fit in 2 bytes\n", stderr);
  550. exit(EXIT_FAILURE);
  551. }
  552. return;
  553. }
  554. else if (1 == number_of_bytes)
  555. {
  556. if((127 < displacement) || (displacement < -128))
  557. {
  558. file_print("A displacement of ", stderr);
  559. file_print(numerate_number(displacement), stderr);
  560. file_print(" does not fit in 1 byte\n", stderr);
  561. exit(EXIT_FAILURE);
  562. }
  563. return;
  564. }
  565. file_print("Invalid number of bytes given\n", stderr);
  566. exit(EXIT_FAILURE);
  567. }
  568. void outputPointer(int displacement, int number_of_bytes)
  569. {
  570. unsigned value = displacement;
  571. /* HALT HARD if we are going to do something BAD*/
  572. range_check(displacement, number_of_bytes);
  573. if(BigEndian)
  574. { /* Deal with BigEndian */
  575. if(4 == number_of_bytes) fputc((value >> 24), output);
  576. if(3 <= number_of_bytes) fputc(((value >> 16)%256), output);
  577. if(2 <= number_of_bytes) fputc(((value >> 8)%256), output);
  578. if(1 <= number_of_bytes) fputc((value % 256), output);
  579. }
  580. else
  581. { /* Deal with LittleEndian */
  582. while(number_of_bytes > 0)
  583. {
  584. unsigned byte = value % 256;
  585. value = value / 256;
  586. fputc(byte, output);
  587. number_of_bytes = number_of_bytes - 1;
  588. }
  589. }
  590. }
  591. int Architectural_displacement(int target, int base)
  592. {
  593. if(0 == Architecture) return (target - base);
  594. else if(1 == Architecture) return (target - base);
  595. else if(2 == Architecture) return (target - base);
  596. else if(40 == Architecture) return (target - base);
  597. file_print("Unknown Architecture, aborting before harm is done\n", stderr);
  598. exit(EXIT_FAILURE);
  599. }
  600. int ConsumePointer(char ch, FILE* source_file, char* s)
  601. {
  602. /* Calculate pointer size*/
  603. if((37 == ch) || (38 == ch)) ip = ip + 4; /* Deal with % and & */
  604. else if((64 == ch) || (36 == ch)) ip = ip + 2; /* Deal with @ and $ */
  605. else if(33 == ch) ip = ip + 1; /* Deal with ! */
  606. else
  607. {
  608. file_print("storePointer given unknown\n", stderr);
  609. exit(EXIT_FAILURE);
  610. }
  611. return consume_token(source_file, s);
  612. }
  613. void storePointer(char ch, FILE* source_file)
  614. {
  615. /* Get string of pointer */
  616. memset (scratch, 0, max_string + 1);
  617. int base_sep_p = (ConsumePointer(ch, source_file, scratch) == 62); /* '>' */
  618. /* Lookup token */
  619. int target = GetTarget(scratch);
  620. int displacement;
  621. int base = ip;
  622. /* Change relative base address to :<base> */
  623. if (base_sep_p)
  624. {
  625. memset (scratch2, 0, max_string + 1);
  626. consume_token (source_file, scratch2);
  627. base = GetTarget (scratch2);
  628. }
  629. displacement = Architectural_displacement(target, base);
  630. /* output calculated difference */
  631. if(33 == ch)
  632. {
  633. if(40 == Architecture) outputPointer(displacement - 7, 1); /* Deal with ! */
  634. else outputPointer(displacement, 1); /* Deal with ! */
  635. }
  636. else if(36 == ch) outputPointer(target, 2); /* Deal with $ */
  637. else if(64 == ch) outputPointer(displacement, 2); /* Deal with @ */
  638. else if(38 == ch) outputPointer(target, 4); /* Deal with & */
  639. else if(37 == ch) outputPointer(displacement, 4); /* Deal with % */
  640. else
  641. {
  642. file_print("storePointer reached impossible case: ch=", stderr);
  643. fputc(ch, stderr);
  644. file_print("\n", stderr);
  645. exit(EXIT_FAILURE);
  646. }
  647. }
  648. void line_Comment(FILE* source_file)
  649. {
  650. int c = fgetc(source_file);
  651. while((10 != c) && (13 != c))
  652. {
  653. c = fgetc(source_file);
  654. }
  655. }
  656. int hex(int c, FILE* source_file)
  657. {
  658. if (c >= '0' && c <= '9') return (c - 48);
  659. else if (c >= 'a' && c <= 'z') return (c - 87);
  660. else if (c >= 'A' && c <= 'Z') return (c - 55);
  661. else if (c == '#' || c == ';') line_Comment(source_file);
  662. return -1;
  663. }
  664. int octal(int c, FILE* source_file)
  665. {
  666. if (c >= '0' && c <= '7') return (c - 48);
  667. else if (c == '#' || c == ';') line_Comment(source_file);
  668. return -1;
  669. }
  670. int binary(int c, FILE* source_file)
  671. {
  672. if (c == '0' || c == '1') return (c - 48);
  673. else if (c == '#' || c == ';') line_Comment(source_file);
  674. return -1;
  675. }
  676. int hold;
  677. int toggle;
  678. void process_byte(char c, FILE* source_file, int write)
  679. {
  680. if(16 == ByteMode)
  681. {
  682. if(0 <= hex(c, source_file))
  683. {
  684. if(toggle)
  685. {
  686. if(write) fputc(((hold * 16)) + hex(c, source_file), output);
  687. ip = ip + 1;
  688. hold = 0;
  689. }
  690. else
  691. {
  692. hold = hex(c, source_file);
  693. }
  694. toggle = !toggle;
  695. }
  696. }
  697. else if(8 ==ByteMode)
  698. {
  699. if(0 <= octal(c, source_file))
  700. {
  701. if(2 == toggle)
  702. {
  703. if(write) fputc(((hold * 8)) + octal(c, source_file), output);
  704. ip = ip + 1;
  705. hold = 0;
  706. toggle = 0;
  707. }
  708. else if(1 == toggle)
  709. {
  710. hold = ((hold * 8) + octal(c, source_file));
  711. toggle = 2;
  712. }
  713. else
  714. {
  715. hold = octal(c, source_file);
  716. toggle = 1;
  717. }
  718. }
  719. }
  720. else if(2 == ByteMode)
  721. {
  722. if(0 <= binary(c, source_file))
  723. {
  724. if(7 == toggle)
  725. {
  726. if(write) fputc((hold * 2) + binary(c, source_file), output);
  727. ip = ip + 1;
  728. hold = 0;
  729. toggle = 0;
  730. }
  731. else
  732. {
  733. hold = ((hold * 2) + binary(c, source_file));
  734. toggle = toggle + 1;
  735. }
  736. }
  737. }
  738. }
  739. void first_pass(struct input_files* input)
  740. {
  741. if(NULL == input) return;
  742. first_pass(input->next);
  743. FILE* source_file = fopen(input->filename, "r");
  744. if(NULL == source_file)
  745. {
  746. file_print("The file: ", stderr);
  747. file_print(input->filename, stderr);
  748. file_print(" can not be opened!\n", stderr);
  749. exit(EXIT_FAILURE);
  750. }
  751. toggle = FALSE;
  752. int c;
  753. for(c = fgetc(source_file); EOF != c; c = fgetc(source_file))
  754. {
  755. /* Check for and deal with label */
  756. if(58 == c)
  757. {
  758. c = storeLabel(source_file, ip);
  759. }
  760. /* check for and deal with relative/absolute pointers to labels */
  761. if((33 == c) || (64 == c) || (36 == c) || (37 == c) || (38 == c))
  762. { /* deal with 1byte pointer !; 2byte pointers (@ and $); 4byte pointers (% and &) */
  763. c = ConsumePointer(c, source_file, NULL);
  764. if (62 == c)
  765. { /* deal with label>base */
  766. c = consume_token (source_file, NULL);
  767. }
  768. }
  769. else process_byte(c, source_file, FALSE);
  770. }
  771. fclose(source_file);
  772. }
  773. void second_pass(struct input_files* input)
  774. {
  775. if(NULL == input) return;
  776. second_pass(input->next);
  777. FILE* source_file = fopen(input->filename, "r");
  778. /* Something that should never happen */
  779. if(NULL == source_file)
  780. {
  781. file_print("The file: ", stderr);
  782. file_print(input->filename, stderr);
  783. file_print(" can not be opened!\nWTF-pass2\n", stderr);
  784. exit(EXIT_FAILURE);
  785. }
  786. toggle = FALSE;
  787. hold = 0;
  788. int c;
  789. for(c = fgetc(source_file); EOF != c; c = fgetc(source_file))
  790. {
  791. if(58 == c) c = consume_token(source_file, NULL); /* Deal with : */
  792. else if((33 == c) || (64 == c) || (36 == c) || (37 == c) || (38 == c)) storePointer(c, source_file); /* Deal with !, @, $, % and & */
  793. else process_byte(c, source_file, TRUE);
  794. }
  795. fclose(source_file);
  796. }
  797. /* Standard C main program */
  798. int main(int argc, char **argv)
  799. {
  800. BigEndian = TRUE;
  801. jump_table = NULL;
  802. Architecture = 0;
  803. Base_Address = 0;
  804. struct input_files* input = NULL;
  805. output = stdout;
  806. char* output_file = "";
  807. exec_enable = FALSE;
  808. ByteMode = 16;
  809. scratch = calloc(max_string + 1, sizeof(char));
  810. scratch2 = calloc(max_string + 1, sizeof(char));
  811. int option_index = 1;
  812. while(option_index <= argc)
  813. {
  814. if(NULL == argv[option_index])
  815. {
  816. option_index = option_index + 1;
  817. }
  818. else if(match(argv[option_index], "--BigEndian"))
  819. {
  820. BigEndian = TRUE;
  821. option_index = option_index + 1;
  822. }
  823. else if(match(argv[option_index], "--LittleEndian"))
  824. {
  825. BigEndian = FALSE;
  826. option_index = option_index + 1;
  827. }
  828. else if(match(argv[option_index], "--exec_enable"))
  829. {
  830. exec_enable = TRUE;
  831. option_index = option_index + 1;
  832. }
  833. else if(match(argv[option_index], "-A") || match(argv[option_index], "--Architecture"))
  834. {
  835. Architecture = numerate_string(argv[option_index + 1]);
  836. option_index = option_index + 2;
  837. }
  838. else if(match(argv[option_index], "-b") || match(argv[option_index], "--binary"))
  839. {
  840. ByteMode = 2;
  841. option_index = option_index + 1;
  842. }
  843. else if(match(argv[option_index], "-B") || match(argv[option_index], "--BaseAddress"))
  844. {
  845. Base_Address = numerate_string(argv[option_index + 1]);
  846. option_index = option_index + 2;
  847. }
  848. else if(match(argv[option_index], "-h") || match(argv[option_index], "--help"))
  849. {
  850. file_print("Usage: ", stderr);
  851. file_print(argv[0], stderr);
  852. file_print(" -f FILENAME1 {-f FILENAME2} (--BigEndian|--LittleEndian)", stderr);
  853. file_print(" [--BaseAddress 12345] [--Architecture 12345]\nArchitecture", stderr);
  854. file_print(" 0: Knight; 1: x86; 2: AMD64; 40: armv7", stderr);
  855. file_print("\nTo leverage octal or binary", stderr);
  856. file_print(" input: --octal, --binary\n", stderr);
  857. exit(EXIT_SUCCESS);
  858. }
  859. else if(match(argv[option_index], "-f") || match(argv[option_index], "--file"))
  860. {
  861. struct input_files* temp = calloc(1, sizeof(struct input_files));
  862. temp->filename = argv[option_index + 1];
  863. temp->next = input;
  864. input = temp;
  865. option_index = option_index + 2;
  866. }
  867. else if(match(argv[option_index], "-o") || match(argv[option_index], "--output"))
  868. {
  869. output_file = argv[option_index + 1];
  870. output = fopen(output_file, "w");
  871. if(NULL == output)
  872. {
  873. file_print("The file: ", stderr);
  874. file_print(argv[option_index + 1], stderr);
  875. file_print(" can not be opened!\n", stderr);
  876. exit(EXIT_FAILURE);
  877. }
  878. option_index = option_index + 2;
  879. }
  880. else if(match(argv[option_index], "-O") || match(argv[option_index], "--octal"))
  881. {
  882. ByteMode = 8;
  883. option_index = option_index + 1;
  884. }
  885. else if(match(argv[option_index], "-V") || match(argv[option_index], "--version"))
  886. {
  887. file_print("hex2 0.3\n", stdout);
  888. exit(EXIT_SUCCESS);
  889. }
  890. else
  891. {
  892. file_print("Unknown option\n", stderr);
  893. exit(EXIT_FAILURE);
  894. }
  895. }
  896. /* Make sure we have a program tape to run */
  897. if (NULL == input)
  898. {
  899. return EXIT_FAILURE;
  900. }
  901. /* Get all of the labels */
  902. ip = Base_Address;
  903. first_pass(input);
  904. /* Fix all the references*/
  905. ip = Base_Address;
  906. second_pass(input);
  907. /* Set file as executable */
  908. if(exec_enable)
  909. {
  910. /* 488 = 750 in octal */
  911. if(0 != chmod(output_file, 488))
  912. {
  913. file_print("Unable to change permissions\n", stderr);
  914. exit(EXIT_FAILURE);
  915. }
  916. }
  917. return EXIT_SUCCESS;
  918. }