waf: moved elf symbol checking to ardupilotwaf

not chibios specific
This commit is contained in:
Andrew Tridgell 2024-05-27 13:58:49 +10:00
parent ceac4969d5
commit aff9175328
4 changed files with 61 additions and 31 deletions

View File

@ -1,12 +1,13 @@
# encoding: utf-8 # encoding: utf-8
from __future__ import print_function 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.Configure import conf
from waflib.Scripting import run_command 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 import os.path, os
from collections import OrderedDict from collections import OrderedDict
import subprocess
import ap_persistent import ap_persistent
@ -258,6 +259,55 @@ def ap_common_vehicle_libraries(bld):
_grouped_programs = {} _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 @conf
def ap_program(bld, def ap_program(bld,
program_groups='bin', program_groups='bin',
@ -279,7 +329,7 @@ def ap_program(bld,
if use_legacy_defines: if use_legacy_defines:
kw['defines'].extend(get_legacy_defines(bld.path.name, bld)) 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) program_groups = Utils.to_list(program_groups)

View File

@ -45,6 +45,9 @@ class Board:
cfg.load('toolchain') cfg.load('toolchain')
cfg.load('cxx_checks') cfg.load('cxx_checks')
# check elf symbols by default
cfg.env.CHECK_SYMBOLS = True
env = waflib.ConfigSet.ConfigSet() env = waflib.ConfigSet.ConfigSet()
def srcpath(path): def srcpath(path):
return cfg.srcnode.make_node(path).abspath() return cfg.srcnode.make_node(path).abspath()
@ -1284,6 +1287,9 @@ class linux(Board):
self.with_can = True self.with_can = True
super(linux, self).configure_env(cfg, env) 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.BOARD_CLASS = "LINUX"
env.DEFINES.update( env.DEFINES.update(

View File

@ -148,31 +148,6 @@ class set_default_parameters(Task.Task):
defaults.save() 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): class generate_bin(Task.Task):
color='CYAN' color='CYAN'
# run_str="${OBJCOPY} -O binary ${SRC} ${TGT}" # run_str="${OBJCOPY} -O binary ${SRC} ${TGT}"
@ -184,8 +159,6 @@ class generate_bin(Task.Task):
def keyword(self): def keyword(self):
return "Generating" return "Generating"
def run(self): def run(self):
check_elf_symbols(self)
if self.env.HAS_EXTERNAL_FLASH_SECTIONS: if self.env.HAS_EXTERNAL_FLASH_SECTIONS:
ret = self.split_sections() ret = self.split_sections()
if (ret < 0): if (ret < 0):
@ -569,7 +542,6 @@ def configure(cfg):
cfg.find_program('make', var='MAKE') cfg.find_program('make', var='MAKE')
#cfg.objcopy = cfg.find_program('%s-%s'%(cfg.env.TOOLCHAIN,'objcopy'), var='OBJCOPY', mandatory=True) #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-objcopy', var='OBJCOPY')
cfg.find_program('arm-none-eabi-nm', var='NM')
env = cfg.env env = cfg.env
bldnode = cfg.bldnode.make_node(cfg.variant) bldnode = cfg.bldnode.make_node(cfg.variant)
def srcpath(path): def srcpath(path):

View File

@ -150,6 +150,8 @@ def configure(cfg):
cfg.find_program('%s-ar' % cfg.env.TOOLCHAIN, var='AR', quiet=True) cfg.find_program('%s-ar' % cfg.env.TOOLCHAIN, var='AR', quiet=True)
cfg.load('compiler_cxx compiler_c') cfg.load('compiler_cxx compiler_c')
cfg.find_program('%s-nm' % cfg.env.TOOLCHAIN, var='NM')
if not cfg.options.disable_gccdeps: if not cfg.options.disable_gccdeps:
cfg.load('gccdeps') cfg.load('gccdeps')