Skip to content

Commit b241b08

Browse files
authored
Allow DWARF with source map (#17484)
This allows generation of DWARF info and source map at the same time. This adds an internal setting, `GENERATE_DWARF`, which is a counterpart of existing `GENERATE_SORUCE_MAP`, because with only `DEBUG_LEVEL` we now don't have a way to tell whether DWARF info is explicitly requested or not, because we set `DEBUG_LEVEL` to 3 when source map is requested. This adds some simple utility functions to `test_other.py` for DWARF and source map verification. Also this enables `try_delete` to delete a list of files. Fixes #16699.
1 parent ae558d9 commit b241b08

File tree

6 files changed

+64
-13
lines changed

6 files changed

+64
-13
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ See docs/process.md for more on how version tagging works.
2020

2121
3.1.17
2222
------
23+
- A source map file and DWARF info in the wasm can now be emitted at the same if
24+
the user gives the both options: `-g -gsource-map`.
2325
- The `align` argument to the makeGetValue/makeSetValue JS library macros was
2426
removed (and replaced with an assert) as it had no uses internally and was
2527
removed (and replaced with an assert) as it had now uses internally and was

emcc.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,8 @@ def consume_arg_file():
31773177
else:
31783178
# for 3+, report -g3 to clang as -g4 etc. are not accepted
31793179
newargs[i] = '-g3'
3180+
if settings.DEBUG_LEVEL == 3:
3181+
settings.GENERATE_DWARF = 1
31803182
if settings.DEBUG_LEVEL == 4:
31813183
settings.GENERATE_SOURCE_MAP = 1
31823184
diagnostics.warning('deprecated', 'please replace -g4 with -gsource-map')

src/settings_internal.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ var MEMORYPROFILER = false;
202202

203203
var GENERATE_SOURCE_MAP = false;
204204

205+
var GENERATE_DWARF = false;
206+
205207
// Memory layout. These are only used/set in RELOCATABLE builds. Otherwise
206208
// memory layout is fixed in the wasm binary at link time.
207209
var STACK_BASE = 0;

tests/test_other.py

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,20 +2425,59 @@ def compile_to_O0_executable(compile_args):
24252425
self.assertEqual(no_size, line_size)
24262426
self.assertEqual(line_size, full_size)
24272427

2428+
# Verify the existence (or lack thereof) of DWARF info in the given wasm file
2429+
def verify_dwarf(self, wasm_file, verify_func):
2430+
self.assertExists(wasm_file)
2431+
info = self.run_process([LLVM_DWARFDUMP, '--all', wasm_file], stdout=PIPE).stdout
2432+
verify_func('DW_TAG_subprogram', info) # Subprogram entry in .debug_info
2433+
verify_func('debug_line[0x', info) # Line table
2434+
2435+
def verify_dwarf_exists(self, wasm_file):
2436+
self.verify_dwarf(wasm_file, self.assertIn)
2437+
2438+
def verify_dwarf_does_not_exist(self, wasm_file):
2439+
self.verify_dwarf(wasm_file, self.assertNotIn)
2440+
2441+
# Verify if the given file name contains a source map
2442+
def verify_source_map_exists(self, map_file):
2443+
self.assertExists(map_file)
2444+
data = json.load(open(map_file))
2445+
# Simply check the existence of required sections
2446+
self.assertIn('version', data)
2447+
self.assertIn('sources', data)
2448+
self.assertIn('mappings', data)
2449+
24282450
def test_dwarf(self):
24292451
def compile_with_dwarf(args, output):
24302452
# Test that -g enables dwarf info in object files and linked wasm
24312453
self.run_process([EMXX, test_file('hello_world.cpp'), '-o', output, '-g'] + args)
2432-
2433-
def verify(output):
2434-
info = self.run_process([LLVM_DWARFDUMP, '--all', output], stdout=PIPE).stdout
2435-
self.assertIn('DW_TAG_subprogram', info) # Ensure there's a subprogram entry in .debug_info
2436-
self.assertIn('debug_line[0x', info) # Ensure there's a line table
2437-
24382454
compile_with_dwarf(['-c'], 'a.o')
2439-
verify('a.o')
2455+
self.verify_dwarf_exists('a.o')
24402456
compile_with_dwarf([], 'a.js')
2441-
verify('a.wasm')
2457+
self.verify_dwarf_exists('a.wasm')
2458+
2459+
def test_dwarf_with_source_map(self):
2460+
source_file = 'hello_world.cpp'
2461+
js_file = 'a.out.js'
2462+
wasm_file = 'a.out.wasm'
2463+
map_file = 'a.out.wasm.map'
2464+
2465+
# Generate only DWARF
2466+
self.emcc(test_file(source_file), ['-g'], js_file)
2467+
self.verify_dwarf_exists(wasm_file)
2468+
self.assertFalse(os.path.isfile(map_file))
2469+
try_delete([wasm_file, map_file, js_file])
2470+
2471+
# Generate only source map
2472+
self.emcc(test_file(source_file), ['-gsource-map'], js_file)
2473+
self.verify_dwarf_does_not_exist(wasm_file)
2474+
self.verify_source_map_exists(map_file)
2475+
try_delete([wasm_file, map_file, js_file])
2476+
2477+
# Generate DWARF with source map
2478+
self.emcc(test_file(source_file), ['-g', '-gsource-map'], js_file)
2479+
self.verify_dwarf_exists(wasm_file)
2480+
self.verify_source_map_exists(map_file)
24422481

24432482
@unittest.skipIf(not scons_path, 'scons not found in PATH')
24442483
@with_env_modify({'EMSCRIPTEN_ROOT': path_from_root()})

tools/building.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,10 +1533,8 @@ def run_binaryen_command(tool, infile, outfile=None, args=None, debug=False, std
15331533

15341534

15351535
def run_wasm_opt(infile, outfile=None, args=[], **kwargs): # noqa
1536-
if outfile and (settings.DEBUG_LEVEL < 3 or settings.GENERATE_SOURCE_MAP):
1537-
# remove any dwarf debug info sections, if the debug level is <3, as
1538-
# we don't need them; also remove them if we use source maps (which are
1539-
# implemented separately from dwarf).
1536+
if outfile and not settings.GENERATE_DWARF:
1537+
# remove any dwarf debug info sections if dwarf is not requested.
15401538
# note that we add this pass first, so that it doesn't interfere with
15411539
# the final set of passes (which may generate stack IR, and nothing
15421540
# should be run after that)

tools/tempfiles.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@
1111
import sys
1212

1313

14+
def try_delete(pathnames):
15+
if isinstance(pathnames, list):
16+
for pathname in pathnames:
17+
try_delete_one(pathname)
18+
else:
19+
try_delete_one(pathnames)
20+
21+
1422
# Attempts to delete given possibly nonexisting or read-only directory tree or filename.
1523
# If any failures occur, the function silently returns without throwing an error.
16-
def try_delete(pathname):
24+
def try_delete_one(pathname):
1725
try:
1826
os.unlink(pathname)
1927
except OSError:

0 commit comments

Comments
 (0)