lwp.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-03-12 Bernard first version
  9. * 2018-11-02 heyuanjie fix complie error in iar
  10. */
  11. #include <rthw.h>
  12. #include <rtthread.h>
  13. #include <dfs_posix.h>
  14. #include <lwp_elf.h>
  15. #include <lwp_console.h>
  16. #ifndef RT_USING_DFS
  17. #error "lwp need file system(RT_USING_DFS)"
  18. #endif
  19. #include "lwp.h"
  20. #define DBG_TAG "LWP"
  21. #define DBG_LVL DBG_WARNING
  22. #include <rtdbg.h>
  23. #define AUX_ARRAY_ITEMS_NR 6
  24. /* aux key */
  25. #define AT_NULL 0
  26. #define AT_IGNORE 1
  27. #define AT_EXECFD 2
  28. #define AT_PHDR 3
  29. #define AT_PHENT 4
  30. #define AT_PHNUM 5
  31. #define AT_PAGESZ 6
  32. #define AT_BASE 7
  33. #define AT_FLAGS 8
  34. #define AT_ENTRY 9
  35. #define AT_NOTELF 10
  36. #define AT_UID 11
  37. #define AT_EUID 12
  38. #define AT_GID 13
  39. #define AT_EGID 14
  40. #define AT_CLKTCK 17
  41. #define AT_PLATFORM 15
  42. #define AT_HWCAP 16
  43. #define AT_FPUCW 18
  44. #define AT_DCACHEBSIZE 19
  45. #define AT_ICACHEBSIZE 20
  46. #define AT_UCACHEBSIZE 21
  47. #define AT_IGNOREPPC 22
  48. #define AT_SECURE 23
  49. #define AT_BASE_PLATFORM 24
  50. #define AT_RANDOM 25
  51. #define AT_HWCAP2 26
  52. #define AT_EXECFN 31
  53. struct process_aux_item
  54. {
  55. uint32_t key;
  56. uint32_t value;
  57. };
  58. struct process_aux
  59. {
  60. struct process_aux_item item[AUX_ARRAY_ITEMS_NR];
  61. };
  62. #ifdef RT_USING_USERSPACE
  63. #ifdef RT_USING_GDBSERVER
  64. #include <hw_breakpoint.h>
  65. #include <lwp_gdbserver.h>
  66. #endif
  67. #include <lwp_mm_area.h>
  68. #include <lwp_user_mm.h>
  69. #define USER_LOAD_VADDR 0x100000
  70. #endif
  71. static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
  72. extern void lwp_user_entry(void *args, const void *text, void *data, void *user_stack);
  73. extern int libc_stdio_get_console(void);
  74. /**
  75. * RT-Thread light-weight process
  76. */
  77. void lwp_set_kernel_sp(uint32_t *sp)
  78. {
  79. rt_thread_self()->kernel_sp = (rt_uint32_t *)sp;
  80. }
  81. uint32_t *lwp_get_kernel_sp(void)
  82. {
  83. #ifdef RT_USING_USERSPACE
  84. return (uint32_t *)rt_thread_self()->sp;
  85. #else
  86. return (uint32_t *)rt_thread_self()->kernel_sp;
  87. #endif
  88. }
  89. #ifdef RT_USING_USERSPACE
  90. static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp)
  91. {
  92. int size = sizeof(int) * 5; /* store argc, argv, envp, aux, NULL */
  93. int *args;
  94. char *str;
  95. char *str_k;
  96. char **new_argve;
  97. int i;
  98. int len;
  99. int *args_k;
  100. struct process_aux *aux;
  101. for (i = 0; i < argc; i++)
  102. {
  103. size += (rt_strlen(argv[i]) + 1);
  104. }
  105. size += (sizeof(int) * argc);
  106. i = 0;
  107. if (envp)
  108. {
  109. while (envp[i] != 0)
  110. {
  111. size += (rt_strlen(envp[i]) + 1);
  112. size += sizeof(int);
  113. i++;
  114. }
  115. }
  116. /* for aux */
  117. size += sizeof(struct process_aux);
  118. if (size > ARCH_PAGE_SIZE)
  119. return RT_NULL;
  120. /* args = (int*)lwp_map_user(lwp, 0, size); */
  121. args = (int *)lwp_map_user(lwp, (void *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE), size);
  122. if (args == RT_NULL)
  123. return RT_NULL;
  124. args_k = (int *)rt_hw_mmu_v2p(&lwp->mmu_info, args);
  125. args_k = (int *)((size_t)args_k - PV_OFFSET);
  126. /* argc, argv[], 0, envp[], 0 , aux[] */
  127. str = (char *)((size_t)args + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  128. str_k = (char *)((size_t)args_k + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  129. new_argve = (char **)&args_k[1];
  130. args_k[0] = argc;
  131. for (i = 0; i < argc; i++)
  132. {
  133. len = rt_strlen(argv[i]) + 1;
  134. new_argve[i] = str;
  135. rt_memcpy(str_k, argv[i], len);
  136. str += len;
  137. str_k += len;
  138. }
  139. new_argve[i] = 0;
  140. i++;
  141. new_argve[i] = 0;
  142. if (envp)
  143. {
  144. int j;
  145. for (j = 0; envp[j] != 0; j++)
  146. {
  147. len = rt_strlen(envp[j]) + 1;
  148. new_argve[i] = str;
  149. rt_memcpy(str_k, envp[j], len);
  150. str += len;
  151. str_k += len;
  152. i++;
  153. }
  154. new_argve[i] = 0;
  155. }
  156. i++;
  157. /* aux */
  158. aux = (struct process_aux *)(new_argve + i);
  159. aux->item[0].key = AT_EXECFN;
  160. aux->item[0].value = (uint32_t)(size_t)new_argve[0];
  161. i += AUX_ARRAY_ITEMS_NR * 2;
  162. new_argve[i] = 0;
  163. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, args_k, size);
  164. lwp->args = args;
  165. return aux;
  166. }
  167. #else
  168. static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp)
  169. {
  170. int size = sizeof(int) * 5; /* store argc, argv, envp, aux, NULL */
  171. int *args;
  172. char *str;
  173. char **new_argve;
  174. int i;
  175. int len;
  176. struct process_aux *aux;
  177. for (i = 0; i < argc; i++)
  178. {
  179. size += (rt_strlen(argv[i]) + 1);
  180. }
  181. size += (sizeof(int) * argc);
  182. i = 0;
  183. if (envp)
  184. {
  185. while (envp[i] != 0)
  186. {
  187. size += (rt_strlen(envp[i]) + 1);
  188. size += sizeof(int);
  189. i++;
  190. }
  191. }
  192. /* for aux */
  193. size += sizeof(struct process_aux);
  194. args = (int *)rt_malloc(size);
  195. if (args == RT_NULL)
  196. return RT_NULL;
  197. /* argc, argv[], 0, envp[], 0 */
  198. str = (char *)((size_t)args + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  199. new_argve = (char **)&args[1];
  200. args[0] = argc;
  201. for (i = 0; i < argc; i++)
  202. {
  203. len = rt_strlen(argv[i]) + 1;
  204. new_argve[i] = str;
  205. rt_memcpy(str, argv[i], len);
  206. str += len;
  207. }
  208. new_argve[i] = 0;
  209. i++;
  210. new_argve[i] = 0;
  211. if (envp)
  212. {
  213. int j;
  214. for (j = 0; envp[j] != 0; j++)
  215. {
  216. len = rt_strlen(envp[j]) + 1;
  217. new_argve[i] = str;
  218. rt_memcpy(str, envp[j], len);
  219. str += len;
  220. i++;
  221. }
  222. new_argve[i] = 0;
  223. }
  224. /* aux */
  225. aux = (struct process_aux *)(new_argve + i);
  226. aux->item[0].key = AT_EXECFN;
  227. aux->item[0].value = (uint32_t)(size_t)new_argve[0];
  228. i += AUX_ARRAY_ITEMS_NR * 2;
  229. new_argve[i] = 0;
  230. lwp->args = args;
  231. return aux;
  232. }
  233. #endif
  234. #define check_off(voff, vlen) \
  235. do \
  236. { \
  237. if (voff > vlen) \
  238. { \
  239. result = -RT_ERROR; \
  240. goto _exit; \
  241. } \
  242. } while (0)
  243. #define check_read(vrlen, vrlen_want) \
  244. do \
  245. { \
  246. if (vrlen < vrlen_want) \
  247. { \
  248. result = -RT_ERROR; \
  249. goto _exit; \
  250. } \
  251. } while (0)
  252. static size_t load_fread(void *ptr, size_t size, size_t nmemb, int fd)
  253. {
  254. size_t read_block = 0;
  255. while (nmemb)
  256. {
  257. size_t count;
  258. count = read(fd, ptr, size * nmemb) / size;
  259. if (count < nmemb)
  260. {
  261. LOG_E("ERROR: file size error!");
  262. break;
  263. }
  264. ptr = (void *)((uint8_t *)ptr + (count * size));
  265. nmemb -= count;
  266. read_block += count;
  267. }
  268. return read_block;
  269. }
  270. typedef struct
  271. {
  272. Elf32_Word st_name;
  273. Elf32_Addr st_value;
  274. Elf32_Word st_size;
  275. unsigned char st_info;
  276. unsigned char st_other;
  277. Elf32_Half st_shndx;
  278. } Elf32_sym;
  279. #ifdef RT_USING_USERSPACE
  280. void lwp_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym);
  281. #else
  282. void lwp_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf32_sym *dynsym);
  283. #endif
  284. static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, struct process_aux *aux)
  285. {
  286. uint32_t i;
  287. uint32_t off = 0;
  288. char *p_section_str = 0;
  289. Elf32_sym *dynsym = 0;
  290. Elf32_Ehdr eheader;
  291. Elf32_Phdr pheader;
  292. Elf32_Shdr sheader;
  293. int result = RT_EOK;
  294. uint32_t magic;
  295. size_t read_len;
  296. void *got_start = 0;
  297. size_t got_size = 0;
  298. void *rel_dyn_start = 0;
  299. size_t rel_dyn_size = 0;
  300. size_t dynsym_off = 0;
  301. size_t dynsym_size = 0;
  302. #ifdef RT_USING_USERSPACE
  303. rt_mmu_info *m_info = &lwp->mmu_info;
  304. #endif
  305. if (len < sizeof eheader)
  306. {
  307. return -RT_ERROR;
  308. }
  309. lseek(fd, 0, SEEK_SET);
  310. read_len = load_fread(&magic, 1, sizeof magic, fd);
  311. check_read(read_len, sizeof magic);
  312. if (memcmp(elf_magic, &magic, 4) != 0)
  313. {
  314. return -RT_ERROR;
  315. }
  316. lseek(fd, off, SEEK_SET);
  317. read_len = load_fread(&eheader, 1, sizeof eheader, fd);
  318. check_read(read_len, sizeof eheader);
  319. if (eheader.e_ident[4] != 1)
  320. { /* not 32bit */
  321. return -RT_ERROR;
  322. }
  323. if (eheader.e_ident[6] != 1)
  324. { /* ver not 1 */
  325. return -RT_ERROR;
  326. }
  327. if ((eheader.e_type != ET_DYN)
  328. #ifdef RT_USING_USERSPACE
  329. && (eheader.e_type != ET_EXEC)
  330. #endif
  331. )
  332. {
  333. /* not pie or exec elf */
  334. return -RT_ERROR;
  335. }
  336. { /* load aux */
  337. #ifdef RT_USING_USERSPACE
  338. void *pa, *va;
  339. #endif
  340. uint8_t *process_header;
  341. size_t process_header_size;
  342. off = eheader.e_phoff;
  343. process_header_size = eheader.e_phnum * sizeof pheader;
  344. if (process_header_size > ARCH_PAGE_SIZE)
  345. return -RT_ERROR;
  346. #ifdef RT_USING_USERSPACE
  347. va = (uint8_t *)lwp_map_user(lwp, (void *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE * 2), process_header_size);
  348. if (!va)
  349. return -RT_ERROR;
  350. pa = rt_hw_mmu_v2p(m_info, va);
  351. process_header = (uint8_t*)pa - PV_OFFSET;
  352. #else
  353. process_header = (uint8_t *)rt_malloc(process_header_size);
  354. if (!process_header)
  355. return -RT_ERROR;
  356. #endif
  357. check_off(off, len);
  358. lseek(fd, off, SEEK_SET);
  359. read_len = load_fread(process_header, 1, process_header_size, fd);
  360. check_read(read_len, process_header_size);
  361. #ifdef RT_USING_USERSPACE
  362. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, process_header, process_header_size);
  363. #endif
  364. aux->item[1].key = AT_PAGESZ;
  365. aux->item[1].value = ARCH_PAGE_SIZE;
  366. aux->item[2].key = AT_RANDOM;
  367. aux->item[2].value = rt_tick_get();
  368. aux->item[3].key = AT_PHDR;
  369. #ifdef RT_USING_USERSPACE
  370. aux->item[3].value = (uint32_t)(size_t)va;
  371. #else
  372. aux->item[3].value = (uint32_t)(size_t)process_header;
  373. #endif
  374. aux->item[4].key = AT_PHNUM;
  375. aux->item[4].value = eheader.e_phnum;
  376. aux->item[5].key = AT_PHENT;
  377. aux->item[5].value = sizeof pheader;
  378. #ifdef RT_USING_USERSPACE
  379. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, aux, sizeof *aux);
  380. #endif
  381. }
  382. off = eheader.e_phoff;
  383. for (i = 0; i < eheader.e_phnum; i++, off += sizeof pheader)
  384. {
  385. check_off(off, len);
  386. lseek(fd, off, SEEK_SET);
  387. read_len = load_fread(&pheader, 1, sizeof pheader, fd);
  388. check_read(read_len, sizeof pheader);
  389. if (pheader.p_type == PT_LOAD)
  390. {
  391. if (pheader.p_filesz > pheader.p_memsz)
  392. {
  393. return -RT_ERROR;
  394. }
  395. if (load_addr)
  396. {
  397. if (eheader.e_type == ET_EXEC)
  398. {
  399. result = -RT_ERROR;
  400. goto _exit;
  401. }
  402. lwp->text_entry = load_addr;
  403. }
  404. else
  405. {
  406. #ifdef RT_USING_USERSPACE
  407. void *va;
  408. if (eheader.e_type == ET_EXEC)
  409. {
  410. if (pheader.p_vaddr != USER_LOAD_VADDR)
  411. {
  412. result = -RT_ERROR;
  413. goto _exit;
  414. }
  415. va = lwp_map_user(lwp, (void *)pheader.p_vaddr, pheader.p_memsz);
  416. }
  417. else
  418. {
  419. va = lwp_map_user(lwp, 0, pheader.p_memsz);
  420. }
  421. if (va)
  422. {
  423. lwp->text_entry = va;
  424. lwp->text_size = pheader.p_memsz;
  425. }
  426. else
  427. {
  428. lwp->text_entry = RT_NULL;
  429. }
  430. #else
  431. #ifdef RT_USING_CACHE
  432. lwp->text_entry = (rt_uint8_t *)rt_malloc_align(pheader.p_memsz, RT_CPU_CACHE_LINE_SZ);
  433. #else
  434. lwp->text_entry = (rt_uint8_t *)rt_malloc(pheader.p_memsz);
  435. #endif
  436. #endif
  437. if (lwp->text_entry == RT_NULL)
  438. {
  439. LOG_E("alloc text memory faild!");
  440. result = -RT_ENOMEM;
  441. goto _exit;
  442. }
  443. else
  444. {
  445. LOG_D("lwp text malloc : %p, size: %d!", lwp->text_entry, lwp->text_size);
  446. }
  447. check_off(pheader.p_offset, len);
  448. lseek(fd, pheader.p_offset, SEEK_SET);
  449. #ifdef RT_USING_USERSPACE
  450. {
  451. uint32_t size = pheader.p_filesz;
  452. void *va_self;
  453. void *pa;
  454. size_t tmp_len = 0;
  455. read_len = 0;
  456. while (size)
  457. {
  458. pa = rt_hw_mmu_v2p(m_info, va);
  459. va_self = (void*)((char*)pa - PV_OFFSET);
  460. LOG_D("va_self = %p pa = %p", va_self, pa);
  461. tmp_len = (size < ARCH_PAGE_SIZE) ? size : ARCH_PAGE_SIZE;
  462. tmp_len = load_fread(va_self, 1, tmp_len, fd);
  463. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, va_self, tmp_len);
  464. read_len += tmp_len;
  465. size -= tmp_len;
  466. va = (void*)((char*)va + ARCH_PAGE_SIZE);
  467. }
  468. }
  469. #else
  470. read_len = load_fread(lwp->text_entry, 1, pheader.p_filesz, fd);
  471. #endif
  472. check_read(read_len, pheader.p_filesz);
  473. }
  474. if (pheader.p_filesz < pheader.p_memsz)
  475. {
  476. #ifdef RT_USING_USERSPACE
  477. void *va = (void*)((char*)lwp->text_entry + pheader.p_filesz);
  478. void *va_self;
  479. void *pa;
  480. uint32_t size = pheader.p_memsz - pheader.p_filesz;
  481. uint32_t size_s;
  482. uint32_t off;
  483. off = pheader.p_filesz & ARCH_PAGE_MASK;
  484. va = (void *)(((size_t)lwp->text_entry + pheader.p_filesz) & ~ARCH_PAGE_MASK);
  485. while (size)
  486. {
  487. size_s = (size < ARCH_PAGE_SIZE - off) ? size : ARCH_PAGE_SIZE - off;
  488. pa = rt_hw_mmu_v2p(m_info, va);
  489. va_self = (void*)((char*)pa - PV_OFFSET);
  490. memset((void*)((char*)va_self + off), 0, size_s);
  491. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void*)((char*)va_self + off), size_s);
  492. off = 0;
  493. size -= size_s;
  494. va = (void*)((char*)va + ARCH_PAGE_SIZE);
  495. }
  496. #else
  497. memset((uint8_t *)lwp->text_entry + pheader.p_filesz, 0, (size_t)(pheader.p_memsz - pheader.p_filesz));
  498. #endif
  499. }
  500. break;
  501. }
  502. }
  503. if (eheader.e_type == ET_DYN)
  504. {
  505. /* section info */
  506. off = eheader.e_shoff;
  507. /* find section string table */
  508. check_off(off, len);
  509. lseek(fd, off + (sizeof sheader) * eheader.e_shstrndx, SEEK_SET);
  510. read_len = load_fread(&sheader, 1, sizeof sheader, fd);
  511. check_read(read_len, sizeof sheader);
  512. p_section_str = (char *)rt_malloc(sheader.sh_size);
  513. if (!p_section_str)
  514. {
  515. LOG_E("out of memory!");
  516. result = -ENOMEM;
  517. goto _exit;
  518. }
  519. check_off(sheader.sh_offset, len);
  520. lseek(fd, sheader.sh_offset, SEEK_SET);
  521. read_len = load_fread(p_section_str, 1, sheader.sh_size, fd);
  522. check_read(read_len, sheader.sh_size);
  523. check_off(off, len);
  524. lseek(fd, off, SEEK_SET);
  525. for (i = 0; i < eheader.e_shnum; i++, off += sizeof sheader)
  526. {
  527. read_len = load_fread(&sheader, 1, sizeof sheader, fd);
  528. check_read(read_len, sizeof sheader);
  529. if (strcmp(p_section_str + sheader.sh_name, "text") == 0)
  530. {
  531. lwp->text_size = sheader.sh_size;
  532. }
  533. else if (strcmp(p_section_str + sheader.sh_name, ".got") == 0)
  534. {
  535. got_start = (void *)((uint8_t *)lwp->text_entry + sheader.sh_addr);
  536. got_size = (size_t)sheader.sh_size;
  537. }
  538. else if (strcmp(p_section_str + sheader.sh_name, ".rel.dyn") == 0)
  539. {
  540. rel_dyn_start = (void *)((uint8_t *)lwp->text_entry + sheader.sh_addr);
  541. rel_dyn_size = (size_t)sheader.sh_size;
  542. }
  543. else if (strcmp(p_section_str + sheader.sh_name, ".dynsym") == 0)
  544. {
  545. dynsym_off = (size_t)sheader.sh_offset;
  546. dynsym_size = (size_t)sheader.sh_size;
  547. }
  548. }
  549. /* reloc */
  550. if (dynsym_size)
  551. {
  552. dynsym = rt_malloc(dynsym_size);
  553. if (!dynsym)
  554. {
  555. LOG_E("ERROR: Malloc error!");
  556. result = -ENOMEM;
  557. goto _exit;
  558. }
  559. check_off(dynsym_off, len);
  560. lseek(fd, dynsym_off, SEEK_SET);
  561. read_len = load_fread(dynsym, 1, dynsym_size, fd);
  562. check_read(read_len, dynsym_size);
  563. }
  564. #ifdef RT_USING_USERSPACE
  565. lwp_elf_reloc(m_info, (void *)lwp->text_entry, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
  566. #else
  567. lwp_elf_reloc((void *)lwp->text_entry, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
  568. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, lwp->text_size);
  569. rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, lwp->text_entry, lwp->text_size);
  570. #endif
  571. }
  572. LOG_D("lwp->text_entry = 0x%p", lwp->text_entry);
  573. LOG_D("lwp->text_size = 0x%p", lwp->text_size);
  574. _exit:
  575. if (dynsym)
  576. {
  577. rt_free(dynsym);
  578. }
  579. if (p_section_str)
  580. {
  581. rt_free(p_section_str);
  582. }
  583. if (result != RT_EOK)
  584. {
  585. LOG_E("lwp dynamic load faild, %d", result);
  586. lwp_ref_dec(lwp);
  587. }
  588. return result;
  589. }
  590. int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size, struct process_aux *aux);
  591. RT_WEAK int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size, struct process_aux *aux)
  592. {
  593. uint8_t *ptr;
  594. int ret = -1;
  595. int len;
  596. int fd = -1;
  597. /* check file name */
  598. RT_ASSERT(filename != RT_NULL);
  599. /* check lwp control block */
  600. RT_ASSERT(lwp != RT_NULL);
  601. /* copy file name to process name */
  602. rt_strncpy(lwp->cmd, filename, RT_NAME_MAX);
  603. if (load_addr != RT_NULL)
  604. {
  605. lwp->lwp_type = LWP_TYPE_FIX_ADDR;
  606. ptr = load_addr;
  607. }
  608. else
  609. {
  610. lwp->lwp_type = LWP_TYPE_DYN_ADDR;
  611. ptr = RT_NULL;
  612. }
  613. fd = open(filename, O_BINARY | O_RDONLY, 0);
  614. if (fd < 0)
  615. {
  616. LOG_E("ERROR: Can't open elf file %s!", filename);
  617. goto out;
  618. }
  619. len = lseek(fd, 0, SEEK_END);
  620. if (len < 0)
  621. {
  622. LOG_E("ERROR: File %s size error!", filename);
  623. goto out;
  624. }
  625. lseek(fd, 0, SEEK_SET);
  626. ret = load_elf(fd, len, lwp, ptr, aux);
  627. if (ret != RT_EOK)
  628. {
  629. LOG_E("lwp load ret = %d", ret);
  630. }
  631. out:
  632. if (fd > 0)
  633. {
  634. close(fd);
  635. }
  636. return ret;
  637. }
  638. void lwp_cleanup(struct rt_thread *tid)
  639. {
  640. rt_base_t level;
  641. struct rt_lwp *lwp;
  642. if (tid == NULL) return;
  643. LOG_I("cleanup thread: %s, stack_addr: %08X", tid->name, tid->stack_addr);
  644. #ifndef RT_USING_USERSPACE
  645. if (tid->user_stack != RT_NULL)
  646. {
  647. rt_free(tid->user_stack);
  648. }
  649. #endif
  650. level = rt_hw_interrupt_disable();
  651. lwp = (struct rt_lwp *)tid->lwp;
  652. lwp_tid_put(tid->tid);
  653. rt_list_remove(&tid->sibling);
  654. lwp_ref_dec(lwp);
  655. rt_hw_interrupt_enable(level);
  656. return;
  657. }
  658. static void lwp_copy_stdio_fdt(struct rt_lwp *lwp)
  659. {
  660. struct dfs_fd *d;
  661. struct dfs_fdtable *lwp_fdt;
  662. lwp_fdt = &lwp->fdt;
  663. /* init 4 fds */
  664. lwp_fdt->fds = rt_calloc(4, sizeof(void *));
  665. if (lwp_fdt->fds)
  666. {
  667. lwp_fdt->maxfd = 4;
  668. d = fd_get(0);
  669. fd_associate(lwp_fdt, 0, d);
  670. d = fd_get(1);
  671. fd_associate(lwp_fdt, 1, d);
  672. d = fd_get(2);
  673. fd_associate(lwp_fdt, 2, d);
  674. }
  675. return;
  676. }
  677. static void lwp_thread_entry(void *parameter)
  678. {
  679. rt_thread_t tid;
  680. struct rt_lwp *lwp;
  681. tid = rt_thread_self();
  682. lwp = (struct rt_lwp *)tid->lwp;
  683. tid->cleanup = lwp_cleanup;
  684. tid->user_stack = RT_NULL;
  685. #ifdef RT_USING_GDBSERVER
  686. if (lwp->debug)
  687. {
  688. lwp->bak_first_ins = *(uint32_t *)lwp->text_entry;
  689. *(uint32_t *)lwp->text_entry = INS_BREAK_CONNECT;
  690. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, sizeof(uint32_t));
  691. icache_invalid_all();
  692. }
  693. #endif
  694. lwp_user_entry(lwp->args, lwp->text_entry, lwp->data_entry, RT_NULL);
  695. }
  696. struct rt_lwp *lwp_self(void)
  697. {
  698. rt_thread_t tid;
  699. tid = rt_thread_self();
  700. if (tid)
  701. {
  702. return (struct rt_lwp *)tid->lwp;
  703. }
  704. return RT_NULL;
  705. }
  706. #ifdef RT_USING_GDBSERVER
  707. pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
  708. #else
  709. pid_t lwp_execve(char *filename, int argc, char **argv, char **envp)
  710. #endif
  711. {
  712. int result;
  713. rt_base_t level;
  714. struct rt_lwp *lwp;
  715. char *thread_name;
  716. char *argv_last = argv[argc - 1];
  717. int bg = 0;
  718. struct process_aux *aux;
  719. int tid = 0;
  720. if (filename == RT_NULL)
  721. return -RT_ERROR;
  722. lwp = lwp_new();
  723. if (lwp == RT_NULL)
  724. {
  725. dbg_log(DBG_ERROR, "lwp struct out of memory!\n");
  726. return -RT_ENOMEM;
  727. }
  728. LOG_D("lwp malloc : %p, size: %d!", lwp, sizeof(struct rt_lwp));
  729. if ((tid = lwp_tid_get()) == 0)
  730. {
  731. lwp_ref_dec(lwp);
  732. return -ENOMEM;
  733. }
  734. #ifdef RT_USING_USERSPACE
  735. if (lwp_user_space_init(lwp) != 0)
  736. {
  737. lwp_tid_put(tid);
  738. lwp_ref_dec(lwp);
  739. return -ENOMEM;
  740. }
  741. #endif
  742. if (argv_last[0] == '&' && argv_last[1] == '\0')
  743. {
  744. argc--;
  745. bg = 1;
  746. }
  747. if ((aux = lwp_argscopy(lwp, argc, argv, envp)) == RT_NULL)
  748. {
  749. lwp_tid_put(tid);
  750. lwp_ref_dec(lwp);
  751. return -ENOMEM;
  752. }
  753. result = lwp_load(filename, lwp, RT_NULL, 0, aux);
  754. if (result == RT_EOK)
  755. {
  756. rt_thread_t thread = RT_NULL;
  757. lwp_copy_stdio_fdt(lwp);
  758. /* obtain the base name */
  759. thread_name = strrchr(filename, '/');
  760. thread_name = thread_name ? thread_name + 1 : filename;
  761. thread = rt_thread_create(thread_name, lwp_thread_entry, RT_NULL,
  762. 1024 * 4, 25, 200);
  763. if (thread != RT_NULL)
  764. {
  765. struct rt_lwp *lwp_self;
  766. thread->tid = tid;
  767. lwp_tid_set_thread(tid, thread);
  768. LOG_D("lwp kernel => (0x%08x, 0x%08x)\n", (rt_uint32_t)thread->stack_addr, (rt_uint32_t)thread->stack_addr + thread->stack_size);
  769. level = rt_hw_interrupt_disable();
  770. lwp_self = (struct rt_lwp *)rt_thread_self()->lwp;
  771. if (lwp_self)
  772. {
  773. /* lwp add to children link */
  774. lwp->sibling = lwp_self->first_child;
  775. lwp_self->first_child = lwp;
  776. lwp->parent = lwp_self;
  777. }
  778. thread->lwp = lwp;
  779. rt_list_insert_after(&lwp->t_grp, &thread->sibling);
  780. #ifdef RT_USING_GDBSERVER
  781. if (debug)
  782. {
  783. lwp->debug = debug;
  784. }
  785. #endif
  786. if ((rt_console_get_foreground() == lwp_self) && !bg)
  787. {
  788. rt_console_set_foreground(lwp);
  789. }
  790. rt_hw_interrupt_enable(level);
  791. rt_thread_startup(thread);
  792. return lwp_to_pid(lwp);
  793. }
  794. }
  795. lwp_tid_put(tid);
  796. lwp_ref_dec(lwp);
  797. return -RT_ERROR;
  798. }
  799. #ifdef RT_USING_GDBSERVER
  800. pid_t exec(char *filename, int debug, int argc, char **argv)
  801. {
  802. return lwp_execve(filename, debug, argc, argv, 0);
  803. }
  804. #else
  805. pid_t exec(char *filename, int argc, char **argv)
  806. {
  807. return lwp_execve(filename, argc, argv, 0);
  808. }
  809. #endif