Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable gdb plugin to work with enclave from buffer #902

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@
import gdb
import struct
import os.path
import os
from ctypes import create_string_buffer
import load_symbol_cmd
import sgx_emmt
import ctypes
import time
import re

# Calculate the bit mode of current debuggee project
Expand All @@ -56,6 +58,7 @@
ENCLAVE_INFO_SIZE = 8 * 7 + 2 * 4
INFO_FMT = 'QQQIIQQQQ'
ENCLAVES_ADDR = {}
DUMPED_ENCLAVE = {}

# The following definitions should strictly align with the struct of
# tcs_t
Expand Down Expand Up @@ -354,6 +357,13 @@ def fini_enclave_debug(self):
return -1
except:
return -1
finally:
# Delete the dumped enclave if any
global DUMPED_ENCLAVE
if self.enclave_path in DUMPED_ENCLAVE:
gdb.execute("call (void)free({0})".format(DUMPED_ENCLAVE[self.enclave_path]))
os.remove(self.enclave_path)
del DUMPED_ENCLAVE[self.enclave_path]

def append_tcs_list(self, tcs_addr):
for tcs_tmp in self.tcs_addr_list:
Expand Down Expand Up @@ -691,6 +701,46 @@ def stop(self):
gdb.execute(gdb_cmd, False, True)
return False

# This breakpoint is to handle enclave creation with buffer
class CreateBufferEnclaveBreakpoint(gdb.Breakpoint):
def __init__(self):
gdb.Breakpoint.__init__ (self, spec="_create_enclave_from_buffer_ex", internal=1)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you mentioned in PR description, we rely on the existence of this symbol _create_enclave_from_buffer_ex. I think this may not be a problem because if the user is actually doing the debugging, s/he needs to install the libsgx-urts-dbgsym package anyway, and the symbols will be there.


def stop(self):
bp_in_urts = is_bp_in_urts()
if bp_in_urts == True:
# Get se_file_t pointer (4th parameter)
file_addr = gdb.parse_and_eval("$rcx")
file_str = read_from_memory(file_addr, 8 + 2*4)
file_tuple = struct.unpack_from("QII", file_str)

if file_tuple[1] == 0:
# If it is null, then it does not have a file. So we dump the buffer

# dump enclave to file
dump_name = "/tmp/enclave_dump_{0}.bin".format(time.time())
buffer_ptr = gdb.parse_and_eval("$rsi")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code assumes we are under 64-bit. Currently we still need to support 32-bit so we may need to add that support as well just like we do for several other internal breakpoints

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, thank you for your review. Indeed I was thinking the same thing about the support for 32-bit as the SDK and SGX is also support 32-bit system. However, I am not sure how to test that since I am running the 64-bit system. I assume I will need to do either cross-compiling or install a 32-bit VM. Perhaps the difference is that the debugger now needs to inspect the stack as the function parameter is now spilled to the stack instead of register. But I guess we can do that. I'll see if I can help in the coming days :)

buffer_len = gdb.parse_and_eval("$rdx")
enclave_bin = read_from_memory(buffer_ptr, buffer_len)
f = open(dump_name, "wb")
f.write(bytearray(enclave_bin))
f.close()

# patch the file to malloc'ed buffer
str_filepath_buf = gdb.execute("call (void*)malloc({0})".format(len(dump_name) + 1), False, True)
str_filepath_buf = int(re.search(r"0x[0-9a-f]+", str_filepath_buf).group(), 16)
filepath_bytes = bytearray()
filepath_bytes.extend(map(ord, dump_name))
filepath_bytes.extend(bytes(0))
write_to_memory(str_filepath_buf, filepath_bytes)
write_to_memory(file_addr, struct.pack('QII', str_filepath_buf, len(dump_name), 0))

# Store the malloc-ed pointer
global DUMPED_ENCLAVE
DUMPED_ENCLAVE[dump_name] = str_filepath_buf

return False

def sgx_debugger_init():
print ("detect urts is loaded, initializing")
global SIZE
Expand All @@ -708,6 +758,7 @@ def sgx_debugger_init():
UpdateOcallFrame()
LoadEventBreakpoint()
UnloadEventBreakpoint()
CreateBufferEnclaveBreakpoint()
GetTCSBreakpoint()
gdb.events.exited.connect(exit_handler)
init_enclaves_debug()
Expand Down