summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--plugins/pychrysalide/arch/vmpa.c3
-rwxr-xr-xsrc/common/endianness.c212
-rwxr-xr-xsrc/common/endianness.h4
-rw-r--r--tests/analysis/contents/endian.py129
5 files changed, 274 insertions, 86 deletions
diff --git a/ChangeLog b/ChangeLog
index d80a44d..ced1ad5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
18-01-24 Cyrille Bagard <nocbos@gmail.com>
+ * plugins/pychrysalide/arch/vmpa.c:
+ Update code.
+
+ * src/common/endianness.c:
+ * src/common/endianness.h:
+ Improve the support of some unusual endiannesses.
+
+ * tests/analysis/contents/endian.py:
+ New entry: extend the test suite with some extra cases.
+
+18-01-24 Cyrille Bagard <nocbos@gmail.com>
+
* src/analysis/binary.c:
Clean the content of loaded binaries.
diff --git a/plugins/pychrysalide/arch/vmpa.c b/plugins/pychrysalide/arch/vmpa.c
index 413d67b..41fb1ad 100644
--- a/plugins/pychrysalide/arch/vmpa.c
+++ b/plugins/pychrysalide/arch/vmpa.c
@@ -554,7 +554,8 @@ static bool py_vmpa_define_constants(PyTypeObject *obj_type)
/* TODO : à bouger vers base ? */
result &= PyDict_AddIntMacro(obj_type, SRE_LITTLE);
- result &= PyDict_AddIntMacro(obj_type, SRE_MIDDLE);
+ result &= PyDict_AddIntMacro(obj_type, SRE_LITTLE_WORD);
+ result &= PyDict_AddIntMacro(obj_type, SRE_BIG_WORD);
result &= PyDict_AddIntMacro(obj_type, SRE_BIG);
return result;
diff --git a/src/common/endianness.c b/src/common/endianness.c
index 4dcee22..3aeca00 100755
--- a/src/common/endianness.c
+++ b/src/common/endianness.c
@@ -24,11 +24,25 @@
#include "endianness.h"
+#include <assert.h>
#include <stdarg.h>
#include <string.h>
+/**
+ * Mutualisation des aiguillages...
+ */
+
+#if __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN
+
+ /* __PDP_ENDIAN et Cie... */
+# error "Congratulations! Your byte order is not supported!"
+
+#endif
+
+
+
/* ---------------------------------------------------------------------------------- */
/* CONVERSION ENTRE BOUTISMES */
/* ---------------------------------------------------------------------------------- */
@@ -63,18 +77,10 @@ uint16_t swap_u16(const uint16_t *value, SourceEndian endian)
result = ((*value >> 0) & 0xff) << 8 | ((*value >> 8) & 0xff) << 0;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
- break;
-
case SRE_BIG:
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -85,14 +91,13 @@ uint16_t swap_u16(const uint16_t *value, SourceEndian endian)
result = *value;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ assert(false);
+ break;
}
@@ -131,18 +136,10 @@ uint32_t swap_u32(const uint32_t *value, SourceEndian endian)
result = ((*value >> 0) & 0xff) << 24 | ((*value >> 8) & 0xff) << 16
| ((*value >> 16) & 0xff) << 8 | ((*value >> 24) & 0xff) << 0;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
- break;
-
case SRE_BIG:
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -154,14 +151,13 @@ uint32_t swap_u32(const uint32_t *value, SourceEndian endian)
result = *value;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ assert(false);
+ break;
}
@@ -202,18 +198,10 @@ uint64_t swap_u64(const uint64_t *value, SourceEndian endian)
| ((*value >> 32) & 0xff) << 24 | ((*value >> 40) & 0xff) << 16
| ((*value >> 48) & 0xff) << 8 | ((*value >> 56) & 0xff) << 0;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
- break;
-
case SRE_BIG:
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -227,14 +215,13 @@ uint64_t swap_u64(const uint64_t *value, SourceEndian endian)
result = *value;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ assert(false);
+ break;
}
@@ -349,16 +336,36 @@ bool read_u16(uint16_t *target, const bin_t *data, phys_t *pos, phys_t end, Sour
*target = data[*pos + 1] | (uint16_t)data[*pos] << 8;
-#else
+#endif
+
+ break;
+
+ case SRE_LITTLE_WORD:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
-# error "TODO : PDP !"
+ *target = data[*pos] << 8 | (uint16_t)data[*pos + 1];
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *target = data[*pos + 1] << 8 | (uint16_t)data[*pos];
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
+ case SRE_BIG_WORD:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *target = data[*pos + 1] << 8 | (uint16_t)data[*pos];
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *target = data[*pos] << 8 | (uint16_t)data[*pos + 1];
+
+#endif
+
break;
case SRE_BIG:
@@ -371,14 +378,13 @@ bool read_u16(uint16_t *target, const bin_t *data, phys_t *pos, phys_t end, Sour
*target = data[*pos] | (uint16_t)data[*pos + 1] << 8;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ return false;
+ break;
}
@@ -424,16 +430,40 @@ bool read_u32(uint32_t *target, const bin_t *data, phys_t *pos, phys_t end, Sour
*target = data[*pos + 3] | (uint32_t)data[*pos + 2] << 8;
*target |= data[*pos + 1] << 16 | (uint32_t)data[*pos] << 24;
-#else
+#endif
+
+ break;
+
+ case SRE_LITTLE_WORD:
-# error "TODO : PDP !"
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *target = data[*pos] << 8 | (uint32_t)data[*pos + 1];
+ *target |= data[*pos + 2] << 24 | (uint32_t)data[*pos + 3] << 16;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *target = data[*pos + 3] << 8 | (uint32_t)data[*pos + 2];
+ *target |= data[*pos + 1] << 24 | (uint32_t)data[*pos] << 16;
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
+ case SRE_BIG_WORD:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *target = data[*pos + 3] << 8 | (uint32_t)data[*pos + 2];
+ *target |= data[*pos + 1] << 24 | (uint32_t)data[*pos] << 16;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *target = data[*pos] << 8 | (uint32_t)data[*pos + 1];
+ *target |= data[*pos + 2] << 24 | (uint32_t)data[*pos + 3] << 16;
+
+#endif
+
break;
case SRE_BIG:
@@ -448,14 +478,13 @@ bool read_u32(uint32_t *target, const bin_t *data, phys_t *pos, phys_t end, Sour
*target = data[*pos] | (uint32_t)data[*pos + 1] << 8;
*target |= data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ return false;
+ break;
}
@@ -505,16 +534,48 @@ bool read_u64(uint64_t *target, const bin_t *data, phys_t *pos, phys_t end, Sour
*target |= (uint64_t)data[*pos + 3] << 32 | (uint64_t)data[*pos + 2] << 40;
*target |= (uint64_t)data[*pos + 1] << 48 | (uint64_t)data[*pos] << 56;
-#else
+#endif
+
+ break;
+
+ case SRE_LITTLE_WORD:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
-# error "TODO : PDP !"
+ *target = (uint64_t)data[*pos] << 8 | (uint64_t)data[*pos + 1];
+ *target |= (uint64_t)data[*pos + 2] << 24 | (uint64_t)data[*pos + 3] << 16;
+ *target |= (uint64_t)data[*pos + 4] << 40 | (uint64_t)data[*pos + 5] << 32;
+ *target |= (uint64_t)data[*pos + 6] << 56 | (uint64_t)data[*pos + 7] << 48;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *target = (uint64_t)data[*pos + 7] << 8 | (uint64_t)data[*pos + 6];
+ *target |= (uint64_t)data[*pos + 5] << 24 | (uint64_t)data[*pos + 4] << 16;
+ *target |= (uint64_t)data[*pos + 3] << 40 | (uint64_t)data[*pos + 2] << 32;
+ *target |= (uint64_t)data[*pos + 1] << 56 | (uint64_t)data[*pos] << 48;
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
+ case SRE_BIG_WORD:
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+ *target = (uint64_t)data[*pos + 7] << 8 | (uint64_t)data[*pos + 6];
+ *target |= (uint64_t)data[*pos + 5] << 24 | (uint64_t)data[*pos + 4] << 16;
+ *target |= (uint64_t)data[*pos + 3] << 40 | (uint64_t)data[*pos + 2] << 32;
+ *target |= (uint64_t)data[*pos + 1] << 56 | (uint64_t)data[*pos] << 48;
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+ *target = (uint64_t)data[*pos] << 8| (uint64_t)data[*pos + 1];
+ *target |= (uint64_t)data[*pos + 2] << 24 | (uint64_t)data[*pos + 3] << 16;
+ *target |= (uint64_t)data[*pos + 4] << 40 | (uint64_t)data[*pos + 5] << 32;
+ *target |= (uint64_t)data[*pos + 6] << 56 | (uint64_t)data[*pos + 7] << 48;
+
+#endif
+
break;
case SRE_BIG:
@@ -533,14 +594,13 @@ bool read_u64(uint64_t *target, const bin_t *data, phys_t *pos, phys_t end, Sour
*target |= (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40;
*target |= (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ return false;
+ break;
}
@@ -589,18 +649,10 @@ bool _write_un(const bin_t *value, size_t size, bin_t *data, off_t *pos, off_t e
for (i = 0; i < size; i++, (*pos)++)
*(data + *pos) = *(value + size - i - 1);
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
- case SRE_MIDDLE:
- return false; /* TODO ! */
- break;
-
case SRE_BIG:
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -613,14 +665,14 @@ bool _write_un(const bin_t *value, size_t size, bin_t *data, off_t *pos, off_t e
memcpy(&data[*pos], value, size);
(*pos) += size;
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ return false;
+ break;
+
}
return true;
@@ -785,18 +837,10 @@ bool _strtoun(uint8_t n, const char *data, size_t *pos, size_t end, SourceEndian
*target64 |= ((uint64_t)tmp) << (8 * (n - 1 - i));
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
- case SRE_MIDDLE:
- /* TODO */
- break;
-
case SRE_BIG:
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -807,14 +851,14 @@ bool _strtoun(uint8_t n, const char *data, size_t *pos, size_t end, SourceEndian
*target64 |= ((uint64_t)tmp) << (8 * i);
-#else
-
-# error "TODO : PDP !"
-
#endif
break;
+ default:
+ return false;
+ break;
+
}
}
diff --git a/src/common/endianness.h b/src/common/endianness.h
index 5ceb2ee..625b7fd 100755
--- a/src/common/endianness.h
+++ b/src/common/endianness.h
@@ -37,12 +37,14 @@
typedef enum _SourceEndian
{
SRE_LITTLE, /* Petits boutistes */
- SRE_MIDDLE, /* Moyens boutistes */
+ SRE_LITTLE_WORD, /* Moyens, façon Honeywell */
+ SRE_BIG_WORD, /* Moyens, façon PDP-11 */
SRE_BIG /* Gros boutistes */
} SourceEndian;
+
/* --------------------------- CONVERSION ENTRE BOUTISMES --------------------------- */
diff --git a/tests/analysis/contents/endian.py b/tests/analysis/contents/endian.py
new file mode 100644
index 0000000..209600a
--- /dev/null
+++ b/tests/analysis/contents/endian.py
@@ -0,0 +1,129 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+# Tests minimalistes pour valider le boutisme des accès mémoire.
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import FileContent, RestrictedContent
+from pychrysalide.arch import vmpa
+import tempfile
+
+
+class TestEndianness(ChrysalideTestCase):
+ """TestCase for analysis.BinContent."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(TestEndianness, cls).setUpClass()
+
+ cls._out = tempfile.NamedTemporaryFile()
+
+ cls._out.write(b'\x01\x02\x03\x04')
+ cls._out.write(b'\x05\x06\x07\x08')
+ cls._out.write(b'\x11\x12\x13\x14')
+ cls._out.write(b'\x15\x16\x17\x18')
+ cls._out.write(b'\x21\x22\x23\x24')
+ cls._out.write(b'\x25\x26\x27\x28')
+ cls._out.write(b'\x31\x32\x33\x34')
+ cls._out.write(b'\x35\x36\x37\x38')
+
+ cls._out.flush()
+
+ cls.log('Using temporary file "%s"' % cls._out.name)
+
+
+ @classmethod
+ def tearDownClass(cls):
+
+ super(TestEndianness, cls).tearDownClass()
+
+ cls.log('Delete file "%s"' % cls._out.name)
+
+ cls._out.close()
+
+
+ def testMiddleEndianness(self):
+ """Test some old endianness."""
+
+ fcnt = FileContent(self._out.name)
+
+ # 16 bits
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u16(start, vmpa.SRE_LITTLE_WORD)
+ self.assertEqual(val, 0x1516)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u16(start, vmpa.SRE_BIG_WORD)
+ self.assertEqual(val, 0x1615)
+
+ # 32 bits
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u32(start, vmpa.SRE_LITTLE_WORD)
+ self.assertEqual(val, 0x17181516)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u32(start, vmpa.SRE_BIG_WORD)
+ self.assertEqual(val, 0x16151817)
+
+ # 64 bits
+
+ start = vmpa(0, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u64(start, vmpa.SRE_LITTLE_WORD)
+ self.assertEqual(val, 0x0708050603040102)
+
+ start = vmpa(0, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u64(start, vmpa.SRE_BIG_WORD)
+ self.assertEqual(val, 0x0201040306050807)
+
+
+ def testEndianness(self):
+ """Test usual endianness."""
+
+ fcnt = FileContent(self._out.name)
+
+ # 16 bits
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u16(start, vmpa.SRE_LITTLE)
+ self.assertEqual(val, 0x1615)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u16(start, vmpa.SRE_BIG)
+ self.assertEqual(val, 0x1516)
+
+ # 32 bits
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u32(start, vmpa.SRE_LITTLE)
+ self.assertEqual(val, 0x18171615)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u32(start, vmpa.SRE_BIG)
+ self.assertEqual(val, 0x15161718)
+
+ # 64 bits
+
+ start = vmpa(0, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u64(start, vmpa.SRE_LITTLE)
+ self.assertEqual(val, 0x0807060504030201)
+
+ start = vmpa(0, vmpa.VMPA_NO_VIRTUAL)
+
+ val = fcnt.read_u64(start, vmpa.SRE_BIG)
+ self.assertEqual(val, 0x0102030405060708)