Skip to content

Commit

Permalink
Linker support to securely inline arithmetic functions.
Browse files Browse the repository at this point in the history
Transparently intercept relocatable arithmetic library calls
inserted by the compiler back-end, so as to redirect them to a
custom code stub inserted in the SM's text section.

This addresses issue #6.
  • Loading branch information
jovanbulck committed Jul 13, 2017
1 parent fd9f839 commit 3e00e24
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 3 deletions.
116 changes: 113 additions & 3 deletions src/drivers/linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ def __init__(self, name, file_name):
self.file_name = file_name


class SmRel:
def __init__(self, sm, offset, sym):
self.sm = sm
self.rela_offset = offset
self.sym = sym.strip('_')

def get_sym(self):
return '__sm_{0}_{1}'.format(self.sm, self.sym)

def get_sect(self):
return '.sm.{0}.text'.format(self.sm)

def get_rela_sect(self):
return '.rela.sm.{0}.text'.format(self.sm)


def rename_syms_sects(file, sym_map, sect_map):
args = []
for old, new in sym_map.items():
Expand All @@ -35,6 +51,18 @@ def rename_syms_sects(file, sym_map, sect_map):
return out_file


# The `--add-symbol` option is only available for GNU binutils > msp430-gcc.
# This function therefore relies on msp430-elf-objcopy from the TI GCC port.
def add_sym(file, sym_map):
args = []
for sym, sect in sym_map.items():
args += ['--add-symbol', '{0}={1}:0,weak'.format(sym, sect)]

args += [file, file]
call_prog('msp430-elf-objcopy', args)
return file


def parse_size(val):
try:
return int(val)
Expand Down Expand Up @@ -143,6 +171,10 @@ def sort_key(entry):
parser.add_argument('--print-default-libs',
help='Print libraries that are always linked',
action='store_true')
parser.add_argument('--inline-arithmetic',
help='Intercept and securely inline integer arithmetic '
'routines inserted by the compiler back-end',
action='store_true')

args, cli_ld_args = parser.parse_known_args()
set_args(args)
Expand All @@ -168,6 +200,7 @@ def sort_key(entry):
sms_irq_handlers = defaultdict(list)
existing_sms = set()
existing_macs = []
elf_relocations = defaultdict(list)

added_set_key_stub = False
added_input_stub = False
Expand All @@ -181,8 +214,8 @@ def sort_key(entry):
i += 1

try:
with open(file_name, 'rb') as file:
elf_file = ELFFile(file)
with open(file_name, 'rb') as f:
elf_file = ELFFile(f)
for section in elf_file.iter_sections():
name = section.name
match = re.match(r'.sm.(\w+).text', name)
Expand Down Expand Up @@ -210,7 +243,8 @@ def sort_key(entry):
# Find call from this SM to others
sym = 'null'
symtab = elf_file.get_section(section['sh_link'])
for rel in section.iter_relocations():
for n in range(section.num_relocations()):
rel = section.get_relocation(n)
prev_sym = sym
sym = symtab.get_symbol(rel['r_info_sym'])

Expand All @@ -224,6 +258,23 @@ def sort_key(entry):
sms_unprotected_calls[sm_name] = set()
sms_unprotected_calls[sm_name].add(prev_sym.name)

# Intercept unprotected arithmetic function calls
# inserted by the compiler back-end; see also:
# llvm/lib/Target/MSP430/MSP430ISelLowering.cpp
# llvm/lib/codegen/TargetLoweringBase.cpp
# https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html
ari_match = re.match(r'__(u|)(ashl|ashr|lshr|mul|div|mod)(q|h|s|d|t)i.*', sym.name)
if ari_match and args.inline_arithmetic:
rela_offset = n * section['sh_entsize']
elf_relocations[file_name].append(
SmRel(sm_name, rela_offset, sym.name))
elif ari_match:
fatal_error("Arithmetic function call '{0}' "
"detected in SM '{1}'. Use the "
"`--inline-arithmetic` option to securely inline "
"integer arithmetic routines inserted by the "
"compiler back-end.".format( sym.name, sm_name))

rel_match = re.match(r'__sm_(\w+)_entry$', sym.name)
if not rel_match:
continue
Expand Down Expand Up @@ -351,6 +402,65 @@ def sort_key(entry):
else:
info('No existing Sancus modules found')


if args.inline_arithmetic:
# create sm_mul asm stub for each unique SM multiplication symbol
sms_relocations = defaultdict(set)
for rels in elf_relocations.values():
for sm_rel in rels:
sms_relocations[sm_rel.sm].add(sm_rel.sym)

# resolve dependencies (hack)
for sm, syms in sms_relocations.items():
if 'divhi3' in syms:
sms_relocations[sm].add('udivhi3')
elif 'modhi3' in syms:
sms_relocations[sm].add('divhi3')
sms_relocations[sm].add('udivhi3')
elif 'umodhi3' in syms:
sms_relocations[sm].add('udivhi3')

