36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# File 'lib/tracer.rb', line 36
def parse_strace(file)
syscall_pattern = /^(\d+) +(\d+\.\d+) (\w+)\((.*?)\) += +(.*?) <(.*?)>$/
signal_pattern = /^(\d+) +(\d+\.\d+) --- (\w+) {(.*)} ---$/
unfinished_pattern = /^(\d+) +(\d+\.\d+) (\w+)\((.*?) +<unfinished \.\.\.>$/
resumed_pattern = /^(\d+) +(\d+\.\d+) <\.\.\. (\w+) resumed>(.*?)?\) += +(.*?) <(.*?)>$/
result = []
unfinished_syscalls = {}
file.each_line do |line|
case line
when syscall_pattern
pid, timestamp, syscall, args, retval, duration = $~.captures
result << Syscall.new(name: syscall, args: args, retval: retval, duration: duration, timestamp: timestamp, pid: pid)
when signal_pattern
pid, timestamp, signal, details = $~.captures
result << TraceSignal.new(name: signal, details: details, timestamp: timestamp, pid: pid)
when unfinished_pattern
pid, timestamp, syscall, args = $~.captures
key = [pid, syscall]
unfinished_syscalls[key] ||= []
unfinished_syscalls[key] << [timestamp, args]
when resumed_pattern
pid, timestamp, syscall, args2, retval, duration = $~.captures
key = [pid, syscall]
if unfinished_syscalls[key]&.any?
start_timestamp, args = unfinished_syscalls[key].pop
result << Syscall.new(name: syscall, args: "#{args}#{args2}", retval: retval, duration: duration, timestamp: start_timestamp, pid: pid)
else
puts "Resumed syscall without a start: #{line}"
end
else
puts "Attempted to parse unrecognized strace line: #{line}"
end
end
result
end
|