mirror of
https://github.com/corda/corda.git
synced 2025-06-17 06:38:21 +00:00
Initial release of Intel SGX for Linux.
This release is used in conjunction with the linux-sgx-driver Intial release: https://github.com/01org/linux-sgx-driver commit-id: 0e865ce5e6b297a787bcdc12d98bada8174be6d7 Intel-id: 33399 Signed-off-by: Angie Chinchilla <angie.v.chinchilla@intel.com>
This commit is contained in:
89
sdk/debugger_interface/linux/Makefile
Normal file
89
sdk/debugger_interface/linux/Makefile
Normal file
@ -0,0 +1,89 @@
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
include ../../../buildenv.mk
|
||||
|
||||
#Don't CFLAGS +=, because it depend on gdb is m32 or m64
|
||||
CFLAGS :=
|
||||
|
||||
CPPFLAGS += -I$(COMMON_DIR)/inc/ \
|
||||
-I$(COMMON_DIR)/inc/internal/
|
||||
|
||||
CFLAGS += -W -Wall -Werror -D_GNU_SOURCE -fpic -fstack-protector
|
||||
LDLIBS += -ldl
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -g -DSE_DEBUG=1
|
||||
endif
|
||||
|
||||
OBJ1 := se_memory.o se_trace.o
|
||||
OBJ2 := se_ptrace.o ptrace_version.o
|
||||
|
||||
OBJS := $(OBJ1) $(OBJ2)
|
||||
|
||||
|
||||
GDB_PLUGINS_FILES := gdb-sgx-plugin/sgx_emmt.py \
|
||||
gdb-sgx-plugin/gdb_sgx_cmd \
|
||||
gdb-sgx-plugin/gdb_sgx_plugin.py \
|
||||
gdb-sgx-plugin/load_symbol_cmd.py \
|
||||
gdb-sgx-plugin/readelf.py
|
||||
|
||||
GDB_OUT_DIR := $(BUILD_DIR)/gdb-sgx-plugin
|
||||
TARGET := libsgx_ptrace.so
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGET) install
|
||||
|
||||
.PHONY:install
|
||||
install: | $(GDB_OUT_DIR) $(GDB_PLUGINS_FILES)
|
||||
$(CP) $(GDB_PLUGINS_FILES) $(GDB_OUT_DIR)
|
||||
$(CP) $(TARGET) $(BUILD_DIR)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) -shared -o $@ $^ $(LDLIBS) $(CFLAGS)
|
||||
|
||||
$(OBJ1): %.o: $(COMMON_DIR)/src/%.c
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||
|
||||
$(OBJ2): %.o: %.c
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||
|
||||
$(GDB_OUT_DIR):
|
||||
@$(MKDIR) $@
|
||||
|
||||
$(BUILD_DIR):
|
||||
@$(MKDIR) $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(RM) $(TARGET) $(OBJS) $(BUILD_DIR)/$(TARGET)
|
||||
@$(RM) -r $(GDB_OUT_DIR)
|
35
sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_cmd
Normal file
35
sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_cmd
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
# the path can be specified by directory command
|
||||
define hook-detach
|
||||
detach_enclaves
|
||||
end
|
597
sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py
Executable file
597
sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py
Executable file
@ -0,0 +1,597 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import gdb
|
||||
import struct
|
||||
import os.path
|
||||
from ctypes import create_string_buffer
|
||||
import load_symbol_cmd
|
||||
import sgx_emmt
|
||||
|
||||
# Calculate the bit mode of current debuggee project
|
||||
SIZE = gdb.parse_and_eval("sizeof(long)")
|
||||
|
||||
ET_SIM = 0x1
|
||||
ET_DEBUG = 0x2
|
||||
PAGE_SIZE = 0x1000
|
||||
# The following definitions should strictly align with the structure of
|
||||
# debug_enclave_info_t in uRTS.
|
||||
# Here we only care about the first 7 items in the structure.
|
||||
# pointer: next_enclave_info, start_addr, tcs_list, lpFileName,
|
||||
# g_peak_heap_used_addr
|
||||
# int32_t: enclave_type, file_name_size
|
||||
ENCLAVE_INFO_SIZE = 5 * 8 + 2 * 4
|
||||
INFO_FMT = 'QQQIIQQ'
|
||||
ENCLAVES_ADDR = {}
|
||||
|
||||
# The following definitions should strictly align with the struct of
|
||||
# tcs_t
|
||||
# Here we only care about the first 8 items in the structure
|
||||
# uint64_t: state, flags, ossa, oentry, aep, ofs_base
|
||||
# uint32_t: nssa, cssa
|
||||
ENCLAVE_TCS_INFO_SIZE = 6*8 + 2*4
|
||||
TCS_INFO_FMT = 'QQQIIQQQ'
|
||||
|
||||
def get_inferior():
|
||||
"""Get current inferior"""
|
||||
try:
|
||||
if len(gdb.inferiors()) == 0:
|
||||
print ("No gdb inferior could be found.")
|
||||
return -1
|
||||
else:
|
||||
inferior = gdb.inferiors()[0]
|
||||
return inferior
|
||||
except AttributeError:
|
||||
print ("This gdb's python support is too old, please update first.")
|
||||
exit()
|
||||
|
||||
def read_from_memory(addr, size):
|
||||
"""Read data with specified size from the specified meomory"""
|
||||
inferior = get_inferior()
|
||||
# actually we can check the addr more securely
|
||||
# ( check the address is inside the enclave)
|
||||
if inferior == -1 or addr == 0:
|
||||
print ("Error happens in read_from_memory: addr = {0:x}".format(int(addr)))
|
||||
return None
|
||||
try:
|
||||
string = inferior.read_memory(addr, size)
|
||||
return string
|
||||
except gdb.MemoryError:
|
||||
print ("Can't access memory at {0:x}.".format(int(addr)))
|
||||
return None
|
||||
|
||||
def write_to_memory(addr, buf):
|
||||
"""Write a specified buffer to the specified memory"""
|
||||
inferior = get_inferior()
|
||||
if inferior == -1 or addr == 0:
|
||||
print ("Error happens in write_to_memory: addr = {0:x}".format(int(addr)))
|
||||
return -1
|
||||
try:
|
||||
inferior.write_memory(addr, buf)
|
||||
return 0
|
||||
except gdb.MemoryError:
|
||||
print ("Can't access memory at {0:x}.".format(int(addr)))
|
||||
return -1
|
||||
|
||||
def target_path_to_host_path(target_path):
|
||||
so_name = os.path.basename(target_path)
|
||||
strpath = gdb.execute("show solib-search-path", False, True)
|
||||
path = strpath.split()[-1]
|
||||
strlen = len(path)
|
||||
path = path[0:strlen-1]
|
||||
host_path = path + "/" + so_name
|
||||
#strlen = len(host_path)
|
||||
#host_path = host_path[0:strlen-7]
|
||||
return host_path
|
||||
|
||||
class enclave_info:
|
||||
"""Class to contain the enclave inforation,
|
||||
such as start address, stack addresses, stack size, etc.
|
||||
The enclave information is for one enclave."""
|
||||
def __init__(self, _next_ei, _start_addr, _enclave_type, _stack_addr_list, \
|
||||
_stack_size, _enclave_path, _heap_addr, _tcs_addr_list):
|
||||
self.next_ei = _next_ei
|
||||
self.start_addr = _start_addr
|
||||
self.enclave_type = _enclave_type
|
||||
self.stack_addr_list = _stack_addr_list
|
||||
self.stack_size = _stack_size
|
||||
self.enclave_path = _enclave_path
|
||||
self.heap_addr = _heap_addr
|
||||
self.tcs_addr_list = _tcs_addr_list
|
||||
def __str__(self):
|
||||
print ("stack address list = {0:s}".format(self.stack_addr_list))
|
||||
return "start_addr = %#x, enclave_path = \"%s\", stack_size = %d" \
|
||||
% (self.start_addr, self.enclave_path, self.stack_size)
|
||||
def __eq__(self, other):
|
||||
if other == None:
|
||||
return False
|
||||
if self.start_addr == other.start_addr:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
def init_enclave_debug(self):
|
||||
# Only product HW enclave can't be debugged
|
||||
if (self.enclave_type & ET_SIM) != ET_SIM and (self.enclave_type & ET_DEBUG) != ET_DEBUG:
|
||||
print ('Warning: {0:s} is a product hardware enclave. It can\'t be debugged and sgx_emmt doesn\'t work'.format(self.enclave_path))
|
||||
return -1
|
||||
# set TCS debug flag
|
||||
for tcs_addr in self.tcs_addr_list:
|
||||
string = read_from_memory(tcs_addr + 8, 4)
|
||||
if string == None:
|
||||
return 0
|
||||
flag = struct.unpack('I', string)[0]
|
||||
flag |= 1
|
||||
gdb_cmd = "set *(unsigned int *)%#x = %#x" %(tcs_addr + 8, flag)
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
#If it is a product enclave, won't reach here.
|
||||
#load enclave symbol
|
||||
if os.path.exists(self.enclave_path) == True:
|
||||
enclave_path = self.enclave_path
|
||||
else:
|
||||
enclave_path = target_path_to_host_path(self.enclave_path)
|
||||
gdb_cmd = load_symbol_cmd.GetLoadSymbolCommand(enclave_path, str(self.start_addr))
|
||||
if gdb_cmd == -1:
|
||||
return 0
|
||||
print (gdb_cmd)
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
global ENCLAVES_ADDR
|
||||
ENCLAVES_ADDR[self.start_addr] = gdb_cmd.split()[2]
|
||||
return 0
|
||||
|
||||
def get_peak_heap_used(self):
|
||||
"""Get the peak value of the heap used"""
|
||||
if self.heap_addr == 0:
|
||||
return -2
|
||||
# read the peak_heap_used value
|
||||
string = read_from_memory(self.heap_addr, SIZE)
|
||||
if string == None:
|
||||
return -1
|
||||
if SIZE == 4:
|
||||
fmt = 'I'
|
||||
elif SIZE == 8:
|
||||
fmt = "Q"
|
||||
peak_heap_used = struct.unpack(fmt, string)[0]
|
||||
return peak_heap_used
|
||||
|
||||
def internal_compare (self, a, b):
|
||||
return (a > b) - (a < b)
|
||||
|
||||
def find_boundary_page_index(self, stack_addr, stack_size):
|
||||
"""Find the unused page index of the boundary for the used and unused pages
|
||||
with the binary search algorithm"""
|
||||
page_index = -1 #record the last unused page index
|
||||
low = 0
|
||||
high = (stack_size>>12) - 1
|
||||
mid = 0
|
||||
# Read the mid page and check if it is used or not
|
||||
# If the mid page is used, then continue to search [mid+1, high]
|
||||
while low <= high:
|
||||
#print "low = %x, high = %x, mid = %x" % (low, high, mid)
|
||||
mid = (low + high)>>1
|
||||
string = read_from_memory(stack_addr + mid*PAGE_SIZE + (PAGE_SIZE>>1), PAGE_SIZE>>1)
|
||||
if string == None:
|
||||
return -2
|
||||
dirty_flag = 0
|
||||
for i in range(0, PAGE_SIZE>>4):
|
||||
temp = struct.unpack_from("Q", string, ((PAGE_SIZE>>4) - 1 - i)*8)[0]
|
||||
if (self.internal_compare(temp, 0xcccccccccccccccc)) != 0:
|
||||
dirty_flag = 1
|
||||
break
|
||||
if dirty_flag == 0:
|
||||
low = mid + 1
|
||||
page_index = mid
|
||||
else:
|
||||
high = mid -1
|
||||
return page_index
|
||||
|
||||
|
||||
def get_peak_stack_used(self):
|
||||
"""Get the peak value of the stack used"""
|
||||
peak_stack_used = 0
|
||||
for stack_addr in self.stack_addr_list:
|
||||
page_index = self.find_boundary_page_index(stack_addr, self.stack_size)
|
||||
if page_index == (self.stack_size)/PAGE_SIZE - 1:
|
||||
continue
|
||||
elif page_index == -2:
|
||||
return -1
|
||||
else:
|
||||
string = read_from_memory(stack_addr + (page_index+1) * PAGE_SIZE, PAGE_SIZE)
|
||||
if string == None:
|
||||
return -1
|
||||
for i in range(0, len(string)):
|
||||
temp = struct.unpack_from("B", string, i)[0]
|
||||
if (self.internal_compare(temp, 0xcc)) != 0:
|
||||
if peak_stack_used < (self.stack_size - (page_index+1) * PAGE_SIZE - i):
|
||||
peak_stack_used = self.stack_size- (page_index+1) * PAGE_SIZE - i
|
||||
break # go to the top for loop
|
||||
return peak_stack_used
|
||||
|
||||
def show_emmt(self):
|
||||
ret = gdb.execute("show sgx_emmt", False, True)
|
||||
if ret.strip() == "sgx_emmt enabled":
|
||||
print ("Enclave: \"{0:s}\"".format(self.enclave_path))
|
||||
peak_stack_used = self.get_peak_stack_used()
|
||||
if peak_stack_used == -1:
|
||||
print ("Failed to collect the stack usage information for \"{0:s}\"".format(self.enclave_path))
|
||||
else:
|
||||
print (" [Peak stack used]: {0:x}".format(peak_stack_used))
|
||||
peak_heap_used = self.get_peak_heap_used()
|
||||
if peak_heap_used == -1:
|
||||
print ("Failed to collect the heap usage information for \"{0:s}\"".format(self.enclave_path))
|
||||
elif peak_heap_used == -2:
|
||||
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.")
|
||||
else:
|
||||
print (" [Peak heap used]: {0:x}".format(peak_heap_used))
|
||||
|
||||
def fini_enclave_debug(self):
|
||||
# If it is HW product enclave, nothing to do
|
||||
if (self.enclave_type & ET_SIM) != ET_SIM and (self.enclave_type & ET_DEBUG) != ET_DEBUG:
|
||||
return -2
|
||||
self.show_emmt()
|
||||
try:
|
||||
# clear TCS debug flag
|
||||
for tcs_addr in self.tcs_addr_list:
|
||||
string = read_from_memory(tcs_addr + 8, 4)
|
||||
if string == None:
|
||||
return -2
|
||||
flag = struct.unpack('I', string)[0]
|
||||
flag &= (~1)
|
||||
gdb_cmd = "set *(unsigned int *)%#x = %#x" %(tcs_addr + 8, flag)
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
#unload symbol
|
||||
if os.path.exists(self.enclave_path) == True:
|
||||
enclave_path = self.enclave_path
|
||||
else:
|
||||
enclave_path = target_path_to_host_path(self.enclave_path)
|
||||
gdb_cmd = load_symbol_cmd.GetUnloadSymbolCommand(enclave_path, str(self.start_addr))
|
||||
if gdb_cmd == -1:
|
||||
return -1
|
||||
print (gdb_cmd)
|
||||
try:
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
global ENCLAVES_ADDR
|
||||
del ENCLAVES_ADDR[self.start_addr]
|
||||
except gdb.error:
|
||||
print ("Old gdb doesn't support remove-file-symbol command")
|
||||
return 0
|
||||
##It is possible enclave has been destroyed, so may raise exception on memory access
|
||||
except gdb.MemoryError:
|
||||
return -1
|
||||
except:
|
||||
return -1
|
||||
|
||||
def retrieve_enclave_info(info_addr = 0):
|
||||
"""retrieve one enclave info"""
|
||||
# Step 1: find the enclave info address
|
||||
if info_addr == 0:
|
||||
if SIZE == 4:
|
||||
info_addr = gdb.parse_and_eval("$eax")
|
||||
elif SIZE == 8:
|
||||
info_addr = gdb.parse_and_eval("$rdi")
|
||||
|
||||
# Step 2: retrieve the enclave info
|
||||
info_str = read_from_memory(info_addr, ENCLAVE_INFO_SIZE)
|
||||
if info_str == None:
|
||||
return None
|
||||
info_tuple = struct.unpack_from(INFO_FMT, info_str, 0)
|
||||
# (next_enclave_info,start_addr,tcs_list,enclave_type,file_name_size,
|
||||
# lpFileName,g_peak_heap_used_addr)
|
||||
#print "next_addr: %#x, start_addr: %#x, tcs_list: %#x, enclave_type:%#x, file_name_size: %#x," \
|
||||
# % (info_tuple[0], info_tuple[1], info_tuple[2], info_tuple[3], info_tuple[4])
|
||||
#print "name_addr: %#x, peak_heap_used_addr: %#x" \
|
||||
# % (info_tuple[5], info_tuple[6])
|
||||
#get enclave path
|
||||
name_str = read_from_memory(info_tuple[5], info_tuple[4])
|
||||
if name_str == None:
|
||||
return None
|
||||
fmt = str(info_tuple[4]) + 's'
|
||||
enclave_path = struct.unpack_from(fmt, name_str)[0].decode(encoding='UTF-8')
|
||||
# get the stack addr list
|
||||
stack_addr_list = []
|
||||
tcs_addr_list = []
|
||||
if SIZE == 4:
|
||||
fmt = '3I'
|
||||
elif SIZE == 8:
|
||||
fmt = '3Q'
|
||||
tcs_info_addr = info_tuple[2]
|
||||
if tcs_info_addr == 0:
|
||||
print ("Error: tcs info address = {0:x}".format(tcs_info_addr))
|
||||
return None
|
||||
|
||||
while tcs_info_addr is not 0:
|
||||
tcs_info_str = read_from_memory(tcs_info_addr, 3*SIZE)
|
||||
if tcs_info_str == None:
|
||||
return None
|
||||
tcs_info_tuple = struct.unpack_from(fmt, tcs_info_str)
|
||||
|
||||
#get tcs struct data
|
||||
tcs_t_str = read_from_memory(tcs_info_tuple[1], ENCLAVE_TCS_INFO_SIZE)
|
||||
if tcs_t_str == None:
|
||||
return None
|
||||
tcs_t_tuple = struct.unpack_from(TCS_INFO_FMT, tcs_t_str)
|
||||
|
||||
if SIZE == 4:
|
||||
td_fmt = '4I'
|
||||
elif SIZE == 8:
|
||||
td_fmt = '4Q'
|
||||
|
||||
#get thread_data_t address
|
||||
td_addr = tcs_t_tuple[7] + info_tuple[1] #thread_data_t = tcs.of_base + debug_enclave_info.start_addr
|
||||
td_str = read_from_memory(td_addr, (4*SIZE))
|
||||
if td_str == None:
|
||||
return None
|
||||
td_tuple = struct.unpack_from(td_fmt, td_str)
|
||||
#print ("thread_info:%#x, last_sp:%#x, stack_base_addr:%#x, stack_limit_addr:%#x" \
|
||||
# % (td_tuple[0], td_tuple[1], td_tuple[2], td_tuple[3]));
|
||||
|
||||
stacksize = td_tuple[2] - td_tuple[3] #stack size = stack_base_addr - stack_limit_addr
|
||||
stack_addr_list.append(td_tuple[3]) #use stack limit addr as stack base address
|
||||
tcs_addr_list.append(tcs_info_tuple[1])
|
||||
tcs_info_addr = tcs_info_tuple[0]
|
||||
|
||||
last_ocall_frame = tcs_info_tuple[2]
|
||||
last_frame = last_ocall_frame
|
||||
|
||||
#print ("last_ocall_frame = {0:x}".format(last_ocall_frame))
|
||||
|
||||
while last_ocall_frame is not 0:
|
||||
if SIZE == 4:
|
||||
of_fmt = '4I'
|
||||
elif SIZE == 8:
|
||||
of_fmt = '4Q'
|
||||
|
||||
ocall_frame = read_from_memory(last_ocall_frame, 4*SIZE)
|
||||
|
||||
if ocall_frame == None:
|
||||
return None
|
||||
ocall_frame_tuple = struct.unpack_from(of_fmt, ocall_frame)
|
||||
last_frame = ocall_frame_tuple[0]
|
||||
|
||||
last_trusted_ocall_frame = td_tuple[1]
|
||||
#print ("last_trusted_ocall_frame = {0:x}".format(last_trusted_ocall_frame))
|
||||
#print ("td_tuple[2] = {0:x}".format(td_tuple[2]))
|
||||
#break
|
||||
|
||||
while last_trusted_ocall_frame != td_tuple[2]:
|
||||
if SIZE == 4:
|
||||
oc_fmt = '20I'
|
||||
elif SIZE == 8:
|
||||
oc_fmt = '20Q'
|
||||
|
||||
oc_str = read_from_memory(last_trusted_ocall_frame, 20*SIZE)
|
||||
if oc_str == None:
|
||||
return None
|
||||
oc_tuple = struct.unpack_from(oc_fmt, oc_str)
|
||||
|
||||
last_trusted_ocall_frame = oc_tuple[6]
|
||||
|
||||
#print ("last_trusted_ocall_frame = {0:x}".format(last_trusted_ocall_frame))
|
||||
#print ("ocall_frame_tuple[1] = {0:x}".format(ocall_frame_tuple[1]))
|
||||
#print ("oc_tuple[18] = {0:x}".format(oc_tuple[18]))
|
||||
#break
|
||||
|
||||
if ocall_frame_tuple[1] == oc_tuple[18]:
|
||||
#ocall_frame.pre_last_frame = 0
|
||||
#ocall_frame.ret = ocall_context.ocall_ret
|
||||
#ocall_frame.xbp = ocall_context.xbp
|
||||
gdb_cmd = "set *(uintptr_t *)%#x = 0" %(last_ocall_frame)
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(last_ocall_frame+(2*SIZE), oc_tuple[11])
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(last_ocall_frame+(3*SIZE), oc_tuple[19])
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
break
|
||||
|
||||
last_ocall_frame = last_frame
|
||||
|
||||
node = enclave_info(info_tuple[0], info_tuple[1], info_tuple[3], stack_addr_list, \
|
||||
stacksize, enclave_path, info_tuple[6], tcs_addr_list)
|
||||
return node
|
||||
|
||||
def handle_load_event():
|
||||
"""Handle the enclave loading event.
|
||||
Firstly, retrieve the enclave info node from register
|
||||
"""
|
||||
node = retrieve_enclave_info()
|
||||
if node != None:
|
||||
node.init_enclave_debug()
|
||||
else:
|
||||
return
|
||||
|
||||
def handle_unload_event():
|
||||
node = retrieve_enclave_info()
|
||||
if node != None:
|
||||
node.fini_enclave_debug()
|
||||
else:
|
||||
return
|
||||
|
||||
def is_bp_in_urts():
|
||||
try:
|
||||
ip = gdb.parse_and_eval("$pc")
|
||||
solib_name = gdb.solib_name(int(str(ip).split()[0], 16))
|
||||
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):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
#If exception happens, just assume it is bp in uRTS.
|
||||
except:
|
||||
return True
|
||||
|
||||
def init_enclaves_debug():
|
||||
enclave_info_addr = gdb.parse_and_eval("*(void**)&g_debug_enclave_info_list")
|
||||
while enclave_info_addr != 0:
|
||||
node = retrieve_enclave_info(enclave_info_addr)
|
||||
if node != None:
|
||||
node.init_enclave_debug()
|
||||
else:
|
||||
return
|
||||
enclave_info_addr = node.next_ei
|
||||
return
|
||||
|
||||
class detach_enclaves (gdb.Command):
|
||||
def __init__ (self):
|
||||
gdb.Command.__init__ (self, "detach_enclaves", gdb.COMMAND_NONE)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
#We reject the command from the input of terminal
|
||||
if from_tty == True:
|
||||
return
|
||||
try:
|
||||
enclave_info_addr = gdb.parse_and_eval("*(void**)&g_debug_enclave_info_list")
|
||||
except:
|
||||
return
|
||||
while enclave_info_addr != 0:
|
||||
node = retrieve_enclave_info(enclave_info_addr)
|
||||
if node != None:
|
||||
node.fini_enclave_debug()
|
||||
else:
|
||||
return
|
||||
enclave_info_addr = node.next_ei
|
||||
|
||||
class UpdateOcallFrame(gdb.Breakpoint):
|
||||
def __init__(self):
|
||||
gdb.Breakpoint.__init__ (self, spec="notify_gdb_to_update", internal=1)
|
||||
|
||||
def stop(self):
|
||||
bp_in_urts = is_bp_in_urts()
|
||||
|
||||
if bp_in_urts == True:
|
||||
|
||||
if SIZE == 4:
|
||||
base_addr = gdb.parse_and_eval("base")
|
||||
tcs_addr = gdb.parse_and_eval("tcs")
|
||||
ocall_frame = gdb.parse_and_eval("of")
|
||||
elif SIZE == 8:
|
||||
base_addr = gdb.parse_and_eval("$rdi")
|
||||
tcs_addr = gdb.parse_and_eval("$rsi")
|
||||
ocall_frame = gdb.parse_and_eval("$rdx")
|
||||
|
||||
#print ("base_addr = {0:x}".format(int(base_addr)))
|
||||
#print ("tcs_addr = {0:x}".format(int(tcs_addr)))
|
||||
#print ("ocall_frame = {0:x}".format(int(ocall_frame)))
|
||||
|
||||
tcs_str = read_from_memory(tcs_addr, ENCLAVE_TCS_INFO_SIZE)
|
||||
if tcs_str == None:
|
||||
return False
|
||||
tcs_tuple = struct.unpack_from(TCS_INFO_FMT, tcs_str)
|
||||
offset = tcs_tuple[7]
|
||||
|
||||
if SIZE == 4:
|
||||
td_fmt = '4I'
|
||||
elif SIZE == 8:
|
||||
td_fmt = '4Q'
|
||||
|
||||
td_str = read_from_memory(base_addr+offset, (4*SIZE))
|
||||
if td_str == None:
|
||||
return False
|
||||
td_tuple = struct.unpack_from(td_fmt, td_str)
|
||||
|
||||
if SIZE == 4:
|
||||
trusted_of_fmt = '20I'
|
||||
elif SIZE == 8:
|
||||
trusted_of_fmt = '20Q'
|
||||
|
||||
last_sp = td_tuple[1]
|
||||
|
||||
trusted_ocall_frame = read_from_memory(last_sp, (20*SIZE))
|
||||
if trusted_ocall_frame == None:
|
||||
return False
|
||||
trusted_ocall_frame_tuple = struct.unpack_from(trusted_of_fmt, trusted_ocall_frame)
|
||||
|
||||
gdb_cmd = "set *(uintptr_t *)%#x = 0" %(ocall_frame)
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(ocall_frame+(2*SIZE), trusted_ocall_frame_tuple[11])
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
gdb_cmd = "set *(uintptr_t *)%#x = %#x" %(ocall_frame+(3*SIZE), trusted_ocall_frame_tuple[19])
|
||||
gdb.execute(gdb_cmd, False, True)
|
||||
|
||||
return False
|
||||
|
||||
class LoadEventBreakpoint(gdb.Breakpoint):
|
||||
def __init__(self):
|
||||
gdb.Breakpoint.__init__ (self, spec="sgx_debug_load_state_add_element", internal=1)
|
||||
|
||||
def stop(self):
|
||||
bp_in_urts = is_bp_in_urts()
|
||||
|
||||
if bp_in_urts == True:
|
||||
handle_load_event()
|
||||
return False
|
||||
|
||||
class UnloadEventBreakpoint(gdb.Breakpoint):
|
||||
def __init__(self):
|
||||
gdb.Breakpoint.__init__ (self, spec="sgx_debug_unload_state_remove_element", internal=1)
|
||||
|
||||
def stop(self):
|
||||
bp_in_urts = is_bp_in_urts()
|
||||
|
||||
if bp_in_urts == True:
|
||||
handle_unload_event()
|
||||
return False
|
||||
|
||||
def sgx_debugger_init():
|
||||
print ("detect urts is loaded, initializing")
|
||||
global SIZE
|
||||
SIZE = gdb.parse_and_eval("sizeof(long)")
|
||||
inited = 0
|
||||
bps = gdb.breakpoints()
|
||||
if None != bps:
|
||||
for bp in bps:
|
||||
if bp.location == "sgx_debug_load_state_add_element":
|
||||
inited = 1
|
||||
break
|
||||
if inited == 0:
|
||||
detach_enclaves()
|
||||
gdb.execute("source gdb_sgx_cmd", False, True)
|
||||
UpdateOcallFrame()
|
||||
LoadEventBreakpoint()
|
||||
UnloadEventBreakpoint()
|
||||
gdb.events.exited.connect(exit_handler)
|
||||
init_enclaves_debug()
|
||||
|
||||
|
||||
def exit_handler(event):
|
||||
# When the inferior exited, remove all enclave symbol
|
||||
for key in ENCLAVES_ADDR.keys():
|
||||
gdb.execute("remove-symbol-file -a %s" % (ENCLAVES_ADDR[key]), False, True)
|
||||
ENCLAVES_ADDR.clear()
|
||||
|
||||
def newobj_handler(event):
|
||||
solib_name = os.path.basename(event.new_objfile.filename)
|
||||
if solib_name == 'libsgx_urts.so' or solib_name == 'libsgx_urts_sim.so' or solib_name == 'libsgx_aesm_service.so':
|
||||
sgx_debugger_init()
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
gdb.events.new_objfile.connect(newobj_handler)
|
||||
sgx_emmt.init_emmt()
|
132
sdk/debugger_interface/linux/gdb-sgx-plugin/load_symbol_cmd.py
Executable file
132
sdk/debugger_interface/linux/gdb-sgx-plugin/load_symbol_cmd.py
Executable file
@ -0,0 +1,132 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
|
||||
import traceback, errno, string, re, sys, time, readelf;
|
||||
|
||||
def GetLoadSymbolCommand(EnclaveFile, Base):
|
||||
text = readelf.ReadElf(EnclaveFile)
|
||||
if text == None:
|
||||
return -1
|
||||
SegsFile = StringIO(text)
|
||||
|
||||
try:
|
||||
FileList = SegsFile.readlines()
|
||||
n=4;
|
||||
m=100;
|
||||
Out = [[[] for ni in range(n)] for mi in range(m)]
|
||||
i=0;
|
||||
Out[99][2] = '0';
|
||||
# Parse the readelf output file to extract the section names and
|
||||
# their offsets and add the Proj base address.
|
||||
for line in FileList:
|
||||
list = line.split();
|
||||
if(len(list) > 0):
|
||||
SegOffset = -1;
|
||||
# The readelf will put a space after the open bracket for single
|
||||
# digit section numbers. This causes the line.split to create
|
||||
# an extra element in the array for these lines.
|
||||
if(re.match('\[\s*[0-9]+\]',list[0])):
|
||||
SegOffset = 0;
|
||||
if(re.match('\s*[0-9]+\]',list[1])):
|
||||
SegOffset = 1;
|
||||
|
||||
if(SegOffset != -1):
|
||||
if (list[SegOffset+1][0] == '.'):
|
||||
# If it is the .text section, put it in a special place in the array
|
||||
# because the 'add-symbol-file' command treats it differently.
|
||||
#print "%#08x" % (int(list[SegOffset+3], 16))
|
||||
if(list[SegOffset+1].find(".text") != -1):
|
||||
Out[99][0] = "-s";
|
||||
Out[99][1] = list[SegOffset+1];
|
||||
Out[99][2] = str(int(list[SegOffset+3], 16) + int(Base, 10));
|
||||
Out[99][3] = " ";
|
||||
elif(int(list[SegOffset+3], 16) != 0):
|
||||
Out[i][0] = "-s";
|
||||
Out[i][1] = list[SegOffset+1];
|
||||
Out[i][2] = str(int(list[SegOffset+3], 16) + int(Base, 10));
|
||||
Out[i][3] = " ";
|
||||
i = i+1;
|
||||
if('0' != Out[99][2]):
|
||||
# The last section must not have the '\' line continuation character.
|
||||
Out[i-1][3] = '';
|
||||
|
||||
# Write the GDB 'add-symbol-file' command with all the arguments to the setup GDB command file.
|
||||
# Note: The mandatory argument for the 'add-symbol-file' command is the .text section without a
|
||||
# '-s .SectionName'. All other sections need the '-s .SectionName'.
|
||||
gdbcmd = "add-symbol-file '" + EnclaveFile + "' " + '%(Location)#08x' % {'Location':int(Out[99][2])} + " -readnow "
|
||||
for j in range(i):
|
||||
gdbcmd += Out[j][0] + " " + Out[j][1] + " " + '%(Location)#08x' % {'Location' : int(Out[j][2])} + " " + Out[j][3]
|
||||
else:
|
||||
return -1
|
||||
|
||||
return gdbcmd
|
||||
|
||||
except:
|
||||
print ("Error parsing enclave file. Check format of file.")
|
||||
return -1
|
||||
|
||||
def GetUnloadSymbolCommand(EnclaveFile, Base):
|
||||
text = readelf.ReadElf(EnclaveFile)
|
||||
if text == None:
|
||||
return -1
|
||||
SegsFile = StringIO(text)
|
||||
|
||||
try:
|
||||
FileList = SegsFile.readlines()
|
||||
# Parse the readelf output file to extract the section names and
|
||||
# their offsets and add the Proj base address.
|
||||
for line in FileList:
|
||||
list = line.split();
|
||||
if(len(list) > 0):
|
||||
SegOffset = -1;
|
||||
# The readelf will put a space after the open bracket for single
|
||||
# digit section numbers. This causes the line.split to create
|
||||
# an extra element in the array for these lines.
|
||||
if(re.match('\[\s*[0-9]+\]',list[0])):
|
||||
SegOffset = 0;
|
||||
if(re.match('\s*[0-9]+\]',list[1])):
|
||||
SegOffset = 1;
|
||||
|
||||
if(SegOffset != -1):
|
||||
if (list[SegOffset+1][0] == '.'):
|
||||
# If it is the .text section, get the .text start address and plus enclave start address
|
||||
if(list[SegOffset+1].find(".text") != -1):
|
||||
return "remove-symbol-file -a " + str(int(list[SegOffset+3], 16) + int(Base, 10))
|
||||
|
||||
except:
|
||||
print ("Error parsing enclave file. Check format of file.")
|
||||
return -1
|
50
sdk/debugger_interface/linux/gdb-sgx-plugin/readelf.py
Executable file
50
sdk/debugger_interface/linux/gdb-sgx-plugin/readelf.py
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
import gdb, subprocess
|
||||
def ReadElf(EnclaveFile):
|
||||
prefix = gdb.execute("get_tc_prefix", False, True)
|
||||
readelf_cmd = 'readelf'
|
||||
|
||||
if prefix.strip() != 'None':
|
||||
readelf_cmd = prefix.strip() + 'readelf'
|
||||
try:
|
||||
text = subprocess.check_output([readelf_cmd,
|
||||
'-W',
|
||||
'-S',
|
||||
EnclaveFile],
|
||||
universal_newlines=True
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
text = None
|
||||
|
||||
return text
|
94
sdk/debugger_interface/linux/gdb-sgx-plugin/sgx_emmt.py
Executable file
94
sdk/debugger_interface/linux/gdb-sgx-plugin/sgx_emmt.py
Executable file
@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Intel Corporation nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
|
||||
import gdb
|
||||
|
||||
ENABLE_EMMT = 0
|
||||
TC_PREFIX = None
|
||||
TC_PREFIX_DONE = False
|
||||
|
||||
class enable_emmt (gdb.Command):
|
||||
def __init__ (self):
|
||||
gdb.Command.__init__ (self, "enable sgx_emmt", gdb.COMMAND_RUNNING)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
global ENABLE_EMMT
|
||||
ENABLE_EMMT = 1
|
||||
|
||||
class disable_emmt (gdb.Command):
|
||||
def __init__ (self):
|
||||
gdb.Command.__init__ (self, "disable sgx_emmt", gdb.COMMAND_RUNNING)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
global ENABLE_EMMT
|
||||
ENABLE_EMMT = 0
|
||||
|
||||
class show_emmt (gdb.Command):
|
||||
def __init__ (self):
|
||||
gdb.Command.__init__ (self, "show sgx_emmt", gdb.COMMAND_RUNNING)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
global ENABLE_EMMT
|
||||
if ENABLE_EMMT == 1:
|
||||
print ("sgx_emmt enabled")
|
||||
if ENABLE_EMMT == 0:
|
||||
print ("sgx_emmt disabled")
|
||||
|
||||
class set_tc_prefix(gdb.Command):
|
||||
def __init__ (self):
|
||||
gdb.Command.__init__ (self, "set_tc_prefix", gdb.COMMAND_NONE)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
global TC_PREFIX, TC_PREFIX_DONE
|
||||
#For internal use, and don't allow input by gdb user
|
||||
if TC_PREFIX_DONE == True:
|
||||
return
|
||||
TC_PREFIX = arg
|
||||
TC_PREFIX_DONE = True
|
||||
|
||||
class get_tc_prefix(gdb.Command):
|
||||
def __init__ (self):
|
||||
gdb.Command.__init__ (self, "get_tc_prefix", gdb.COMMAND_NONE)
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
global TC_PREFIX
|
||||
#For internal use, and don't allow output to tty
|
||||
if from_tty == True:
|
||||
return
|
||||
print (TC_PREFIX)
|
||||
|
||||
def init_emmt():
|
||||
enable_emmt()
|
||||
disable_emmt()
|
||||
show_emmt()
|
||||
set_tc_prefix()
|
||||
get_tc_prefix()
|
44
sdk/debugger_interface/linux/ptrace_version.c
Normal file
44
sdk/debugger_interface/linux/ptrace_version.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "se_version.h"
|
||||
#include "se_cdefs.h"
|
||||
|
||||
#define __CONCAT(x, y) x/**/y
|
||||
|
||||
#define SGX_PTRACE_VERSION_STR __CONCAT("SGX_PTRACE_VERSION_", STRFILEVER)
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
const char * sgx_ptrace_version = SGX_PTRACE_VERSION_STR;
|
||||
|
||||
|
||||
SGX_ACCESS_VERSION(ptrace, 1)
|
594
sdk/debugger_interface/linux/se_ptrace.c
Normal file
594
sdk/debugger_interface/linux/se_ptrace.c
Normal file
@ -0,0 +1,594 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2016 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "arch.h"
|
||||
#include "thread_data.h"
|
||||
#include "util.h"
|
||||
#include "se_trace.h"
|
||||
#include "se_memory.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <elf.h>
|
||||
#include <assert.h>
|
||||
|
||||
//NOTE: Need align with thread_data_t in RTS.
|
||||
#define ELF32_SSA_FS_OFFSET 0x34
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define SSA2USER_REG(to, from, name) to->r##name = from.r##name
|
||||
#define USER_REG2SSA(to, from, name) to.r##name = from->r##name
|
||||
#else
|
||||
#define SSA2USER_REG(to, from, name) to->e##name = from.e##name
|
||||
#define USER_REG2SSA(to, from, name) to.e##name = from->e##name
|
||||
#endif
|
||||
|
||||
#define XSTATE_MAX_SIZE 832
|
||||
|
||||
typedef enum _direction_t
|
||||
{
|
||||
FORWARD,
|
||||
BACKWARD
|
||||
} direction_t;
|
||||
|
||||
|
||||
typedef long int (* ptrace_t)(enum __ptrace_request request, pid_t pid,
|
||||
void *addr, void *data);
|
||||
|
||||
static ptrace_t g_sys_ptrace = NULL;
|
||||
__attribute__((constructor)) void init()
|
||||
{
|
||||
g_sys_ptrace = (ptrace_t)dlsym(RTLD_NEXT, "ptrace");
|
||||
}
|
||||
|
||||
#ifdef SE_DEBUG
|
||||
static void dump_ssa_gregs(ssa_gpr_t* gpr) __attribute__((unused));
|
||||
void dump_ssa_gregs(ssa_gpr_t* gpr)
|
||||
{
|
||||
SE_TRACE(SE_TRACE_DEBUG, "ssa generic registers:\n");
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xbx = %#lx\t", gpr->REG(bx));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xcx = %#lx\t", gpr->REG(cx));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xdx = %#lx\t", gpr->REG(dx));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xsi = %#lx\t", gpr->REG(si));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xdi = %#lx\t", gpr->REG(di));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xbp = %#lx\t", gpr->REG(bp));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xax = %#lx\t", gpr->REG(ax));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xip = %#lx\t", gpr->REG(ip));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xflags = %#lx\t", gpr->REG(flags));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xsp = %#lx\t", gpr->REG(sp));
|
||||
}
|
||||
|
||||
static void dump_regs(struct user_regs_struct *regs) __attribute__((unused));
|
||||
void dump_regs(struct user_regs_struct *regs)
|
||||
{
|
||||
SE_TRACE(SE_TRACE_DEBUG, "user regisers:\n");
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xbx = %#x\t", regs->REG(bx));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xcx = %#x\t", regs->REG(cx));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xdx = %#x\t", regs->REG(dx));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xsi = %#x\t", regs->REG(si));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xdi = %#x\t", regs->REG(di));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xbp = %#x\t", regs->REG(bp));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xax = %#x\t", regs->REG(ax));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xip = %#x\t", regs->REG(ip));
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xflags = %#x\t", regs->eflags);
|
||||
SE_TRACE(SE_TRACE_DEBUG, "xsp = %#x\t", regs->REG(sp));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define dump_ssa_gregs(gpr)
|
||||
#define dump_regs(regs)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __x86_64__
|
||||
static int get_exec_class(pid_t pid)
|
||||
{
|
||||
char filename[64];
|
||||
int fd = -1;
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
|
||||
snprintf(filename, 64, "/proc/%d/exe", pid);
|
||||
fd = open(filename, O_RDONLY | O_LARGEFILE);
|
||||
if(fd == -1)
|
||||
return ELFCLASSNONE;
|
||||
if(-1 == read(fd, e_ident, EI_NIDENT))
|
||||
{
|
||||
return ELFCLASSNONE;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return e_ident[EI_CLASS];
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint32_t get_ssa_frame_size(pid_t pid, thread_data_t* td)
|
||||
{
|
||||
uint32_t ssa_frame_size = td->ssa_frame_size;
|
||||
#ifdef __x86_64__
|
||||
//on x64, we may debug elf32 enclave, we need refer to different offset in td field.
|
||||
if(ELFCLASS32 == get_exec_class(pid))
|
||||
{
|
||||
ssa_frame_size = *GET_PTR(uint32_t, td, ELF32_SSA_FS_OFFSET);
|
||||
}
|
||||
#else
|
||||
UNUSED(pid);
|
||||
#endif
|
||||
|
||||
//When debug trts, ssa_frame_size in TD is not initialized, so the value will be 0.
|
||||
//It is a limitation to debug trts. As work around, the default size is 1 page, so
|
||||
//we can debug enclave from the start of enclave_entry.
|
||||
if(0 == ssa_frame_size)
|
||||
ssa_frame_size = 1;
|
||||
|
||||
return ssa_frame_size;
|
||||
}
|
||||
|
||||
/*
|
||||
*This function get the position/offset with SSA
|
||||
* @pid, process id
|
||||
* @tcs_addr, TCS start address
|
||||
* @dir, calculate the position from start of SSA or from the end of SSA
|
||||
* @offset, offset from the start
|
||||
* @size, size of data from the postion that is going to be accessed
|
||||
* @pos, the result of postion that the function output
|
||||
* @return, TRUE on success, FALSE on fail. The result is copied to parameter pos
|
||||
* */
|
||||
static int get_ssa_pos(pid_t pid, long tcs_addr, direction_t dir, long offset, long size, long *pos)
|
||||
{
|
||||
tcs_t tcs;
|
||||
thread_data_t td;
|
||||
uint32_t ssa_frame_size = 0;
|
||||
long addr = 0;
|
||||
|
||||
//read TCS;
|
||||
if(!se_read_process_mem(pid, (void *)tcs_addr, (void *)&tcs, 72, NULL))
|
||||
return FALSE;
|
||||
|
||||
//Align with RTS. We assume TD is next to TCS
|
||||
long ssa_start = tcs_addr + TCS_SIZE;
|
||||
//ossa point to the start address of SSA, and fs/gs point to the start address of TD.
|
||||
long td_start = ssa_start - tcs.ossa + tcs.ofs_base;
|
||||
//Read thread data; On x64, sizeof(thread_data_t) of elf64 is larger than elf32,
|
||||
//so it won't miss any field if it is elf32 executable;
|
||||
if(!se_read_process_mem(pid, (void *)td_start, (void *)&td, sizeof(thread_data_t), NULL))
|
||||
return FALSE;
|
||||
ssa_frame_size = get_ssa_frame_size(pid, &td);
|
||||
//The request should not exceed ssa frame boundary.
|
||||
if((offset + size) > (long)ssa_frame_size * SE_PAGE_SIZE)
|
||||
return FALSE;
|
||||
|
||||
assert(tcs.cssa > 0);
|
||||
//If it is required to calculate from the start of SSA
|
||||
if(FORWARD == dir)
|
||||
{
|
||||
addr = ssa_start + (tcs.cssa - 1) * ssa_frame_size * SE_PAGE_SIZE + offset;
|
||||
|
||||
}
|
||||
//If it is required to calculate from the end of SSA
|
||||
else if(BACKWARD == dir)
|
||||
{
|
||||
addr = ssa_start + tcs.cssa * ssa_frame_size * SE_PAGE_SIZE - offset;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
*pos = addr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline int read_ssa(pid_t pid, long tcs_addr, direction_t dir, long offset, long size, void *buf)
|
||||
{
|
||||
long addr = 0;
|
||||
|
||||
if(!get_ssa_pos(pid, tcs_addr, dir, offset, size, &addr))
|
||||
return FALSE;
|
||||
|
||||
//read the content of ssa
|
||||
if(!se_read_process_mem(pid, (void *)addr, buf, size, NULL))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline int write_ssa(pid_t pid, long tcs_addr, direction_t dir, long offset, long size, void *buf)
|
||||
{
|
||||
long addr = 0;
|
||||
|
||||
if(!get_ssa_pos(pid, tcs_addr, dir, offset, size, &addr))
|
||||
return FALSE;
|
||||
|
||||
//write the content of ssa
|
||||
if(!se_write_process_mem(pid, (void *)addr, buf, size, NULL))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline int get_ssa_gpr(pid_t pid, long tcs_addr, ssa_gpr_t* gpr)
|
||||
{
|
||||
//read general registers. ssa_gpr_t is elf32/elf64 independent.
|
||||
return read_ssa(pid, tcs_addr, BACKWARD, sizeof(ssa_gpr_t), sizeof(ssa_gpr_t), (void *)gpr);
|
||||
}
|
||||
|
||||
static inline int set_ssa_gpr(pid_t pid, long tcs_addr, ssa_gpr_t* gpr)
|
||||
{
|
||||
//read general registers. ssa_gpr_t is elf32/elf64 independent.
|
||||
return write_ssa(pid, tcs_addr, BACKWARD, sizeof(ssa_gpr_t), sizeof(ssa_gpr_t), (void *)gpr);
|
||||
}
|
||||
|
||||
static inline int get_ssa_fpregs(pid_t pid, long tcs_addr, struct user_fpregs_struct* fpregs)
|
||||
{
|
||||
return read_ssa(pid, tcs_addr, FORWARD, 0, sizeof(struct user_fpregs_struct), (void *)fpregs);
|
||||
}
|
||||
|
||||
static inline int set_ssa_fpregs(pid_t pid, long tcs_addr, struct user_fpregs_struct* fpregs)
|
||||
{
|
||||
return write_ssa(pid, tcs_addr, FORWARD, 0, sizeof(struct user_fpregs_struct), (void *)fpregs);
|
||||
}
|
||||
|
||||
#if !defined(__x86_64__) && !defined(__x86_64)
|
||||
static inline int get_ssa_fpxregs(pid_t pid, long tcs_addr, struct user_fpxregs_struct* fpxregs)
|
||||
{
|
||||
return read_ssa(pid, tcs_addr, FORWARD, 0, sizeof(struct user_fpxregs_struct), (void *)fpxregs);
|
||||
}
|
||||
|
||||
static inline int set_ssa_fpxregs(pid_t pid, long tcs_addr, struct user_fpxregs_struct* fpxregs)
|
||||
{
|
||||
return write_ssa(pid, tcs_addr, FORWARD, 0, sizeof(struct user_fpxregs_struct), (void *)fpxregs);
|
||||
}
|
||||
#else
|
||||
#define get_ssa_fpxregs get_ssa_fpregs
|
||||
#define set_ssa_fpxregs set_ssa_fpregs
|
||||
#define user_fpxregs_struct user_fpregs_struct
|
||||
#endif
|
||||
|
||||
static inline int get_ssa_xstate(pid_t pid, long tcs_addr, int len, char *buf)
|
||||
{
|
||||
return read_ssa(pid, tcs_addr, FORWARD, 0, len, buf);
|
||||
}
|
||||
|
||||
static inline int set_ssa_xstate(pid_t pid, long tcs_addr, int len, char *buf)
|
||||
{
|
||||
return write_ssa(pid, tcs_addr, FORWARD, 0, len, buf);
|
||||
}
|
||||
|
||||
static int get_enclave_gregs(pid_t pid, struct user_regs_struct *regs, long tcs_addr)
|
||||
{
|
||||
ssa_gpr_t gpr;
|
||||
if(!get_ssa_gpr(pid, tcs_addr, &gpr))
|
||||
return -1;
|
||||
|
||||
//convert gpr to user_regs_struct.
|
||||
SSA2USER_REG(regs, gpr, bx);
|
||||
SSA2USER_REG(regs, gpr, cx);
|
||||
SSA2USER_REG(regs, gpr, dx);
|
||||
SSA2USER_REG(regs, gpr, si);
|
||||
SSA2USER_REG(regs, gpr, di);
|
||||
SSA2USER_REG(regs, gpr, bp);
|
||||
SSA2USER_REG(regs, gpr, ax);
|
||||
SSA2USER_REG(regs, gpr, ip);
|
||||
regs->eflags = gpr.REG(flags);
|
||||
SSA2USER_REG(regs, gpr, sp);
|
||||
#ifdef __x86_64__
|
||||
SSA2USER_REG(regs, gpr, 8);
|
||||
SSA2USER_REG(regs, gpr, 9);
|
||||
SSA2USER_REG(regs, gpr, 10);
|
||||
SSA2USER_REG(regs, gpr, 11);
|
||||
SSA2USER_REG(regs, gpr, 12);
|
||||
SSA2USER_REG(regs, gpr, 13);
|
||||
SSA2USER_REG(regs, gpr, 14);
|
||||
SSA2USER_REG(regs, gpr, 15);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_enclave_gregs(pid_t pid, struct user_regs_struct *regs, long tcs_addr)
|
||||
{
|
||||
ssa_gpr_t gpr;
|
||||
|
||||
//Since there is some field won't be written, we need save it first
|
||||
if(!get_ssa_gpr(pid, tcs_addr, &gpr))
|
||||
return -1;
|
||||
|
||||
//convert gpr to user_regs_struct.
|
||||
USER_REG2SSA(gpr, regs, bx);
|
||||
USER_REG2SSA(gpr, regs, cx);
|
||||
USER_REG2SSA(gpr, regs, dx);
|
||||
USER_REG2SSA(gpr, regs, si);
|
||||
USER_REG2SSA(gpr, regs, di);
|
||||
USER_REG2SSA(gpr, regs, bp);
|
||||
USER_REG2SSA(gpr, regs, ax);
|
||||
USER_REG2SSA(gpr, regs, ip);
|
||||
gpr.REG(flags) = regs->eflags;
|
||||
USER_REG2SSA(gpr, regs, sp);
|
||||
#ifdef __x86_64__
|
||||
USER_REG2SSA(gpr, regs, 8);
|
||||
USER_REG2SSA(gpr, regs, 9);
|
||||
USER_REG2SSA(gpr, regs, 10);
|
||||
USER_REG2SSA(gpr, regs, 11);
|
||||
USER_REG2SSA(gpr, regs, 12);
|
||||
USER_REG2SSA(gpr, regs, 13);
|
||||
USER_REG2SSA(gpr, regs, 14);
|
||||
USER_REG2SSA(gpr, regs, 15);
|
||||
#endif
|
||||
|
||||
//write general registers to ssa
|
||||
if(!set_ssa_gpr(pid, tcs_addr, &gpr))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_eresume(pid_t pid, struct user_regs_struct *regs)
|
||||
{
|
||||
unsigned int instr;
|
||||
|
||||
if(!se_read_process_mem(pid, (void *)regs->REG(ip), (char *)&instr, sizeof(instr), NULL))
|
||||
return FALSE;
|
||||
if((ENCLU == (instr & 0xffffff))
|
||||
&& (SE_ERESUME == regs->REG(ax)))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static long int get_regs(pid_t pid, void* addr, void* data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!data)
|
||||
return -1;
|
||||
struct user_regs_struct *regs = (struct user_regs_struct *)data;
|
||||
if(-1 == (ret = g_sys_ptrace(PTRACE_GETREGS, pid, addr, data)))
|
||||
return -1;
|
||||
if(is_eresume(pid, regs))
|
||||
{
|
||||
//If it is ERESUME instruction, set the real register value
|
||||
if(-1 == get_enclave_gregs(pid, regs, regs->REG(bx)))
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long int set_regs(pid_t pid, void* addr, void* data)
|
||||
{
|
||||
int ret = 0;
|
||||
struct user_regs_struct aep_regs;
|
||||
|
||||
if(!data)
|
||||
return -1;
|
||||
if(-1 == g_sys_ptrace(PTRACE_GETREGS, pid, 0, (void*)&aep_regs))
|
||||
return -1;
|
||||
if(is_eresume(pid, &aep_regs))
|
||||
{
|
||||
struct user_regs_struct *regs = (struct user_regs_struct *)data;
|
||||
//get tcs address
|
||||
if(-1 == (ret = set_enclave_gregs(pid, regs, aep_regs.REG(bx))))
|
||||
return -1;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_sys_ptrace(PTRACE_SETREGS, pid, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
static long int get_fpregs(pid_t pid, void* addr, void* data, int extend)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!data)
|
||||
return -1;
|
||||
struct user_regs_struct regs;
|
||||
if(-1 == (ret = g_sys_ptrace(PTRACE_GETREGS, pid, 0, ®s)))
|
||||
return -1;
|
||||
if(is_eresume(pid, ®s))
|
||||
{
|
||||
if(extend)
|
||||
ret = get_ssa_fpxregs(pid, regs.REG(bx), (struct user_fpxregs_struct *)data);
|
||||
else
|
||||
ret = get_ssa_fpregs(pid, regs.REG(bx), (struct user_fpregs_struct *)data);
|
||||
if(ret)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_sys_ptrace(PTRACE_GETFPREGS, pid, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
static long int set_fpregs(pid_t pid, void* addr, void* data, int extend)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if(!data)
|
||||
return -1;
|
||||
struct user_regs_struct regs;
|
||||
if(-1 == (ret = g_sys_ptrace(PTRACE_GETREGS, pid, 0, ®s)))
|
||||
return -1;
|
||||
if(is_eresume(pid, ®s))
|
||||
{
|
||||
if(extend)
|
||||
ret = set_ssa_fpxregs(pid, regs.REG(bx), (struct user_fpxregs_struct *)data);
|
||||
else
|
||||
ret = set_ssa_fpregs(pid, regs.REG(bx), (struct user_fpregs_struct *)data);
|
||||
if(ret)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_sys_ptrace(PTRACE_GETFPREGS, pid, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
static long int get_regset(pid_t pid, void* addr, void* data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long type = (unsigned long)addr;
|
||||
|
||||
if(!data)
|
||||
return -1;
|
||||
struct user_regs_struct regs;
|
||||
if(-1 == (ret = g_sys_ptrace(PTRACE_GETREGS, pid, 0, ®s)))
|
||||
return -1;
|
||||
|
||||
if(is_eresume(pid, ®s))
|
||||
{
|
||||
if(NT_X86_XSTATE != type)
|
||||
{
|
||||
SE_TRACE(SE_TRACE_WARNING, "unexpected type for PTRACE_GETREGSET\n");
|
||||
return -1;
|
||||
}
|
||||
struct iovec *iov = (struct iovec *)data;
|
||||
if(iov->iov_base && iov->iov_len
|
||||
&& get_ssa_xstate(pid, regs.REG(bx), iov->iov_len, (char *)iov->iov_base))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_sys_ptrace(PTRACE_GETREGSET, pid, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
static long int set_regset(pid_t pid, void* addr, void* data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long type = (unsigned long)addr;
|
||||
|
||||
if(!data)
|
||||
return -1;
|
||||
struct user_regs_struct regs;
|
||||
if(-1 == (ret = g_sys_ptrace(PTRACE_GETREGS, pid, 0, ®s)))
|
||||
return -1;
|
||||
|
||||
if(is_eresume(pid, ®s))
|
||||
{
|
||||
if(NT_X86_XSTATE != type)
|
||||
{
|
||||
SE_TRACE(SE_TRACE_WARNING, "unexpected type for PTRACE_SETREGSET\n");
|
||||
return -1;
|
||||
}
|
||||
struct iovec *iov = (struct iovec *)data;
|
||||
if(iov->iov_base && iov->iov_len
|
||||
&& set_ssa_xstate(pid, regs.REG(bx), iov->iov_len, (char *)iov->iov_base))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_sys_ptrace(PTRACE_SETREGSET, pid, addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
long int ptrace (enum __ptrace_request __request, ...)
|
||||
{
|
||||
pid_t pid;
|
||||
void *addr, *data;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, __request);
|
||||
pid = va_arg(ap, pid_t);
|
||||
addr = va_arg(ap, void *);
|
||||
data = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
|
||||
if(__request == PTRACE_GETREGS)
|
||||
{
|
||||
return get_regs(pid, addr, data);
|
||||
}
|
||||
else if(__request == PTRACE_SETREGS)
|
||||
{
|
||||
return set_regs(pid, addr, data);
|
||||
}
|
||||
#if 0
|
||||
//some old system may require this command to get register
|
||||
else if(__request == PTRACE_PEEKUSER)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
else if(__request == PTRACE_GETFPREGS)
|
||||
{
|
||||
return get_fpregs(pid, addr, data, FALSE);
|
||||
}
|
||||
else if(__request == PTRACE_SETFPREGS)
|
||||
{
|
||||
return set_fpregs(pid, addr, data, FALSE);
|
||||
|
||||
}
|
||||
else if(__request == PTRACE_GETFPXREGS)
|
||||
{
|
||||
return get_fpregs(pid, addr, data, TRUE);
|
||||
}
|
||||
else if(__request == PTRACE_SETFPXREGS)
|
||||
{
|
||||
return set_fpregs(pid, addr, data, TRUE);
|
||||
}
|
||||
|
||||
//xstave for avx
|
||||
else if(__request == PTRACE_GETREGSET)
|
||||
{
|
||||
return get_regset(pid, addr, data);
|
||||
}
|
||||
else if(__request == PTRACE_SETREGSET)
|
||||
{
|
||||
return set_regset(pid, addr, data);
|
||||
}
|
||||
//For other request just forward it to real ptrace call;
|
||||
return g_sys_ptrace(__request, pid, addr, data);
|
||||
}
|
Reference in New Issue
Block a user