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
30 changes: 17 additions & 13 deletions mwccgap/mwccgap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
31 changes: 22 additions & 9 deletions tests/test_mwccgap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,38 @@


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)

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)