# add asm stubs for final linking step
for sm, syms in sms_relocations.items():
for sym in syms:
sym_map = {'__sm_mulhi3' : '__sm_{}_mulhi3'.format(sm),
'__sm_divhi3' : '__sm_{}_divhi3'.format(sm),
'__sm_udivhi3' : '__sm_{}_udivhi3'.format(sm),
'__sm_modhi3' : '__sm_{}_modhi3'.format(sm),
'__sm_umodhi3' : '__sm_{}_umodhi3'.format(sm)
}
sect_map = {'.sm.text' : '.sm.{}.text'.format(sm)}
obj = sancus.paths.get_data_path() + '/sm_{}.o'.format(sym)
input_files.append(rename_syms_sects(obj, sym_map, sect_map))

for fn in elf_relocations:
# add patched symbol names to infile
sym_map = { sm_rel.get_sym() : sm_rel.get_sect() for
sm_rel in elf_relocations[fn] }
add_sym(fn, sym_map)

with open(fn, 'r+b') as f:
elf_file = ELFFile(f)
symtab = elf_file.get_section_by_name('.symtab')

for sm_rel in elf_relocations[fn]:
# calculate relocation offset (file has changed after add_sym)
relasect = elf_file.get_section_by_name(sm_rel.get_rela_sect())
offset = relasect['sh_offset'] + sm_rel.rela_offset

# get symbol table index of added symbol
for sym_idx in range(symtab.num_symbols()):
if symtab.get_symbol(sym_idx).name == sm_rel.get_sym():
break

# overwrite symbol table index in targeted relocation
# skip r_offset and patch r_info lower byte (litte endian)
info("Patching relocation for symbol '{0}' in SM '{1}' ({2})".
format(sm_rel.get_sym(), sm_rel.sm, fn))
f.seek(offset+5)
f.write(bytes([sym_idx]))


# create output sections for the the SM to be inserted in the linker script
text_section = '''.text.sm.{0} :
{{
Expand Down
12 changes: 12 additions & 0 deletions src/stubs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ add_object(sm_isr_dummy.o sm_isr_dummy.s)
add_object(sm_exit.o sm_exit.s)
add_object(sm_verify.o sm_verify.s)

add_object(sm_mulhi3.o sm_mulhi3.s)
add_object(sm_udivhi3.o sm_udivhi3.s)
add_object(sm_divhi3.o sm_divhi3.s)
add_object(sm_modhi3.o sm_modhi3.s)
add_object(sm_umodhi3.o sm_umodhi3.s)

include(UseSancusCC)
set(EXTRA_FLAGS -I${CMAKE_SOURCE_DIR}/src/sancus_support)
add_object(sm_output.o sm_output.c ${EXTRA_FLAGS})
Expand All @@ -23,6 +29,12 @@ set(STUBS
${CMAKE_CURRENT_BINARY_DIR}/sm_output.o
${CMAKE_CURRENT_BINARY_DIR}/sm_input.o
${CMAKE_CURRENT_BINARY_DIR}/sm_set_key.o

${CMAKE_CURRENT_BINARY_DIR}/sm_mulhi3.o
${CMAKE_CURRENT_BINARY_DIR}/sm_divhi3.o
${CMAKE_CURRENT_BINARY_DIR}/sm_udivhi3.o
${CMAKE_CURRENT_BINARY_DIR}/sm_modhi3.o
${CMAKE_CURRENT_BINARY_DIR}/sm_umodhi3.o
)

install(FILES ${STUBS}
Expand Down
29 changes: 29 additions & 0 deletions src/stubs/sm_divhi3.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.section ".sm.text"
.align 2
.global __sm_divhi3
.type __sm_divhi3,@function

__sm_divhi3:
clr r13
tst r15
jge 1f
mov #3, r13
inv r15
inc r15
1: tst r14
jge 2f
xor.b #1, r13
inv r14
inc r14
2: push r13
call #__sm_udivhi3
pop r13
bit.b #2, r13
jz 3f
inv r14
inc r14
3: bit.b #1, r13
jz 4f
inv r15
inc r15
4: ret
9 changes: 9 additions & 0 deletions src/stubs/sm_modhi3.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.section ".sm.text"
.align 2
.global __sm_modhi3
.type __sm_modhi3,@function

__sm_modhi3:
call #__sm_divhi3
mov r14, r15
ret
22 changes: 22 additions & 0 deletions src/stubs/sm_mulhi3.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.section ".sm.text"
.align 2
.global __sm_mulhi3
.type __sm_mulhi3,@function

; \arg r14: a
; \arg r15: b
; \ret r15: a*b
; \note: clobbers r13
__sm_mulhi3:
mov r15, r13
clr r15
1: tst r14
jz 3f
clrc
rrc r13
jnc 2f
add r14, r15
2: rla r14
tst r13
jnz 1b
3: ret
18 changes: 18 additions & 0 deletions src/stubs/sm_udivhi3.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.section ".sm.text"
.align 2
.global __sm_udivhi3
.type __sm_udivhi3,@function

__sm_udivhi3:
mov.b #16, r12
mov r14, r13
clr r14
1: rla r15
rlc r14
cmp r13, r14
jnc 2f
sub r13, r14
bis #1, r15
2: dec r12
jnz 1b
ret
9 changes: 9 additions & 0 deletions src/stubs/sm_umodhi3.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.section ".sm.text"
.align 2
.global __sm_umodhi3
.type __sm_umodhi3,@function

__sm_umodhi3:
call #__sm_udivhi3
mov r14, r15
ret

0 comments on commit 3e00e24

Please sign in to comment.