Skip to content

Instantly share code, notes, and snippets.

@JayKickliter
Last active June 9, 2022 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JayKickliter/0afcba258445c7022a965878057b6d3c to your computer and use it in GitHub Desktop.
Save JayKickliter/0afcba258445c7022a965878057b6d3c to your computer and use it in GitHub Desktop.
Debugging enif_protobuf segfault

Steps

# The following three lines are from the erl wrapper, 
# which is usually called instead of erlexec itself
export ROOTDIR="/home/jay/.local/OTP-23.3.4.8-debug/lib/erlang"
export BINDIR=$ROOTDIR/erts-11.2.2.7/bin
export EMU=beam

cgdb ~/.local/OTP-23.3.4.8-debug/lib/erlang/erts-11.2.2.7/bin/erlexec

We can't set a breakpoint on a NIF which isn't loaded yet. So we first tell GDB to treat unknown breakpoints as pendind, then we set the breakpoint of the NIF we're interested in.

(gdb) set breakpoint pending on
(gdb) break ep_node.c:714 if spot->node == 0
No source file named ep_node.c.
Breakpoint 1 (ep_node.c:714 if spot->node == 0) pending.

Start the Erlang emulator and evaluate some source we know will lead to the NIF we're interested in.

(gdb) run -pa _build/default/checkouts/enif_protobuf/ebin -pa _build/default/lib/*/ebin/ -noshell -eval "enif_protobuf:load_cache(libp2p_peer_pb:get_proto_defs()), init:stop()"
Thread 5 "1_scheduler" hit Breakpoint 1, stack_ensure_all (env=0x7fffb447ed70, cache=0x7fffb60011f8) at /home/jay/he/erlanglibp2p/_build/default/lib/enif_protobuf/c_src/ep_node.c:714
(gdb) info locals
i = 0
j = 1
stack_size = 93824994084036
spot = 0x7fffb6002158
field = 0x7fffb6001788
stack = 0x7fffb6000bb8
state = 0x7fffb6000960
(gdb) p *spot
$1 = {
  type = 1,
  need_length = 0 '\000',
  sentinel_size = 0,
  pos = 0,
  node = 0x0,
  field = 0x0,
  array = 0x0,
  list = 0,
  t_arr = 0x0,
  t_size = 0,
  t_used = 0,
  result = 0,
  end_sentinel = 0x0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment