lwp.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /*
  2. * Copyright (c) 2006-2021, 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. * 2021-02-03 lizhirui add 64-bit arch support and riscv64 arch support
  11. */
  12. #include <rthw.h>
  13. #include <rtthread.h>
  14. #include <dfs_posix.h>
  15. #include <lwp_elf.h>
  16. #include <lwp_console.h>
  17. #ifndef RT_USING_DFS
  18. #error "lwp need file system(RT_USING_DFS)"
  19. #endif
  20. #include "lwp.h"
  21. #include "lwp_arch.h"
  22. #define DBG_TAG "LWP"
  23. #define DBG_LVL DBG_WARNING
  24. #include <rtdbg.h>
  25. #ifdef RT_USING_USERSPACE
  26. #ifdef RT_USING_GDBSERVER
  27. #include <hw_breakpoint.h>
  28. #include <lwp_gdbserver.h>
  29. #endif
  30. #include <lwp_mm_area.h>
  31. #include <lwp_user_mm.h>
  32. #endif
  33. static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
  34. extern void lwp_user_entry(void *args, const void *text, void *data, void *k_stack);
  35. extern int libc_stdio_get_console(void);
  36. int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *const envp[]);
  37. /**
  38. * RT-Thread light-weight process
  39. */
  40. void lwp_set_kernel_sp(uint32_t *sp)
  41. {
  42. rt_thread_self()->kernel_sp = (rt_uint32_t *)sp;
  43. }
  44. uint32_t *lwp_get_kernel_sp(void)
  45. {
  46. #ifdef RT_USING_USERSPACE
  47. return (uint32_t *)rt_thread_self()->sp;
  48. #else
  49. return (uint32_t *)rt_thread_self()->kernel_sp;
  50. #endif
  51. }
  52. #ifdef RT_USING_USERSPACE
  53. struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp)
  54. {
  55. int size = sizeof(int) * 5; /* store argc, argv, envp, aux, NULL */
  56. int *args;
  57. char *str;
  58. char *str_k;
  59. char **new_argve;
  60. int i;
  61. int len;
  62. int *args_k;
  63. struct process_aux *aux;
  64. for (i = 0; i < argc; i++)
  65. {
  66. size += (rt_strlen(argv[i]) + 1);
  67. }
  68. size += (sizeof(int) * argc);
  69. i = 0;
  70. if (envp)
  71. {
  72. while (envp[i] != 0)
  73. {
  74. size += (rt_strlen(envp[i]) + 1);
  75. size += sizeof(int);
  76. i++;
  77. }
  78. }
  79. /* for aux */
  80. size += sizeof(struct process_aux);
  81. if (size > ARCH_PAGE_SIZE)
  82. {
  83. return RT_NULL;
  84. }
  85. /* args = (int *)lwp_map_user(lwp, 0, size); */
  86. args = (int *)lwp_map_user(lwp, (void *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE), size, 0);
  87. if (args == RT_NULL)
  88. {
  89. return RT_NULL;
  90. }
  91. args_k = (int *)rt_hw_mmu_v2p(&lwp->mmu_info, args);
  92. args_k = (int *)((size_t)args_k - PV_OFFSET);
  93. /* argc, argv[], 0, envp[], 0 , aux[] */
  94. str = (char *)((size_t)args + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  95. str_k = (char *)((size_t)args_k + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  96. new_argve = (char **)&args_k[1];
  97. args_k[0] = argc;
  98. for (i = 0; i < argc; i++)
  99. {
  100. len = rt_strlen(argv[i]) + 1;
  101. new_argve[i] = str;
  102. rt_memcpy(str_k, argv[i], len);
  103. str += len;
  104. str_k += len;
  105. }
  106. new_argve[i] = 0;
  107. i++;
  108. new_argve[i] = 0;
  109. if (envp)
  110. {
  111. int j;
  112. for (j = 0; envp[j] != 0; j++)
  113. {
  114. len = rt_strlen(envp[j]) + 1;
  115. new_argve[i] = str;
  116. rt_memcpy(str_k, envp[j], len);
  117. str += len;
  118. str_k += len;
  119. i++;
  120. }
  121. new_argve[i] = 0;
  122. }
  123. i++;
  124. /* aux */
  125. aux = (struct process_aux *)(new_argve + i);
  126. aux->item[0].key = AT_EXECFN;
  127. aux->item[0].value = (uint32_t)(size_t)new_argve[0];
  128. i += AUX_ARRAY_ITEMS_NR * 2;
  129. new_argve[i] = 0;
  130. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, args_k, size);
  131. lwp->args = args;
  132. return aux;
  133. }
  134. #else
  135. static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp)
  136. {
  137. int size = sizeof(int) * 5; /* store argc, argv, envp, aux, NULL */
  138. int *args;
  139. char *str;
  140. char **new_argve;
  141. int i;
  142. int len;
  143. struct process_aux *aux;
  144. for (i = 0; i < argc; i++)
  145. {
  146. size += (rt_strlen(argv[i]) + 1);
  147. }
  148. size += (sizeof(int) * argc);
  149. i = 0;
  150. if (envp)
  151. {
  152. while (envp[i] != 0)
  153. {
  154. size += (rt_strlen(envp[i]) + 1);
  155. size += sizeof(int);
  156. i++;
  157. }
  158. }
  159. /* for aux */
  160. size += sizeof(struct process_aux);
  161. args = (int *)rt_malloc(size);
  162. if (args == RT_NULL)
  163. {
  164. return RT_NULL;
  165. }
  166. /* argc, argv[], 0, envp[], 0 */
  167. str = (char *)((size_t)args + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  168. new_argve = (char **)&args[1];
  169. args[0] = argc;
  170. for (i = 0; i < argc; i++)
  171. {
  172. len = rt_strlen(argv[i]) + 1;
  173. new_argve[i] = str;
  174. rt_memcpy(str, argv[i], len);
  175. str += len;
  176. }
  177. new_argve[i] = 0;
  178. i++;
  179. new_argve[i] = 0;
  180. if (envp)
  181. {
  182. int j;
  183. for (j = 0; envp[j] != 0; j++)
  184. {
  185. len = rt_strlen(envp[j]) + 1;
  186. new_argve[i] = str;
  187. rt_memcpy(str, envp[j], len);
  188. str += len;
  189. i++;
  190. }
  191. new_argve[i] = 0;
  192. }
  193. /* aux */
  194. aux = (struct process_aux *)(new_argve + i);
  195. aux->item[0].key = AT_EXECFN;
  196. aux->item[0].value = (uint32_t)(size_t)new_argve[0];
  197. i += AUX_ARRAY_ITEMS_NR * 2;
  198. new_argve[i] = 0;
  199. lwp->args = args;
  200. return aux;
  201. }
  202. #endif
  203. #define check_off(voff, vlen) \
  204. do \
  205. { \
  206. if (voff > vlen) \
  207. { \
  208. result = -RT_ERROR; \
  209. goto _exit; \
  210. } \
  211. } while (0)
  212. #define check_read(vrlen, vrlen_want) \
  213. do \
  214. { \
  215. if (vrlen < vrlen_want) \
  216. { \
  217. result = -RT_ERROR; \
  218. goto _exit; \
  219. } \
  220. } while (0)
  221. static size_t load_fread(void *ptr, size_t size, size_t nmemb, int fd)
  222. {
  223. size_t read_block = 0;
  224. while (nmemb)
  225. {
  226. size_t count;
  227. count = read(fd, ptr, size * nmemb) / size;
  228. if (count < nmemb)
  229. {
  230. LOG_E("ERROR: file size error!");
  231. break;
  232. }
  233. ptr = (void *)((uint8_t *)ptr + (count * size));
  234. nmemb -= count;
  235. read_block += count;
  236. }
  237. return read_block;
  238. }
  239. #ifdef ARCH_CPU_64BIT
  240. #define Elf_Word Elf64_Word
  241. #define Elf_Addr Elf64_Addr
  242. #define Elf_Half Elf64_Half
  243. #define Elf_Ehdr Elf64_Ehdr
  244. #define Elf_Phdr Elf64_Phdr
  245. #define Elf_Shdr Elf64_Shdr
  246. #else
  247. #define Elf_Word Elf32_Word
  248. #define Elf_Addr Elf32_Addr
  249. #define Elf_Half Elf32_Half
  250. #define Elf_Ehdr Elf32_Ehdr
  251. #define Elf_Phdr Elf32_Phdr
  252. #define Elf_Shdr Elf32_Shdr
  253. #endif
  254. typedef struct
  255. {
  256. Elf_Word st_name;
  257. Elf_Addr st_value;
  258. Elf_Word st_size;
  259. unsigned char st_info;
  260. unsigned char st_other;
  261. Elf_Half st_shndx;
  262. } Elf_sym;
  263. #ifdef RT_USING_USERSPACE
  264. 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, Elf_sym *dynsym);
  265. #else
  266. void lwp_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, void *got_start, size_t got_size, Elf_sym *dynsym);
  267. #endif
  268. #ifdef RT_USING_USERSPACE
  269. struct map_range
  270. {
  271. void *start;
  272. size_t size;
  273. };
  274. static void expand_map_range(struct map_range *m, void *start, size_t size)
  275. {
  276. if (!m->start)
  277. {
  278. m->start = start;
  279. m->size = size;
  280. }
  281. else
  282. {
  283. void *end = (void *)((char*)start + size);
  284. void *mend = (void *)((char*)m->start + m->size);
  285. if (m->start > start)
  286. {
  287. m->start = start;
  288. }
  289. if (mend < end)
  290. {
  291. mend = end;
  292. }
  293. m->size = (char *)mend - (char *)m->start;
  294. }
  295. }
  296. static int map_range_ckeck(struct map_range *m1, struct map_range *m2)
  297. {
  298. void *m1_start = (void *)((size_t)m1->start & ~ARCH_PAGE_MASK);
  299. void *m1_end = (void *)((((size_t)m1->start + m1->size) + ARCH_PAGE_MASK) & ~ARCH_PAGE_MASK);
  300. void *m2_start = (void *)((size_t)m2->start & ~ARCH_PAGE_MASK);
  301. void *m2_end = (void *)((((size_t)m2->start + m2->size) + ARCH_PAGE_MASK) & ~ARCH_PAGE_MASK);
  302. if (m1->size)
  303. {
  304. if (m1_start < (void *)USER_LOAD_VADDR)
  305. {
  306. return -1;
  307. }
  308. if (m1_start > (void *)USER_STACK_VSTART)
  309. {
  310. return -1;
  311. }
  312. if (m1_end < (void *)USER_LOAD_VADDR)
  313. {
  314. return -1;
  315. }
  316. if (m1_end > (void *)USER_STACK_VSTART)
  317. {
  318. return -1;
  319. }
  320. }
  321. if (m2->size)
  322. {
  323. if (m2_start < (void *)USER_LOAD_VADDR)
  324. {
  325. return -1;
  326. }
  327. if (m2_start > (void *)USER_STACK_VSTART)
  328. {
  329. return -1;
  330. }
  331. if (m2_end < (void *)USER_LOAD_VADDR)
  332. {
  333. return -1;
  334. }
  335. if (m2_end > (void *)USER_STACK_VSTART)
  336. {
  337. return -1;
  338. }
  339. }
  340. if ((m1->size != 0) && (m2->size != 0))
  341. {
  342. if (m1_start < m2_start)
  343. {
  344. if (m1_end > m2_start)
  345. {
  346. return -1;
  347. }
  348. }
  349. else /* m2_start <= m1_start */
  350. {
  351. if (m2_end > m1_start)
  352. {
  353. return -1;
  354. }
  355. }
  356. }
  357. return 0;
  358. }
  359. #endif
  360. static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, struct process_aux *aux)
  361. {
  362. uint32_t i;
  363. uint32_t off = 0;
  364. size_t load_off = 0;
  365. char *p_section_str = 0;
  366. Elf_sym *dynsym = 0;
  367. Elf_Ehdr eheader;
  368. Elf_Phdr pheader;
  369. Elf_Shdr sheader;
  370. int result = RT_EOK;
  371. uint32_t magic;
  372. size_t read_len;
  373. void *got_start = 0;
  374. size_t got_size = 0;
  375. void *rel_dyn_start = 0;
  376. size_t rel_dyn_size = 0;
  377. size_t dynsym_off = 0;
  378. size_t dynsym_size = 0;
  379. #ifdef RT_USING_USERSPACE
  380. struct map_range user_area[2] = {{NULL, 0}, {NULL, 0}}; /* 0 is text, 1 is data */
  381. void *pa, *va;
  382. void *va_self;
  383. #endif
  384. #ifdef RT_USING_USERSPACE
  385. rt_mmu_info *m_info = &lwp->mmu_info;
  386. #endif
  387. if (len < sizeof eheader)
  388. {
  389. return -RT_ERROR;
  390. }
  391. lseek(fd, 0, SEEK_SET);
  392. read_len = load_fread(&magic, 1, sizeof magic, fd);
  393. check_read(read_len, sizeof magic);
  394. if (memcmp(elf_magic, &magic, 4) != 0)
  395. {
  396. return -RT_ERROR;
  397. }
  398. lseek(fd, off, SEEK_SET);
  399. read_len = load_fread(&eheader, 1, sizeof eheader, fd);
  400. check_read(read_len, sizeof eheader);
  401. #ifndef ARCH_CPU_64BIT
  402. if (eheader.e_ident[4] != 1)
  403. { /* not 32bit */
  404. return -RT_ERROR;
  405. }
  406. #else
  407. if (eheader.e_ident[4] != 2)
  408. { /* not 64bit */
  409. return -RT_ERROR;
  410. }
  411. #endif
  412. if (eheader.e_ident[6] != 1)
  413. { /* ver not 1 */
  414. return -RT_ERROR;
  415. }
  416. if ((eheader.e_type != ET_DYN)
  417. #ifdef RT_USING_USERSPACE
  418. && (eheader.e_type != ET_EXEC)
  419. #endif
  420. )
  421. {
  422. /* not pie or exec elf */
  423. return -RT_ERROR;
  424. }
  425. #ifdef RT_USING_USERSPACE
  426. {
  427. off = eheader.e_phoff;
  428. for (i = 0; i < eheader.e_phnum; i++, off += sizeof pheader)
  429. {
  430. check_off(off, len);
  431. lseek(fd, off, SEEK_SET);
  432. read_len = load_fread(&pheader, 1, sizeof pheader, fd);
  433. check_read(read_len, sizeof pheader);
  434. if (pheader.p_type == PT_DYNAMIC)
  435. {
  436. /* load ld.so */
  437. return 1; /* 1 means dynamic */
  438. }
  439. }
  440. }
  441. #endif
  442. if (eheader.e_entry != 0)
  443. {
  444. if ((eheader.e_entry != USER_LOAD_VADDR)
  445. && (eheader.e_entry != LDSO_LOAD_VADDR))
  446. {
  447. /* the entry is invalidate */
  448. return -RT_ERROR;
  449. }
  450. }
  451. { /* load aux */
  452. uint8_t *process_header;
  453. size_t process_header_size;
  454. off = eheader.e_phoff;
  455. process_header_size = eheader.e_phnum * sizeof pheader;
  456. #ifdef RT_USING_USERSPACE
  457. if (process_header_size > ARCH_PAGE_SIZE - sizeof(char[16]))
  458. {
  459. return -RT_ERROR;
  460. }
  461. va = (uint8_t *)lwp_map_user(lwp, (void *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE * 2), process_header_size, 0);
  462. if (!va)
  463. {
  464. return -RT_ERROR;
  465. }
  466. pa = rt_hw_mmu_v2p(m_info, va);
  467. process_header = (uint8_t *)pa - PV_OFFSET;
  468. #else
  469. process_header = (uint8_t *)rt_malloc(process_header_size + sizeof(char[16]));
  470. if (!process_header)
  471. {
  472. return -RT_ERROR;
  473. }
  474. #endif
  475. check_off(off, len);
  476. lseek(fd, off, SEEK_SET);
  477. read_len = load_fread(process_header, 1, process_header_size, fd);
  478. check_read(read_len, process_header_size);
  479. #ifdef RT_USING_USERSPACE
  480. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, process_header, process_header_size);
  481. #endif
  482. aux->item[1].key = AT_PAGESZ;
  483. #ifdef RT_USING_USERSPACE
  484. aux->item[1].value = ARCH_PAGE_SIZE;
  485. #else
  486. aux->item[1].value = RT_MM_PAGE_SIZE;
  487. #endif
  488. aux->item[2].key = AT_RANDOM;
  489. {
  490. uint32_t random_value = rt_tick_get();
  491. uint8_t *random;
  492. #ifdef RT_USING_USERSPACE
  493. uint8_t *krandom;
  494. random = (uint8_t *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE - sizeof(char[16]));
  495. krandom = (uint8_t *)rt_hw_mmu_v2p(m_info, random);
  496. krandom = (uint8_t *)krandom - PV_OFFSET;
  497. rt_memcpy(krandom, &random_value, sizeof random_value);
  498. #else
  499. random = (uint8_t *)(process_header + process_header_size);
  500. rt_memcpy(random, &random_value, sizeof random_value);
  501. #endif
  502. aux->item[2].value = (uint32_t)(size_t)random;
  503. }
  504. aux->item[3].key = AT_PHDR;
  505. #ifdef RT_USING_USERSPACE
  506. aux->item[3].value = (uint32_t)(size_t)va;
  507. #else
  508. aux->item[3].value = (uint32_t)(size_t)process_header;
  509. #endif
  510. aux->item[4].key = AT_PHNUM;
  511. aux->item[4].value = eheader.e_phnum;
  512. aux->item[5].key = AT_PHENT;
  513. aux->item[5].value = sizeof pheader;
  514. #ifdef RT_USING_USERSPACE
  515. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, aux, sizeof *aux);
  516. #endif
  517. }
  518. if (load_addr)
  519. {
  520. load_off = (size_t)load_addr;
  521. }
  522. #ifdef RT_USING_USERSPACE
  523. else
  524. {
  525. /* map user */
  526. off = eheader.e_shoff;
  527. for (i = 0; i < eheader.e_shnum; i++, off += sizeof sheader)
  528. {
  529. check_off(off, len);
  530. lseek(fd, off, SEEK_SET);
  531. read_len = load_fread(&sheader, 1, sizeof sheader, fd);
  532. check_read(read_len, sizeof sheader);
  533. if ((sheader.sh_flags & SHF_ALLOC) == 0)
  534. {
  535. continue;
  536. }
  537. switch (sheader.sh_type)
  538. {
  539. case SHT_PROGBITS:
  540. if ((sheader.sh_flags & SHF_WRITE) == 0)
  541. {
  542. expand_map_range(&user_area[0], (void *)sheader.sh_addr, sheader.sh_size);
  543. }
  544. else
  545. {
  546. expand_map_range(&user_area[1], (void *)sheader.sh_addr, sheader.sh_size);
  547. }
  548. break;
  549. case SHT_NOBITS:
  550. expand_map_range(&user_area[1], (void *)sheader.sh_addr, sheader.sh_size);
  551. break;
  552. default:
  553. expand_map_range(&user_area[1], (void *)sheader.sh_addr, sheader.sh_size);
  554. break;
  555. }
  556. }
  557. if (user_area[0].size == 0)
  558. {
  559. /* no code */
  560. result = -RT_ERROR;
  561. goto _exit;
  562. }
  563. if (user_area[0].start == NULL)
  564. {
  565. /* DYN */
  566. load_off = USER_LOAD_VADDR;
  567. user_area[0].start = (void *)((char*)user_area[0].start + load_off);
  568. user_area[1].start = (void *)((char*)user_area[1].start + load_off);
  569. }
  570. if (map_range_ckeck(&user_area[0], &user_area[1]) != 0)
  571. {
  572. result = -RT_ERROR;
  573. goto _exit;
  574. }
  575. /* text and data */
  576. for (i = 0; i < 2; i++)
  577. {
  578. if (user_area[i].size != 0)
  579. {
  580. va = lwp_map_user(lwp, user_area[i].start, user_area[i].size, (int)(i == 0));
  581. if (!va || (va != user_area[i].start))
  582. {
  583. result = -RT_ERROR;
  584. goto _exit;
  585. }
  586. }
  587. }
  588. lwp->text_size = user_area[0].size;
  589. }
  590. #else
  591. else
  592. {
  593. size_t start = -1UL;
  594. size_t end = 0UL;
  595. size_t total_size;
  596. off = eheader.e_shoff;
  597. for (i = 0; i < eheader.e_shnum; i++, off += sizeof sheader)
  598. {
  599. check_off(off, len);
  600. lseek(fd, off, SEEK_SET);
  601. read_len = load_fread(&sheader, 1, sizeof sheader, fd);
  602. check_read(read_len, sizeof sheader);
  603. if ((sheader.sh_flags & SHF_ALLOC) == 0)
  604. {
  605. continue;
  606. }
  607. switch (sheader.sh_type)
  608. {
  609. case SHT_PROGBITS:
  610. case SHT_NOBITS:
  611. if (start > sheader.sh_addr)
  612. {
  613. start = sheader.sh_addr;
  614. }
  615. if (sheader.sh_addr + sheader.sh_size > end)
  616. {
  617. end = sheader.sh_addr + sheader.sh_size;
  618. }
  619. break;
  620. default:
  621. break;
  622. }
  623. }
  624. total_size = end - start;
  625. #ifdef RT_USING_CACHE
  626. load_off = (size_t)rt_malloc_align(total_size, RT_CPU_CACHE_LINE_SZ);
  627. #else
  628. load_off = (size_t)rt_malloc(total_size);
  629. #endif
  630. if (load_off == 0)
  631. {
  632. LOG_E("alloc text memory faild!");
  633. result = -RT_ENOMEM;
  634. goto _exit;
  635. }
  636. else
  637. {
  638. LOG_D("lwp text malloc : %p, size: %d!", (void *)load_off, lwp->text_size);
  639. }
  640. lwp->load_off = load_off; /* for free */
  641. lwp->text_size = total_size;
  642. }
  643. #endif
  644. lwp->text_entry = (void *)(eheader.e_entry + load_off);
  645. off = eheader.e_phoff;
  646. for (i = 0; i < eheader.e_phnum; i++, off += sizeof pheader)
  647. {
  648. check_off(off, len);
  649. lseek(fd, off, SEEK_SET);
  650. read_len = load_fread(&pheader, 1, sizeof pheader, fd);
  651. check_read(read_len, sizeof pheader);
  652. if (pheader.p_type == PT_LOAD)
  653. {
  654. if (pheader.p_filesz > pheader.p_memsz)
  655. {
  656. return -RT_ERROR;
  657. }
  658. check_off(pheader.p_offset, len);
  659. lseek(fd, pheader.p_offset, SEEK_SET);
  660. #ifdef RT_USING_USERSPACE
  661. {
  662. uint32_t size = pheader.p_filesz;
  663. size_t tmp_len = 0;
  664. va = (void *)(pheader.p_vaddr + load_addr);
  665. read_len = 0;
  666. while (size)
  667. {
  668. pa = rt_hw_mmu_v2p(m_info, va);
  669. va_self = (void *)((char *)pa - PV_OFFSET);
  670. LOG_D("va_self = %p pa = %p", va_self, pa);
  671. tmp_len = (size < ARCH_PAGE_SIZE) ? size : ARCH_PAGE_SIZE;
  672. tmp_len = load_fread(va_self, 1, tmp_len, fd);
  673. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, va_self, tmp_len);
  674. read_len += tmp_len;
  675. size -= tmp_len;
  676. va = (void *)((char *)va + ARCH_PAGE_SIZE);
  677. }
  678. }
  679. #else
  680. read_len = load_fread((void*)(pheader.p_vaddr + load_off), 1, pheader.p_filesz, fd);
  681. #endif
  682. check_read(read_len, pheader.p_filesz);
  683. if (pheader.p_filesz < pheader.p_memsz)
  684. {
  685. #ifdef RT_USING_USERSPACE
  686. uint32_t size = pheader.p_memsz - pheader.p_filesz;
  687. uint32_t size_s;
  688. uint32_t off;
  689. off = pheader.p_filesz & ARCH_PAGE_MASK;
  690. va = (void *)((pheader.p_vaddr + pheader.p_filesz + load_off) & ~ARCH_PAGE_MASK);
  691. while (size)
  692. {
  693. size_s = (size < ARCH_PAGE_SIZE - off) ? size : ARCH_PAGE_SIZE - off;
  694. pa = rt_hw_mmu_v2p(m_info, va);
  695. va_self = (void *)((char *)pa - PV_OFFSET);
  696. memset((void *)((char *)va_self + off), 0, size_s);
  697. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void *)((char *)va_self + off), size_s);
  698. off = 0;
  699. size -= size_s;
  700. va = (void *)((char *)va + ARCH_PAGE_SIZE);
  701. }
  702. #else
  703. memset((uint8_t *)pheader.p_vaddr + pheader.p_filesz + load_off, 0, (size_t)(pheader.p_memsz - pheader.p_filesz));
  704. #endif
  705. }
  706. }
  707. }
  708. /* relocate */
  709. if (eheader.e_type == ET_DYN)
  710. {
  711. /* section info */
  712. off = eheader.e_shoff;
  713. /* find section string table */
  714. check_off(off, len);
  715. lseek(fd, off + (sizeof sheader) * eheader.e_shstrndx, SEEK_SET);
  716. read_len = load_fread(&sheader, 1, sizeof sheader, fd);
  717. check_read(read_len, sizeof sheader);
  718. p_section_str = (char *)rt_malloc(sheader.sh_size);
  719. if (!p_section_str)
  720. {
  721. LOG_E("out of memory!");
  722. result = -ENOMEM;
  723. goto _exit;
  724. }
  725. check_off(sheader.sh_offset, len);
  726. lseek(fd, sheader.sh_offset, SEEK_SET);
  727. read_len = load_fread(p_section_str, 1, sheader.sh_size, fd);
  728. check_read(read_len, sheader.sh_size);
  729. check_off(off, len);
  730. lseek(fd, off, SEEK_SET);
  731. for (i = 0; i < eheader.e_shnum; i++, off += sizeof sheader)
  732. {
  733. read_len = load_fread(&sheader, 1, sizeof sheader, fd);
  734. check_read(read_len, sizeof sheader);
  735. if (strcmp(p_section_str + sheader.sh_name, ".got") == 0)
  736. {
  737. got_start = (void *)((uint8_t *)sheader.sh_addr + load_off);
  738. got_size = (size_t)sheader.sh_size;
  739. }
  740. else if (strcmp(p_section_str + sheader.sh_name, ".rel.dyn") == 0)
  741. {
  742. rel_dyn_start = (void *)((uint8_t *)sheader.sh_addr + load_off);
  743. rel_dyn_size = (size_t)sheader.sh_size;
  744. }
  745. else if (strcmp(p_section_str + sheader.sh_name, ".dynsym") == 0)
  746. {
  747. dynsym_off = (size_t)sheader.sh_offset;
  748. dynsym_size = (size_t)sheader.sh_size;
  749. }
  750. }
  751. /* reloc */
  752. if (dynsym_size)
  753. {
  754. dynsym = rt_malloc(dynsym_size);
  755. if (!dynsym)
  756. {
  757. LOG_E("ERROR: Malloc error!");
  758. result = -ENOMEM;
  759. goto _exit;
  760. }
  761. check_off(dynsym_off, len);
  762. lseek(fd, dynsym_off, SEEK_SET);
  763. read_len = load_fread(dynsym, 1, dynsym_size, fd);
  764. check_read(read_len, dynsym_size);
  765. }
  766. #ifdef RT_USING_USERSPACE
  767. lwp_elf_reloc(m_info, (void *)load_off, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
  768. #else
  769. lwp_elf_reloc((void *)load_off, rel_dyn_start, rel_dyn_size, got_start, got_size, dynsym);
  770. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, lwp->text_size);
  771. rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, lwp->text_entry, lwp->text_size);
  772. #endif
  773. }
  774. LOG_D("lwp->text_entry = 0x%p", lwp->text_entry);
  775. LOG_D("lwp->text_size = 0x%p", lwp->text_size);
  776. _exit:
  777. if (dynsym)
  778. {
  779. rt_free(dynsym);
  780. }
  781. if (p_section_str)
  782. {
  783. rt_free(p_section_str);
  784. }
  785. if (result != RT_EOK)
  786. {
  787. LOG_E("lwp load faild, %d", result);
  788. }
  789. return result;
  790. }
  791. int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size, struct process_aux *aux);
  792. RT_WEAK int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size, struct process_aux *aux)
  793. {
  794. uint8_t *ptr;
  795. int ret = -1;
  796. int len;
  797. int fd = -1;
  798. /* check file name */
  799. RT_ASSERT(filename != RT_NULL);
  800. /* check lwp control block */
  801. RT_ASSERT(lwp != RT_NULL);
  802. /* copy file name to process name */
  803. rt_strncpy(lwp->cmd, filename, RT_NAME_MAX);
  804. if (load_addr != RT_NULL)
  805. {
  806. lwp->lwp_type = LWP_TYPE_FIX_ADDR;
  807. ptr = load_addr;
  808. }
  809. else
  810. {
  811. lwp->lwp_type = LWP_TYPE_DYN_ADDR;
  812. ptr = RT_NULL;
  813. }
  814. fd = open(filename, O_BINARY | O_RDONLY, 0);
  815. if (fd < 0)
  816. {
  817. LOG_E("ERROR: Can't open elf file %s!", filename);
  818. goto out;
  819. }
  820. len = lseek(fd, 0, SEEK_END);
  821. if (len < 0)
  822. {
  823. LOG_E("ERROR: File %s size error!", filename);
  824. goto out;
  825. }
  826. lseek(fd, 0, SEEK_SET);
  827. ret = load_elf(fd, len, lwp, ptr, aux);
  828. if ((ret != RT_EOK) && (ret != 1))
  829. {
  830. LOG_E("lwp load ret = %d", ret);
  831. }
  832. out:
  833. if (fd > 0)
  834. {
  835. close(fd);
  836. }
  837. return ret;
  838. }
  839. void lwp_cleanup(struct rt_thread *tid)
  840. {
  841. rt_base_t level;
  842. struct rt_lwp *lwp;
  843. if (tid == NULL)
  844. {
  845. return;
  846. }
  847. LOG_I("cleanup thread: %s, stack_addr: %08X", tid->name, tid->stack_addr);
  848. #ifndef RT_USING_USERSPACE
  849. if (tid->user_stack != RT_NULL)
  850. {
  851. rt_free(tid->user_stack);
  852. }
  853. #endif
  854. level = rt_hw_interrupt_disable();
  855. lwp = (struct rt_lwp *)tid->lwp;
  856. lwp_tid_put(tid->tid);
  857. rt_list_remove(&tid->sibling);
  858. lwp_ref_dec(lwp);
  859. rt_hw_interrupt_enable(level);
  860. return;
  861. }
  862. static void lwp_copy_stdio_fdt(struct rt_lwp *lwp)
  863. {
  864. struct dfs_fd *d;
  865. struct dfs_fdtable *lwp_fdt;
  866. lwp_fdt = &lwp->fdt;
  867. /* init 4 fds */
  868. lwp_fdt->fds = rt_calloc(4, sizeof(void *));
  869. if (lwp_fdt->fds)
  870. {
  871. lwp_fdt->maxfd = 4;
  872. d = fd_get(0);
  873. fd_associate(lwp_fdt, 0, d);
  874. d = fd_get(1);
  875. fd_associate(lwp_fdt, 1, d);
  876. d = fd_get(2);
  877. fd_associate(lwp_fdt, 2, d);
  878. }
  879. return;
  880. }
  881. static void lwp_thread_entry(void *parameter)
  882. {
  883. rt_thread_t tid;
  884. struct rt_lwp *lwp;
  885. tid = rt_thread_self();
  886. lwp = (struct rt_lwp *)tid->lwp;
  887. tid->cleanup = lwp_cleanup;
  888. tid->user_stack = RT_NULL;
  889. #ifdef RT_USING_GDBSERVER
  890. if (lwp->debug)
  891. {
  892. lwp->bak_first_ins = *(uint32_t *)lwp->text_entry;
  893. *(uint32_t *)lwp->text_entry = INS_BREAK_CONNECT;
  894. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, sizeof(uint32_t));
  895. icache_invalid_all();
  896. }
  897. #endif
  898. lwp_user_entry(lwp->args, lwp->text_entry, lwp->data_entry, tid->stack_addr + tid->stack_size);
  899. }
  900. struct rt_lwp *lwp_self(void)
  901. {
  902. rt_thread_t tid;
  903. tid = rt_thread_self();
  904. if (tid)
  905. {
  906. return (struct rt_lwp *)tid->lwp;
  907. }
  908. return RT_NULL;
  909. }
  910. #ifdef RT_USING_GDBSERVER
  911. pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp)
  912. #else
  913. pid_t lwp_execve(char *filename, int argc, char **argv, char **envp)
  914. #endif
  915. {
  916. int result;
  917. rt_base_t level;
  918. struct rt_lwp *lwp;
  919. char *thread_name;
  920. char *argv_last = argv[argc - 1];
  921. int bg = 0;
  922. struct process_aux *aux;
  923. int tid = 0;
  924. if (filename == RT_NULL)
  925. {
  926. return -RT_ERROR;
  927. }
  928. lwp = lwp_new();
  929. if (lwp == RT_NULL)
  930. {
  931. dbg_log(DBG_ERROR, "lwp struct out of memory!\n");
  932. return -RT_ENOMEM;
  933. }
  934. LOG_D("lwp malloc : %p, size: %d!", lwp, sizeof(struct rt_lwp));
  935. if ((tid = lwp_tid_get()) == 0)
  936. {
  937. lwp_ref_dec(lwp);
  938. return -ENOMEM;
  939. }
  940. #ifdef RT_USING_USERSPACE
  941. if (lwp_user_space_init(lwp) != 0)
  942. {
  943. lwp_tid_put(tid);
  944. lwp_ref_dec(lwp);
  945. return -ENOMEM;
  946. }
  947. #endif
  948. if (argv_last[0] == '&' && argv_last[1] == '\0')
  949. {
  950. argc--;
  951. bg = 1;
  952. }
  953. if ((aux = lwp_argscopy(lwp, argc, argv, envp)) == RT_NULL)
  954. {
  955. lwp_tid_put(tid);
  956. lwp_ref_dec(lwp);
  957. return -ENOMEM;
  958. }
  959. result = lwp_load(filename, lwp, RT_NULL, 0, aux);
  960. if (result == 1)
  961. {
  962. /* dynmaic */
  963. lwp_unmap_user(lwp, (void *)(KERNEL_VADDR_START - ARCH_PAGE_SIZE));
  964. result = load_ldso(lwp, filename, argv, envp);
  965. }
  966. if (result == RT_EOK)
  967. {
  968. rt_thread_t thread = RT_NULL;
  969. lwp_copy_stdio_fdt(lwp);
  970. /* obtain the base name */
  971. thread_name = strrchr(filename, '/');
  972. thread_name = thread_name ? thread_name + 1 : filename;
  973. thread = rt_thread_create(thread_name, lwp_thread_entry, RT_NULL,
  974. LWP_TASK_STACK_SIZE, 25, 200);
  975. if (thread != RT_NULL)
  976. {
  977. struct rt_lwp *self_lwp;
  978. thread->tid = tid;
  979. lwp_tid_set_thread(tid, thread);
  980. LOG_D("lwp kernel => (0x%08x, 0x%08x)\n", (rt_uint32_t)thread->stack_addr,
  981. (rt_uint32_t)thread->stack_addr + thread->stack_size);
  982. level = rt_hw_interrupt_disable();
  983. self_lwp = lwp_self();
  984. if (self_lwp)
  985. {
  986. /* lwp add to children link */
  987. lwp->sibling = self_lwp->first_child;
  988. self_lwp->first_child = lwp;
  989. lwp->parent = self_lwp;
  990. }
  991. thread->lwp = lwp;
  992. rt_list_insert_after(&lwp->t_grp, &thread->sibling);
  993. #ifdef RT_USING_GDBSERVER
  994. if (debug)
  995. {
  996. lwp->debug = debug;
  997. }
  998. #endif
  999. if ((rt_console_get_foreground() == self_lwp) && !bg)
  1000. {
  1001. rt_console_set_foreground(lwp);
  1002. }
  1003. rt_hw_interrupt_enable(level);
  1004. rt_thread_startup(thread);
  1005. return lwp_to_pid(lwp);
  1006. }
  1007. }
  1008. lwp_tid_put(tid);
  1009. lwp_ref_dec(lwp);
  1010. return -RT_ERROR;
  1011. }
  1012. #ifdef RT_USING_GDBSERVER
  1013. pid_t exec(char *filename, int debug, int argc, char **argv)
  1014. {
  1015. return lwp_execve(filename, debug, argc, argv, 0);
  1016. }
  1017. #else
  1018. pid_t exec(char *filename, int argc, char **argv)
  1019. {
  1020. return lwp_execve(filename, argc, argv, 0);
  1021. }
  1022. #endif