From 85e1943843d7d1f2d74e98a305f5f5252310e93e Mon Sep 17 00:00:00 2001 From: Thomas Lamb Date: Sat, 7 Mar 2026 19:38:36 -0500 Subject: [PATCH] Handle both bugged and unbugged __sinit_ behaviors --- mwccgap/mwccgap.py | 30 +++++++++++++++++------------- tests/test_mwccgap.py | 31 ++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/mwccgap/mwccgap.py b/mwccgap/mwccgap.py index 5cc0755..536d385 100755 --- a/mwccgap/mwccgap.py +++ b/mwccgap/mwccgap.py @@ -293,12 +293,14 @@ def replace_sinit(symbol_name, temp_file_name, c_file_name): Substitute original file name into MWCC static initializer symbol names When files contain static initializer code (e.g. static definitions - referencing the address of another static variable), MWCC emits the - symbols: - - `.p__sinit_foo.cpp[...]` - - `__sinit_foo.cpp[...]` - - `.mwcats___sinit_foo.cpp[...]` - where `[...]` is enough space characters to fill the symbol name buffer. + referencing the address of another static variable), MWCC emits the symbols: + - `.p__sinit_foo.cpp` + - `__sinit_foo.cpp` + - `.mwcats___sinit_foo.cpp` + + On certain versions of MWCC, the symbol generation code is bugged. When + generating the symbol name, the first character is treated as the minimum + format width and the filename is right padded. `.p__sinit_foo.cpp` is a pointer object in the `.ctor` section, with a reloc pointing to `__sinit_foo.cpp`. This is linked into a table alongside @@ -313,10 +315,12 @@ def replace_sinit(symbol_name, temp_file_name, c_file_name): using the temporary file's name. We replace it with the original file name to operate transparently & enable linking these symbols. """ - # symmetrically ljust to handle both smaller & longer cases - old = temp_file_name.ljust(len(c_file_name)) - new = c_file_name.ljust(len(old)) - assert len(old) == len(new) - fixed_name = symbol_name.replace(old, new) - assert fixed_name.find(temp_file_name) == -1 - return fixed_name + prefix, _, symbol_file_name = symbol_name.partition(SYMBOL_SINIT) + assert len(symbol_file_name) > 0 + + # MWCC bug: filename is padded based on first character of file name + if len(symbol_file_name) > len(temp_file_name): + assert symbol_file_name == temp_file_name.ljust(ord(temp_file_name[0])) + return prefix + SYMBOL_SINIT + c_file_name.ljust(ord(c_file_name[0])) + + return prefix + SYMBOL_SINIT + c_file_name diff --git a/tests/test_mwccgap.py b/tests/test_mwccgap.py index 28ab789..ec49811 100644 --- a/tests/test_mwccgap.py +++ b/tests/test_mwccgap.py @@ -5,16 +5,11 @@ class TestSinitSymbolNames(unittest.TestCase): - def test_unrelated(self): - symbol_name = "some_function" - result = replace_sinit(symbol_name, "tmp12234567.c", "test.cpp") - self.assertEqual(symbol_name, result) - def test_short_filename(self): c_file_name = "short.cpp" temp_f_name = "tmp12456789.c" - symbol_name = f".p__sinit_{temp_f_name}".ljust(253) - expect_name = f".p__sinit_{c_file_name}".ljust(253) + symbol_name = f".p__sinit_{temp_f_name}" + expect_name = f".p__sinit_{c_file_name}" result = replace_sinit(symbol_name, temp_f_name, c_file_name) self.assertEqual(expect_name, result) @@ -22,8 +17,26 @@ def test_short_filename(self): def test_long_filename(self): c_file_name = "extra_long_name.cpp" temp_f_name = "tmp12456789.c" - symbol_name = f"__sinit_{temp_f_name}".ljust(253) - expect_name = f"__sinit_{c_file_name}".ljust(253) + symbol_name = f"__sinit_{temp_f_name}" + expect_name = f"__sinit_{c_file_name}" + + result = replace_sinit(symbol_name, temp_f_name, c_file_name) + self.assertEqual(expect_name, result) + + def test_short_filename_bugged_symbols(self): + c_file_name = "short.cpp" + temp_f_name = "tmp12456789.c" + symbol_name = f".p__sinit_{temp_f_name.ljust(ord(temp_f_name[0]))}" + expect_name = f".p__sinit_{c_file_name.ljust(ord(c_file_name[0]))}" + + result = replace_sinit(symbol_name, temp_f_name, c_file_name) + self.assertEqual(expect_name, result) + + def test_long_filename_bugged_symbols(self): + c_file_name = "extra_long_name.cpp" + temp_f_name = "tmp12456789.c" + symbol_name = f"__sinit_{temp_f_name.ljust(ord(temp_f_name[0]))}" + expect_name = f"__sinit_{c_file_name.ljust(ord(c_file_name[0]))}" result = replace_sinit(symbol_name, temp_f_name, c_file_name) self.assertEqual(expect_name, result)