Skip to content

zig cc: Compiling with rdynamic and fvisibility options fails to find symbols #9701

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

Closed
greenfork opened this issue Sep 8, 2021 · 10 comments
Closed
Milestone

Comments

@greenfork
Copy link

I'm trying to compile https://github.com/janet-lang/janet on version v1.17.1 with latest zig 0.8.1 (same for 0.8.0). It works with gcc and clang. I use arch linux x64_86.

Steps to reproduce:

  1. git clone https://github.com/janet-lang/janet
  2. cd janet
  3. git checkout v1.17.1
  4. make CC='zig cc'
Output

zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/abstract.boot.o -c src/core/abstract.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/array.boot.o -c src/core/array.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/asm.boot.o -c src/core/asm.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/buffer.boot.o -c src/core/buffer.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/bytecode.boot.o -c src/core/bytecode.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/capi.boot.o -c src/core/capi.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/cfuns.boot.o -c src/core/cfuns.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/compile.boot.o -c src/core/compile.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/corelib.boot.o -c src/core/corelib.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/debug.boot.o -c src/core/debug.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/emit.boot.o -c src/core/emit.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/ev.boot.o -c src/core/ev.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/fiber.boot.o -c src/core/fiber.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/gc.boot.o -c src/core/gc.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/inttypes.boot.o -c src/core/inttypes.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/io.boot.o -c src/core/io.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/marsh.boot.o -c src/core/marsh.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/math.boot.o -c src/core/math.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/net.boot.o -c src/core/net.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/os.boot.o -c src/core/os.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/parse.boot.o -c src/core/parse.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/peg.boot.o -c src/core/peg.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/pp.boot.o -c src/core/pp.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/regalloc.boot.o -c src/core/regalloc.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/run.boot.o -c src/core/run.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/specials.boot.o -c src/core/specials.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/state.boot.o -c src/core/state.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/string.boot.o -c src/core/string.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/strtod.boot.o -c src/core/strtod.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/struct.boot.o -c src/core/struct.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/symcache.boot.o -c src/core/symcache.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/table.boot.o -c src/core/table.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/thread.boot.o -c src/core/thread.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/tuple.boot.o -c src/core/tuple.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/util.boot.o -c src/core/util.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/value.boot.o -c src/core/value.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/vector.boot.o -c src/core/vector.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/vm.boot.o -c src/core/vm.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/core/wrap.boot.o -c src/core/wrap.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/boot/array_test.boot.o -c src/boot/array_test.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/boot/boot.boot.o -c src/boot/boot.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/boot/buffer_test.boot.o -c src/boot/buffer_test.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/boot/number_test.boot.o -c src/boot/number_test.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/boot/system_test.boot.o -c src/boot/system_test.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/boot/table_test.boot.o -c src/boot/table_test.c
zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/janet_boot build/core/abstract.boot.o build/core/array.boot.o build/core/asm.boot.o build/core/buffer.boot.o build/core/bytecode.boot.o build/core/capi.boot.o build/core/cfuns.boot.o build/core/compile.boot.o build/core/corelib.boot.o build/core/debug.boot.o build/core/emit.boot.o build/core/ev.boot.o build/core/fiber.boot.o build/core/gc.boot.o build/core/inttypes.boot.o build/core/io.boot.o build/core/marsh.boot.o build/core/math.boot.o build/core/net.boot.o build/core/os.boot.o build/core/parse.boot.o build/core/peg.boot.o build/core/pp.boot.o build/core/regalloc.boot.o build/core/run.boot.o build/core/specials.boot.o build/core/state.boot.o build/core/string.boot.o build/core/strtod.boot.o build/core/struct.boot.o build/core/symcache.boot.o build/core/table.boot.o build/core/thread.boot.o build/core/tuple.boot.o build/core/util.boot.o build/core/value.boot.o build/core/vector.boot.o build/core/vm.boot.o build/core/wrap.boot.o build/boot/array_test.boot.o build/boot/boot.boot.o build/boot/buffer_test.boot.o build/boot/number_test.boot.o build/boot/system_test.boot.o build/boot/table_test.boot.o -lm -lpthread -lrt -ldl
build/janet_boot . JANET_PATH '/usr/local/lib/janet' > build/c/janet.c
make: *** [Makefile:154: build/c/janet.c] Error 132
  1. Run again for better errors make CC='zig cc'
Output Formatting is a bit off, github interprets `>>>` as a quote

zig cc -DJANET_BOOTSTRAP -DJANET_BUILD="\"e1c4fc29\"" -O0 -g -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/janet_boot build/core/abstract.boot.o build/core/array.boot.o build/core/asm.boot.o build/core/buffer.boot.o build/core/bytecode.boot.o build/core/capi.boot.o build/core/cfuns.boot.o build/core/compile.boot.o build/core/corelib.boot.o build/core/debug.boot.o build/core/emit.boot.o build/core/ev.boot.o build/core/fiber.boot.o build/core/gc.boot.o build/core/inttypes.boot.o build/core/io.boot.o build/core/marsh.boot.o build/core/math.boot.o build/core/net.boot.o build/core/os.boot.o build/core/parse.boot.o build/core/peg.boot.o build/core/pp.boot.o build/core/regalloc.boot.o build/core/run.boot.o build/core/specials.boot.o build/core/state.boot.o build/core/string.boot.o build/core/strtod.boot.o build/core/struct.boot.o build/core/symcache.boot.o build/core/table.boot.o build/core/thread.boot.o build/core/tuple.boot.o build/core/util.boot.o build/core/value.boot.o build/core/vector.boot.o build/core/vm.boot.o build/core/wrap.boot.o build/boot/array_test.boot.o build/boot/boot.boot.o build/boot/buffer_test.boot.o build/boot/number_test.boot.o build/boot/system_test.boot.o build/boot/table_test.boot.o -lm -lpthread -lrt -ldl
zig cc -O2 -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -c build/c/janet.c -o build/janet.o
cp src/mainclient/shell.c build/c/shell.c
zig cc -O2 -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -c build/c/shell.c -o build/shell.o
zig cc -rdynamic -O2 -std=c99 -Wall -Wextra -Isrc/include -Isrc/conf -fvisibility=hidden -fPIC -o build/janet build/janet.o build/shell.o -lm -lpthread -lrt -ldl
ld.lld: error: undefined symbol: janet_arity
>>> referenced by shell.c
>>>               build/shell.o:(janet_line_getter)

ld.lld: error: undefined symbol: janet_getstring

referenced by shell.c
build/shell.o:(janet_line_getter)

ld.lld: error: undefined symbol: janet_getbuffer

referenced by shell.c
build/shell.o:(janet_line_getter)

ld.lld: error: undefined symbol: janet_gettable

referenced by shell.c
build/shell.o:(janet_line_getter)

ld.lld: error: undefined symbol: janet_buffer

referenced by shell.c
build/shell.o:(janet_line_getter)

ld.lld: error: undefined symbol: janet_csymbol

referenced by shell.c
build/shell.o:(janet_line_getter)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced 8 more times

ld.lld: error: undefined symbol: janet_nanbox_from_cpointer

referenced by shell.c
build/shell.o:(janet_line_getter)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced 10 more times

ld.lld: error: undefined symbol: janet_nanbox_from_pointer

referenced by shell.c
build/shell.o:(janet_line_getter)
referenced by shell.c
build/shell.o:(main)
referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_dynfile

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_buffer_push_u8

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(refresh)

ld.lld: error: undefined symbol: janet_symbol

referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_table_get

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced 5 more times

ld.lld: error: undefined symbol: janet_nanbox_to_pointer

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced 4 more times

ld.lld: error: undefined symbol: janet_nanbox_from_bits

referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_dynprintf

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_nanbox_from_double

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_get

referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)
referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_buffer_ensure

referenced by shell.c
build/shell.o:(janet_line_get)

ld.lld: error: undefined symbol: janet_init

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_table

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_table_put

referenced by shell.c
build/shell.o:(main)
referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_core_env

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_array

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_cstring

