Skip to content

Commit

Permalink
waf: prevent use of C++ library calls that can cause exceptions
Browse files Browse the repository at this point in the history
this cleans up our blacklist of library functions, and ensures there
can be no accidential use of std:: functions that cause exceptions in
flight code on HAL_ChibiOS
  • Loading branch information
tridge committed Feb 21, 2024
1 parent 20cb709 commit 4ad1231
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
8 changes: 7 additions & 1 deletion Tools/ardupilotwaf/ardupilotwaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ def ap_program(bld,
program_dir=None,
use_legacy_defines=True,
program_name=None,
vehicle_binary=True,
**kw):
if 'target' in kw:
bld.fatal('Do not pass target for program')
Expand Down Expand Up @@ -300,6 +301,9 @@ def ap_program(bld,
program_dir=program_dir,
**kw
)

tg.env.vehicle_binary = vehicle_binary

if 'use' in kw and bld.env.STATIC_LINKING:
# ensure we link against vehicle library
tg.env.STLIB += [kw['use']]
Expand All @@ -313,7 +317,7 @@ def ap_program(bld,
@conf
def ap_example(bld, **kw):
kw['program_groups'] = 'examples'
ap_program(bld, use_legacy_defines=False, **kw)
ap_program(bld, use_legacy_defines=False, vehicle_binary=False, **kw)

def unique_list(items):
'''remove duplicate elements from a list while maintaining ordering'''
Expand Down Expand Up @@ -383,6 +387,7 @@ def ap_find_tests(bld, use=[], DOUBLE_PRECISION_SOURCES=[]):
program_name=f.change_ext('').name,
program_groups='tests',
use_legacy_defines=False,
vehicle_binary=False,
cxxflags=['-Wno-undef'],
)
filename = os.path.basename(f.abspath())
Expand Down Expand Up @@ -444,6 +449,7 @@ def ap_find_benchmarks(bld, use=[]):
includes=includes,
source=[f],
use=use,
vehicle_binary=False,
program_name=f.change_ext('').name,
program_groups='benchmarks',
use_legacy_defines=False,
Expand Down
52 changes: 40 additions & 12 deletions Tools/ardupilotwaf/chibios.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import pickle
import struct
import base64
import subprocess

_dynamic_env_data = {}
def _load_dynamic_env_data(bld):
Expand Down Expand Up @@ -143,6 +144,27 @@ def run(self):
defaults.save()


def check_elf_symbols(task):
'''
check for disallowed symbols in elf file, such as C++ exceptions
'''
elfpath = task.inputs[0].abspath()

if not task.env.vehicle_binary or task.env.SIM_ENABLED:
# we only want to check symbols for vehicle binaries, allowing examples
# to use C++ exceptions. We also allow them in simulator builds
return

# we use string find on these symbols, so this catches all types of throw
# calls this should catch all uses of exceptions unless the compiler
# manages to inline them
blacklist = ['std::__throw']

nmout = subprocess.getoutput("%s -C %s" % (task.env.get_flat('NM'), elfpath))
for b in blacklist:
if nmout.find(b) != -1:
raise Errors.WafError("Disallowed symbol in %s: %s" % (elfpath, b))

class generate_bin(Task.Task):
color='CYAN'
# run_str="${OBJCOPY} -O binary ${SRC} ${TGT}"
Expand All @@ -154,6 +176,8 @@ class generate_bin(Task.Task):
def keyword(self):
return "Generating"
def run(self):
check_elf_symbols(self)

if self.env.HAS_EXTERNAL_FLASH_SECTIONS:
ret = self.split_sections()
if (ret < 0):
Expand Down Expand Up @@ -529,6 +553,7 @@ def configure(cfg):
cfg.find_program('make', var='MAKE')
#cfg.objcopy = cfg.find_program('%s-%s'%(cfg.env.TOOLCHAIN,'objcopy'), var='OBJCOPY', mandatory=True)
cfg.find_program('arm-none-eabi-objcopy', var='OBJCOPY')
cfg.find_program('arm-none-eabi-nm', var='NM')
env = cfg.env
bldnode = cfg.bldnode.make_node(cfg.variant)
def srcpath(path):
Expand Down Expand Up @@ -716,16 +741,19 @@ def build(bld):
if bld.env.ENABLE_CRASHDUMP:
bld.env.LINKFLAGS += ['-Wl,-whole-archive', 'modules/ChibiOS/libcc.a', '-Wl,-no-whole-archive']
# list of functions that will be wrapped to move them out of libc into our
# own code note that we also include functions that we deliberately don't
# implement anywhere (the FILE* functions). This allows us to get link
# errors if we accidentially try to use one of those functions either
# directly or via another libc call
wraplist = ['sscanf', 'fprintf', 'snprintf', 'vsnprintf','vasprintf','asprintf','vprintf','scanf',
'printf',
'fopen', 'fflush', 'fwrite', 'fread', 'fputs', 'fgets',
'clearerr', 'fseek', 'ferror', 'fclose', 'tmpfile', 'getc', 'ungetc', 'feof',
'ftell', 'freopen', 'remove', 'vfprintf', 'fscanf',
'_gettimeofday', '_times', '_times_r', '_gettimeofday_r', 'time', 'clock',
'_sbrk', '_sbrk_r', '_malloc_r', '_calloc_r', '_free_r']
for w in wraplist:
# own code
wraplist = ['sscanf', 'fprintf', 'snprintf', 'vsnprintf', 'vasprintf', 'asprintf', 'vprintf', 'scanf', 'printf']

# list of functions that we will give a link error for if they are
# used. This is to prevent accidential use of these functions
blacklist = ['_sbrk', '_sbrk_r', '_malloc_r', '_calloc_r', '_free_r', 'ftell',
'fopen', 'fflush', 'fwrite', 'fread', 'fputs', 'fgets',
'clearerr', 'fseek', 'ferror', 'fclose', 'tmpfile', 'getc', 'ungetc', 'feof',
'ftell', 'freopen', 'remove', 'vfprintf', 'vfprintf_r', 'fscanf',
'_gettimeofday', '_times', '_times_r', '_gettimeofday_r', 'time', 'clock']

# these functions use global state that is not thread safe
blacklist += ['gmtime']

for w in wraplist + blacklist:
bld.env.LINKFLAGS += ['-Wl,--wrap,%s' % w]

0 comments on commit 4ad1231

Please sign in to comment.