summaryrefslogtreecommitdiffstats
path: root/src/include/unaligned_memory.h
diff options
context:
space:
mode:
authorMatias Larsson <matias.larsson@matthews.se>2022-11-24 18:22:55 +0100
committerPeng Wu <alexepico@gmail.com>2022-11-29 16:16:21 +0800
commit8bcea4710bd328ef74dc852d9fdffb3c47ed8abe (patch)
tree88a92418b2408d31aeb5ae21d04a5ae1c4ce4a8d /src/include/unaligned_memory.h
parent521340f02907dae96f6f13dbf7997a34ebe864f2 (diff)
downloadlibpinyin-8bcea4710bd328ef74dc852d9fdffb3c47ed8abe.tar.gz
libpinyin-8bcea4710bd328ef74dc852d9fdffb3c47ed8abe.tar.xz
libpinyin-8bcea4710bd328ef74dc852d9fdffb3c47ed8abe.zip
Fix libpinyin crash on ARMv7
Fix the alignment trap in get_unigram_frequency(). Fix also other places where this same trap could happen (depending on compiler and surrounding code). The trap happened when the ARM GCC generated a SIMD instruction (specifically VLDR) to load 32 bits in a single instruction, and when the memory address was not aligned to 32 bits. VLDR traps if the address is not aligned. GCC generated the instruction because of the cast to uint32 from the address. The fix is to allocate a uint32 variable in stack and use memcpy to copy the data to that variable. This way we ensure that appropriate instructions are generated. **Links** About the issue with GCC: https://trust-in-soft.com/blog/2020/04/06/gcc-always-assumes-aligned-pointer-accesses/ How Linux does it: https://elixir.bootlin.com/linux/v5.10.155/source/include/linux/unaligned/memmove.h#L13 ARM documentation: https://documentation-service.arm.com/static/5f8dc043f86e16515cdbbc92?token= See 'A3.2.1 Unaligned data access'
Diffstat (limited to 'src/include/unaligned_memory.h')
-rw-r--r--src/include/unaligned_memory.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/include/unaligned_memory.h b/src/include/unaligned_memory.h
new file mode 100644
index 0000000..27b2f19
--- /dev/null
+++ b/src/include/unaligned_memory.h
@@ -0,0 +1,43 @@
+#ifndef UNALIGNED_MEMORY_H
+#define UNALIGNED_MEMORY_H
+
+#include <cstring>
+
+/**
+ * UnalignedMemory: Safe unaligned memory access.
+ *
+ * Some instruction sets, or some instructions in some instruction sets
+ * require that memory access is aligned to a specific boundary. These
+ * instructions may trap on unaligned access.
+ *
+ * This class provides methods to load and store values at unaligned
+ * addresses. It ensures that the compiler doesn't generate instructions
+ * that could trap on the unaligned memory access.
+ */
+
+namespace pinyin{
+ template <typename T>
+ class UnalignedMemory{
+ public:
+ /**
+ * Read a value from a possibly unaligned memory address.
+ *
+ */
+ static T load(const void * src) {
+ T value;
+ memcpy(&value, src, sizeof(T));
+ return value;
+ }
+
+ /**
+ * Store a value into a possibly unaligned memory address.
+ *
+ */
+ static void store(T value, void * dest) {
+ memcpy(dest, &value, sizeof(T));
+ }
+ };
+};
+
+
+#endif