shim_debug.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. * shim_debug.c
  17. *
  18. * This file contains codes for registering libraries to GDB.
  19. */
  20. #include <shim_internal.h>
  21. #include <shim_tls.h>
  22. #include <shim_handle.h>
  23. #include <shim_vma.h>
  24. #include <shim_checkpoint.h>
  25. #include <shim_fs.h>
  26. #include <shim_ipc.h>
  27. #include <pal.h>
  28. #include <pal_error.h>
  29. #include <fcntl.h>
  30. struct gdb_link_map
  31. {
  32. void * l_addr;
  33. char * l_name;
  34. void * l_ld;
  35. struct gdb_link_map *l_next, *l_prev;
  36. };
  37. struct gdb_r_debug
  38. {
  39. int r_version;
  40. struct gdb_link_map *r_map;
  41. uintptr_t r_brk;
  42. enum
  43. {
  44. RT_CONSISTENT,
  45. RT_ADD,
  46. RT_DELETE,
  47. } r_state;
  48. uintptr_t r_ldbase;
  49. };
  50. struct gdb_r_debug __libc_r_debug;
  51. extern struct gdb_r_debug _r_debug;
  52. extern void _dl_debug_state_trigger (void);
  53. static struct gdb_link_map * link_map_list = NULL;
  54. static inline char * translate_file_path (const char * path)
  55. {
  56. struct shim_dentry * dent = NULL;
  57. int ret = path_lookupat(NULL, path, 0, &dent);
  58. if (ret < 0)
  59. return NULL;
  60. struct shim_mount * fs = dent->fs;
  61. if (!fs->d_ops->open)
  62. return NULL;
  63. char * new_uri = NULL;
  64. struct shim_handle * hdl = get_new_handle();
  65. if (!hdl)
  66. return NULL;
  67. set_handle_fs(hdl, fs);
  68. hdl->dentry = dent;
  69. ret = fs->d_ops->open(hdl, dent, O_RDONLY);
  70. if (ret < 0)
  71. goto out;
  72. new_uri = qstrtostr(&hdl->uri, false);
  73. out:
  74. put_handle(hdl);
  75. return new_uri;
  76. }
  77. void __libc_dl_debug_state (void)
  78. {
  79. /* first make sure libc map list matches the shadow map list */
  80. if (link_map_list) {
  81. struct gdb_link_map *m = link_map_list, *n;
  82. for ( ; m ; m = m->l_next) {
  83. for (n = __libc_r_debug.r_map ; n ; n = n->l_next)
  84. if (m->l_addr == n->l_addr)
  85. break;
  86. if (!n) {
  87. if (m->l_prev)
  88. m->l_prev->l_next = m->l_next;
  89. if (m->l_next)
  90. m->l_next->l_prev = m->l_prev;
  91. if (m == link_map_list)
  92. link_map_list = m->l_next;
  93. }
  94. }
  95. }
  96. /* now find the end of the shadow map list, where we are adding to */
  97. struct gdb_link_map *prev = NULL;
  98. struct gdb_link_map **tail = &_r_debug.r_map;
  99. while (*tail) {
  100. prev = *tail;
  101. tail = &(*tail)->l_next;
  102. }
  103. /* add new maps to the shadow map list */
  104. struct gdb_link_map **t = tail;
  105. struct gdb_link_map *m = __libc_r_debug.r_map;
  106. for ( ; m ; m = m->l_next) {
  107. struct gdb_link_map *re = _r_debug.r_map;
  108. while (re && re->l_addr != m->l_addr)
  109. re = re->l_next;
  110. if (re)
  111. continue;
  112. char * uri = translate_file_path(m->l_name);
  113. if (!uri)
  114. continue;
  115. debug("add a library for gdb: %s\n", uri);
  116. struct gdb_link_map * new = malloc(sizeof(struct gdb_link_map));
  117. new->l_addr = m->l_addr;
  118. new->l_ld = m->l_ld;
  119. new->l_name = uri;
  120. new->l_prev = prev;
  121. prev = *t = new;
  122. new->l_next = NULL;
  123. t = &new->l_next;
  124. }
  125. if (!link_map_list)
  126. link_map_list = *tail;
  127. _r_debug.r_state = __libc_r_debug.r_state;
  128. _dl_debug_state_trigger();
  129. }
  130. void clean_link_map_list (void)
  131. {
  132. if (!link_map_list)
  133. return;
  134. _r_debug.r_state = RT_DELETE;
  135. _dl_debug_state_trigger();
  136. if (link_map_list->l_prev)
  137. link_map_list->l_prev->l_next = NULL;
  138. if (_r_debug.r_map == link_map_list)
  139. _r_debug.r_map = NULL;
  140. struct gdb_link_map * m = link_map_list;
  141. for ( ; m ; m = m->l_next)
  142. free(m);
  143. link_map_list = NULL;
  144. _r_debug.r_state = RT_CONSISTENT;
  145. _dl_debug_state_trigger();
  146. }
  147. void remove_r_debug (void * addr)
  148. {
  149. struct gdb_link_map * m = _r_debug.r_map;
  150. for ( ; m && m != link_map_list ; m = m->l_next)
  151. if (m->l_addr == addr)
  152. break;
  153. if (!m || m == link_map_list)
  154. return;
  155. _r_debug.r_state = RT_DELETE;
  156. _dl_debug_state_trigger();
  157. debug("remove a library for gdb: %s\n", m->l_name);
  158. if (m->l_prev)
  159. m->l_prev->l_next = m->l_next;
  160. if (m->l_next)
  161. m->l_next->l_prev = m->l_prev;
  162. if (_r_debug.r_map == m)
  163. _r_debug.r_map = m->l_next;
  164. _r_debug.r_state = RT_CONSISTENT;
  165. _dl_debug_state_trigger();
  166. }
  167. void append_r_debug (const char * uri, void * addr, void * dyn_addr)
  168. {
  169. struct gdb_link_map * new = malloc(sizeof(struct gdb_link_map));
  170. int uri_len = strlen(uri);
  171. char * new_uri = malloc(uri_len + 1);
  172. memcpy(new_uri, uri, uri_len + 1);
  173. new->l_addr = addr;
  174. new->l_ld = dyn_addr;
  175. new->l_name = new_uri;
  176. struct gdb_link_map *prev = NULL;
  177. struct gdb_link_map **tail = &_r_debug.r_map;
  178. while (*tail && *tail != link_map_list) {
  179. prev = *tail;
  180. tail = &(*tail)->l_next;
  181. }
  182. _r_debug.r_state = RT_ADD;
  183. _dl_debug_state_trigger();
  184. debug("add a library for gdb: %s\n", new->l_name);
  185. new->l_prev = prev;
  186. new->l_next = link_map_list;
  187. *tail = new;
  188. if (link_map_list)
  189. link_map_list->l_prev = new;
  190. _r_debug.r_state = RT_CONSISTENT;
  191. _dl_debug_state_trigger();
  192. }
  193. DEFINE_MIGRATE_FUNC(gdb_map)
  194. MIGRATE_FUNC_BODY(gdb_map)
  195. {
  196. struct gdb_link_map *m = link_map_list;
  197. struct gdb_link_map *newm = NULL;
  198. while (m) {
  199. ADD_OFFSET(sizeof(struct gdb_link_map));
  200. ADD_FUNC_ENTRY(*offset);
  201. if (!dry) {
  202. newm = (struct gdb_link_map *) (base + *offset);
  203. memcpy(newm, m, sizeof(struct gdb_link_map));
  204. newm->l_prev = newm->l_next = NULL;
  205. }
  206. ADD_OFFSET(strlen(m->l_name) + 1);
  207. if (!dry) {
  208. newm->l_name = (char *) (base + *offset);
  209. memcpy(newm->l_name, m->l_name, strlen(m->l_name) + 1);
  210. }
  211. m = m->l_next;
  212. }
  213. }
  214. END_MIGRATE_FUNC
  215. RESUME_FUNC_BODY(gdb_map)
  216. {
  217. uint64_t off = GET_FUNC_ENTRY();
  218. _r_debug.r_state = RT_ADD;
  219. _dl_debug_state_trigger ();
  220. struct gdb_link_map *map = (struct gdb_link_map *) (base + off);
  221. RESUME_REBASE(map->l_name);
  222. RESUME_REBASE(map->l_prev);
  223. RESUME_REBASE(map->l_next);
  224. struct gdb_link_map *prev = NULL;
  225. struct gdb_link_map **tail = &link_map_list;
  226. while (*tail) {
  227. prev = *tail;
  228. tail = &(*tail)->l_next;
  229. }
  230. map->l_prev = prev;
  231. *tail = map;
  232. tail = &_r_debug.r_map;
  233. while (*tail && *tail != link_map_list) {
  234. prev = *tail;
  235. tail = &(*tail)->l_next;
  236. }
  237. *tail = link_map_list;
  238. link_map_list->l_prev = prev;
  239. #ifdef DEBUG_RESUME
  240. debug("gdb: %s loaded at %p\n", map->l_name, map->l_addr);
  241. #endif
  242. _r_debug.r_state = RT_CONSISTENT;
  243. _dl_debug_state_trigger ();
  244. }
  245. END_RESUME_FUNC