blob: f9654ed4f02d1280d851e87e14ab5bf7da26e9be [file] [log] [blame]
Mike Frysinger69cb41d2013-08-11 20:08:19 -04001# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Generate minidump symbols for use by the Crash server.
6
7Note: This should be run inside the chroot.
8
9This produces files in the breakpad format required by minidump_stackwalk and
10the crash server to dump stack information.
11
12Basically it scans all the split .debug files in /build/$BOARD/usr/lib/debug/
13and converts them over using the `dump_syms` programs. Those plain text .sym
14files are then stored in /build/$BOARD/usr/lib/debug/breakpad/.
15
Mike Frysinger02e1e072013-11-10 22:11:34 -050016If you want to actually upload things, see upload_symbols.py.
17"""
Mike Frysinger69cb41d2013-08-11 20:08:19 -040018
19import collections
20import ctypes
Chris McDonaldb55b7032021-06-17 16:41:32 -060021import logging
Mike Frysinger69cb41d2013-08-11 20:08:19 -040022import multiprocessing
23import os
Mike Frysinger69cb41d2013-08-11 20:08:19 -040024
Chris McDonaldb55b7032021-06-17 16:41:32 -060025from chromite.cbuildbot import cbuildbot_alerts
Mike Frysinger06a51c82021-04-06 11:39:17 -040026from chromite.lib import build_target_lib
Mike Frysinger69cb41d2013-08-11 20:08:19 -040027from chromite.lib import commandline
28from chromite.lib import cros_build_lib
29from chromite.lib import osutils
30from chromite.lib import parallel
Mike Frysinger96ad3f22014-04-24 23:27:27 -040031from chromite.lib import signals
Alex Klein1809f572021-09-09 11:28:37 -060032from chromite.utils import file_util
Mike Frysinger69cb41d2013-08-11 20:08:19 -040033
Mike Frysinger807d8282022-04-28 22:45:17 -040034
Stephen Boydfc1c8032021-10-06 20:58:37 -070035# Elf files that don't exist but have a split .debug file installed.
36ALLOWED_DEBUG_ONLY_FILES = {
37 'boot/vmlinux',
38}
Mike Frysinger69cb41d2013-08-11 20:08:19 -040039
40SymbolHeader = collections.namedtuple('SymbolHeader',
41 ('cpu', 'id', 'name', 'os',))
42
43
44def ReadSymsHeader(sym_file):
45 """Parse the header of the symbol file
46
47 The first line of the syms file will read like:
48 MODULE Linux arm F4F6FA6CCBDEF455039C8DE869C8A2F40 blkid
49
50 https://code.google.com/p/google-breakpad/wiki/SymbolFiles
51
52 Args:
53 sym_file: The symbol file to parse
Mike Frysinger1a736a82013-12-12 01:50:59 -050054
Mike Frysinger69cb41d2013-08-11 20:08:19 -040055 Returns:
56 A SymbolHeader object
Mike Frysinger1a736a82013-12-12 01:50:59 -050057
Mike Frysinger69cb41d2013-08-11 20:08:19 -040058 Raises:
59 ValueError if the first line of |sym_file| is invalid
60 """
Alex Klein1809f572021-09-09 11:28:37 -060061 with file_util.Open(sym_file, 'rb') as f:
Mike Frysinger374ba4f2019-11-14 23:45:15 -050062 header = f.readline().decode('utf-8').split()
Mike Frysinger69cb41d2013-08-11 20:08:19 -040063
64 if header[0] != 'MODULE' or len(header) != 5:
65 raise ValueError('header of sym file is invalid')
Mike Frysinger50cedd32014-02-09 23:03:18 -050066
Mike Frysinger69cb41d2013-08-11 20:08:19 -040067 return SymbolHeader(os=header[1], cpu=header[2], id=header[3], name=header[4])
68
69
70def GenerateBreakpadSymbol(elf_file, debug_file=None, breakpad_dir=None,
Don Garrett39f0dc62015-09-24 15:18:31 -070071 strip_cfi=False, num_errors=None,
72 dump_syms_cmd='dump_syms'):
Mike Frysinger69cb41d2013-08-11 20:08:19 -040073 """Generate the symbols for |elf_file| using |debug_file|
74
75 Args:
76 elf_file: The file to dump symbols for
77 debug_file: Split debug file to use for symbol information
78 breakpad_dir: The dir to store the output symbol file in
Mike Frysinger69cb41d2013-08-11 20:08:19 -040079 strip_cfi: Do not generate CFI data
80 num_errors: An object to update with the error count (needs a .value member)
Don Garrett39f0dc62015-09-24 15:18:31 -070081 dump_syms_cmd: Command to use for dumping symbols.
Mike Frysinger1a736a82013-12-12 01:50:59 -050082
Mike Frysinger69cb41d2013-08-11 20:08:19 -040083 Returns:
Mike Frysinger5c219f02021-06-09 01:25:33 -040084 The name of symbol file written out on success, or the failure count.
Mike Frysinger69cb41d2013-08-11 20:08:19 -040085 """
Don Garrette548cff2015-09-23 14:36:21 -070086 assert breakpad_dir
Mike Frysinger69cb41d2013-08-11 20:08:19 -040087 if num_errors is None:
88 num_errors = ctypes.c_int()
Stephen Boydfc1c8032021-10-06 20:58:37 -070089 debug_file_only = not os.path.exists(elf_file)
Mike Frysinger69cb41d2013-08-11 20:08:19 -040090
Mike Frysinger2808deb2016-01-28 01:22:13 -050091 cmd_base = [dump_syms_cmd, '-v']
Mike Frysinger69cb41d2013-08-11 20:08:19 -040092 if strip_cfi:
93 cmd_base += ['-c']
94 # Some files will not be readable by non-root (e.g. set*id /bin/su).
95 needs_sudo = not os.access(elf_file, os.R_OK)
96
97 def _DumpIt(cmd_args):
98 if needs_sudo:
Mike Frysinger45602c72019-09-22 02:15:11 -040099 run_command = cros_build_lib.sudo_run
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400100 else:
Mike Frysinger45602c72019-09-22 02:15:11 -0400101 run_command = cros_build_lib.run
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400102 return run_command(
Mike Frysinger0282d222019-12-17 17:15:48 -0500103 cmd_base + cmd_args, stderr=True, stdout=temp.name,
Mike Frysingerf5a3b2d2019-12-12 14:36:17 -0500104 check=False, debug_level=logging.DEBUG)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400105
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700106 def _CrashCheck(result, file_or_files, msg):
107 if result.returncode:
Chris McDonaldb55b7032021-06-17 16:41:32 -0600108 cbuildbot_alerts.PrintBuildbotStepWarnings()
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700109 if result.returncode < 0:
110 logging.warning('dump_syms %s crashed with %s; %s',
111 file_or_files, signals.StrSignal(-result.returncode),
112 msg)
113 else:
114 logging.warning('dump_syms %s returned %d; %s',
115 file_or_files, result.returncode, msg)
116 logging.warning('output:\n%s', result.stderr.decode('utf-8'))
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400117
118 osutils.SafeMakedirs(breakpad_dir)
Mike Frysinger374ba4f2019-11-14 23:45:15 -0500119 with cros_build_lib.UnbufferedNamedTemporaryFile(
120 dir=breakpad_dir, delete=False) as temp:
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400121 if debug_file:
122 # Try to dump the symbols using the debug file like normal.
Stephen Boydfc1c8032021-10-06 20:58:37 -0700123 if debug_file_only:
124 cmd_args = [debug_file]
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700125 file_or_files = debug_file
Stephen Boydfc1c8032021-10-06 20:58:37 -0700126 else:
127 cmd_args = [elf_file, os.path.dirname(debug_file)]
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700128 file_or_files = [elf_file, debug_file]
Stephen Boydfc1c8032021-10-06 20:58:37 -0700129
Ivan Penkovcc969482022-06-28 00:09:58 +0000130 result = _DumpIt(cmd_args)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400131
132 if result.returncode:
133 # Sometimes dump_syms can crash because there's too much info.
134 # Try dumping and stripping the extended stuff out. At least
Mike Frysingerdcad4e02018-08-03 16:20:02 -0400135 # this way we'll get the extended symbols. https://crbug.com/266064
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700136 _CrashCheck(result, file_or_files, 'retrying w/out CFI')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400137 cmd_args = ['-c', '-r'] + cmd_args
138 result = _DumpIt(cmd_args)
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700139 _CrashCheck(result, file_or_files, 'retrying w/out debug')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400140
141 basic_dump = result.returncode
142 else:
143 basic_dump = True
144
145 if basic_dump:
146 # If that didn't work (no debug, or dump_syms still failed), try
147 # dumping just the file itself directly.
148 result = _DumpIt([elf_file])
149 if result.returncode:
150 # A lot of files (like kernel files) contain no debug information,
151 # do not consider such occurrences as errors.
Chris McDonaldb55b7032021-06-17 16:41:32 -0600152 cbuildbot_alerts.PrintBuildbotStepWarnings()
Mike Frysinger374ba4f2019-11-14 23:45:15 -0500153 if b'file contains no debugging information' in result.stderr:
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700154 logging.warning('dump_syms failed; giving up entirely.')
155 logging.warning('No symbols found for %s', elf_file)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400156 else:
157 num_errors.value += 1
Ian Barkley-Yeung58286d62022-08-09 14:56:13 -0700158 _CrashCheck(result, elf_file, 'giving up entirely')
Mike Frysinger374ba4f2019-11-14 23:45:15 -0500159 os.unlink(temp.name)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400160 return num_errors.value
161
162 # Move the dumped symbol file to the right place:
163 # /build/$BOARD/usr/lib/debug/breakpad/<module-name>/<id>/<module-name>.sym
164 header = ReadSymsHeader(temp)
Ralph Nathan03047282015-03-23 11:09:32 -0700165 logging.info('Dumped %s as %s : %s', elf_file, header.name, header.id)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400166 sym_file = os.path.join(breakpad_dir, header.name, header.id,
167 header.name + '.sym')
168 osutils.SafeMakedirs(os.path.dirname(sym_file))
169 os.rename(temp.name, sym_file)
Mike Frysinger60ec1012013-10-21 00:11:10 -0400170 os.chmod(sym_file, 0o644)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400171
Don Garrettc9de3ac2015-10-01 15:40:10 -0700172 return sym_file
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400173
174
175def GenerateBreakpadSymbols(board, breakpad_dir=None, strip_cfi=False,
Mike Frysingeref9ab2f2013-08-26 22:16:00 -0400176 generate_count=None, sysroot=None,
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700177 num_processes=None, clean_breakpad=False,
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700178 exclude_dirs=(), file_list=None):
179 """Generate symbols for this board.
180
181 If |file_list| is None, symbols are generated for all executables, otherwise
182 only for the files included in |file_list|.
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400183
184 TODO(build):
185 This should be merged with buildbot_commands.GenerateBreakpadSymbols()
186 once we rewrite cros_generate_breakpad_symbols in python.
187
188 Args:
189 board: The board whose symbols we wish to generate
190 breakpad_dir: The full path to the breakpad directory where symbols live
191 strip_cfi: Do not generate CFI data
192 generate_count: If set, only generate this many symbols (meant for testing)
193 sysroot: The root where to find the corresponding ELFs
Mike Frysingeref9ab2f2013-08-26 22:16:00 -0400194 num_processes: Number of jobs to run in parallel
Mike Frysinger9a628bb2013-10-24 15:51:37 -0400195 clean_breakpad: Should we `rm -rf` the breakpad output dir first; note: we
196 do not do any locking, so do not run more than one in parallel when True
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700197 exclude_dirs: List of dirs (relative to |sysroot|) to not search
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700198 file_list: Only generate symbols for files in this list. Each file must be a
199 full path (including |sysroot| prefix).
200 TODO(build): Support paths w/o |sysroot|.
Mike Frysinger1a736a82013-12-12 01:50:59 -0500201
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400202 Returns:
203 The number of errors that were encountered.
204 """
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400205 if sysroot is None:
Mike Frysinger06a51c82021-04-06 11:39:17 -0400206 sysroot = build_target_lib.get_default_sysroot_path(board)
Mike Frysinger3f571af2016-08-31 23:56:53 -0400207 if breakpad_dir is None:
208 breakpad_dir = FindBreakpadDir(board, sysroot=sysroot)
Mike Frysinger9a628bb2013-10-24 15:51:37 -0400209 if clean_breakpad:
Ralph Nathan03047282015-03-23 11:09:32 -0700210 logging.info('cleaning out %s first', breakpad_dir)
Mike Frysinger9a628bb2013-10-24 15:51:37 -0400211 osutils.RmDir(breakpad_dir, ignore_missing=True, sudo=True)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400212 # Make sure non-root can write out symbols as needed.
213 osutils.SafeMakedirs(breakpad_dir, sudo=True)
214 if not os.access(breakpad_dir, os.W_OK):
Mike Frysinger45602c72019-09-22 02:15:11 -0400215 cros_build_lib.sudo_run(['chown', '-R', str(os.getuid()), breakpad_dir])
Mike Frysinger3f571af2016-08-31 23:56:53 -0400216 debug_dir = FindDebugDir(board, sysroot=sysroot)
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700217 exclude_paths = [os.path.join(debug_dir, x) for x in exclude_dirs]
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700218 if file_list is None:
219 file_list = []
220 file_filter = dict.fromkeys([os.path.normpath(x) for x in file_list], False)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400221
Ralph Nathan03047282015-03-23 11:09:32 -0700222 logging.info('generating breakpad symbols using %s', debug_dir)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400223
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700224 # Let's locate all the debug_files and elfs first along with the debug file
225 # sizes. This way we can start processing the largest files first in parallel
226 # with the small ones.
227 # If |file_list| was given, ignore all other files.
228 targets = []
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700229 for root, dirs, files in os.walk(debug_dir):
230 if root in exclude_paths:
Ralph Nathan03047282015-03-23 11:09:32 -0700231 logging.info('Skipping excluded dir %s', root)
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700232 del dirs[:]
233 continue
234
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400235 for debug_file in files:
236 debug_file = os.path.join(root, debug_file)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400237 # Turn /build/$BOARD/usr/lib/debug/sbin/foo.debug into
238 # /build/$BOARD/sbin/foo.
239 elf_file = os.path.join(sysroot, debug_file[len(debug_dir) + 1:-6])
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700240
241 if file_filter:
242 if elf_file in file_filter:
243 file_filter[elf_file] = True
244 elif debug_file in file_filter:
245 file_filter[debug_file] = True
246 else:
247 continue
248
249 # Filter out files based on common issues with the debug file.
250 if not debug_file.endswith('.debug'):
251 continue
252
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700253 elif os.path.islink(debug_file):
254 # The build-id stuff is common enough to filter out by default.
255 if '/.build-id/' in debug_file:
Ralph Nathan5a582ff2015-03-20 18:18:30 -0700256 msg = logging.debug
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700257 else:
Ralph Nathan446aee92015-03-23 14:44:56 -0700258 msg = logging.warning
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700259 msg('Skipping symbolic link %s', debug_file)
260 continue
261
262 # Filter out files based on common issues with the elf file.
Stephen Boydfc1c8032021-10-06 20:58:37 -0700263 elf_path = os.path.relpath(elf_file, sysroot)
264 debug_only = elf_path in ALLOWED_DEBUG_ONLY_FILES
265 if not os.path.exists(elf_file) and not debug_only:
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400266 # Sometimes we filter out programs from /usr/bin but leave behind
267 # the .debug file.
Ralph Nathan446aee92015-03-23 14:44:56 -0700268 logging.warning('Skipping missing %s', elf_file)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400269 continue
270
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700271 targets.append((os.path.getsize(debug_file), elf_file, debug_file))
272
Allen Webba955f572022-02-11 10:23:05 -0600273 bg_errors = parallel.WrapMultiprocessing(multiprocessing.Value, 'i')
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700274 if file_filter:
Mike Frysinger0bdbc102019-06-13 15:27:29 -0400275 files_not_found = [x for x, found in file_filter.items() if not found]
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700276 bg_errors.value += len(files_not_found)
277 if files_not_found:
Ralph Nathan59900422015-03-24 10:41:17 -0700278 logging.error('Failed to find requested files: %s', files_not_found)
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700279
280 # Now start generating symbols for the discovered elfs.
281 with parallel.BackgroundTaskRunner(GenerateBreakpadSymbol,
Don Garrette548cff2015-09-23 14:36:21 -0700282 breakpad_dir=breakpad_dir,
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700283 strip_cfi=strip_cfi,
284 num_errors=bg_errors,
285 processes=num_processes) as queue:
286 for _, elf_file, debug_file in sorted(targets, reverse=True):
287 if generate_count == 0:
288 break
289
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400290 queue.put([elf_file, debug_file])
291 if generate_count is not None:
292 generate_count -= 1
293 if generate_count == 0:
294 break
295
296 return bg_errors.value
297
298
Mike Frysinger3f571af2016-08-31 23:56:53 -0400299def FindDebugDir(board, sysroot=None):
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400300 """Given a |board|, return the path to the split debug dir for it"""
Mike Frysinger3f571af2016-08-31 23:56:53 -0400301 if sysroot is None:
Mike Frysinger06a51c82021-04-06 11:39:17 -0400302 sysroot = build_target_lib.get_default_sysroot_path(board)
Yu-Ju Hongdd9bb2b2014-01-03 17:08:26 -0800303 return os.path.join(sysroot, 'usr', 'lib', 'debug')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400304
305
Mike Frysinger3f571af2016-08-31 23:56:53 -0400306def FindBreakpadDir(board, sysroot=None):
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400307 """Given a |board|, return the path to the breakpad dir for it"""
Mike Frysinger3f571af2016-08-31 23:56:53 -0400308 return os.path.join(FindDebugDir(board, sysroot=sysroot), 'breakpad')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400309
310
311def main(argv):
312 parser = commandline.ArgumentParser(description=__doc__)
313
314 parser.add_argument('--board', default=None,
315 help='board to generate symbols for')
316 parser.add_argument('--breakpad_root', type='path', default=None,
Mike Frysinger3f571af2016-08-31 23:56:53 -0400317 help='root output directory for breakpad symbols')
318 parser.add_argument('--sysroot', type='path', default=None,
319 help='root input directory for files')
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700320 parser.add_argument('--exclude-dir', type=str, action='append',
321 default=[],
322 help='directory (relative to |board| root) to not search')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400323 parser.add_argument('--generate-count', type=int, default=None,
324 help='only generate # number of symbols')
Mike Frysinger9a628bb2013-10-24 15:51:37 -0400325 parser.add_argument('--noclean', dest='clean', action='store_false',
326 default=True,
327 help='do not clean out breakpad dir before running')
Mike Frysingeref9ab2f2013-08-26 22:16:00 -0400328 parser.add_argument('--jobs', type=int, default=None,
329 help='limit number of parallel jobs')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400330 parser.add_argument('--strip_cfi', action='store_true', default=False,
331 help='do not generate CFI data (pass -c to dump_syms)')
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700332 parser.add_argument('file_list', nargs='*', default=None,
333 help='generate symbols for only these files '
334 '(e.g. /build/$BOARD/usr/bin/foo)')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400335
336 opts = parser.parse_args(argv)
Mike Frysinger90e49ca2014-01-14 14:42:07 -0500337 opts.Freeze()
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400338
Mike Frysinger3f571af2016-08-31 23:56:53 -0400339 if opts.board is None and opts.sysroot is None:
340 cros_build_lib.Die('--board or --sysroot is required')
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400341
342 ret = GenerateBreakpadSymbols(opts.board, breakpad_dir=opts.breakpad_root,
343 strip_cfi=opts.strip_cfi,
Mike Frysingeref9ab2f2013-08-26 22:16:00 -0400344 generate_count=opts.generate_count,
Mike Frysinger3f571af2016-08-31 23:56:53 -0400345 sysroot=opts.sysroot,
Mike Frysinger9a628bb2013-10-24 15:51:37 -0400346 num_processes=opts.jobs,
Shawn Nematbakhsh2c169cb2013-10-29 16:23:58 -0700347 clean_breakpad=opts.clean,
Prathmesh Prabhu9995e9b2013-10-31 16:43:55 -0700348 exclude_dirs=opts.exclude_dir,
349 file_list=opts.file_list)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400350 if ret:
Ralph Nathan59900422015-03-24 10:41:17 -0700351 logging.error('encountered %i problem(s)', ret)
Mike Frysinger69cb41d2013-08-11 20:08:19 -0400352 # Since exit(status) gets masked, clamp it to 1 so we don't inadvertently
353 # return 0 in case we are a multiple of the mask.
354 ret = 1
355
356 return ret