referenced by shell.c
build/shell.o:(main)
referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_array_push

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_resolve

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_fiber

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_loop_fiber

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_deinit

referenced by shell.c
build/shell.o:(main)

ld.lld: error: undefined symbol: janet_buffer_init

referenced by shell.c
build/shell.o:(refresh)

ld.lld: error: undefined symbol: janet_buffer_push_cstring

referenced by shell.c
build/shell.o:(refresh)
referenced by shell.c
build/shell.o:(refresh)
referenced by shell.c
build/shell.o:(refresh)

ld.lld: error: undefined symbol: janet_buffer_push_bytes

referenced by shell.c
build/shell.o:(refresh)

ld.lld: error: undefined symbol: janet_buffer_deinit

referenced by shell.c
build/shell.o:(refresh)
make: *** [Makefile:179: build/janet] Error 1

@marler8997
Copy link
Contributor

Interesting. I stepped through the execution with GDB and found that in the push_traversal_node function in value.c, the top-level if statement evaluates to false, then it jumps past the end of the function where it executes and "undefined instruction". I'll see if I can find more, maybe come up with a minimal reproduction example.

@marler8997
Copy link
Contributor

marler8997 commented Sep 8, 2021

Here's a minimal reproduction:

int main() {
  int *traversal = 0;
  *(++traversal) = 0;
  return 0;
}
$ zig cc issue.c
$ ./a.out
Illegal instruction (core dumped)

This goldbolt link should show the bad assembly that's produced: https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:___c,selection:(endColumn:2,endLineNumber:5,positionColumn:2,positionLineNumber:5,selectionStartColumn:2,selectionStartLineNumber:5,startColumn:2,startLineNumber:5),source:'int+main()+%7B%0A++int+*traversal+%3D+0%3B%0A++*(%2B%2Btraversal)+%3D+0%3B%0A++return+0%3B%0A%7D'),l:'5',n:'0',o:'C+source+%231',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:zcc080,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:___c,libs:!(),options:'',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'zig+cc+0.8.0+(C,+Editor+%231,+Compiler+%231)',t:'0'),(h:output,i:(compiler:1,editor:1,fontScale:14,fontUsePx:'0',wrap:'1'),l:'5',n:'0',o:'Output+of+zig+cc+0.8.0+(Compiler+%231)',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4

main:
 push   rbp
 mov    rbp,rsp
 ud1    eax,DWORD PTR [eax+0x13]
 int3   
 int3   
 int3   
 int3   
 int3   
 int3   
 int3   

The ud1 instruction is an undefined instruction which is what is triggering the illegal instruction signal. Note that this is what clang 12.0.1 produces:

main:                                   # @main
        push    rbp
        mov     rbp, rsp
        mov     dword ptr [rbp - 4], 0
        mov     qword ptr [rbp - 16], 0
        mov     rax, qword ptr [rbp - 16]
        mov     rcx, rax
        add     rcx, 4
        mov     qword ptr [rbp - 16], rcx
        mov     dword ptr [rax + 4], 0
        xor     eax, eax
        pop     rbp
        ret

@marler8997
Copy link
Contributor

marler8997 commented Sep 8, 2021

Ok it looks like clang will also produce this undefined instruction with the following compilation options:

-fsanitize=undefined -fsanitize-trap=undefined -Og

See:
https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:___c,selection:(endColumn:2,endLineNumber:5,positionColumn:2,positionLineNumber:5,selectionStartColumn:2,selectionStartLineNumber:5,startColumn:2,startLineNumber:5),source:'int+main()+%7B%0A++int+*traversal+%3D+0%3B%0A++*(%2B%2Btraversal)+%3D+0%3B%0A++return+0%3B%0A%7D'),l:'5',n:'0',o:'C+source+%231',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:cclang1201,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:___c,libs:!(),options:'-fsanitize%3Dundefined+-fsanitize-trap%3Dundefined+-Og',selection:(endColumn:38,endLineNumber:2,positionColumn:38,positionLineNumber:2,selectionStartColumn:38,selectionStartLineNumber:2,startColumn:38,startLineNumber:2),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+clang+12.0.1+(C,+Editor+%231,+Compiler+%231)',t:'0'),(h:output,i:(compiler:1,editor:1,fontScale:14,fontUsePx:'0',wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+clang+12.0.1+(Compiler+%231)',t:'0')),k:50,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4

