xref: /aosp_15_r20/external/perfetto/tools/extract_linux_syscall_tables (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1#!/usr/bin/env python3
2
3import contextlib
4import os
5import re
6import sys
7
8from urllib.request import urlopen
9
10PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
11SELF_PATH = os.path.relpath(__file__, PROJECT_ROOT).replace('\\', '/')
12
13syscalls = {}
14archs = ['arm64', 'arm32', 'x86', 'x86_64']
15
16
17def print_tables():
18  print('// DO NOT EDIT. Auto-generated by %s' % SELF_PATH)
19  print('#ifndef SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_')
20  print('#define SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_')
21  print('')
22  print('#include <stdint.h>')
23  print('')
24  print('#include "src/kernel_utils/syscall_table.h"')
25  print('')
26  print('namespace perfetto {')
27  print('')
28  # First of all merge all the syscall names from all tables and emit one big
29  # string with unique names.
30  syscall_names = set()
31  for arch in archs:
32    tab = syscalls[arch]
33    for i in range(max(tab.keys()) + 1):
34      syscall_names.add(tab.get(i, ''))
35  print('constexpr char kAllSyscalllNames[] =')
36  offset_by_name = {}
37  last_off = 0
38  for syscall_name in sorted(syscall_names):
39    if syscall_name in offset_by_name:
40      continue
41    print('  "%s\\0"' % syscall_name)
42    offset_by_name[syscall_name] = last_off
43    last_off += len(syscall_name) + 1
44  if last_off >= 0xffff:
45    raise Exception('SyscallTable::OffT must be increased to uint32_t')
46  print(';\n')
47  # Then print the individual tables.
48  for arch in archs:
49    tab = syscalls[arch]
50    print('struct SyscallTable_%s {' % arch)
51    print('  static constexpr const char* names = kAllSyscalllNames;')
52    print('  static constexpr SyscallTable::OffT offsets[] {')
53    for i in range(max(tab.keys()) + 1):
54      syscall_name = tab.get(i, '')
55      print('%d, // %d: %s' % (offset_by_name[syscall_name], i, syscall_name))
56    print('  };')
57    print('};\n')
58  print('}  // namespace perfetto')
59  print('#endif  // SRC_KERNEL_UTILS_SYSCALL_TABLE_GENERATED_H_')
60
61
62# Parses a .tbl file (new format).
63def parse_tlb(data):
64  table = {}
65  for line in data.splitlines():
66    line = line.strip()
67    if line.startswith('#') or not (line):
68      continue
69    parts = line.split()
70    table[int(parts[0])] = 'sys_' + parts[2]
71  return table
72
73
74# Parses a #define __NR_xx 1234 old-style unistd.h header.
75def parse_def(data):
76  table = {}
77  for line in data.splitlines():
78    m = re.match(r'^#define\s+__NR\d*?_(\w+)\s+(\d+)\s*$', line.strip())
79    if not m or m.group(1) == 'syscalls':  # __NR_syscalls is just a sentinel.
80      continue
81    table[int(m.group(2))] = 'sys_' + m.group(1)
82  return table
83
84
85def Main():
86  KSRC = 'https://raw.githubusercontent.com/torvalds/linux/v6.7/'
87
88  response = urlopen(KSRC + 'arch/x86/entry/syscalls/syscall_64.tbl')
89  syscalls['x86_64'] = parse_tlb(response.read().decode())
90
91  response = urlopen(KSRC + 'arch/x86/entry/syscalls/syscall_32.tbl')
92  syscalls['x86'] = parse_tlb(response.read().decode())
93
94  response = urlopen(KSRC + 'arch/arm/tools/syscall.tbl')
95  syscalls['arm32'] = parse_tlb(response.read().decode())
96
97  # From:
98  # arch/arm64/include/asm/unistd.h
99  #   -> arch/arm64/include/uapi/asm/unistd.h
100  #     -> include/uapi/asm-generic/unistd.h
101  response = urlopen(KSRC + 'include/uapi/asm-generic/unistd.h')
102  syscalls['arm64'] = parse_def(response.read().decode())
103
104  dst_file = os.path.join(PROJECT_ROOT, 'src', 'kernel_utils',
105                          'syscall_table_generated.h')
106  tmp_file = dst_file + '.tmp'
107
108  print('Writing ', dst_file)
109  with open(tmp_file, 'w') as f:
110    with contextlib.redirect_stdout(f):
111      print_tables()
112  os.rename(tmp_file, dst_file)
113
114  print('Running clang-format (might fail if depot_tools isn\'t in the PATH)')
115  os.system('clang-format -i ' + dst_file)
116
117if __name__ == '__main__':
118  sys.exit(Main())
119