Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test/other/test_symbol_map.O2.symbols
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
0:run_js
1:emscripten_asm_const_int
2:__wasm_call_ctors
3:foo::cpp_func\28int\29
3:foo::cpp_func(int)
4:middle
5:main
6:_emscripten_stack_restore
Expand Down
2 changes: 1 addition & 1 deletion test/other/test_symbol_map.O3.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
1:emscripten_asm_const_int
2:middle
3:main
4:foo::cpp_func\28int\29
4:foo::cpp_func(int)
5:__wasm_call_ctors
48 changes: 32 additions & 16 deletions tools/building.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,24 +1081,40 @@ def instrument_js_for_safe_heap(js_file):
return acorn_optimizer(js_file, ['safeHeap'])


def read_name_section(wasm_file):
with webassembly.Module(wasm_file) as module:
for section in module.sections():
if section.type == webassembly.SecType.CUSTOM:
module.seek(section.offset)
if module.read_string() == 'name':
name_map = {}
# The name section is made up sub-section.
# We are looking for the function names sub-section
while module.tell() < section.offset + section.size:
name_type = module.read_uleb()
subsection_size = module.read_uleb()
subsection_end = module.tell() + subsection_size
if name_type == webassembly.NameType.FUNCTION:
# We found the function names sub-section
num_names = module.read_uleb()
for _ in range(num_names):
id = module.read_uleb()
name = module.read_string()
name_map[id] = name
return name_map
module.seek(subsection_end)

return name_map


@ToolchainProfiler.profile()
def handle_final_wasm_symbols(wasm_file, symbols_file, debug_info):
def write_symbol_map(wasm_file, symbols_file):
logger.debug('handle_final_wasm_symbols')
args = []
if symbols_file:
args += ['--print-function-map']
else:
# suppress the wasm-opt warning regarding "no output file specified"
args += ['--quiet']
output = run_wasm_opt(wasm_file, args=args, stdout=PIPE)
if symbols_file:
utils.write_file(symbols_file, output)
if not debug_info:
# strip the names section using llvm-objcopy. this is slightly slower than
# using wasm-opt (we could run wasm-opt without -g here and just tell it to
# write the file back out), but running wasm-opt would undo StackIR
# optimizations, if we did those.
strip(wasm_file, wasm_file, sections=['name'])
names = read_name_section(wasm_file)
assert(names)
strings = [f'{id}:{name}' for id, name in names.items()]
contents = '\n'.join(strings) + '\n'
utils.write_file(symbols_file, contents)


def is_ar(filename):
Expand Down
5 changes: 3 additions & 2 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -2413,8 +2413,9 @@ def phase_binaryen(target, options, wasm_target):
if options.emit_symbol_map:
intermediate_debug_info -= 1
if generating_wasm:
building.handle_final_wasm_symbols(wasm_file=wasm_target, symbols_file=symbols_file, debug_info=intermediate_debug_info)
save_intermediate_with_wasm('symbolmap', wasm_target)
building.write_symbol_map(wasm_target, symbols_file)
if not intermediate_debug_info:
building.strip(wasm_target, wasm_target, sections=['name'])

if settings.GENERATE_DWARF and settings.SEPARATE_DWARF and generating_wasm:
# if the dwarf filename wasn't provided, use the default target + a suffix
Expand Down
15 changes: 15 additions & 0 deletions tools/webassembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,21 @@ class TargetFeaturePrefix(IntEnum):
DISALLOWED = 0x2d


class NameType(IntEnum):
MODULE = 0
FUNCTION = 1
LOCAL = 2
LABEL = 3
TYPE = 4
TABLE = 5
MEMORY = 6
GLOBAL = 7
ELEMSEGMENT = 8
DATASEGMENT = 9
FIELD = 10
TAG = 11


class InvalidWasmError(BaseException):
pass

Expand Down