main:                                   # @main
        ud1 eax, dword ptr [eax + 19]

I found this combination of clang options by using ZIG_VERBOSE_CC=1 and taking all the clang options and minimizing them.

This is looking like it might be a bug with Clang. We should confirm this and if true create an issue upstream.

@marler8997
Copy link
Contributor

By the way you can get around this issue by disabling undefined behavior sanitization:

make CC='zig cc -fno-sanitize=undefined'

This brings me to an error about ar not being defined, so you can fix that with this:

make CC='zig cc -fno-sanitize=undefined' AR='zig ar'

@N00byEdge
Copy link
Contributor

This isn't a bug, dereferencing null is UB in C++, right?

@alexrp
Copy link
Member

alexrp commented Sep 8, 2021

That looks like legitimate UB that UBSan is catching to me.

Try building with -fno-delete-null-pointer-checks and see what happens? I think this is the flag you're supposed to use if you're developing for environments where dereferencing null (or pointers derived from it) is valid.

@marler8997
Copy link
Contributor

@N00byEdge yes it looks like I minimized the example too much. The original code that causes the undefined instruction is not dereferencing NULL. The actual UB comes from this code:

static void push_traversal_node(void *lhs, void *rhs, int32_t index2) {
    JanetTraversalNode node;
    node.self = (JanetGCObject *) lhs;
    node.other = (JanetGCObject *) rhs;
    node.index = 0;
    node.index2 = index2;
    if (janet_vm.traversal + 1 >= janet_vm.traversal_top) {
        size_t oldsize = janet_vm.traversal - janet_vm.traversal_base;
        size_t newsize = 2 * oldsize + 1;
        if (newsize < 128) {
            newsize = 128;
        }
        JanetTraversalNode *tn = janet_realloc(janet_vm.traversal_base, newsize * sizeof(JanetTraversalNode));
        if (tn == NULL) {
            JANET_OUT_OF_MEMORY;
        }
        janet_vm.traversal_base = tn;
        janet_vm.traversal_top = janet_vm.traversal_base + newsize;
        janet_vm.traversal = janet_vm.traversal_base + oldsize;
    }
    *(++janet_vm.traversal) = node;
}

I minified this again and came up with this:

int main() {
  int *start = 0;
  int *next = start + 1;
  return 0;
}

Relating this back to the original code, it looks like the problem occurs when you perform a pointer/int addition and the pointer is set to 0 (or NULL). As you can see from the original code, they check whether the traversal buffer has space by checking if it is greater than traversal_top:

    if (janet_vm.traversal + 1 >= janet_vm.traversal_top) {

It appears this is where the UB occurs, since when the janet VM is initialized traversal is NULL. So it looks like Clang is able to figure out that when this function is called, traversal will always be 0 the first time through, and so it flags this situation as UB?

@marler8997
Copy link
Contributor

Thanks for @MasterQ32 , he informed me that pointer arithmetic on a NULL pointer is UB. So this is not a bug with clang.

One thing to note is that the user experience that comes from -fsanitize-trap=X is not very good. It would be wonderful if Zig could turn these into panics and print a stack trace!

@N00byEdge
Copy link
Contributor

One thing to note is that the user experience that comes from -fsanitize-trap=X is not very good. It would be wonderful if Zig could turn these into panics and print a stack trace!

Yeah definitely would be the case, but that sounds like a lot of effort just for another language than the compiler is targetting. Sounds like something that could be achieved by creating ubsan hooks in zig though instead of using traps/ud, so may not be that bad when using llvm.

@greenfork
Copy link
Author

@marler8997 thank you for the quick response and your research! I successfully used your suggested command to build the binary, and since this is a bug in Janet source code, I believe the issue can be closed.

@andrewrk andrewrk added this to the 0.9.0 milestone Nov 20, 2021
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

5 participants