forked from OSchip/llvm-project
138 lines
4.1 KiB
Python
Executable File
138 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
"""Generate skeletal functions with a variety .cfi_ directives.
|
|
The purpose is to produce object-file test inputs to lld with a
|
|
variety of compact unwind encodings.
|
|
"""
|
|
from __future__ import print_function
|
|
import random
|
|
import argparse
|
|
import string
|
|
from math import factorial
|
|
from itertools import permutations
|
|
|
|
lsda_n = 0
|
|
lsda_odds = 0.0
|
|
func_size_low = 0x10
|
|
func_size_high = 0x100
|
|
saved_regs = ["%r15", "%r14", "%r13", "%r12", "%rbx"]
|
|
saved_regs_combined = list(list(permutations(saved_regs, i))
|
|
for i in range(0,6))
|
|
|
|
def print_function(name):
|
|
global lsda_odds
|
|
have_lsda = (random.random() < lsda_odds)
|
|
frame_size = random.randint(4, 64) * 16
|
|
frame_offset = -random.randint(0, (frame_size/16 - 4)) * 16
|
|
reg_count = random.randint(0, 5)
|
|
reg_combo = random.randint(0, factorial(reg_count) - 1)
|
|
regs_saved = saved_regs_combined[reg_count][reg_combo]
|
|
global func_size_low, func_size_high
|
|
func_size = random.randint(func_size_low, func_size_high) * 0x10
|
|
func_size_high += 1
|
|
if func_size_high % 0x10 == 0:
|
|
func_size_low += 1
|
|
|
|
print("""\
|
|
### %s regs=%d frame=%d lsda=%s size=%d
|
|
.section __TEXT,__text,regular,pure_instructions
|
|
.p2align 4, 0x90
|
|
.globl %s
|
|
%s:
|
|
.cfi_startproc""" % (
|
|
name, reg_count, frame_size, have_lsda, func_size, name, name))
|
|
if have_lsda:
|
|
global lsda_n
|
|
lsda_n += 1
|
|
print("""\
|
|
.cfi_personality 155, ___gxx_personality_v0
|
|
.cfi_lsda 16, Lexception%d""" % lsda_n)
|
|
print("""\
|
|
pushq %%rbp
|
|
.cfi_def_cfa_offset %d
|
|
.cfi_offset %%rbp, %d
|
|
movq %%rsp, %%rbp
|
|
.cfi_def_cfa_register %%rbp""" % (frame_size, frame_offset + 6*8))
|
|
for i in range(reg_count):
|
|
print(".cfi_offset %s, %d" % (regs_saved[i], frame_offset+(i*8)))
|
|
print("""\
|
|
.fill %d
|
|
popq %%rbp
|
|
retq
|
|
.cfi_endproc
|
|
""" % (func_size - 6))
|
|
|
|
if have_lsda:
|
|
print("""\
|
|
.section __TEXT,__gcc_except_tab
|
|
.p2align 2
|
|
Lexception%d:
|
|
.space 0x10
|
|
""" % lsda_n)
|
|
return func_size
|
|
|
|
def random_seed():
|
|
"""Generate a seed that can easily be passsed back in via --seed=STRING"""
|
|
return ''.join(random.choice(string.ascii_lowercase) for i in range(10))
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description=__doc__,
|
|
epilog="""\
|
|
Function sizes begin small then monotonically increase. The goal is
|
|
to produce early pages that are full and later pages that are less
|
|
than full, in order to test handling for both cases. Full pages
|
|
contain the maximum of 1021 compact unwind entries for a total page
|
|
size = 4 KiB.
|
|
|
|
Use --pages=N or --functions=N to control the size of the output.
|
|
Default is --pages=2, meaning produce at least two full pages of
|
|
compact unwind entries, plus some more. The calculatation is sloppy.
|
|
""")
|
|
parser.add_argument('--seed', type=str, default=random_seed(),
|
|
help='Seed the random number generator')
|
|
parser.add_argument('--pages', type=int, default=2,
|
|
help='Number of compact-unwind pages')
|
|
parser.add_argument('--functions', type=int, default=None,
|
|
help='Number of functions to generate')
|
|
parser.add_argument('--encodings', type=int, default=127,
|
|
help='Maximum number of unique unwind encodings (default = 127)')
|
|
parser.add_argument('--lsda', type=int, default=0,
|
|
help='Percentage of functions with personality & LSDA (default = 10')
|
|
args = parser.parse_args()
|
|
random.seed(args.seed)
|
|
p2align = 14
|
|
global lsda_odds
|
|
lsda_odds = args.lsda / 100.0
|
|
|
|
print("""\
|
|
### seed=%s lsda=%f p2align=%d
|
|
.section __TEXT,__text,regular,pure_instructions
|
|
.p2align %d, 0x90
|
|
""" % (args.seed, lsda_odds, p2align, p2align))
|
|
|
|
size = 0
|
|
base = (1 << p2align)
|
|
if args.functions:
|
|
for n in range(args.functions):
|
|
size += print_function("x%08x" % (size+base))
|
|
else:
|
|
while size < (args.pages << 24):
|
|
size += print_function("x%08x" % (size+base))
|
|
|
|
print("""\
|
|
.section __TEXT,__text,regular,pure_instructions
|
|
.globl _main
|
|
.p2align 4, 0x90
|
|
_main:
|
|
retq
|
|
|
|
.p2align 4, 0x90
|
|
___gxx_personality_v0:
|
|
retq
|
|
""")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|