summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAhmad Fatoum <[email protected]>2018-02-24 23:46:27 +0100
committerAhmad Fatoum <[email protected]>2018-02-24 23:59:56 +0100
commit1430d0190684c6f78e1bce759eae240c94fba61c (patch)
treebdf0709f9a75a25a805845997b0e356b6580bcfd
parent6026ed61a5eaa43df4b2a91c8c47c8f2661d47de (diff)
downloadraylib-1430d0190684c6f78e1bce759eae240c94fba61c.tar.gz
raylib-1430d0190684c6f78e1bce759eae240c94fba61c.zip
jar_xm: Workaround for unaligned pointer accesses
jar_xm.h does some shady pointer casts leading to unaligned accesses and breaking strict aliasing. x86 has special circuitry for doing unaligned accesses, but on other architectures, it may trap and require kernel fix-up or crash outright. With this patch, one obstacle in porting raylib to the GameBoy Advance has been removed. Go for it ;-) To avoid having to rewrite that `mempool' code, insert padding before structs and instruct the compiler (GCC, most importantly), to be gentle when optimizing. This fixes #490 (Unless we got ourselves 256-bit pointers, if so, hello future!)
-rwxr-xr-xCMakeLists.txt2
-rw-r--r--src/Makefile4
-rw-r--r--src/external/jar_xm.h11
3 files changed, 16 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0e70eab4..1d98ffea 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,6 +29,8 @@ endfunction()
add_if_flag_works(-Werror=pointer-arith CMAKE_C_FLAGS)
add_if_flag_works(-Werror=implicit-function-declaration CMAKE_C_FLAGS)
+# src/external/jar_xm.h does shady stuff
+add_if_flag_works(-fno-strict-aliasing CMAKE_C_FLAGS)
if (ENABLE_ASAN)
add_if_flag_works(-fno-omit-frame-pointer CMAKE_C_FLAGS CMAKE_LINKER_FLAGS)
diff --git a/src/Makefile b/src/Makefile
index e001b4ef..53551174 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -291,7 +291,9 @@ endif
# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
# -Werror=pointer-arith catch unportable code that does direct arithmetic on void pointers
-CFLAGS += -O1 -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Werror=pointer-arith
+# -fno-strict-aliasing jar_xm.h does shady stuff (breaks strict aliasing)
+CFLAGS += -O1 -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Werror=pointer-arith
+-fno-strict-aliasing
ifeq ($(RAYLIB_BUILD_MODE), DEBUG)
CFLAGS += -g
diff --git a/src/external/jar_xm.h b/src/external/jar_xm.h
index 15b31fd0..df199e06 100644
--- a/src/external/jar_xm.h
+++ b/src/external/jar_xm.h
@@ -612,6 +612,8 @@ int jar_xm_create_context(jar_xm_context_t** ctxp, const char* moddata, uint32_t
return jar_xm_create_context_safe(ctxp, moddata, SIZE_MAX, rate);
}
+#define ALIGN(x, b) (((x) + ((b) - 1)) & ~((b) - 1))
+#define ALIGN_PTR(x, b) (void*)(((uintptr_t)(x) + ((b) - 1)) & ~((b) - 1))
int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, size_t moddata_length, uint32_t rate) {
#if JAR_XM_DEFENSIVE
int ret;
@@ -644,9 +646,11 @@ int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, siz
ctx->rate = rate;
mempool = jar_xm_load_module(ctx, moddata, moddata_length, mempool);
+ mempool = ALIGN_PTR(mempool, 16);
ctx->channels = (jar_xm_channel_context_t*)mempool;
mempool += ctx->module.num_channels * sizeof(jar_xm_channel_context_t);
+ mempool = ALIGN_PTR(mempool, 16);
ctx->global_volume = 1.f;
ctx->amplification = .25f; /* XXX: some bad modules may still clip. Find out something better. */
@@ -671,6 +675,7 @@ int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, siz
ch->actual_panning = .5f;
}
+ mempool = ALIGN_PTR(mempool, 16);
ctx->row_loop_count = (uint8_t*)mempool;
mempool += MAX_NUM_ROWS * sizeof(uint8_t);
@@ -856,9 +861,11 @@ size_t jar_xm_get_memory_needed_for_context(const char* moddata, size_t moddata_
num_patterns = READ_U16(offset + 10);
memory_needed += num_patterns * sizeof(jar_xm_pattern_t);
+ memory_needed = ALIGN(memory_needed, 16);
num_instruments = READ_U16(offset + 12);
memory_needed += num_instruments * sizeof(jar_xm_instrument_t);
+ memory_needed = ALIGN(memory_needed, 16);
memory_needed += MAX_NUM_ROWS * READ_U16(offset + 4) * sizeof(uint8_t); /* Module length */
@@ -875,6 +882,7 @@ size_t jar_xm_get_memory_needed_for_context(const char* moddata, size_t moddata_
/* Pattern header length + packed pattern data size */
offset += READ_U32(offset) + READ_U16(offset + 7);
}
+ memory_needed = ALIGN(memory_needed, 16);
/* Read instrument headers */
for(uint16_t i = 0; i < num_instruments; ++i) {
@@ -940,9 +948,11 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd
mod->patterns = (jar_xm_pattern_t*)mempool;
mempool += mod->num_patterns * sizeof(jar_xm_pattern_t);
+ mempool = ALIGN_PTR(mempool, 16);
mod->instruments = (jar_xm_instrument_t*)mempool;
mempool += mod->num_instruments * sizeof(jar_xm_instrument_t);
+ mempool = ALIGN_PTR(mempool, 16);
uint16_t flags = READ_U32(offset + 14);
mod->frequency_type = (flags & (1 << 0)) ? jar_xm_LINEAR_FREQUENCIES : jar_xm_AMIGA_FREQUENCIES;
@@ -1032,6 +1042,7 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd
offset += packed_patterndata_size;
}
+ mempool = ALIGN_PTR(mempool, 16);
/* Read instruments */
for(uint16_t i = 0; i < ctx->module.num_instruments; ++i) {