gdb_sgx_plugin.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions
  7. # are met:
  8. #
  9. # * Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above copyright
  12. # notice, this list of conditions and the following disclaimer in
  13. # the documentation and/or other materials provided with the
  14. # distribution.
  15. # * Neither the name of Intel Corporation nor the names of its
  16. # contributors may be used to endorse or promote products derived
  17. # from this software without specific prior written permission.
  18. #
  19. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #
  31. #
  32. from __future__ import print_function
  33. import gdb
  34. import struct
  35. import os.path
  36. from ctypes import create_string_buffer
  37. import load_symbol_cmd
  38. import sgx_emmt
  39. # Calculate the bit mode of current debuggee project
  40. SIZE = gdb.parse_and_eval("sizeof(long)")
  41. ET_SIM = 0x1
  42. ET_DEBUG = 0x2
  43. PAGE_SIZE = 0x1000
  44. # The following definitions should strictly align with the structure of
  45. # debug_enclave_info_t in uRTS.
  46. # Here we only care about the first 7 items in the structure.
  47. # pointer: next_enclave_info, start_addr, tcs_list, lpFileName,
  48. # g_peak_heap_used_addr
  49. # int32_t: enclave_type, file_name_size
  50. ENCLAVE_INFO_SIZE = 5 * 8 + 2 * 4
  51. INFO_FMT = 'QQQIIQQ'
  52. ENCLAVES_ADDR = {}
  53. # The following definitions should strictly align with the struct of
  54. # tcs_t
  55. # Here we only care about the first 8 items in the structure
  56. # uint64_t: state, flags, ossa, oentry, aep, ofs_base
  57. # uint32_t: nssa, cssa
  58. ENCLAVE_TCS_INFO_SIZE = 6*8 + 2*4
  59. TCS_INFO_FMT = 'QQQIIQQQ'
  60. def get_inferior():
  61. """Get current inferior"""
  62. try:
  63. if len(gdb.inferiors()) == 0:
  64. print ("No gdb inferior could be found.")
  65. return -1
  66. else:
  67. inferior = gdb.inferiors()[0]
  68. return inferior
  69. except AttributeError:
  70. print ("This gdb's python support is too old, please update first.")
  71. exit()
  72. def read_from_memory(addr, size):
  73. """Read data with specified size from the specified meomory"""
  74. inferior = get_inferior()
  75. # actually we can check the addr more securely
  76. # ( check the address is inside the enclave)
  77. if inferior == -1 or addr == 0:
  78. print ("Error happens in read_from_memory: addr = {0:x}".format(int(addr)))
  79. return None
  80. try:
  81. string = inferior.read_memory(addr, size)
  82. return string
  83. except gdb.MemoryError:
  84. print ("Can't access memory at {0:x}.".format(int(addr)))
  85. return None
  86. def write_to_memory(addr, buf):
  87. """Write a specified buffer to the specified memory"""
  88. inferior = get_inferior()
  89. if inferior == -1 or addr == 0:
  90. print ("Error happens in write_to_memory: addr = {0:x}".format(int(addr)))
  91. return -1
  92. try:
  93. inferior.write_memory(addr, buf)
  94. return 0
  95. except gdb.MemoryError:
  96. print ("Can't access memory at {0:x}.".format(int(addr)))
  97. return -1
  98. def target_path_to_host_path(target_path):
  99. so_name = os.path.basename(target_path)
  100. strpath = gdb.execute("show solib-search-path", False, True)
  101. path = strpath.split()[-1]
  102. strlen = len(path)
  103. path = path[0:strlen-1]
  104. host_path = path + "/" + so_name
  105. #strlen = len(host_path)
  106. #host_path = host_path[0:strlen-7]
  107. return host_path
  108. class enclave_info(object):
  109. """Class to contain the enclave inforation,
  110. such as start address, stack addresses, stack size, etc.
  111. The enclave information is for one enclave."""
  112. def __init__(self, _next_ei, _start_addr, _enclave_type, _stack_addr_list, \
  113. _stack_size, _enclave_path, _heap_addr, _tcs_addr_list):
  114. self.next_ei = _next_ei
  115. self.start_addr = _start_addr
  116. self.enclave_type = _enclave_type
  117. self.stack_addr_list = _stack_addr_list
  118. self.stack_size = _stack_size
  119. self.enclave_path = _enclave_path
  120. self.heap_addr = _heap_addr
  121. self.tcs_addr_list = _tcs_addr_list
  122. def __str__(self):
  123. print ("stack address list = {0:s}".format(self.stack_addr_list))
  124. return "start_addr = %#x, enclave_path = \"%s\", stack_size = %d" \
  125. % (self.start_addr, self.enclave_path, self.stack_size)
  126. def __eq__(self, other):
  127. if other == None:
  128. return False
  129. if self.start_addr == other.start_addr:
  130. return True
  131. else:
  132. return False
  133. def init_enclave_debug(self):
  134. # Only product HW enclave can't be debugged
  135. if (self.enclave_type & ET_SIM) != ET_SIM and (self.enclave_type & ET_DEBUG) != ET_DEBUG:
  136. print ('Warning: {0:s} is a product hardware enclave. It can\'t be debugged and sgx_emmt doesn\'t work'.format(self.enclave_path))
  137. return -1
  138. # set TCS debug flag
  139. for tcs_addr in self.tcs_addr_list:
  140. string = read_from_memory(tcs_addr + 8, 4)
  141. if string == None:
  142. return 0
  143. flag = struct.unpack('I', string)[0]
  144. flag |= 1
  145. gdb_cmd = "set *(unsigned int *)%#x = %#x" %(tcs_addr + 8, flag)
  146. gdb.execute(gdb_cmd, False, True)
  147. #If it is a product enclave, won't reach here.
  148. #load enclave symbol
  149. if os.path.exists(self.enclave_path) == True:
  150. enclave_path = self.enclave_path
  151. else:
  152. enclave_path = target_path_to_host_path(self.enclave_path)
  153. gdb_cmd = load_symbol_cmd.GetLoadSymbolCommand(enclave_path, str(self.start_addr))
  154. if gdb_cmd == -1:
  155. return 0
  156. print (gdb_cmd)
  157. gdb.execute(gdb_cmd, False, True)
  158. global ENCLAVES_ADDR
  159. ENCLAVES_ADDR[self.start_addr] = gdb_cmd.split()[2]
  160. return 0
  161. def get_peak_heap_used(self):
  162. """Get the peak value of the heap used"""
  163. if self.heap_addr == 0:
  164. return -2
  165. # read the peak_heap_used value
  166. string = read_from_memory(self.heap_addr, SIZE)
  167. if string == None:
  168. return -1
  169. if SIZE == 4:
  170. fmt = 'I'
  171. elif SIZE == 8:
  172. fmt = "Q"
  173. peak_heap_used = struct.unpack(fmt, string)[0]
  174. return peak_heap_used
  175. def internal_compare (self, a, b):
  176. return (a > b) - (a < b)
  177. def find_boundary_page_index(self, stack_addr, stack_size):
  178. """Find the unused page index of the boundary for the used and unused pages
  179. with the binary search algorithm"""
  180. page_index = -1 #record the last unused page index
  181. low = 0
  182. high = (stack_size>>12) - 1
  183. mid = 0
  184. # Read the mid page and check if it is used or not
  185. # If the mid page is used, then continue to search [mid+1, high]
  186. while low <= high:
  187. #print "low = %x, high = %x, mid = %x" % (low, high, mid)
  188. mid = (low + high)>>1
  189. string = read_from_memory(stack_addr + mid*PAGE_SIZE + (PAGE_SIZE>>1), PAGE_SIZE>>1)
  190. if string == None:
  191. return -2
  192. dirty_flag = 0
  193. for i in range(0, PAGE_SIZE>>4):
  194. temp = struct.unpack_from("Q", string, ((PAGE_SIZE>>4) - 1 - i)*8)[0]
  195. if (self.internal_compare(temp, 0xcccccccccccccccc)) != 0:
  196. dirty_flag = 1
  197. break
  198. if dirty_flag == 0:
  199. low = mid + 1
  200. page_index = mid
  201. else:
  202. high = mid -1
  203. return page_index
  204. def get_peak_stack_used(self):
  205. """Get the peak value of the stack used"""
  206. peak_stack_used = 0
  207. for stack_addr in self.stack_addr_list:
  208. page_index = self.find_boundary_page_index(stack_addr, self.stack_size)
  209. if page_index == (self.stack_size)/PAGE_SIZE - 1:
  210. continue
  211. elif page_index == -2:
  212. return -1
  213. else:
  214. string = read_from_memory(stack_addr + (page_index+1) * PAGE_SIZE, PAGE_SIZE)
  215. if string == None:
  216. return -1
  217. for i in range(0, len(string)):
  218. temp = struct.unpack_from("B", string, i)[0]
  219. if (self.internal_compare(temp, 0xcc)) != 0:
  220. if peak_stack_used < (self.stack_size - (page_index+1) * PAGE_SIZE - i):
  221. peak_stack_used = self.stack_size- (page_index+1) * PAGE_SIZE - i
  222. break # go to the top for loop
  223. return peak_stack_used
  224. def show_emmt(self):
  225. ret = gdb.execute("show sgx_emmt", False, True)
  226. if ret.strip() == "sgx_emmt enabled":
  227. print ("Enclave: \"{0:s}\"".format(self.enclave_path))
  228. peak_stack_used = self.get_peak_stack_used()
  229. if peak_stack_used == -1:
  230. print ("Failed to collect the stack usage information for \"{0:s}\"".format(self.enclave_path))
  231. else:
  232. print (" [Peak stack used]: {0:x}".format(peak_stack_used))
  233. peak_heap_used = self.get_peak_heap_used()
  234. if peak_heap_used == -1:
  235. print ("Failed to collect the heap usage information for \"{0:s}\"".format(self.enclave_path))
  236. elif peak_heap_used == -2:
  237. print (" [Can't get peak heap used]: You may use version script to control symbol export. Please export \'g_peak_heap_used\' in your version script.")
  238. else:
  239. print (" [Peak heap used]: {0:x}".format(peak_heap_used))
  240. def fini_enclave_debug(self):
  241. # If it is HW product enclave, nothing to do
  242. if (self.enclave_type & ET_SIM) != ET_SIM and (self.enclave_type & ET_DEBUG) != ET_DEBUG:
  243. return -2
  244. self.show_emmt()
  245. try:
  246. # clear TCS debug flag
  247. for tcs_addr in self.tcs_addr_list:
  248. string = read_from_memory(tcs_addr + 8, 4)
  249. if string == None:
  250. return -2
  251. flag = struct.unpack('I', string)[0]
  252. flag &= (~1)
  253. gdb_cmd = "set *(unsigned int *)%#x = %#x" %(tcs_addr + 8, flag)
  254. gdb.execute(gdb_cmd, False, True)
  255. #unload symbol
  256. if os.path.exists(self.enclave_path) == True:
  257. enclave_path = self.enclave_path
  258. else:
  259. enclave_path = target_path_to_host_path(self.enclave_path)
  260. gdb_cmd = load_symbol_cmd.GetUnloadSymbolCommand(enclave_path, str(self.start_addr))
  261. if gdb_cmd == -1:
  262. return -1
  263. print (gdb_cmd)
  264. try:
  265. gdb.execute(gdb_cmd, False, True)
  266. global ENCLAVES_ADDR
  267. del ENCLAVES_ADDR[self.start_addr]
  268. except gdb.error:
  269. print ("Old gdb doesn't support remove-file-symbol command")
  270. return 0
  271. ##It is possible enclave has been destroyed, so may raise exception on memory access
  272. except gdb.MemoryError:
  273. return -1
  274. except:
  275. return -1
  276. def retrieve_enclave_info(info_addr = 0):
  277. """retrieve one enclave info"""
  278. # Step 1: find the enclave info address
  279. if info_addr == 0:
  280. if SIZE == 4:
  281. info_addr = gdb.parse_and_eval("$eax")
  282. elif SIZE == 8:
  283. info_addr = gdb.parse_and_eval("$rdi")
  284. # Step 2: retrieve the enclave info
  285. info_str = read_from_memory(info_addr, ENCLAVE_INFO_SIZE)
  286. if info_str == None:
  287. return None
  288. info_tuple = struct.unpack_from(INFO_FMT, info_str, 0)
  289. # (next_enclave_info,start_addr,tcs_list,enclave_type,file_name_size,
  290. # lpFileName,g_peak_heap_used_addr)
  291. #print "next_addr: %#x, start_addr: %#x, tcs_list: %#x, enclave_type:%#x, file_name_size: %#x," \
  292. # % (info_tuple[0], info_tuple[1], info_tuple[2], info_tuple[3], info_tuple[4])
  293. #print "name_addr: %#x, peak_heap_used_addr: %#x" \
  294. # % (info_tuple[5], info_tuple[6])
  295. #get enclave path
  296. name_str = read_from_memory(info_tuple[5], info_tuple[4])
  297. if name_str == None:
  298. return None
  299. fmt = str(info_tuple[4]) + 's'
  300. enclave_path = struct.unpack_from(fmt, name_str)[0].decode(encoding='UTF-8')
  301. # get the stack addr list
  302. stack_addr_list = []
  303. tcs_addr_list = []
  304. if SIZE == 4:
  305. fmt = '3I'
  306. elif SIZE == 8:
  307. fmt = '3Q'
  308. tcs_info_addr = info_tuple[2]
  309. if tcs_info_addr == 0:
  310. print ("Error: tcs info address = {0:x}".format(tcs_info_addr))
  311. return None
  312. while tcs_info_addr is not 0:
  313. tcs_info_str = read_from_memory(tcs_info_addr, 3*SIZE)
  314. if tcs_info_str == None:
  315. return None
  316. tcs_info_tuple = struct.unpack_from(fmt, tcs_info_str)
  317. #get tcs struct data
  318. tcs_t_str = read_from_memory(tcs_info_tuple[1], ENCLAVE_TCS_INFO_SIZE)
  319. if tcs_t_str == None:
  320. return None
  321. tcs_t_tuple = struct.unpack_from(TCS_INFO_FMT, tcs_t_str)
  322. if SIZE == 4:
  323. td_fmt = '4I'
  324. elif SIZE == 8:
  325. td_fmt = '4Q'
  326. #get thread_data_t address
  327. td_addr = tcs_t_tuple[7] + info_tuple[1] #thread_data_t = tcs.of_base + debug_enclave_info.start_addr
  328. td_str = read_from_memory(td_addr, (4*SIZE))
  329. if td_str == None:
  330. return None
  331. td_tuple = struct.unpack_from(td_fmt, td_str)
  332. #print ("thread_info:%#x, last_sp:%#x, stack_base_addr:%#x, stack_limit_addr:%#x" \
  333. # % (td_tuple[0], td_tuple[1], td_tuple[2], td_tuple[3]));
  334. stacksize = td_tuple[2] - td_tuple[3] #stack size = stack_base_addr - stack_limit_addr
  335. stack_addr_list.append(td_tuple[3]) #use stack limit addr as stack base address
  336. tcs_addr_list.append(tcs_info_tuple[1])
  337. tcs_info_addr = tcs_info_tuple[0]
  338. last_ocall_frame = tcs_info_tuple[2]
  339. last_frame = last_ocall_frame
  340. #print ("last_ocall_frame = {0:x}".format(last_ocall_frame))
  341. while last_ocall_frame is not 0:
  342. if SIZE == 4:
  343. of_fmt = '4I'
  344. elif SIZE == 8:
  345. of_fmt = '4Q'
  346. ocall_frame = read_from_memory(last_ocall_frame, 4*SIZE)
  347. if ocall_frame == None:
  348. return None
  349. ocall_frame_tuple = struct.unpack_from(of_fmt, ocall_frame)
  350. last_frame = ocall_frame_tuple[0]
  351. last_trusted_ocall_frame = td_tuple[1]
  352. #print ("last_trusted_ocall_frame = {0:x}".format(last_trusted_ocall_frame))
  353. #print ("td_tuple[2] = {0:x}".format(td_tuple[2]))
  354. #break
  355. while last_trusted_ocall_frame != td_tuple[2]:
  356. if SIZE == 4:
  357. oc_fmt = '20I'
  358. elif SIZE == 8:
  359. oc_fmt = '20Q'
  360. oc_str = read_from_memory(last_trusted_ocall_frame, 20*SIZE)
  361. if oc_str == None:
  362. return None
  363. oc_tuple = struct.unpack_from(oc_fmt, oc_str)
  364. last_trusted_ocall_frame = oc_tuple[6]
  365. #print ("last_trusted_ocall_frame = {0:x}".format(last_trusted_ocall_frame))
  366. #print ("ocall_frame_tuple[1] = {0:x}".format(ocall_frame_tuple[1]))
  367. #print ("oc_tuple[18] = {0:x}".format(oc_tuple[18]))
  368. #break
  369. if ocall_frame_tuple[1] == oc_tuple[18]:
  370. #ocall_frame.pre_last_frame = 0
  371. #ocall_frame.ret = ocall_context.ocall_ret
  372. #ocall_frame.xbp = ocall_context.xbp
  373. gdb_cmd = "set *(uintptr_t *)%#x = 0" %(last_ocall_frame)
  374. gdb.execute(gdb_cmd, False, True)
  375. gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(last_ocall_frame+(2*SIZE), oc_tuple[11])
  376. gdb.execute(gdb_cmd, False, True)
  377. gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(last_ocall_frame+(3*SIZE), oc_tuple[19])
  378. gdb.execute(gdb_cmd, False, True)
  379. break
  380. last_ocall_frame = last_frame
  381. node = enclave_info(info_tuple[0], info_tuple[1], info_tuple[3], stack_addr_list, \
  382. stacksize, enclave_path, info_tuple[6], tcs_addr_list)
  383. return node
  384. def handle_load_event():
  385. """Handle the enclave loading event.
  386. Firstly, retrieve the enclave info node from register
  387. """
  388. node = retrieve_enclave_info()
  389. if node != None:
  390. node.init_enclave_debug()
  391. else:
  392. return
  393. def handle_unload_event():
  394. node = retrieve_enclave_info()
  395. if node != None:
  396. node.fini_enclave_debug()
  397. else:
  398. return
  399. def is_bp_in_urts():
  400. try:
  401. ip = gdb.parse_and_eval("$pc")
  402. solib_name = gdb.solib_name(int(str(ip).split()[0], 16))
  403. if(solib_name.find("libsgx_urts.so") == -1 and solib_name.find("libsgx_urts_sim.so") == -1 and solib_name.find("libsgx_aesm_service.so") == -1):
  404. return False
  405. else:
  406. return True
  407. #If exception happens, just assume it is bp in uRTS.
  408. except:
  409. return True
  410. def init_enclaves_debug():
  411. enclave_info_addr = gdb.parse_and_eval("*(void**)&g_debug_enclave_info_list")
  412. while enclave_info_addr != 0:
  413. node = retrieve_enclave_info(enclave_info_addr)
  414. if node != None:
  415. node.init_enclave_debug()
  416. else:
  417. return
  418. enclave_info_addr = node.next_ei
  419. return
  420. class detach_enclaves (gdb.Command):
  421. def __init__ (self):
  422. gdb.Command.__init__ (self, "detach_enclaves", gdb.COMMAND_NONE)
  423. def invoke (self, arg, from_tty):
  424. #We reject the command from the input of terminal
  425. if from_tty == True:
  426. return
  427. try:
  428. enclave_info_addr = gdb.parse_and_eval("*(void**)&g_debug_enclave_info_list")
  429. except:
  430. return
  431. while enclave_info_addr != 0:
  432. node = retrieve_enclave_info(enclave_info_addr)
  433. if node != None:
  434. node.fini_enclave_debug()
  435. else:
  436. return
  437. enclave_info_addr = node.next_ei
  438. class UpdateOcallFrame(gdb.Breakpoint):
  439. def __init__(self):
  440. gdb.Breakpoint.__init__ (self, spec="notify_gdb_to_update", internal=1)
  441. def stop(self):
  442. bp_in_urts = is_bp_in_urts()
  443. if bp_in_urts == True:
  444. if SIZE == 4:
  445. base_addr = gdb.parse_and_eval("$eax")
  446. tcs_addr = gdb.parse_and_eval("$edx")
  447. ocall_frame = gdb.parse_and_eval("$ecx")
  448. elif SIZE == 8:
  449. base_addr = gdb.parse_and_eval("$rdi")
  450. tcs_addr = gdb.parse_and_eval("$rsi")
  451. ocall_frame = gdb.parse_and_eval("$rdx")
  452. #print ("base_addr = {0:x}".format(int(base_addr)))
  453. #print ("tcs_addr = {0:x}".format(int(tcs_addr)))
  454. #print ("ocall_frame = {0:x}".format(int(ocall_frame)))
  455. tcs_str = read_from_memory(tcs_addr, ENCLAVE_TCS_INFO_SIZE)
  456. if tcs_str == None:
  457. return False
  458. tcs_tuple = struct.unpack_from(TCS_INFO_FMT, tcs_str)
  459. offset = tcs_tuple[7]
  460. if SIZE == 4:
  461. td_fmt = '4I'
  462. elif SIZE == 8:
  463. td_fmt = '4Q'
  464. td_str = read_from_memory(base_addr+offset, (4*SIZE))
  465. if td_str == None:
  466. return False
  467. td_tuple = struct.unpack_from(td_fmt, td_str)
  468. if SIZE == 4:
  469. trusted_of_fmt = '20I'
  470. elif SIZE == 8:
  471. trusted_of_fmt = '20Q'
  472. last_sp = td_tuple[1]
  473. trusted_ocall_frame = read_from_memory(last_sp, (20*SIZE))
  474. if trusted_ocall_frame == None:
  475. return False
  476. trusted_ocall_frame_tuple = struct.unpack_from(trusted_of_fmt, trusted_ocall_frame)
  477. gdb_cmd = "set *(uintptr_t *)%#x = 0" %(int(ocall_frame))
  478. gdb.execute(gdb_cmd, False, True)
  479. gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(int(ocall_frame+(2*SIZE)), trusted_ocall_frame_tuple[11])
  480. gdb.execute(gdb_cmd, False, True)
  481. gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(int(ocall_frame+(3*SIZE)), trusted_ocall_frame_tuple[19])
  482. gdb.execute(gdb_cmd, False, True)
  483. return False
  484. class LoadEventBreakpoint(gdb.Breakpoint):
  485. def __init__(self):
  486. gdb.Breakpoint.__init__ (self, spec="sgx_debug_load_state_add_element", internal=1)
  487. def stop(self):
  488. bp_in_urts = is_bp_in_urts()
  489. if bp_in_urts == True:
  490. handle_load_event()
  491. return False
  492. class UnloadEventBreakpoint(gdb.Breakpoint):
  493. def __init__(self):
  494. gdb.Breakpoint.__init__ (self, spec="sgx_debug_unload_state_remove_element", internal=1)
  495. def stop(self):
  496. bp_in_urts = is_bp_in_urts()
  497. if bp_in_urts == True:
  498. handle_unload_event()
  499. return False
  500. def sgx_debugger_init():
  501. print ("detect urts is loaded, initializing")
  502. global SIZE
  503. SIZE = gdb.parse_and_eval("sizeof(long)")
  504. inited = 0
  505. bps = gdb.breakpoints()
  506. if None != bps:
  507. for bp in bps:
  508. if bp.location == "sgx_debug_load_state_add_element":
  509. inited = 1
  510. break
  511. if inited == 0:
  512. detach_enclaves()
  513. gdb.execute("source gdb_sgx_cmd", False, True)
  514. UpdateOcallFrame()
  515. LoadEventBreakpoint()
  516. UnloadEventBreakpoint()
  517. gdb.events.exited.connect(exit_handler)
  518. init_enclaves_debug()
  519. def exit_handler(event):
  520. # When the inferior exited, remove all enclave symbol
  521. for key in list(ENCLAVES_ADDR.keys()):
  522. gdb.execute("remove-symbol-file -a %s" % (ENCLAVES_ADDR[key]), False, True)
  523. ENCLAVES_ADDR.clear()
  524. def newobj_handler(event):
  525. solib_name = os.path.basename(event.new_objfile.filename)
  526. if solib_name == 'libsgx_urts.so' or solib_name == 'libsgx_urts_sim.so' or solib_name == 'libsgx_aesm_service.so':
  527. sgx_debugger_init()
  528. return
  529. if __name__ == "__main__":
  530. gdb.events.new_objfile.connect(newobj_handler)
  531. sgx_emmt.init_emmt()