#!/usr/bin/env python3
"""Generate many skeletal functions with a thick call graph spanning a
large address space to induce lld to create branch-islands for arm64.
"""
from __future__ import print_function
import random
import argparse
import string
from pprint import pprint
from math import factorial
from itertools import permutations
# This list comes from libSystem.tbd and contains a sizeable subset
# of dylib calls available for all MacOS target archs.
libSystem_calls = (
"__CurrentRuneLocale",
"__DefaultRuneLocale",
"__Exit",
"__NSGetArgc",
"__NSGetArgv",
"__NSGetEnviron",
"__NSGetMachExecuteHeader",
"__NSGetProgname",
"__PathLocale",
"__Read_RuneMagi",
"___Balloc_D2A",
"___Bfree_D2A",
"___ULtod_D2A",
"____mb_cur_max",
"____mb_cur_max_l",
"____runetype",
"____runetype_l",
"____tolower",
"____tolower_l",
"____toupper",
"____toupper_l",
"___add_ovflpage",
"___addel",
"___any_on_D2A",
"___assert_rtn",
"___b2d_D2A",
"___big_delete",
"___big_insert",
"___big_keydata",
"___big_return",
"___big_split",
"___bigtens_D2A",
"___bt_close",
"___bt_cmp",
"___bt_defcmp",
"___bt_defpfx",
"___bt_delete",
"___bt_dleaf",
"___bt_fd",
"___bt_free",
"___bt_get",
"___bt_new",
"___bt_open",
"___bt_pgin",
"___bt_pgout",
"___bt_put",
"___bt_ret",
"___bt_search",
"___bt_seq",
"___bt_setcur",
"___bt_split",
"___bt_sync",
"___buf_free",
"___call_hash",
"___cleanup",
"___cmp_D2A",
"___collate_equiv_match",
"___collate_load_error",
"___collate_lookup",
"___collate_lookup_l",
"___copybits_D2A",
"___cxa_atexit",
"___cxa_finalize",
"___cxa_finalize_ranges",
"___cxa_thread_atexit",
"___d2b_D2A",
"___dbpanic",
"___decrement_D2A",
"___default_hash",
"___default_utx",
"___delpair",
"___diff_D2A",
"___dtoa",
"___expand_table",
"___fflush",
"___fgetwc",
"___find_bigpair",
"___find_last_page",
"___fix_locale_grouping_str",
"___fread",
"___free_ovflpage",
"___freedtoa",
"___gdtoa",
"___gdtoa_locks",
"___get_buf",
"___get_page",
"___gethex_D2A",
"___getonlyClocaleconv",
"___hash_open",
"___hdtoa",
"___hexdig_D2A",
"___hexdig_init_D2A",
"___hexnan_D2A",
"___hi0bits_D2A",
"___hldtoa",
"___i2b_D2A",
"___ibitmap",
"___increment_D2A",
"___isctype",
"___istype",
"___istype_l",
"___ldtoa",
"___libc_init",
"___lo0bits_D2A",
"___log2",
"___lshift_D2A",
"___maskrune",
"___maskrune_l",
"___match_D2A",
"___mb_cur_max",
"___mb_sb_limit",
"___memccpy_chk",
"___memcpy_chk",
"___memmove_chk",
"___memset_chk",
"___mult_D2A",
"___multadd_D2A",
"___nrv_alloc_D2A",
"___opendir2",
"___ovfl_delete",
"___ovfl_get",
"___ovfl_put",
"___pow5mult_D2A",
"___put_page",
"___quorem_D2A",
"___ratio_D2A",
"___rec_close",
"___rec_delete",
"___rec_dleaf",
"___rec_fd",
"___rec_fmap",
"___rec_fpipe",
"___rec_get",
"___rec_iput",
"___rec_open",
"___rec_put",
"___rec_ret",
"___rec_search",
"___rec_seq",
"___rec_sync",
"___rec_vmap",
"___rec_vpipe",
"___reclaim_buf",
"___rshift_D2A",
"___rv_alloc_D2A",
"___s2b_D2A",
"___sF",
"___sclose",
"___sdidinit",
"___set_ones_D2A",
"___setonlyClocaleconv",
"___sflags",
"___sflush",
"___sfp",
"___sfvwrite",
"___sglue",
"___sinit",
"___slbexpand",
"___smakebuf",
"___snprintf_chk",
"___snprintf_object_size_chk",
"___split_page",
"___sprintf_chk",
"___sprintf_object_size_chk",
"___sread",
"___srefill",
"___srget",
"___sseek",
"___stack_chk_fail",
"___stack_chk_guard",
"___stderrp",
"___stdinp",
"___stdoutp",
"___stpcpy_chk",
"___stpncpy_chk",
"___strcat_chk",
"___strcp_D2A",
"___strcpy_chk",
"___strlcat_chk",
"___strlcpy_chk",
"___strncat_chk",
"___strncpy_chk",
"___strtodg",
"___strtopdd",
"___sum_D2A",
"___svfscanf",
"___swbuf",
"___swhatbuf",
"___swrite",
"___swsetup",
"___tens_D2A",
"___tinytens_D2A",
"___tolower",
"___tolower_l",
"___toupper",
"___toupper_l",
"___trailz_D2A",
"___ulp_D2A",
"___ungetc",
"___ungetwc",
"___vsnprintf_chk",
"___vsprintf_chk",
"___wcwidth",
"___wcwidth_l",
"__allocenvstate",
"__atexit_receipt",
"__c_locale",
"__cleanup",
"__closeutx",
"__copyenv",
"__cthread_init_routine",
"__deallocenvstate",
"__endutxent",
"__flockfile_debug_stub",
"__fseeko",
"__ftello",
"__fwalk",
"__getenvp",
"__getutxent",
"__getutxid",
"__getutxline",
"__inet_aton_check",
"__init_clock_port",
"__int_to_time",
"__libc_fork_child",
"__libc_initializer",
"__long_to_time",
"__mkpath_np",
"__mktemp",
"__openutx",
"__os_assert_log",
"__os_assert_log_ctx",
"__os_assumes_log",
"__os_assumes_log_ctx",
"__os_avoid_tail_call",
"__os_crash",
"__os_crash_callback",
"__os_crash_fmt",
"__os_debug_log",
"__os_debug_log_error_str",
"__putenvp",
"__pututxline",
"__rand48_add",
"__rand48_mult",
"__rand48_seed",
"__readdir_unlocked",
"__reclaim_telldir",
"__seekdir",
"__setenvp",
"__setutxent",
"__sigaction_nobind",
"__sigintr",
"__signal_nobind",
"__sigvec_nobind",
"__sread",
"__sseek",
"__subsystem_init",
"__swrite",
"__time32_to_time",
"__time64_to_time",
"__time_to_int",
"__time_to_long",
"__time_to_time32",
"__time_to_time64",
"__unsetenvp",
"__utmpxname",
"_a64l",
"_abort",
"_abort_report_np",
"_abs",
"_acl_add_flag_np",
"_acl_add_perm",
"_acl_calc_mask",
"_acl_clear_flags_np",
"_acl_clear_perms",
"_acl_copy_entry",
"_acl_copy_ext",
"_acl_copy_ext_native",
"_acl_copy_int",
"_acl_copy_int_native",
"_acl_create_entry",
"_acl_create_entry_np",
"_acl_delete_def_file",
"_acl_delete_entry",
"_acl_delete_fd_np",
"_acl_delete_file_np",
"_acl_delete_flag_np",
"_acl_delete_link_np",
"_acl_delete_perm",
"_acl_dup",
"_acl_free",
"_acl_from_text",
"_acl_get_entry",
"_acl_get_fd",
"_acl_get_fd_np",
"_acl_get_file",
"_acl_get_flag_np",
"_acl_get_flagset_np",
"_acl_get_link_np",
"_acl_get_perm_np",
"_acl_get_permset",
"_acl_get_permset_mask_np",
"_acl_get_qualifier",
"_acl_get_tag_type",
"_acl_init",
"_acl_maximal_permset_mask_np",
"_acl_set_fd",
"_acl_set_fd_np",
"_acl_set_file",
"_acl_set_flagset_np",
"_acl_set_link_np",
"_acl_set_permset",
"_acl_set_permset_mask_np",
"_acl_set_qualifier",
"_acl_set_tag_type",
"_acl_size",
"_acl_to_text",
"_acl_valid",
"_acl_valid_fd_np",
"_acl_valid_file_np",
"_acl_valid_link",
"_addr2ascii",
"_alarm",
"_alphasort",
"_arc4random",
"_arc4random_addrandom",
"_arc4random_buf",
"_arc4random_stir",
"_arc4random_uniform",
"_ascii2addr",
"_asctime",
"_asctime_r",
"_asprintf",
"_asprintf_l",
"_asxprintf",
"_asxprintf_exec",
"_atexit",
"_atexit_b",
"_atof",
"_atof_l",
"_atoi",
"_atoi_l",
"_atol",
"_atol_l",
"_atoll",
"_atoll_l",
"_backtrace",
"_backtrace_from_fp",
"_backtrace_image_offsets",
"_backtrace_symbols",
"_backtrace_symbols_fd",
"_basename",
"_basename_r",
"_bcopy",
"_brk",
"_bsd_signal",
"_bsearch",
"_bsearch_b",
"_btowc",
"_btowc_l",
"_catclose",
"_catgets",
"_catopen",
"_cfgetispeed",
"_cfgetospeed",
"_cfmakeraw",
"_cfsetispeed",
"_cfsetospeed",
"_cfsetspeed",
"_cgetcap",
"_cgetclose",
"_cgetent",
"_cgetfirst",
"_cgetmatch",
"_cgetnext",
"_cgetnum",
"_cgetset",
"_cgetstr",
"_cgetustr",
"_chmodx_np",
"_clearerr",
"_clearerr_unlocked",
"_clock",
"_clock_getres",
"_clock_gettime",
"_clock_gettime_nsec_np",
"_clock_port",
"_clock_sem",
"_clock_settime",
"_closedir",
"_compat_mode",
"_confstr",
"_copy_printf_domain",
"_creat",
"_crypt",
"_ctermid",
"_ctermid_r",
"_ctime",
"_ctime_r",
"_daemon",
"_daylight",
"_dbm_clearerr",
"_dbm_close",
"_dbm_delete",
"_dbm_dirfno",
"_dbm_error",
"_dbm_fetch",
"_dbm_firstkey",
"_dbm_nextkey",
"_dbm_open",
"_dbm_store",
"_dbopen",
"_devname",
"_devname_r",
"_difftime",
"_digittoint",
"_digittoint_l",
"_dirfd",
"_dirname",
"_dirname_r",
"_div",
"_dprintf",
"_dprintf_l",
"_drand48",
"_duplocale",
"_dxprintf",
"_dxprintf_exec",
"_ecvt",
"_encrypt",
"_endttyent",
"_endusershell",
"_endutxent",
"_endutxent_wtmp",
"_erand48",
"_err",
"_err_set_exit",
"_err_set_exit_b",
"_err_set_file",
"_errc",
"_errx",
"_execl",
"_execle",
"_execlp",
"_execv",
"_execvP",
"_execvp",
"_exit",
"_f_prealloc",
"_fchmodx_np",
"_fclose",
"_fcvt",
"_fdopen",
"_fdopendir",
"_feof",
"_feof_unlocked",
"_ferror",
"_ferror_unlocked",
"_fflagstostr",
"_fflush",
"_fgetc",
"_fgetln",
"_fgetpos",
"_fgetrune",
"_fgets",
"_fgetwc",
"_fgetwc_l",
"_fgetwln",
"_fgetwln_l",
"_fgetws",
"_fgetws_l",
"_fileno",
"_fileno_unlocked",
"_filesec_dup",
"_filesec_free",
"_filesec_get_property",
"_filesec_init",
"_filesec_query_property",
"_filesec_set_property",
"_filesec_unset_property",
"_flockfile",
"_fmemopen",
"_fmtcheck",
"_fmtmsg",
"_fnmatch",
"_fopen",
"_fork",
"_forkpty",
"_fparseln",
"_fprintf",
"_fprintf_l",
"_fpurge",
"_fputc",
"_fputrune",
"_fputs",
"_fputwc",
"_fputwc_l",
"_fputws",
"_fputws_l",
"_fread",
"_free_printf_comp",
"_free_printf_domain",
"_freelocale",
"_freopen",
"_fscanf",
"_fscanf_l",
"_fseek",
"_fseeko",
"_fsetpos",
"_fstatvfs",
"_fstatx_np",
"_fsync_volume_np",
"_ftell",
"_ftello",
"_ftime",
"_ftok",
"_ftrylockfile",
"_fts_children",
"_fts_close",
"_fts_open",
"_fts_open_b",
"_fts_read",
"_fts_set",
"_ftw",
"_fungetrune",
"_funlockfile",
"_funopen",
"_fwide",
"_fwprintf",
"_fwprintf_l",
"_fwrite",
"_fwscanf",
"_fwscanf_l",
"_fxprintf",
"_fxprintf_exec",
"_gcvt",
"_getbsize",
"_getc",
"_getc_unlocked",
"_getchar",
"_getchar_unlocked",
"_getcwd",
"_getdate",
"_getdate_err",
"_getdelim",
"_getdiskbyname",
"_getenv",
"_gethostid",
"_gethostname",
"_getipv4sourcefilter",
"_getlastlogx",
"_getlastlogxbyname",
"_getline",
"_getloadavg",
"_getlogin",
"_getlogin_r",
"_getmntinfo",
"_getmntinfo_r_np",
"_getmode",
"_getopt",
"_getopt_long",
"_getopt_long_only",
"_getpagesize",
"_getpass",
"_getpeereid",
"_getprogname",
"_gets",
"_getsourcefilter",
"_getsubopt",
"_gettimeofday",
"_getttyent",
"_getttynam",
"_getusershell",
"_getutmp",
"_getutmpx",
"_getutxent",
"_getutxent_wtmp",
"_getutxid",
"_getutxline",
"_getvfsbyname",
"_getw",
"_getwc",
"_getwc_l",
"_getwchar",
"_getwchar_l",
"_getwd",
"_glob",
"_glob_b",
"_globfree",
"_gmtime",
"_gmtime_r",
"_grantpt",
"_hash_create",
"_hash_destroy",
"_hash_purge",
"_hash_search",
"_hash_stats",
"_hash_traverse",
"_hcreate",
"_hdestroy",
"_heapsort",
"_heapsort_b",
"_hsearch",
"_imaxabs",
"_imaxdiv",
"_inet_addr",
"_inet_aton",
"_inet_lnaof",
"_inet_makeaddr",
"_inet_net_ntop",
"_inet_net_pton",
"_inet_neta",
"_inet_netof",
"_inet_network",
"_inet_nsap_addr",
"_inet_nsap_ntoa",
"_inet_ntoa",
"_inet_ntop",
"_inet_ntop4",
"_inet_ntop6",
"_inet_pton",
"_initstate",
"_insque",
"_isalnum",
"_isalnum_l",
"_isalpha",
"_isalpha_l",
"_isascii",
"_isatty",
"_isblank",
"_isblank_l",
"_iscntrl",
"_iscntrl_l",
"_isdigit",
"_isdigit_l",
"_isgraph",
"_isgraph_l",
"_ishexnumber",
"_ishexnumber_l",
"_isideogram",
"_isideogram_l",
"_islower",
"_islower_l",
"_isnumber",
"_isnumber_l",
"_isphonogram",
"_isphonogram_l",
"_isprint",
"_isprint_l",
"_ispunct",
"_ispunct_l",
"_isrune",
"_isrune_l",
"_isspace",
"_isspace_l",
"_isspecial",
"_isspecial_l",
"_isupper",
"_isupper_l",
"_iswalnum",
"_iswalnum_l",
"_iswalpha",
"_iswalpha_l",
"_iswascii",
"_iswblank",
"_iswblank_l",
"_iswcntrl",
"_iswcntrl_l",
"_iswctype",
"_iswctype_l",
"_iswdigit",
"_iswdigit_l",
"_iswgraph",
"_iswgraph_l",
"_iswhexnumber",
"_iswhexnumber_l",
"_iswideogram",
"_iswideogram_l",
"_iswlower",
"_iswlower_l",
"_iswnumber",
"_iswnumber_l",
"_iswphonogram",
"_iswphonogram_l",
"_iswprint",
"_iswprint_l",
"_iswpunct",
"_iswpunct_l",
"_iswrune",
"_iswrune_l",
"_iswspace",
"_iswspace_l",
"_iswspecial",
"_iswspecial_l",
"_iswupper",
"_iswupper_l",
"_iswxdigit",
"_iswxdigit_l",
"_isxdigit",
"_isxdigit_l",
"_jrand48",
"_kOSThermalNotificationPressureLevelName",
"_killpg",
"_l64a",
"_labs",
"_lchflags",
"_lchmod",
"_lcong48",
"_ldiv",
"_lfind",
"_link_addr",
"_link_ntoa",
"_llabs",
"_lldiv",
"_localeconv",
"_localeconv_l",
"_localtime",
"_localtime_r",
"_lockf",
"_login",
"_login_tty",
"_logout",
"_logwtmp",
"_lrand48",
"_lsearch",
"_lstatx_np",
"_lutimes",
"_mblen",
"_mblen_l",
"_mbmb",
"_mbrlen",
"_mbrlen_l",
"_mbrrune",
"_mbrtowc",
"_mbrtowc_l",
"_mbrune",
"_mbsinit",
"_mbsinit_l",
"_mbsnrtowcs",
"_mbsnrtowcs_l",
"_mbsrtowcs",
"_mbsrtowcs_l",
"_mbstowcs",
"_mbstowcs_l",
"_mbtowc",
"_mbtowc_l",
"_memmem",
"_memset_s",
"_mergesort",
"_mergesort_b",
"_mkdirx_np",
"_mkdtemp",
"_mkdtempat_np",
"_mkfifox_np",
"_mkostemp",
"_mkostemps",
"_mkostempsat_np",
"_mkpath_np",
"_mkpathat_np",
"_mkstemp",
"_mkstemp_dprotected_np",
"_mkstemps",
"_mkstempsat_np",
"_mktemp",
"_mktime",
"_monaddition",
"_moncontrol",
"_moncount",
"_moninit",
"_monitor",
"_monoutput",
"_monreset",
"_monstartup",
"_mpool_close",
"_mpool_filter",
"_mpool_get",
"_mpool_new",
"_mpool_open",
"_mpool_put",
"_mpool_sync",
"_mrand48",
"_nanosleep",
"_new_printf_comp",
"_new_printf_domain",
"_newlocale",
"_nextwctype",
"_nextwctype_l",
"_nftw",
"_nice",
"_nl_langinfo",
"_nl_langinfo_l",
"_nrand48",
"_nvis",
"_off32",
"_off64",
"_offtime",
"_open_memstream",
"_open_with_subsystem",
"_open_wmemstream",
"_opendev",
"_opendir",
"_openpty",
"_openx_np",
"_optarg",
"_opterr",
"_optind",
"_optopt",
"_optreset",
"_pause",
"_pclose",
"_perror",
"_popen",
"_posix2time",
"_posix_openpt",
"_posix_spawnp",
"_printf",
"_printf_l",
"_psignal",
"_psort",
"_psort_b",
"_psort_r",
"_ptsname",
"_ptsname_r",
"_putc",
"_putc_unlocked",
"_putchar",
"_putchar_unlocked",
"_putenv",
"_puts",
"_pututxline",
"_putw",
"_putwc",
"_putwc_l",
"_putwchar",
"_putwchar_l",
"_qsort",
"_qsort_b",
"_qsort_r",
"_querylocale",
"_radixsort",
"_raise",
"_rand",
"_rand_r",
"_random",
"_rb_tree_count",
"_rb_tree_find_node",
"_rb_tree_find_node_geq",
"_rb_tree_find_node_leq",
"_rb_tree_init",
"_rb_tree_insert_node",
"_rb_tree_iterate",
"_rb_tree_remove_node",
"_readdir",
"_readdir_r",
"_readpassphrase",
"_reallocf",
"_realpath",
"_recv",
"_regcomp",
"_regcomp_l",
"_regerror",
"_regexec",
"_regfree",
"_register_printf_domain_function",
"_register_printf_domain_render_std",
"_regncomp",
"_regncomp_l",
"_regnexec",
"_regwcomp",
"_regwcomp_l",
"_regwexec",
"_regwncomp",
"_regwncomp_l",
"_regwnexec",
"_remove",
"_remque",
"_rewind",
"_rewinddir",
"_rindex",
"_rpmatch",
"_sbrk",
"_scandir",
"_scandir_b",
"_scanf",
"_scanf_l",
"_seed48",
"_seekdir",
"_send",
"_setbuf",
"_setbuffer",
"_setenv",
"_sethostid",
"_sethostname",
"_setinvalidrune",
"_setipv4sourcefilter",
"_setkey",
"_setlinebuf",
"_setlocale",
"_setlogin",
"_setmode",
"_setpgrp",
"_setprogname",
"_setrgid",
"_setruid",
"_setrunelocale",
"_setsourcefilter",
"_setstate",
"_settimeofday",
"_setttyent",
"_setusershell",
"_setutxent",
"_setutxent_wtmp",
"_setvbuf",
"_sigaction",
"_sigaddset",
"_sigaltstack",
"_sigblock",
"_sigdelset",
"_sigemptyset",
"_sigfillset",
"_sighold",
"_sigignore",
"_siginterrupt",
"_sigismember",
"_signal",
"_sigpause",
"_sigrelse",
"_sigset",
"_sigsetmask",
"_sigvec",
"_skip",
"_sl_add",
"_sl_find",
"_sl_free",
"_sl_init",
"_sleep",
"_snprintf",
"_snprintf_l",
"_snvis",
"_sockatmark",
"_sprintf",
"_sprintf_l",
"_sradixsort",
"_srand",
"_srand48",
"_sranddev",
"_srandom",
"_srandomdev",
"_sscanf",
"_sscanf_l",
"_stat_with_subsystem",
"_statvfs",
"_statx_np",
"_stpcpy",
"_stpncpy",
"_strcasecmp",
"_strcasecmp_l",
"_strcasestr",
"_strcasestr_l",
"_strcat",
"_strcoll",
"_strcoll_l",
"_strcspn",
"_strdup",
"_strenvisx",
"_strerror",
"_strerror_r",
"_strfmon",
"_strfmon_l",
"_strftime",
"_strftime_l",
"_strmode",
"_strncasecmp",
"_strncasecmp_l",
"_strncat",
"_strndup",
"_strnstr",
"_strnunvis",
"_strnunvisx",
"_strnvis",
"_strnvisx",
"_strpbrk",
"_strptime",
"_strptime_l",
"_strrchr",
"_strsenvisx",
"_strsep",
"_strsignal",
"_strsignal_r",
"_strsnvis",
"_strsnvisx",
"_strspn",
"_strsvis",
"_strsvisx",
"_strtod",
"_strtod_l",
"_strtof",
"_strtof_l",
"_strtofflags",
"_strtoimax",
"_strtoimax_l",
"_strtok",
"_strtok_r",
"_strtol",
"_strtol_l",
"_strtold",
"_strtold_l",
"_strtoll",
"_strtoll_l",
"_strtonum",
"_strtoq",
"_strtoq_l",
"_strtoul",
"_strtoul_l",
"_strtoull",
"_strtoull_l",
"_strtoumax",
"_strtoumax_l",
"_strtouq",
"_strtouq_l",
"_strunvis",
"_strunvisx",
"_strvis",
"_strvisx",
"_strxfrm",
"_strxfrm_l",
"_suboptarg",
"_svis",
"_swab",
"_swprintf",
"_swprintf_l",
"_swscanf",
"_swscanf_l",
"_sxprintf",
"_sxprintf_exec",
"_sync_volume_np",
"_sys_errlist",
"_sys_nerr",
"_sys_siglist",
"_sys_signame",
"_sysconf",
"_sysctl",
"_sysctlbyname",
"_sysctlnametomib",
"_system",
"_tcdrain",
"_tcflow",
"_tcflush",
"_tcgetattr",
"_tcgetpgrp",
"_tcgetsid",
"_tcsendbreak",
"_tcsetattr",
"_tcsetpgrp",
"_tdelete",
"_telldir",
"_tempnam",
"_tfind",
"_thread_stack_pcs",
"_time",
"_time2posix",
"_timegm",
"_timelocal",
"_timeoff",
"_times",
"_timespec_get",
"_timezone",
"_timingsafe_bcmp",
"_tmpfile",
"_tmpnam",
"_toascii",
"_tolower",
"_tolower_l",
"_toupper",
"_toupper_l",
"_towctrans",
"_towctrans_l",
"_towlower",
"_towlower_l",
"_towupper",
"_towupper_l",
"_tre_ast_new_catenation",
"_tre_ast_new_iter",
"_tre_ast_new_literal",
"_tre_ast_new_node",
"_tre_ast_new_union",
"_tre_compile",
"_tre_fill_pmatch",
"_tre_free",
"_tre_mem_alloc_impl",
"_tre_mem_destroy",
"_tre_mem_new_impl",
"_tre_parse",
"_tre_stack_destroy",
"_tre_stack_new",
"_tre_stack_num_objects",
"_tre_tnfa_run_backtrack",
"_tre_tnfa_run_parallel",
"_tsearch",
"_ttyname",
"_ttyname_r",
"_ttyslot",
"_twalk",
"_tzname",
"_tzset",
"_tzsetwall",
"_ualarm",
"_ulimit",
"_umaskx_np",
"_uname",
"_ungetc",
"_ungetwc",
"_ungetwc_l",
"_unlockpt",
"_unsetenv",
"_unvis",
"_uselocale",
"_usleep",
"_utime",
"_utmpxname",
"_uuid_clear",
"_uuid_compare",
"_uuid_copy",
"_uuid_generate",
"_uuid_generate_random",
"_uuid_generate_time",
"_uuid_is_null",
"_uuid_pack",
"_uuid_parse",
"_uuid_unpack",
"_uuid_unparse",
"_uuid_unparse_lower",
"_uuid_unparse_upper",
"_vasprintf",
"_vasprintf_l",
"_vasxprintf",
"_vasxprintf_exec",
"_vdprintf",
"_vdprintf_l",
"_vdxprintf",
"_vdxprintf_exec",
"_verr",
"_verrc",
"_verrx",
"_vfprintf",
"_vfprintf_l",
"_vfscanf",
"_vfscanf_l",
"_vfwprintf",
"_vfwprintf_l",
"_vfwscanf",
"_vfwscanf_l",
"_vfxprintf",
"_vfxprintf_exec",
"_vis",
"_vprintf",
"_vprintf_l",
"_vscanf",
"_vscanf_l",
"_vsnprintf",
"_vsnprintf_l",
"_vsprintf",
"_vsprintf_l",
"_vsscanf",
"_vsscanf_l",
"_vswprintf",
"_vswprintf_l",
"_vswscanf",
"_vswscanf_l",
"_vsxprintf",
"_vsxprintf_exec",
"_vwarn",
"_vwarnc",
"_vwarnx",
"_vwprintf",
"_vwprintf_l",
"_vwscanf",
"_vwscanf_l",
"_vxprintf",
"_vxprintf_exec",
"_wait",
"_wait3",
"_waitpid",
"_warn",
"_warnc",
"_warnx",
"_wcpcpy",
"_wcpncpy",
"_wcrtomb",
"_wcrtomb_l",
"_wcscasecmp",
"_wcscasecmp_l",
"_wcscat",
"_wcschr",
"_wcscmp",
"_wcscoll",
"_wcscoll_l",
"_wcscpy",
"_wcscspn",
"_wcsdup",
"_wcsftime",
"_wcsftime_l",
"_wcslcat",
"_wcslcpy",
"_wcslen",
"_wcsncasecmp",
"_wcsncasecmp_l",
"_wcsncat",
"_wcsncmp",
"_wcsncpy",
"_wcsnlen",
"_wcsnrtombs",
"_wcsnrtombs_l",
"_wcspbrk",
"_wcsrchr",
"_wcsrtombs",
"_wcsrtombs_l",
"_wcsspn",
"_wcsstr",
"_wcstod",
"_wcstod_l",
"_wcstof",
"_wcstof_l",
"_wcstoimax",
"_wcstoimax_l",
"_wcstok",
"_wcstol",
"_wcstol_l",
"_wcstold",
"_wcstold_l",
"_wcstoll",
"_wcstoll_l",
"_wcstombs",
"_wcstombs_l",
"_wcstoul",
"_wcstoul_l",
"_wcstoull",
"_wcstoull_l",
"_wcstoumax",
"_wcstoumax_l",
"_wcswidth",
"_wcswidth_l",
"_wcsxfrm",
"_wcsxfrm_l",
"_wctob",
"_wctob_l",
"_wctomb",
"_wctomb_l",
"_wctrans",
"_wctrans_l",
"_wctype",
"_wctype_l",
"_wcwidth",
"_wcwidth_l",
"_wmemchr",
"_wmemcmp",
"_wmemcpy",
"_wmemmove",
"_wmemset",
"_wordexp",
"_wordfree",
"_wprintf",
"_wprintf_l",
"_wscanf",
"_wscanf_l",
"_wtmpxname",
"_xprintf",
"_xprintf_exec",
)
def print_here_head(name):
print(
"""\
(tee %s.s |llvm-mc -filetype=obj -triple %s -o %s.o) <<END_OF_FILE &"""
% (name, triple, name)
)
def print_here_tail():
print(
"""\
END_OF_FILE
"""
)
def print_function_head(p2align, name):
if args.os == "macos":
print(
"""\
.section __TEXT,__text,regular,pure_instructions
.p2align %d, 0x90
.globl _%s
_%s:"""
% (p2align, name, name)
)
elif args.os == "windows":
print(
"""\
.text
.def %s;
.scl 2;
.type 32;
.endef
.globl %s
.p2align %d
%s:"""
% (name, name, p2align, name)
)
elif args.os == "linux":
print(
"""\
.text
.p2align %d
.globl %s
%s:"""
% (p2align, name, name)
)
def print_function(addr, size, addrs):
name = "x%08x" % addr
calls = random.randint(0, size >> 12)
print_here_head(name)
print(
"""\
### %s size=%x calls=%x"""
% (name, size, calls)
)
print_function_head(4, name)
for i in range(calls):
print(
" bl %sx%08x\n .p2align 4"
% (
"_" if args.os == "macos" else "",
addrs[random.randint(0, len(addrs) - 1)],
)
)
if args.os == "macos":
print(
" bl %s\n .p2align 4"
% (libSystem_calls[random.randint(0, len(libSystem_calls) - 1)])
)
fill = size - 4 * (calls + 1)
assert fill > 0
print(
"""\
.fill 0x%x
ret"""
% (fill)
)
print_here_tail()
def random_seed():
"""Generate a seed that can easily be passed back in via --seed=STRING"""
return "".join(random.choice(string.ascii_lowercase) for i in range(10))
def generate_sizes(base, megabytes):
total = 0
while total < megabytes:
size = random.randint(0x100, 0x10000) * 0x10
yield size
total += size
def generate_addrs(addr, sizes):
i = 0
while i < len(sizes):
yield addr
addr += sizes[i]
i += 1
def main():
parser = argparse.ArgumentParser(
description=__doc__,
epilog="""\
WRITEME
""",
)
parser.add_argument(
"--seed",
type=str,
default=random_seed(),
help="Seed the random number generator",
)
parser.add_argument(
"--size",
type=int,
default=None,
help="Total text size to generate, in megabytes",
)
parser.add_argument(
"--os", type=str, default="macos", help="Target OS: macos, windows, or linux"
)
global args
args = parser.parse_args()
triples = {
"macos": "arm64-apple-macos",
"linux": "aarch64-pc-linux",
"windows": "aarch64-pc-windows",
}
global triple
triple = triples.get(args.os)
print(
"""\
### seed=%s triple=%s
"""
% (args.seed, triple)
)
random.seed(args.seed)
base = 0x4010
megabytes = (int(args.size) if args.size else 512) * 1024 * 1024
sizes = [size for size in generate_sizes(base, megabytes)]
addrs = [addr for addr in generate_addrs(base, sizes)]
for i in range(len(addrs)):
print_function(addrs[i], sizes[i], addrs)
print_here_head("main")
print(
"""\
### _x%08x
"""
% (addrs[-1] + sizes[-1])
)
print_function_head(14 if args.os == "macos" else 4, "main")
print(" ret")
print_here_tail()
print("wait")
if __name__ == "__main__":
main()