From aff9175328fd55d7df761008c3c9ef9173dc93c5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 May 2024 13:58:49 +1000 Subject: [PATCH] waf: moved elf symbol checking to ardupilotwaf not chibios specific --- Tools/ardupilotwaf/ardupilotwaf.py | 56 ++++++++++++++++++++++++++++-- Tools/ardupilotwaf/boards.py | 6 ++++ Tools/ardupilotwaf/chibios.py | 28 --------------- Tools/ardupilotwaf/toolchain.py | 2 ++ 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/Tools/ardupilotwaf/ardupilotwaf.py b/Tools/ardupilotwaf/ardupilotwaf.py index d20eef7e50..1f5a628ff5 100644 --- a/Tools/ardupilotwaf/ardupilotwaf.py +++ b/Tools/ardupilotwaf/ardupilotwaf.py @@ -1,12 +1,13 @@ # encoding: utf-8 from __future__ import print_function -from waflib import Build, ConfigSet, Configure, Context, Errors, Logs, Options, Utils +from waflib import Build, ConfigSet, Configure, Context, Errors, Logs, Options, Utils, Task from waflib.Configure import conf from waflib.Scripting import run_command -from waflib.TaskGen import before_method, feature +from waflib.TaskGen import before_method, after_method, feature import os.path, os from collections import OrderedDict +import subprocess import ap_persistent @@ -258,6 +259,55 @@ def ap_common_vehicle_libraries(bld): _grouped_programs = {} +class check_elf_symbols(Task.Task): + color='CYAN' + always_run = True + def keyword(self): + return "checking symbols" + + def run(self): + ''' + check for disallowed symbols in elf file, such as C++ exceptions + ''' + elfpath = self.inputs[0].abspath() + + if not self.env.CHECK_SYMBOLS: + # checking symbols disabled on this build + return + + if not self.env.vehicle_binary or self.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', + 'operator new[](unsigned int)', + 'operator new[](unsigned long)', + 'operator new(unsigned int)', + 'operator new(unsigned long)'] + + nmout = subprocess.getoutput("%s -C %s" % (self.env.get_flat('NM'), elfpath)) + for b in blacklist: + if nmout.find(b) != -1: + raise Errors.WafError("Disallowed symbol in %s: %s" % (elfpath, b)) + + +@feature('post_link') +@after_method('process_source') +def post_link(self): + ''' + setup tasks to run after link stage + ''' + self.link_task.always_run = True + + link_output = self.link_task.outputs[0] + + check_elf_task = self.create_task('check_elf_symbols', src=link_output) + check_elf_task.set_run_after(self.link_task) + @conf def ap_program(bld, program_groups='bin', @@ -279,7 +329,7 @@ def ap_program(bld, if use_legacy_defines: kw['defines'].extend(get_legacy_defines(bld.path.name, bld)) - kw['features'] = kw.get('features', []) + bld.env.AP_PROGRAM_FEATURES + kw['features'] = kw.get('features', []) + bld.env.AP_PROGRAM_FEATURES + ['post_link'] program_groups = Utils.to_list(program_groups) diff --git a/Tools/ardupilotwaf/boards.py b/Tools/ardupilotwaf/boards.py index 9c50faf4a3..8cb702ddcf 100644 --- a/Tools/ardupilotwaf/boards.py +++ b/Tools/ardupilotwaf/boards.py @@ -45,6 +45,9 @@ class Board: cfg.load('toolchain') cfg.load('cxx_checks') + # check elf symbols by default + cfg.env.CHECK_SYMBOLS = True + env = waflib.ConfigSet.ConfigSet() def srcpath(path): return cfg.srcnode.make_node(path).abspath() @@ -1284,6 +1287,9 @@ class linux(Board): self.with_can = True super(linux, self).configure_env(cfg, env) + # can't do symbol checking on Linux due to exception usage in libc++ + env.CHECK_SYMBOLS = False + env.BOARD_CLASS = "LINUX" env.DEFINES.update( diff --git a/Tools/ardupilotwaf/chibios.py b/Tools/ardupilotwaf/chibios.py index 1d1c5052cb..7e20f40fc5 100644 --- a/Tools/ardupilotwaf/chibios.py +++ b/Tools/ardupilotwaf/chibios.py @@ -148,31 +148,6 @@ class set_default_parameters(Task.Task): 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', - 'operator new[](unsigned int)', - 'operator new[](unsigned long)', - 'operator new(unsigned int)', - 'operator new(unsigned long)'] - - 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}" @@ -184,8 +159,6 @@ 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): @@ -569,7 +542,6 @@ 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): diff --git a/Tools/ardupilotwaf/toolchain.py b/Tools/ardupilotwaf/toolchain.py index eb86084307..9347876c1f 100644 --- a/Tools/ardupilotwaf/toolchain.py +++ b/Tools/ardupilotwaf/toolchain.py @@ -150,6 +150,8 @@ def configure(cfg): cfg.find_program('%s-ar' % cfg.env.TOOLCHAIN, var='AR', quiet=True) cfg.load('compiler_cxx compiler_c') + cfg.find_program('%s-nm' % cfg.env.TOOLCHAIN, var='NM') + if not cfg.options.disable_gccdeps: cfg.load('gccdeps')