Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeError: memory access out of bounds inside posix_memalign, is there any way to have a libc with debug symbols? #13131

Closed
rubu opened this issue Dec 29, 2020 · 6 comments

Comments

@rubu
Copy link

rubu commented Dec 29, 2020

So I am getting RuntimeError: memory access out of bounds while trying to build dav1d to wasm. I forked an existing project which seems to be abandoned at the beginning of 2019 (and since I had to tweak a lot of build flags to make it work with the latest emscripten I assume it did work and maybe some breaking changes are causing this). My fork can be found here to see the build flags etc. Now that I have all the debug stuff enabled can nicely see the stack trace:

RuntimeError: memory access out of bounds
    at SAFE_HEAP_LOAD_i32_4_4 (http://localhost:8000/dav1d.debug.wasm:wasm-function[744]:0x140e9f)
    at attempt_allocate(Region*, unsigned long, unsigned long) (http://localhost:8000/dav1d.debug.wasm:wasm-function[691]:0x13fd17)
    at emmalloc_memalign (http://localhost:8000/dav1d.debug.wasm:wasm-function[690]:0x13fb62)
    at posix_memalign (http://localhost:8000/dav1d.debug.wasm:wasm-function[698]:0x1403fb)
    at dav1d_alloc_aligned.3 (http://localhost:8000/dav1d.debug.wasm:wasm-function[626]:0x1378e5)
    at dav1d_open (http://localhost:8000/dav1d.debug.wasm:wasm-function[624]:0x136994)
    at djs_init (http://localhost:8000/dav1d.debug.wasm:wasm-function[642]:0x13b19b)
    at Dav1d._init (http://localhost:8000/dav1d.mjs:99:25)
    at http://localhost:8000/dav1d.mjs:80:7
    at async http://localhost:8000/test.mjs:31:13

It seems that inside SAFE_HEAP_LOAD_i32_4_4 the i32.load instruction is called with -4 on the stack, so the error makes sense. But that seems to happen inside libc. I'm attaching screenshots form each of the stack frames, but the call from the C code seems quite naive - posix_memalign is called with 3536 as the size and 32 as the alignment, and those values seem to work in a trivial example. Also, my segfault handler is called befor that happens, which also makes sense since there is a call $segfault in SAFE_HEAP_LOAD_i32_4_4 before the load. I would assume that to debug this I would need a wasm libc built with -g4 as well? How does one do that? I Googled a lot but the Emscripten pages mention building llvm but not the toolchain.

Here is the faulting region in SAFE_HEAP_LOAD_i32_4_4:
Screenshot 2020-12-29 at 18 28 50
Here is attempt_allocate:
Screenshot 2020-12-29 at 18 29 05
Here is posix_memalign:
Screenshot 2020-12-29 at 18 29 24

@sbc100
Copy link
Collaborator

sbc100 commented Dec 29, 2020

I have a PR open to add debug symbols to all system libraries: #13078

@rubu
Copy link
Author

rubu commented Dec 29, 2020

@sbc100 thanks:) Is there anything else I can do to dig deeper? I am quite new to WebAssembly but quite good with C++ and have learned a lot during the last two days starting from 0 :D My biggest issue here is that I really can't map the instructions I see with the code in emmalloc.cpp, so I can't locate the faulty region (and I assume this version of runtime I am getting is also heavily optimized).

@sbc100
Copy link
Collaborator

sbc100 commented Dec 29, 2020

Is there some reason you are building with emmalloc (-s MALLOC=emmalloc) rather than the default allocator (dlmalloc)?

Normally an error like this that shows up in the allocator is a sign or memory corruptions somewhere else, since bugs in the allocators are fairly unlikely. You could try building with --sanitize=address to see that that reports any issues at runtime.

@rubu
Copy link
Author

rubu commented Dec 29, 2020

That part was from the original code, but I can try changing that. And yeah, I tried AddressSantizer since it helps in most cases, but when that is turned on i get a warning from the dav1d lib that aligned malloc is not available:

#if defined(HAVE_ALIGNED_MALLOC) || defined(HAVE_MEMALIGN)
#include <malloc.h>
#endif

/*
 * Allocate 32-byte aligned memory. The return value can be released
 * by calling the standard free() function.
 */
static inline void *dav1d_alloc_aligned(size_t sz, size_t align) {
#ifdef HAVE_POSIX_MEMALIGN
    void *ptr;
    assert(!(align & (align - 1)));
    if (posix_memalign(&ptr, align, sz)) return NULL;
    return ptr;
#elif defined(HAVE_ALIGNED_MALLOC)
    return _aligned_malloc(sz, align);
#elif defined(HAVE_MEMALIGN)
    return memalign(align, sz);
#else
#error Missing aligned alloc implementation
#endif
}

During my tons of reading I stumbled upon your comment in another issue where you mentioned that toggling features actually change the libc being used, so I would assume that sanitized libc does not conain this? Also I am now quite confused that the original author had sbrk() in the original js, which does not make sense to me since while debugging the instructions in the runtime I see that emscripten embeds it's own version.

@sbc100 sorry if I sound pushy, but may I contact you in the Discord channel at any convenient for you for more pointer? And thanks for all the answers so far.

@rubu
Copy link
Author

rubu commented Dec 29, 2020

@sbc100 oh wow, removing -s MALLOC=emmalloc got me much further :) Thanks, well I thought that the stuff that was in that repo was there for a reason. Thank you very much. Will have to look into how malloc is implemented to understand the difference.

@rubu
Copy link
Author

rubu commented Dec 29, 2020

Closing this since changing the allocator fixed, and +1 for the feature to have system libs with debug info.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants