From 6b5bced2f88e1a2a3e19f1b8f88491e4c02cca2e Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 28 Jan 2020 17:47:18 -0800 Subject: [PATCH 1/3] Don't depend on llvm-nm to detect archive indexes There is an llvm but that mean that certain binary files get mistaken for COFF object which means llvm-nm will error out: https://bugs.llvm.org/show_bug.cgi?id=44683 Instead write out own trivial ar parser to detect the presence of that index. Fixes: #10195 --- emcc.py | 37 ++++++++++++++++++++++++++----------- tests/test_other.py | 10 ++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/emcc.py b/emcc.py index fdae1bc40bf1e..90dc74cb93eca 100755 --- a/emcc.py +++ b/emcc.py @@ -480,21 +480,36 @@ def do_emscripten(infile, memfile): return outfile +def is_ar_file_with_missing_index(archive_file): + # We parse the archive header outselves because llvm-nm --print-armap is slower and less + # reliable. + # See: https://github.com/emscripten-core/emscripten/issues/10195 + archive_header = b'!\n' + file_header_size = 60 + + with open(archive_file, 'rb') as f: + header = f.read(len(archive_header)) + if header != archive_header: + # This is not even an ar file + return False + file_header = f.read(file_header_size) + if len(file_header) != file_header_size: + # We don't have any file entires at all so we don't consider the index missing + return False + + name = file_header[:16].strip() + # If '/' is the name of the first file we have an index + return name != '/' + + def ensure_archive_index(archive_file): # Fastcomp linking works without archive indexes. if not shared.Settings.WASM_BACKEND or not shared.Settings.AUTO_ARCHIVE_INDEXES: return - # Ignore stderr since llvm-nm prints "no symbols" to stderr for each object that has no symbols - stdout = run_process([shared.LLVM_NM, '--print-armap', archive_file], stdout=PIPE, stderr=PIPE).stdout - stdout = stdout.strip() - # Ignore empty archives - if not stdout: - return - if stdout.startswith('Archive map\n') or stdout.startswith('Archive index\n'): - return - shared.warning('%s: archive is missing an index; Use emar when creating libraries to ensure an index is created', archive_file) - shared.warning('%s: adding index', archive_file) - run_process([shared.LLVM_RANLIB, archive_file]) + if is_ar_file_with_missing_index(archive_file): + shared.warning('%s: archive is missing an index; Use emar when creating libraries to ensure an index is created', archive_file) + shared.warning('%s: adding index', archive_file) + run_process([shared.LLVM_RANLIB, archive_file]) # diff --git a/tests/test_other.py b/tests/test_other.py index 579f9b52cec9e..06a33960575fc 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8728,6 +8728,16 @@ def test_archive_no_index(self): # The default behavior is to add archive indexes automatically. run_process([PYTHON, EMCC, 'libfoo.a', 'hello_world.o']) + def test_archive_non_objects(self): + create_test_file('file.txt', 'test file') + # llvm-nm has issues with files that start with two or more null bytes since it thinks they + # are COFF files. Ensure that we correctly ignore such files when we process them. + create_test_file('zeros.bin', '\0\0\0\0') + run_process([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c')]) + # No index added. + run_process([PYTHON, EMAR, 'crS', 'libfoo.a', 'file.txt', 'zeros.bin', 'hello_world.o']) + run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), 'libfoo.a']) + def test_flag_aliases(self): def assert_aliases_match(flag1, flag2, flagarg, extra_args): results = {} From 94542970006d49d30a848a146284a98dd5f492b0 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 3 Feb 2020 16:27:16 -0800 Subject: [PATCH 2/3] fix --- tests/test_other.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_other.py b/tests/test_other.py index 06a33960575fc..cdae644d62cff 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8735,7 +8735,9 @@ def test_archive_non_objects(self): create_test_file('zeros.bin', '\0\0\0\0') run_process([PYTHON, EMCC, '-c', path_from_root('tests', 'hello_world.c')]) # No index added. - run_process([PYTHON, EMAR, 'crS', 'libfoo.a', 'file.txt', 'zeros.bin', 'hello_world.o']) + # --format=darwin (the default on OSX has a strange issue where it add extra + # newlines to files: https://bugs.llvm.org/show_bug.cgi?id=42562 + run_process([PYTHON, EMAR, 'crS', '--format=gnu', 'libfoo.a', 'file.txt', 'zeros.bin', 'hello_world.o']) run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), 'libfoo.a']) def test_flag_aliases(self): From f4ba89680f5da22c2960f43cd1fcdbb739c2e5c8 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 3 Feb 2020 17:17:35 -0800 Subject: [PATCH 3/3] disable --- tests/test_other.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_other.py b/tests/test_other.py index cdae644d62cff..bbacabd6373d0 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8728,6 +8728,7 @@ def test_archive_no_index(self): # The default behavior is to add archive indexes automatically. run_process([PYTHON, EMCC, 'libfoo.a', 'hello_world.o']) + @no_fastcomp('AUTO_ARCHIVE_INDEXES only applies to wasm backend') def test_archive_non_objects(self): create_test_file('file.txt', 'test file') # llvm-nm has issues with files that start with two or more null bytes since it thinks they