syscalls.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. // See LICENSE for license details.
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5. #include <stdio.h>
  6. #include <limits.h>
  7. #include <sys/signal.h>
  8. #include <sys/times.h>
  9. #include "encoding.h"
  10. #define SYS_write 64
  11. #undef strcmp
  12. static uintptr_t syscall(uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t arg2)
  13. {
  14. volatile uint64_t magic_mem[8] __attribute__((aligned(64)));
  15. magic_mem[0] = which;
  16. magic_mem[1] = arg0;
  17. magic_mem[2] = arg1;
  18. magic_mem[3] = arg2;
  19. __sync_synchronize();
  20. return magic_mem[0];
  21. }
  22. void printstr(const char* s)
  23. {
  24. syscall(SYS_write, 1, (uintptr_t)s, strlen(s));
  25. }
  26. #ifndef AGRV_ENTRY
  27. #define AGRV_ENTRY main
  28. #endif
  29. int __attribute__((weak)) AGRV_ENTRY(int argc, char** argv)
  30. {
  31. // single-threaded programs override this function.
  32. printstr("Implement main()!\n");
  33. return -1;
  34. }
  35. #ifndef NEED_MINIMAL
  36. extern uint32_t __data_vma;
  37. extern uint32_t __data_lma;
  38. extern uint32_t __data_size;
  39. extern uint32_t __rodata_vma;
  40. extern uint32_t __rodata_lma;
  41. extern uint32_t __rodata_size;
  42. extern uint32_t __sdata_vma;
  43. extern uint32_t __sdata_lma;
  44. extern uint32_t __sdata_size;
  45. extern uint32_t __sram_text_vma;
  46. extern uint32_t __sram_text_lma;
  47. extern uint32_t __sram_text_size;
  48. extern uint32_t __itim_text_vma;
  49. extern uint32_t __itim_text_lma;
  50. extern uint32_t __itim_text_size;
  51. extern uint32_t __exec_text_vma;
  52. extern uint32_t __exec_text_lma;
  53. extern uint32_t __exec_text_size;
  54. extern uint32_t __bss_vma;
  55. extern uint32_t __bss_size;
  56. extern uint32_t __sbss_vma;
  57. extern uint32_t __sbss_size;
  58. extern void(*__preinit_array_start)();
  59. extern void(*__preinit_array_end)();
  60. extern void(*__init_array_start)();
  61. extern void(*__init_array_end)();
  62. extern void(*__fini_array_start)();
  63. extern void(*__fini_array_end)();
  64. __attribute__((section(".text.init")))
  65. void _init(void)
  66. {
  67. memcpy(&__exec_text_vma, &__exec_text_lma, (int)&__exec_text_size);
  68. memcpy(&__itim_text_vma, &__itim_text_lma, (int)&__itim_text_size);
  69. memcpy(&__data_vma, &__data_lma, (int)&__data_size);
  70. memcpy(&__rodata_vma, &__rodata_lma, (int)&__rodata_size);
  71. memcpy(&__sdata_vma, &__sdata_lma, (int)&__sdata_size);
  72. memcpy(&__sram_text_vma, &__sram_text_lma, (int)&__sram_text_size);
  73. memset(&__bss_vma, 0, (int)&__bss_size);
  74. memset(&__sbss_vma, 0, (int)&__sbss_size);
  75. for (void(**p)() = &__preinit_array_start; p < &__preinit_array_end; ++p) {
  76. (*p)();
  77. }
  78. for (void(**p)() = &__init_array_start; p < &__init_array_end; ++p) {
  79. (*p)();
  80. }
  81. int ret = AGRV_ENTRY(0, 0);
  82. for (void(**p)() = &__fini_array_start; p < &__fini_array_end; ++p) {
  83. (*p)();
  84. }
  85. while (1);
  86. }
  87. #endif
  88. #undef putchar
  89. __attribute__((weak)) int putchar(int ch)
  90. {
  91. return 0;
  92. }
  93. void printhex(uint64_t x)
  94. {
  95. char str[17];
  96. int i;
  97. for (i = 0; i < 16; i++)
  98. {
  99. str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10);
  100. x >>= 4;
  101. }
  102. str[16] = 0;
  103. printstr(str);
  104. }
  105. size_t printnum(void (*putch)(int, void**, size_t, size_t), void **putdat,
  106. unsigned long long num, int base, int width, int padc, size_t idx, size_t size)
  107. {
  108. unsigned digs[sizeof(num)*CHAR_BIT];
  109. int pos = 0;
  110. int hex_base = 'a';
  111. if (base < 0) {
  112. hex_base = 'A';
  113. base = -base;
  114. }
  115. while (1)
  116. {
  117. unsigned long long div = num / base;
  118. digs[pos++] = num - div * base;
  119. if (num < base)
  120. break;
  121. num = div;
  122. }
  123. while (width-- > pos)
  124. putch(padc, putdat, idx++, size);
  125. while (pos-- > 0)
  126. putch(digs[pos] + (digs[pos] >= 10 ? hex_base - 10 : '0'), putdat, idx++, size);
  127. return idx;
  128. }
  129. static unsigned long long getuint(va_list *ap, int lflag)
  130. {
  131. if (lflag >= 2)
  132. return va_arg(*ap, unsigned long long);
  133. else if (lflag)
  134. return va_arg(*ap, unsigned long);
  135. else
  136. return va_arg(*ap, unsigned int);
  137. }
  138. static long long getint(va_list *ap, int lflag)
  139. {
  140. if (lflag >= 2)
  141. return va_arg(*ap, long long);
  142. else if (lflag)
  143. return va_arg(*ap, long);
  144. else
  145. return va_arg(*ap, int);
  146. }
  147. static float getfloat(va_list *ap)
  148. {
  149. return va_arg(*ap, double);
  150. }
  151. int vprintfmt(void (*putch)(int, void**, size_t, size_t), void **putdat, const char *fmt, va_list ap, size_t size)
  152. {
  153. register const char* p;
  154. const char* last_fmt;
  155. register char ch;
  156. unsigned long long num;
  157. float fval;
  158. int base, lflag, width, precision, precision2, altflag;
  159. char padc;
  160. size_t idx = 0;
  161. while (1) {
  162. while ((ch = *fmt) != '%') {
  163. if (ch == '\0')
  164. return idx;
  165. fmt++;
  166. putch(ch, putdat, idx++, size);
  167. }
  168. fmt++;
  169. // Process a %-escape sequence
  170. last_fmt = fmt;
  171. padc = ' ';
  172. width = -1;
  173. precision = -1;
  174. precision2 = -1;
  175. lflag = 0;
  176. altflag = 0;
  177. reswitch:
  178. switch (ch = *fmt++) {
  179. // flag to pad on the right
  180. case '-':
  181. padc = '-';
  182. goto reswitch;
  183. // flag to pad with 0's instead of spaces
  184. case '0':
  185. padc = '0';
  186. goto reswitch;
  187. // width field
  188. case '1':
  189. case '2':
  190. case '3':
  191. case '4':
  192. case '5':
  193. case '6':
  194. case '7':
  195. case '8':
  196. case '9':
  197. case '.':
  198. precision = 0; precision2 = -1;
  199. for (; ; ++fmt) {
  200. if (ch == '.') {
  201. precision2 = 0;
  202. } else if (precision2 >= 0) {
  203. precision2 = precision2 * 10 + ch - '0';
  204. } else {
  205. precision = precision * 10 + ch - '0';
  206. }
  207. ch = *fmt;
  208. if (ch != '.' && (ch < '0' || ch > '9'))
  209. break;
  210. }
  211. goto process_precision;
  212. case '*':
  213. precision = va_arg(ap, int);
  214. goto process_precision;
  215. #if 0 //ZZZZZZZZ
  216. case '.':
  217. if (width < 0)
  218. width = 0;
  219. goto reswitch;
  220. #endif
  221. case '#':
  222. altflag = 1;
  223. goto reswitch;
  224. process_precision:
  225. if (width < 0)
  226. width = precision, precision = -1;
  227. goto reswitch;
  228. // long flag (doubled for long long)
  229. case 'l':
  230. lflag++;
  231. goto reswitch;
  232. // short flag (h or hh), ignored
  233. case 'h':
  234. goto reswitch;
  235. // character
  236. case 'c':
  237. putch(va_arg(ap, int), putdat, idx++, size);
  238. break;
  239. // string
  240. case 's':
  241. if ((p = va_arg(ap, char *)) == NULL)
  242. p = "(null)";
  243. if (width > 0 && padc != '-')
  244. for (width -= strnlen(p, precision); width > 0; width--)
  245. putch(padc, putdat, idx++, size);
  246. for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) {
  247. putch(ch, putdat, idx++, size);
  248. p++;
  249. if (lflag && *p == '\0') { // Very simple but incomplete way to handle %ls (wchar)
  250. p++;
  251. }
  252. }
  253. for (; width > 0; width--)
  254. putch(' ', putdat, idx++, size);
  255. break;
  256. // (signed) decimal
  257. case 'd':
  258. case 'i':
  259. num = getint(&ap, lflag);
  260. if ((long long) num < 0) {
  261. putch('-', putdat, idx++, size);
  262. num = -(long long) num;
  263. }
  264. base = 10;
  265. goto signed_number;
  266. // unsigned decimal
  267. case 'u':
  268. base = 10;
  269. goto unsigned_number;
  270. // (unsigned) octal
  271. case 'o':
  272. // should do something with padding so it's always 3 octits
  273. base = 8;
  274. goto unsigned_number;
  275. // pointer
  276. case 'p':
  277. lflag = 1;
  278. putch('0', putdat, idx++, size);
  279. putch('x', putdat, idx++, size);
  280. /* fall through to 'x' */
  281. // (unsigned) hexadecimal
  282. case 'x':
  283. case 'X':
  284. base = ch == 'x' ? 16 : -16;
  285. unsigned_number:
  286. num = getuint(&ap, lflag);
  287. signed_number:
  288. idx = printnum(putch, putdat, num, base, width, padc, idx, size);
  289. break;
  290. case 'f':
  291. floating_number:
  292. fval = getfloat(&ap);
  293. if (fval < 0) {
  294. putch('-', putdat, idx++, size);
  295. fval = -fval;
  296. }
  297. if (precision2 < 0) {
  298. precision2 = 3;
  299. }
  300. if (width >= 0) {
  301. width -= precision2;
  302. if (precision2 > 0) {
  303. --width;
  304. }
  305. }
  306. base = 10;
  307. #ifdef PRINTF_LONG_LONG_FLOAT_SUPPORT
  308. // Under riscv32imafc this needs about 6K-byte code of soft float library
  309. num = (int long long)(fval);
  310. fval -= num;
  311. #else
  312. // Without PRINTF_LONG_LONG_FLOAT_SUPPORT floating point numbers greater than INT_MAX will be printed as INT_MAX.
  313. num = (int)(fval);
  314. fval -= (unsigned)num;
  315. #endif
  316. idx = printnum(putch, putdat, num, base, width, padc, idx, size);
  317. if (precision2 > 0) {
  318. num = 0;
  319. width = precision2;
  320. padc = '0';
  321. putch('.', putdat, idx++, size);
  322. while (precision2-- > 0) {
  323. fval *= 10.;
  324. }
  325. num = (int)(fval+1e-6);
  326. idx = printnum(putch, putdat, num, base, width, padc, idx, size);
  327. }
  328. break;
  329. // escaped '%' character
  330. case '%':
  331. putch(ch, putdat, idx++, size);
  332. break;
  333. // unrecognized escape sequence - just print it literally
  334. default:
  335. putch('%', putdat, idx++, size);
  336. fmt = last_fmt;
  337. break;
  338. }
  339. }
  340. return idx;
  341. }
  342. static void sprintf_putch(int ch, void** data, size_t idx, size_t size)
  343. {
  344. char** pstr = (char**)data;
  345. **pstr = ch;
  346. (*pstr)++;
  347. }
  348. static void snprintf_putch(int ch, void** data, size_t idx, size_t size)
  349. {
  350. if (idx < size) {
  351. char** pstr = (char**)data;
  352. **pstr = ch;
  353. (*pstr)++;
  354. }
  355. }
  356. int puts(const char *s)
  357. {
  358. return printf("%s\n", s);
  359. }
  360. int vprintf(const char* fmt, va_list ap)
  361. {
  362. return vprintfmt((void*)putchar, 0, fmt, ap, 0);
  363. }
  364. int vfprintf(FILE *fp, const char* fmt, va_list ap)
  365. {
  366. return vprintf(fmt, ap);
  367. }
  368. int vdprintf(int fd, const char* fmt, va_list ap)
  369. {
  370. return vprintf(fmt, ap);
  371. }
  372. int vsprintf(char* str, const char* fmt, va_list ap)
  373. {
  374. int ret = vprintfmt(sprintf_putch, (void**)&str, fmt, ap, 0);
  375. *str = 0;
  376. return ret;
  377. }
  378. int vsnprintf(char* str, size_t size, const char* fmt, va_list ap)
  379. {
  380. int ret = vprintfmt(snprintf_putch, (void**)&str, fmt, ap, size-1);
  381. *str = 0;
  382. return ret;
  383. }
  384. int printf(const char* fmt, ...)
  385. {
  386. va_list ap; va_start(ap, fmt);
  387. int ret = vprintf(fmt, ap);
  388. va_end(ap); return ret;
  389. }
  390. int fprintf(FILE *fp, const char *fmt, ...)
  391. {
  392. va_list ap; va_start(ap, fmt);
  393. int ret = vfprintf(fp, fmt, ap);
  394. va_end(ap); return ret;
  395. }
  396. int dprintf(int fd, const char *fmt, ...)
  397. {
  398. va_list ap; va_start(ap, fmt);
  399. int ret = vdprintf(fd, fmt, ap);
  400. va_end(ap); return ret;
  401. }
  402. int sprintf(char* str, const char* fmt, ...)
  403. {
  404. va_list ap; va_start(ap, fmt);
  405. int ret = vsprintf(str, fmt, ap);
  406. va_end(ap); return ret;
  407. }
  408. int snprintf(char* str, size_t size, const char* fmt, ...)
  409. {
  410. va_list ap; va_start(ap, fmt);
  411. int ret = vsnprintf(str, size, fmt, ap);
  412. va_end(ap); return ret;
  413. }
  414. __attribute__((section(".text.init")))
  415. void* memcpy(void* dest, const void* src, size_t len)
  416. {
  417. if ((((uintptr_t)dest | (uintptr_t)src | len) & (sizeof(uintptr_t)-1)) == 0) {
  418. const uintptr_t* s = src;
  419. uintptr_t *d = dest;
  420. while (d < (uintptr_t*)(dest + len))
  421. *d++ = *s++;
  422. } else {
  423. const char* s = src;
  424. char *d = dest;
  425. while (d < (char*)(dest + len))
  426. *d++ = *s++;
  427. }
  428. return dest;
  429. }
  430. __attribute__((section(".text.init")))
  431. void* memset(void* dest, int byte, size_t len)
  432. {
  433. if ((((uintptr_t)dest | len) & (sizeof(uintptr_t)-1)) == 0) {
  434. uintptr_t word = byte & 0xFF;
  435. word |= word << 8;
  436. word |= word << 16;
  437. word |= word << 16 << 16;
  438. volatile uintptr_t *d = dest;
  439. while (d < (uintptr_t*)(dest + len))
  440. *d++ = word;
  441. } else {
  442. volatile char *d = dest;
  443. while (d < (char*)(dest + len))
  444. *d++ = byte;
  445. }
  446. return dest;
  447. }
  448. size_t strlen(const char *s)
  449. {
  450. const char *p = s;
  451. while (*p)
  452. p++;
  453. return p - s;
  454. }
  455. size_t strnlen(const char *s, size_t n)
  456. {
  457. const char *p = s;
  458. while (n-- && *p)
  459. p++;
  460. return p - s;
  461. }
  462. int strcmp(const char* s1, const char* s2)
  463. {
  464. unsigned char c1, c2;
  465. do {
  466. c1 = *s1++;
  467. c2 = *s2++;
  468. } while (c1 != 0 && c1 == c2);
  469. return c1 - c2;
  470. }
  471. char* strcpy(char* dest, const char* src)
  472. {
  473. char* d = dest;
  474. while ((*d++ = *src++))
  475. ;
  476. return dest;
  477. }
  478. long atol(const char* str)
  479. {
  480. long res = 0;
  481. int sign = 0;
  482. while (*str == ' ')
  483. str++;
  484. if (*str == '-' || *str == '+') {
  485. sign = *str == '-';
  486. str++;
  487. }
  488. while (*str) {
  489. res *= 10;
  490. res += *str++ - '0';
  491. }
  492. return sign ? -res : res;
  493. }
  494. // Dummy implementation of system call functions.
  495. int _close (int file)
  496. {
  497. return 0;
  498. }
  499. #include <sys/stat.h>
  500. int _fstat(int file, struct stat *st)
  501. {
  502. return 0;
  503. }
  504. int _isatty(int file)
  505. {
  506. return 0;
  507. }
  508. int _lseek (int file, int offset, int whence)
  509. {
  510. return 0;
  511. }
  512. int _open(const char *pathname, int flags)
  513. {
  514. return 0;
  515. }
  516. int _kill(int pid, int sig)
  517. {
  518. return 0;
  519. }
  520. int _getpid(void)
  521. {
  522. return 0;
  523. }
  524. int _read_r(void)
  525. {
  526. return 0;
  527. }
  528. int _write_r(void)
  529. {
  530. return 0;
  531. }
  532. clock_t _times(struct tms *tt)
  533. {
  534. return 0;
  535. }