You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Original bug ID: 5509 Reporter: jm Status: closed (set by @xavierleroy on 2013-08-31T10:46:35Z) Resolution: fixed Priority: high Severity: major Platform: amd64 OS: Debian GNU/linux OS Version: squeeze Version: 3.13.0+dev Fixed in version: 3.13.0+dev Category: ~DO NOT USE (was: OCaml general)
as -o '/home/julm/tmp/camlstartup066daf.o' 't.native.startup.s'
gcc -o 't.native' '-L/usr/local/lib/ocaml' '/home/julm/tmp/camlstartup066daf.o' '/usr/local/lib/ocaml/std_exit.o' 't.o' '/usr/local/lib/ocaml/stdlib.a' '-Tt.o.ld' '-Wl,-M=t.native.ld-map' '/usr/local/lib/ocaml/libasmrun.a' -lm -ldl
grep camlT t.native.ld-map
0x0000000000403fa0 camlT__code_begin
0x0000000000403fa0 camlT__entry
0x0000000000403ffc camlT__code_end
0x000000000061efb4 . = (ALIGN (0x1000) + (0x1000 - ((camlT__data_end - camlT__data_begin) + 0x4)))
0x000000000061efb8 camlT__data_begin
0x000000000061efc0 camlT
0x000000000061efc8 camlT__1
0x000000000061f000 camlT__data_end
0x000000000061f004 camlT__frametable
gdb ./t.native
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see: http://www.gnu.org/software/gdb/bugs/...
Reading symbols from /home/julm/src/ocaml/bug/unregistered-gc-memory-page-with-empty-block-last-in-a-section-and-bad-luck/t.native...(no debugging symbols found)...done.
Breakpoint 1 at 0x407e65
Breakpoint 2 at 0x408c0d
caml_page_table_modify(page=0x629)
caml_page_table_modify(page=0x61b)
caml_page_table_modify(page=0x61b)
caml_page_table_modify(page=0x61c)
caml_page_table_modify(page=0x61e)
caml_page_table_modify(page=0x61b)
caml_equal(0x61eff8(page=0x61e),0x61f000(page=0x61f))
Fatal error: exception Assert_failure("t.ml", 1, 0)
Program exited with code 02.
(gdb) q
here one can see that the page=0x61f is not registered with caml_page_table_modify() in caml_main() despite that a caml value ([||]) is officially located in it (null size, at the begining, with its header in the previous page).
maybe the culprit is caml_page_table_add(), but i don't know:
=== 8< === byterun/memory.c
202 uintnat pend = ((uintnat) end - 1) & Page_mask;
=== >8 ===
till then that confuses Classify_addr() which reports that the [||] is outside the heap, which in turn confuses Is_in_value_area() then compare_val():
=== 8< === byterun/compare.c
148 /* If one of the objects is outside the heap (but is not an atom),
149 use address comparison. Since both addresses are 2-aligned,
150 shift lsb off to avoid overflow in subtraction. /
151 if (! Is_in_value_area(v1) || ! Is_in_value_area(v2)) {
152 if (v1 == v2) goto next_item;
153 return (v1 >> 1) - (v2 >> 1);
154 / Subtraction above cannot result in UNORDERED */
155 }
=== >8 ===
where that return makes the assert() fail.
naturally default.ld.patch is only there to reproduce by aligning the last [||] on a page end (multiple of 0x1000 = 2^12) ; and you may have to adapt it for your reproducing.
fyi, i originally hit this bug with Random.State.make [||] raising Division_by_zero when Lwt was initializing itself.
as a side note: i don't understand why more memory in .data is used for [||] instead of using the preallocated Atom(0).
The text was updated successfully, but these errors were encountered:
This is the most elaborate repro case I've seen. I'm in awe.
I just committed (rev. 12166) a simple fix. Because some assemblers/linkers dislike symbols that point "one past" the end of a section, the ocamlopt code emitters already put an extra zero word at the end of the static data segments. (Well, the I386/MASM emitter did not, but it's now fixed.) Given this, I just included this zero word in the data segment as it is passed to caml_page_table_modify. I'm pretty sure this should fix the issue, but let me know if it isn't the case.
Using the atom table for empty static blocks is another possibility. It would require more special-casing in the code emitters, though, and I'd have to check that it wouldn't raise issues with dynamic loading of .cmxs files (normally not, but I'm not 100% sure at this point).
Original bug ID: 5509
Reporter: jm
Status: closed (set by @xavierleroy on 2013-08-31T10:46:35Z)
Resolution: fixed
Priority: high
Severity: major
Platform: amd64
OS: Debian GNU/linux
OS Version: squeeze
Version: 3.13.0+dev
Fixed in version: 3.13.0+dev
Category: ~DO NOT USE (was: OCaml general)
Bug description
% head -n -0 t.ml default.ld.patch .gdbinit Makefile
==> t.ml <==
assert ([||] = [||])
==> default.ld.patch <==
--- default.ld 2012-02-18 03:19:46.739570701 +0100
+++ t.o.ld 2012-02-18 03:24:14.135564872 +0100
@@ -134,5 +126,11 @@
.data :
{
SORT(CONSTRUCTORS)
}
==> .gdbinit <==
break caml_page_table_modify if (($rdi>>12) <= 0xFFFF)
page <= 0xFFFF to avoid flood
commands
silent
printf "caml_page_table_modify(page=0x%x)\n",($rdi>>12)
continue
end
#break camlT__entry
break caml_equal
commands
silent
printf "caml_equal(0x%x(page=0x%x),0x%x(page=0x%x))\n",$rdi,($rdi>>12),$rsi,($rsi>>12)
continue
end
run
==> Makefile <==
.PHONY: t.native
all: t.native
c clean:
rm -f t.native t.native.ld-map t.native.startup.s map.ld t.cmi t.cmx t.o t.o.ld t.s
t.o.ld: default.ld.patch
ld --verbose | sed >$@ -ne '/^====/,/^====/{s/^====*$$//;p}'
patch -p0 <$< || rm $@
t.native: t.ml t.o.ld
ocamlopt -o $@ -verbose -S -dstartup -cclib -Tt.o.ld -cclib -Wl,-M=t.native.ld-map t.ml
grep camlT t.native.ld-map
gdb ./t.native
% make
ld --verbose | sed >t.o.ld -ne '/^====/,/^====/{s/^====*$//;p}'
patch -p0 <default.ld.patch || rm t.o.ld
patching file t.o.ld
ocamlopt -o t.native -verbose -S -dstartup -cclib -Tt.o.ld -cclib -Wl,-M=t.native.ld-map t.ml
grep camlT t.native.ld-map
0x0000000000403fa0 camlT__code_begin
0x0000000000403fa0 camlT__entry
0x0000000000403ffc camlT__code_end
0x000000000061efb4 . = (ALIGN (0x1000) + (0x1000 - ((camlT__data_end - camlT__data_begin) + 0x4)))
0x000000000061efb8 camlT__data_begin
0x000000000061efc0 camlT
0x000000000061efc8 camlT__1
0x000000000061f000 camlT__data_end
0x000000000061f004 camlT__frametable
gdb ./t.native
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/...
Reading symbols from /home/julm/src/ocaml/bug/unregistered-gc-memory-page-with-empty-block-last-in-a-section-and-bad-luck/t.native...(no debugging symbols found)...done.
Breakpoint 1 at 0x407e65
Breakpoint 2 at 0x408c0d
caml_page_table_modify(page=0x629)
caml_page_table_modify(page=0x61b)
caml_page_table_modify(page=0x61b)
caml_page_table_modify(page=0x61c)
caml_page_table_modify(page=0x61e)
caml_page_table_modify(page=0x61b)
caml_equal(0x61eff8(page=0x61e),0x61f000(page=0x61f))
Fatal error: exception Assert_failure("t.ml", 1, 0)
Program exited with code 02.
(gdb) q
here one can see that the page=0x61f is not registered with caml_page_table_modify() in caml_main() despite that a caml value ([||]) is officially located in it (null size, at the begining, with its header in the previous page).
maybe the culprit is caml_page_table_add(), but i don't know:
=== 8< === byterun/memory.c
202 uintnat pend = ((uintnat) end - 1) & Page_mask;
=== >8 ===
till then that confuses Classify_addr() which reports that the [||] is outside the heap, which in turn confuses Is_in_value_area() then compare_val():
=== 8< === byterun/compare.c
148 /* If one of the objects is outside the heap (but is not an atom),
149 use address comparison. Since both addresses are 2-aligned,
150 shift lsb off to avoid overflow in subtraction. /
151 if (! Is_in_value_area(v1) || ! Is_in_value_area(v2)) {
152 if (v1 == v2) goto next_item;
153 return (v1 >> 1) - (v2 >> 1);
154 / Subtraction above cannot result in UNORDERED */
155 }
=== >8 ===
where that return makes the assert() fail.
naturally default.ld.patch is only there to reproduce by aligning the last [||] on a page end (multiple of 0x1000 = 2^12) ; and you may have to adapt it for your reproducing.
fyi, i originally hit this bug with Random.State.make [||] raising Division_by_zero when Lwt was initializing itself.
as a side note: i don't understand why more memory in .data is used for [||] instead of using the preallocated Atom(0).
The text was updated successfully, but these errors were encountered: