3 """Generate many skeletal functions with a thick call graph spanning a
4 large address space to induce lld to create branch-islands for arm64.
7 from __future__
import print_function
11 from pprint
import pprint
12 from math
import factorial
13 from itertools
import permutations
15 # This list comes from libSystem.tbd and contains a sizeable subset
16 # of dylib calls available for all MacOS target archs.
18 "__CurrentRuneLocale",
19 "__DefaultRuneLocale",
24 "__NSGetMachExecuteHeader",
74 "___collate_equiv_match",
75 "___collate_load_error",
77 "___collate_lookup_l",
81 "___cxa_finalize_ranges",
82 "___cxa_thread_atexit",
96 "___fix_locale_grouping_str",
105 "___getonlyClocaleconv",
109 "___hexdig_init_D2A",
168 "___setonlyClocaleconv",
178 "___snprintf_object_size_chk",
181 "___sprintf_object_size_chk",
187 "___stack_chk_guard",
228 "__cthread_init_routine",
231 "__flockfile_debug_stub",
243 "__libc_initializer",
249 "__os_assert_log_ctx",
251 "__os_assumes_log_ctx",
252 "__os_avoid_tail_call",
254 "__os_crash_callback",
257 "__os_debug_log_error_str",
263 "__readdir_unlocked",
268 "__sigaction_nobind",
291 "_acl_clear_flags_np",
295 "_acl_copy_ext_native",
297 "_acl_copy_int_native",
299 "_acl_create_entry_np",
300 "_acl_delete_def_file",
303 "_acl_delete_file_np",
304 "_acl_delete_flag_np",
305 "_acl_delete_link_np",
315 "_acl_get_flagset_np",
319 "_acl_get_permset_mask_np",
320 "_acl_get_qualifier",
323 "_acl_maximal_permset_mask_np",
327 "_acl_set_flagset_np",
330 "_acl_set_permset_mask_np",
331 "_acl_set_qualifier",
337 "_acl_valid_file_np",
343 "_arc4random_addrandom",
346 "_arc4random_uniform",
365 "_backtrace_from_fp",
366 "_backtrace_image_offsets",
367 "_backtrace_symbols",
368 "_backtrace_symbols_fd",
399 "_clearerr_unlocked",
403 "_clock_gettime_nsec_np",
410 "_copy_printf_domain",
492 "_filesec_get_property",
494 "_filesec_query_property",
495 "_filesec_set_property",
496 "_filesec_unset_property",
518 "_free_printf_domain",
566 "_getipv4sourcefilter",
568 "_getlastlogxbyname",
718 "_kOSThermalNotificationPressureLevelName",
777 "_mkstemp_dprotected_np",
800 "_new_printf_domain",
814 "_open_with_subsystem",
862 "_rb_tree_find_node",
863 "_rb_tree_find_node_geq",
864 "_rb_tree_find_node_leq",
866 "_rb_tree_insert_node",
868 "_rb_tree_remove_node",
880 "_register_printf_domain_function",
881 "_register_printf_domain_render_std",
911 "_setipv4sourcefilter",
967 "_stat_with_subsystem",
1075 "_thread_stack_pcs",
1098 "_tre_ast_new_catenation",
1099 "_tre_ast_new_iter",
1100 "_tre_ast_new_literal",
1101 "_tre_ast_new_node",
1102 "_tre_ast_new_union",
1106 "_tre_mem_alloc_impl",
1108 "_tre_mem_new_impl",
1110 "_tre_stack_destroy",
1112 "_tre_stack_num_objects",
1113 "_tre_tnfa_run_backtrack",
1114 "_tre_tnfa_run_parallel",
1141 "_uuid_generate_random",
1142 "_uuid_generate_time",
1148 "_uuid_unparse_lower",
1149 "_uuid_unparse_upper",
1288 def print_here_head(name
):
1291 (tee %s.s |llvm-mc -filetype=obj -triple %s -o %s.o) <<END_OF_FILE &"""
1292 % (name
, triple
, name
)
1296 def print_here_tail():
1304 def print_function_head(p2align
, name
):
1305 if args
.os
== "macos":
1308 .section __TEXT,__text,regular,pure_instructions
1312 % (p2align
, name
, name
)
1314 elif args
.os
== "windows":
1325 % (name
, name
, p2align
, name
)
1327 elif args
.os
== "linux":
1334 % (p2align
, name
, name
)
1338 def print_function(addr
, size
, addrs
):
1339 name
= "x%08x" % addr
1340 calls
= random
.randint(0, size
>> 12)
1341 print_here_head(name
)
1344 ### %s size=%x calls=%x"""
1345 % (name
, size
, calls
)
1347 print_function_head(4, name
)
1348 for i
in range(calls
):
1350 " bl %sx%08x\n .p2align 4"
1352 "_" if args
.os
== "macos" else "",
1353 addrs
[random
.randint(0, len(addrs
) - 1)],
1356 if args
.os
== "macos":
1358 " bl %s\n .p2align 4"
1359 % (libSystem_calls
[random
.randint(0, len(libSystem_calls
) - 1)])
1361 fill
= size
- 4 * (calls
+ 1)
1373 """Generate a seed that can easily be passed back in via --seed=STRING"""
1374 return "".join(random
.choice(string
.ascii_lowercase
) for i
in range(10))
1377 def generate_sizes(base
, megabytes
):
1379 while total
< megabytes
:
1380 size
= random
.randint(0x100, 0x10000) * 0x10
1385 def generate_addrs(addr
, sizes
):
1387 while i
< len(sizes
):
1394 parser
= argparse
.ArgumentParser(
1395 description
=__doc__
,
1400 parser
.add_argument(
1403 default
=random_seed(),
1404 help="Seed the random number generator",
1406 parser
.add_argument(
1410 help="Total text size to generate, in megabytes",
1412 parser
.add_argument(
1413 "--os", type=str, default
="macos", help="Target OS: macos, windows, or linux"
1416 args
= parser
.parse_args()
1418 "macos": "arm64-apple-macos",
1419 "linux": "aarch64-pc-linux",
1420 "windows": "aarch64-pc-windows",
1423 triple
= triples
.get(args
.os
)
1427 ### seed=%s triple=%s
1429 % (args
.seed
, triple
)
1432 random
.seed(args
.seed
)
1435 megabytes
= (int(args
.size
) if args
.size
else 512) * 1024 * 1024
1436 sizes
= [size
for size
in generate_sizes(base
, megabytes
)]
1437 addrs
= [addr
for addr
in generate_addrs(base
, sizes
)]
1439 for i
in range(len(addrs
)):
1440 print_function(addrs
[i
], sizes
[i
], addrs
)
1442 print_here_head("main")
1447 % (addrs
[-1] + sizes
[-1])
1449 print_function_head(14 if args
.os
== "macos" else 4, "main")
1455 if __name__
== "__main__":