Although you can use several tools, I would suggest you to use GDB if possible, since it has a built-in feature of breaking at each function call.
Now, what you can do, is to run your program two times - first, without pressing buttons, and second, with doing so. I'm attatching a python script that will print each function call with a number of calls to it, to the file named output. Feel free to use it for your purposes:
#!/usr/bin/env python3
import gdb
import re
breakpoints = []
gdb.execute('rbreak', to_string=True)
gdb.execute('run', to_string=True)
try:
while True:
a = gdb.execute('continue', to_string=True)
reg = gdb.execute('info registers rip', to_string=True)
b = reg.split()[1][2:]
f = reg.split()[3]
c = gdb.execute('info breakpoints', to_string=True).split('\n')
d = [s for s in c if b in s]
if len(d) > 1:
sys.exit(1)
e = d[0].split()[0].split('.')[0]
gdb.execute('disable breakpoints ' + e)
breakpoints.append(e)
breakpoints.append(f)
except:
f = open("output", "w+")
[f.write(b + '\n') for b in breakpoints]
f.close()
You can invoke it by running gdb name_of_your_program
and then source gdb.py
assuming that the script name is gdb.py.
After doing this two times, you will get two files: one containing all function calls, while not pressing buttons, and the other one containing function calls when buttons are being pressed. Simply running diff
on this files will reveal which functions are responsible for button press handling.
If, for some reason you cannot use GDB, this answer shows the way it can be done in radare2.