Skip to content

Commit

Permalink
Parse names without _u suffix and add tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
CycleOfTheAbsurd committed Apr 10, 2024
1 parent 690c7cc commit 240be21
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ Navigate to Edit -> Plugins -> Nimfilt and click on it.
You can set Nimfilt to automatically execute when a loaded file is recognized as a Nim binary. To do so, set the `AUTO_RUN` global variable to `True` in `nimfilt_ida.py`


## Running tests

Nimfilt uses the [unittest](https://docs.python.org/3/library/unittest.html) package from the Python standard library for unit testing. You can run the test suite using the following command: `python -m unittest test/*.py`.


## Features

Current features include:
Expand Down
4 changes: 2 additions & 2 deletions nimfilt.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,12 @@ def demangle_function(name: str) -> str:
class NimName():
def __init__(self, namestr):
# <Function name>__<Package Name>_u<numeric ID>_<numeric IDA suffix>.<compiler suffix>@<C++ mangled arguments>
m = re.fullmatch(r'@?([a-zA-Z0-9_]+_?)__(.*)(_u[0-9]+)(_[0-9]+)?(\.[a-z]+\.[0-9]+)?(@[0-9]+)?', namestr)
m = re.fullmatch(r'@?([a-zA-Z0-9_]+_?)__([^@_]+)(_u[0-9]+)?(_[0-9]+)?(\.[a-z]+\.[0-9]+)?(@[0-9]+)?', namestr)
if m is None or len(m.group(1)) <= 1:
raise ValueError("Invalid Nim function name \"{}\"".format(namestr))
self.fnname = demangle_function(m.group(1))
self.pkgname = demangle_module(m.group(2))
self.suffix = m.group(3)[1:]
self.suffix = None if m.group(3) is None else m.group(3)[1:]
self.ida_suffix = m.group(4)
self.num_args = m.group(6)

Expand Down
51 changes: 51 additions & 0 deletions test/test_names.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import unittest
import nimfilt

class TestNameParsing(unittest.TestCase):
def test_simple_name(self):
n = nimfilt.NimName("@add__system_u2308@8")
self.assertTrue(n.is_std())
self.assertEqual(n.fnname, "add")
self.assertEqual(n.pkgname, "system")
self.assertEqual(n.suffix, "u2308")
self.assertIsNone(n.ida_suffix)
self.assertEqual(n.num_args, "@8")

def test_name_all_fields(self):
n = nimfilt.NimName("@add__system_u2308_1.link.88@16")
self.assertTrue(n.is_std())
self.assertEqual(n.fnname, "add")
self.assertEqual(n.pkgname, "system")
self.assertEqual(n.suffix, "u2308")
self.assertEqual(n.ida_suffix, "_1")
self.assertEqual(n.num_args, "@16")

def test_init_name(self):
n = nimfilt.NimInitName("@atmlibatssystemdotnim_Init000@0")
self.assertTrue(n.is_std)
self.assertEqual(n.fnname, "Init000")
self.assertEqual(n.pkgname, "lib/system")
self.assertIsNone(n.suffix)
self.assertIsNone(n.ida_suffix)
self.assertEqual(n.num_args, "@0")

def test_wrong_name(self):
with self.assertRaises(ValueError):
nimfilt.NimName("____w64_mingwthr_remove_key_dtor")
with self.assertRaises(ValueError):
nimfilt.NimName("@atmlibatssystemdotnim_Init000@0")

with self.assertRaises(ValueError):
nimfilt.NimInitName("____w64_mingwthr_remove_key_dtor")
with self.assertRaises(ValueError):
nimfilt.NimInitName("@add__system_u2308@8")

class TestDemangling(unittest.TestCase):
def test_func_name(self):
n = nimfilt.NimName("@eqdestroy___stdZ80rivateZntpath_u119@4")
self.assertEqual(n.fnname, "=destroy")
self.assertEqual(n.pkgname, "std/Private/ntpath")


if __name__ == "__main__":
unittest.main()

0 comments on commit 240be21

Please sign in to comment.