db_main.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * db_main.c
  17. *
  18. * This file contains the main function of the PAL loader, which loads and
  19. * processes environment, arguments and manifest.
  20. */
  21. #include "pal_defs.h"
  22. #include "pal.h"
  23. #include "pal_internal.h"
  24. #include "pal_security.h"
  25. #include "pal_debug.h"
  26. #include "pal_error.h"
  27. #include "api.h"
  28. #include <sysdeps/generic/ldsodefs.h>
  29. #include <elf/elf.h>
  30. #include <bits/dlfcn.h>
  31. /* allocate memory for page size constants */
  32. PAL_NUM allocsize, allocshift, allocmask;
  33. PAL_CONTROL __pal_control;
  34. PAL_CONTROL * pal_control_addr (void)
  35. {
  36. return &__pal_control;
  37. }
  38. /* initialize the value of pal_config attributes */
  39. struct pal_config pal_config;
  40. struct pal_sec_info pal_sec_info;
  41. #define leave \
  42. do { printf("PAL terminated at " __FILE__ ":%d\n", __LINE__); \
  43. _DkProcessExit(1); } while (0)
  44. int load_libraries (struct config_store * root_config, const char ** msg)
  45. {
  46. /* we will not make any assumption for where the libraries are loaded */
  47. char cfgbuf[CONFIG_MAX];
  48. int len, ret = 0;
  49. /* loader.preload: any other libraries to preload. The can be multiple
  50. URIs, seperated by commas */
  51. if ((len = get_config(root_config, "loader.preload", cfgbuf,
  52. CONFIG_MAX)) > 0) {
  53. char * c = cfgbuf, * token = c;
  54. do {
  55. if (*c == ',' || !(*(c))) {
  56. if (c > token) {
  57. *c = 0;
  58. if ((ret = load_elf_object(token, OBJECT_PRELOAD)) < 0) {
  59. if (msg)
  60. *msg = "Unable to load preload library\n";
  61. return ret;
  62. }
  63. }
  64. token = c + 1;
  65. }
  66. } while (*(c++));
  67. }
  68. return 0;
  69. }
  70. static void read_envs (const char *** envpp)
  71. {
  72. const char ** envp = *envpp;
  73. if (!pal_config.root_config)
  74. goto done;
  75. char cfgbuf[CONFIG_MAX];
  76. /* loader.env.* and loader.exclude.env: filtering host environment
  77. * variables */
  78. int nenvs = get_config_entries(pal_config.root_config, "loader.env", cfgbuf,
  79. CONFIG_MAX);
  80. if (nenvs > 0) {
  81. struct env { const char * str; int len, idx; } * envs
  82. = __alloca(sizeof(struct env) * nenvs);
  83. char * cfg = cfgbuf;
  84. for (int i = 0 ; i < nenvs ; i++) {
  85. int len = strlen(cfg);
  86. char * str = __alloca(len + 1);
  87. envs[i].str = str;
  88. envs[i].len = len;
  89. envs[i].idx = -1;
  90. memcpy(str, cfg, len + 1);
  91. cfg += len + 1;
  92. }
  93. int envc = 0, add = nenvs;
  94. for (const char ** e = envp ; *e ; e++) {
  95. envc++;
  96. const char * p = *e;
  97. while (*p && *p != '=')
  98. p++;
  99. for (int i = 0 ; i < nenvs ; i++)
  100. if (envs[i].len == p - *e && !memcmp(envs[i].str, *e, p - *e)) {
  101. envs[i].idx = envc - 1;
  102. add--;
  103. break;
  104. }
  105. }
  106. if (add) {
  107. const char ** new_envp =
  108. malloc(sizeof(const char *) * (envc + add + 1));
  109. memcpy(new_envp, envp, sizeof(const char *) * envc);
  110. envp = new_envp;
  111. envp[envc + add] = NULL;
  112. }
  113. char key[CONFIG_MAX] = "loader.env.";
  114. const char ** ptr;
  115. for (int i = 0 ; i < nenvs ; i++) {
  116. const char * str = envs[i].str;
  117. int len = envs[i].len;
  118. int idx = envs[i].idx;
  119. int bytes;
  120. ptr = &envp[(idx == -1) ? envc++ : idx];
  121. memcpy(key + 11, str, len + 1);
  122. if ((bytes = get_config(pal_config.root_config, key, cfgbuf,
  123. CONFIG_MAX)) > 0) {
  124. char * e = malloc(len + bytes + 2);
  125. memcpy(e, str, len);
  126. e[len] = '=';
  127. memcpy(e + len + 1, cfgbuf, bytes + 1);
  128. *ptr = e;
  129. } else {
  130. char * e = malloc(len + 2);
  131. memcpy(e, str, len);
  132. e[len] = '=';
  133. e[len + 1] = 0;
  134. *ptr = e;
  135. }
  136. }
  137. }
  138. done:
  139. *envpp = envp;
  140. }
  141. void start_execution (int argc, const char ** argv, const char ** envp);
  142. void pal_main (int argc, const char ** argv, const char ** envp)
  143. {
  144. char cfgbuf[CONFIG_MAX];
  145. int ret;
  146. pal_config.pagesize = _DkGetPagesize();
  147. pal_config.alloc_align = _DkGetAllocationAlignment();
  148. /* some constants for page manipulation and allocation alignment */
  149. allocsize = pal_config.alloc_align;
  150. allocshift = allocsize - 1;
  151. allocmask = ~allocshift;
  152. init_slab_mgr();
  153. /* reloaction of loader is done here. starting from this point, the global
  154. symbols of loader should be accessible. */
  155. pal_config.lib_text_start = (void *) &text_start;
  156. pal_config.lib_text_end = (void *) &text_end;
  157. pal_config.lib_data_start = (void *) &data_start;
  158. pal_config.lib_data_end = (void *) &data_end;
  159. __pal_control.pagesize = pal_config.pagesize;
  160. __pal_control.alloc_align = allocsize;
  161. __pal_control.library_begin = &text_start;
  162. __pal_control.library_end = &data_end;
  163. /*
  164. * _DkInitHost must set up the following values:
  165. * pal_config.manifest
  166. * pal_config.manifest_handle
  167. * pal_config.exec
  168. * pal_config.exec_handle
  169. * pal_config.root_config
  170. */
  171. if (_DkInitHost(&argc, &argv) < 0)
  172. leave;
  173. __pal_control.manifest_handle = pal_config.manifest_handle;
  174. __pal_control.executable = pal_config.exec;
  175. /* all of the preloaded libraries are loaded,
  176. time to play with executable */
  177. if (pal_config.exec_handle) {
  178. ret = load_elf_object_by_handle(pal_config.exec_handle, OBJECT_EXEC);
  179. if (ret < 0) {
  180. printf("Unable to load executable (%d)\n", PAL_STRERROR(ret));
  181. leave;
  182. }
  183. }
  184. read_envs(&envp);
  185. if (pal_config.root_config) {
  186. struct config_store * cfg = pal_config.root_config;
  187. const char * msg;
  188. if (load_libraries(cfg, &msg) < 0) {
  189. printf("%s\n", msg);
  190. leave;
  191. }
  192. if (get_config(cfg, "loader.daemonize", cfgbuf,
  193. CONFIG_MAX) > 0 &&
  194. cfgbuf[0] == '1' && !cfgbuf[1])
  195. pal_config.daemonize = true;
  196. if (get_config(cfg, "loader.debug_type", cfgbuf,
  197. CONFIG_MAX) > 0) {
  198. PAL_HANDLE handle = NULL;
  199. if (!memcmp(cfgbuf, "inline", 7)) {
  200. _DkStreamOpen(&handle, "dev:tty", PAL_ACCESS_RDWR, 0, 0, 0);
  201. } else if (!memcmp(cfgbuf, "file", 5)) {
  202. if (get_config(cfg, "loader.debug_file", cfgbuf,
  203. CONFIG_MAX) > 0) {
  204. _DkStreamOpen(&handle, cfgbuf, PAL_ACCESS_RDWR,
  205. PAL_SHARE_OWNER_R|PAL_SHARE_OWNER_W,
  206. PAL_CREAT_TRY, 0);
  207. }
  208. }
  209. __pal_control.debug_stream = handle;
  210. }
  211. if ((ret = get_config(cfg, "loader.syscall_symbol", cfgbuf,
  212. CONFIG_MAX)) > 0)
  213. pal_config.syscall_sym_name = remalloc(cfgbuf, ret + 1);
  214. free_config(cfg);
  215. _DkStreamUnmap(cfg->raw_data, ALLOC_ALIGNUP(cfg->raw_size));
  216. free(cfg);
  217. pal_config.root_config = NULL;
  218. }
  219. __pal_control.manifest_handle = pal_config.manifest_handle;
  220. __pal_control.executable = pal_config.exec;
  221. __pal_control.user_address_begin = pal_config.user_addr_start;
  222. __pal_control.user_address_end = pal_config.user_addr_end;
  223. /* Now we will start the execution */
  224. start_execution(argc, argv, envp);
  225. /* We wish we will never reached here */
  226. printf("unexpected termination\n");
  227. leave;
  228. }