|
8 | 8 | # line/column number, potentially including inlining.
|
9 | 9 | # If the wasm has separate DWARF info, do the above with the side file
|
10 | 10 | # If there is a source map, we can parse it to get file and line number.
|
11 |
| -# If there is an emscripten symbol map, we can parse that to get the symbol name |
12 |
| -# If there is a name section or symbol table, llvm-nm can show the symbol name. |
| 11 | +# If there is an emscripten symbol map, we can use that to get the symbol name |
| 12 | +# If there is a name section or symbol table, llvm-symbolizer can show the |
| 13 | +# symbol name. |
| 14 | +# Separate DWARF and emscripten symbol maps are not supported yet. |
13 | 15 |
|
14 | 16 | import argparse
|
15 | 17 | import json
|
@@ -50,21 +52,27 @@ def get_codesec_offset(module):
|
50 | 52 |
|
51 | 53 |
|
52 | 54 | def has_debug_line_section(module):
|
53 |
| - for sec in module.sections(): |
54 |
| - if sec.name == ".debug_line": |
55 |
| - return True |
56 |
| - return False |
| 55 | + return module.get_custom_section('.debug_line') is not None |
| 56 | + |
| 57 | + |
| 58 | +def has_name_section(module): |
| 59 | + return module.get_custom_section('name') is not None |
| 60 | + |
57 | 61 |
|
| 62 | +def has_linking_section(module): |
| 63 | + return module.get_custom_section('linking') is not None |
58 | 64 |
|
59 |
| -def symbolize_address_dwarf(module, address): |
60 |
| - vma_adjust = get_codesec_offset(module) |
| 65 | + |
| 66 | +def symbolize_address_symbolizer(module, address, is_dwarf=False): |
| 67 | + vma_adjust = get_codesec_offset(module) if is_dwarf else 0 |
61 | 68 | cmd = [LLVM_SYMBOLIZER, '-e', module.filename, f'--adjust-vma={vma_adjust}',
|
62 | 69 | str(address)]
|
63 | 70 | out = shared.run_process(cmd, stdout=subprocess.PIPE).stdout.strip()
|
64 | 71 | out_lines = out.splitlines()
|
| 72 | + |
65 | 73 | # Source location regex, e.g., /abc/def.c:3:5
|
66 | 74 | SOURCE_LOC_RE = re.compile(r'(.+):(\d+):(\d+)$')
|
67 |
| - # llvm-dwarfdump prints two lines per location. The first line contains a |
| 75 | + # llvm-symbolizer prints two lines per location. The first line contains a |
68 | 76 | # function name, and the second contains a source location like
|
69 | 77 | # '/abc/def.c:3:5'. If the function or source info is not available, it will
|
70 | 78 | # be printed as '??', in which case we store None. If the line and column info
|
@@ -210,30 +218,32 @@ def main(args):
|
210 | 218 | with webassembly.Module(args.wasm_file) as module:
|
211 | 219 | base = 16 if args.address.lower().startswith('0x') else 10
|
212 | 220 | address = int(args.address, base)
|
213 |
| - symbolized = 0 |
214 | 221 |
|
215 | 222 | if args.addrtype == 'code':
|
216 | 223 | address += get_codesec_offset(module)
|
217 | 224 |
|
218 | 225 | if ((has_debug_line_section(module) and not args.source) or
|
219 |
| - 'dwarf' in args.source): |
220 |
| - symbolize_address_dwarf(module, address) |
221 |
| - symbolized += 1 |
222 |
| - |
223 |
| - if ((get_sourceMappingURL_section(module) and not args.source) or |
224 |
| - 'sourcemap' in args.source): |
| 226 | + 'dwarf' in args.source): |
| 227 | + symbolize_address_symbolizer(module, address, is_dwarf=True) |
| 228 | + elif ((get_sourceMappingURL_section(module) and not args.source) or |
| 229 | + 'sourcemap' in args.source): |
225 | 230 | symbolize_address_sourcemap(module, address, args.file)
|
226 |
| - symbolized += 1 |
227 |
| - |
228 |
| - if not symbolized: |
| 231 | + elif ((has_name_section(module) and not args.source) or |
| 232 | + 'names' in args.source): |
| 233 | + symbolize_address_symbolizer(module, address, is_dwarf=False) |
| 234 | + elif ((has_linking_section(module) and not args.source) or |
| 235 | + 'symtab' in args.source): |
| 236 | + symbolize_address_symbolizer(module, address, is_dwarf=False) |
| 237 | + else: |
229 | 238 | raise Error('No .debug_line or sourceMappingURL section found in '
|
230 | 239 | f'{module.filename}.'
|
231 | 240 | " I don't know how to symbolize this file yet")
|
232 | 241 |
|
233 | 242 |
|
234 | 243 | def get_args():
|
235 | 244 | parser = argparse.ArgumentParser()
|
236 |
| - parser.add_argument('-s', '--source', choices=['dwarf', 'sourcemap'], |
| 245 | + parser.add_argument('-s', '--source', choices=['dwarf', 'sourcemap', |
| 246 | + 'names', 'symtab'], |
237 | 247 | help='Force debug info source type', default=())
|
238 | 248 | parser.add_argument('-f', '--file', action='store',
|
239 | 249 | help='Force debug info source file')
|
|
0 commit comments