#! /usr/bin/env python # encoding: utf-8 from waflib import TaskGen FRAGMENT_ATOMIC='''int i; int main(void) { __atomic_load_n(&i, __ATOMIC_ACQUIRE); __atomic_store_n(&i, 1, __ATOMIC_RELEASE); return 0; }''' FRAGMENT_SYNC='''int i; int main (void) { __sync_bool_compare_and_swap (&i, i, i); __sync_lock_test_and_set (&i, 1); __sync_lock_release (&i); return 0; }''' FRAGMENT_GETPAGESIZE='''#include int main(void) { return getpagesize() }''' FRAGMENT_GETEXECNAME='''#include int main(void) { return getexecname() != 0 }''' FRAGMENT_STRNLEN='''#include int main(int argc, char **argv) { return (int)strnlen(argv[0], 10); }''' FRAGMENT_DL_ITERATE_PHDR='''#include <%s> int main(void) { return dl_iterate_phdr(0, 0); }''' FRAGMENT_FCNTL='''#include int main(void) { return fcntl(0, 0, 0); }''' FRAGMENT_GETIPINFO='''#include "unwind.h" struct _Unwind_Context *context; int ip_before_insn = 0; int main(void) { return _Unwind_GetIPInfo(context, &ip_before_insn); }''' FRAGMENT_LOADQUERY='''#include #include int main(void) { return loadquery(0, 0, 0); }''' FRAGMENT_KERN_PROC='''#include #if !defined(%s) || !defined(KERN_PROC_PATHNAME) #error #endif int main(void) { return 0; }''' FRAGMENT_LSTAT='''#include struct stat st; int main(int argc, char **argv) { return lstat(argv[0], &st); }''' FRAGMENT_READLINK='''#include char buf[100]; int main(int argc, char **argv) { return readlink(argv[0], buf, sizeof(buf)); }''' def options(opt): pass def configure(conf): # add unsupported platforms here if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos']: return # win32 has it's own dbghelp-based backtrace, that's why we ship PDBs if conf.env.COMPILER_CC == 'msvc': return if not conf.path.find_dir('libbacktrace') or not conf.path.find_dir('libbacktrace/config'): conf.fatal('Can\'t find libbacktrace submodule. Run `git submodule update --init --recursive`.') return if conf.env.DEST_SIZEOF_VOID_P == 8: conf.define('BACKTRACE_ELF_SIZE', 64) conf.define('BACKTRACE_XCOFF_SIZE', 64) else: conf.define('BACKTRACE_ELF_SIZE', 32) conf.define('BACKTRACE_XCOFF_SIZE', 32) conf.define('_ALL_SOURCE', 1) conf.define('_GNU_SOURCE', 1) conf.define('_POSIX_PTHREAD_SEMANTICS', 1) conf.define('_TANDEM_SOURCE', 1) conf.define('__EXTENSIONS__', 1) conf.define('_DARWIN_USE_64_BIT_INODE', 1) conf.define('_LARGE_FILES', 1) conf.define('_POSIX_SOURCE', 1) conf.define('_POSIX_1_SOURCE', 1) conf.check_large_file(compiler='c', execute=False, mandatory=False) # sets _FILE_OFFSET_BITS conf.env.CFLAGS_EXTRAFLAGS = conf.filter_cflags(['-funwind-tables', '-g'], []) if conf.filter_cflags(['-frandom-seed=test'], []): conf.env.HAVE_FRANDOM_SEED = True def check_header(hdr): return {'header_name':hdr, 'msg':'... %s header' % hdr, 'mandatory':False, 'id':hdr} conf.multicheck( check_header('dlfcn.h'), check_header('inttypes.h'), check_header('link.h'), check_header('sys/link.h'), check_header('mach-o/dyld.h'), check_header('memory.h'), check_header('stdint.h'), check_header('stdlib.h'), check_header('strings.h'), check_header('string.h'), check_header('sys/ldr.h'), check_header('sys/mman.h'), check_header('sys/stat.h'), check_header('sys/types.h'), check_header('tlhelp32.h'), check_header('unistd.h'), check_header('windows.h'), {'fragment':FRAGMENT_ATOMIC, 'msg':'... __atomic extensions', 'define_name':'HAVE_ATOMIC_FUNCTIONS', 'mandatory':False}, {'fragment':FRAGMENT_SYNC, 'msg':'... __sync extensions', 'define_name':'HAVE_SYNC_FUNCTIONS', 'mandatory':False}, {'fragment':FRAGMENT_GETPAGESIZE, 'msg':'... getpagesize function', 'define_name':'HAVE_DECL_GETPAGESIZE', 'mandatory':False}, {'fragment':FRAGMENT_STRNLEN, 'msg':'... strnlen function', 'define_name':'HAVE_DECL_STRNLEN', 'mandatory':False}, {'fragment':FRAGMENT_DL_ITERATE_PHDR % 'link.h', 'msg':'... dl_iterate_phdr function in link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['link.h'], 'mandatory':False}, {'fragment':FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', 'msg':'... dl_iterate_phdr function in sys/link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['sys/link.h'], 'mandatory':False}, {'fragment':FRAGMENT_FCNTL,'msg':'... fnctl function', 'define_name':'HAVE_FCNTL', 'mandatory':False}, {'fragment':FRAGMENT_GETEXECNAME,'msg':'... getexecname function','define_name':'HAVE_GETEXECNAME', 'mandatory':False}, {'fragment':FRAGMENT_GETIPINFO, 'msg':'... _Unwind_GetIPInfo function', 'define_name':'HAVE_GETIPINFO', 'mandatory':False}, {'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC', 'msg': '... KERN_PROC and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC', 'mandatory':False}, {'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC_ARGS', 'msg': '... KERN_PROC_ARGS and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC_ARGS', 'mandatory':False}, {'fragment':FRAGMENT_LOADQUERY, 'msg': '... loadquery function', 'define_name':'HAVE_LOADQUERY', 'mandatory':False}, {'fragment':FRAGMENT_LSTAT, 'msg': '... lstat function', 'define_name':'HAVE_LSTAT', 'mandatory':False}, {'fragment':FRAGMENT_READLINK, 'msg': '... readlink function', 'define_name':'HAVE_READLINK', 'mandatory':False}, {'lib':'lzma', 'define_name':'HAVE_LIBLZMA', 'uselib_store':'lzma', 'msg':'... lzma library', 'mandatory':False}, {'lib':'z', 'define_name':'HAVE_ZLIB', 'uselib_store':'z', 'msg':'... zlib library', 'mandatory':False}, {'lib':'zstd', 'define_name':'HAVE_ZSTD', 'uselib_store':'zstd', 'msg':'... zstd library', 'mandatory':False}, msg='Checking for in parallel' ) conf.write_config_header() conf.define('BACKTRACE_SUPPORTED', 1) conf.define('BACKTRACE_USES_MALLOC', 0) conf.define('BACKTRACE_SUPPORTS_THREADS', 1) conf.define('BACKTRACE_SUPPORTS_DATA', conf.env.DEST_BINFMT in ['elf', 'mac-o']) conf.write_config_header('backtrace-supported.h') @TaskGen.feature('frandomseed') @TaskGen.after_method('process_source') @TaskGen.before_method('apply_link') def process_frandom_seed(ctx): tasks = getattr(ctx, 'compiled_tasks', []) for task in tasks: out = task.outputs[0] task.env.CFLAGS = list(task.env.CFLAGS) # need a copy task.env.CFLAGS += ['-frandom-seed=%s' % out.path_from(out.ctx.bldnode)] def build(bld): # we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c', 'mmap.c', 'mmapio.c'] if bld.env.DEST_BINFMT == 'pe': sources += ['pecoff.c'] elif bld.env.DEST_BINFMT == 'mac-o': sources += ['macho.c'] elif bld.env.DEST_BINFMT == 'elf': sources += ['elf.c'] else: sources += ['unknown.c'] task = bld.stlib( source = ['libbacktrace/' + i for i in sources], target = 'libbacktrace', features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '', use = 'EXTRAFLAGS lzma z zstd', includes = '. libbacktrace/', export_defines = 'HAVE_LIBBACKTRACE=1', export_includes = 'libbacktrace/' )