Bug 5484 – GC segfaults on FreeBSD 64 / scanning issues for .data and .bss sections

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
druntime
Product
D
Version
D2
Platform
x86_64
OS
FreeBSD
Creation time
2011-01-25T11:34:00Z
Last change time
2011-06-03T22:10:36Z
Assigned to
nobody
Creator
code

Attachments

IDFilenameSummaryContent-TypeSize
877section_headers_64elf64-x86-64-freebsdtext/plain4284
878section_headers_32elf32-i386-freebsdtext/plain3754

Comments

Comment #0 by code — 2011-01-25T11:34:53Z
Created attachment 877 elf64-x86-64-freebsd IMHO FreeBSD is missing _data__start/_data__end/_bss_start__/_bss_end__ symbols. The current strategy is to use etext and _end as scanning range. From compiling "void main() {}" -m32: nm out | grep etext -> 08055b38 A etext nm out | grep _end -> 0805ba04 A _end -m64: nm out | grep etext -> 0000000000411012 A etext nm out | grep _end -> 0000000000619988 A _end This is not optimal as it spans over some read only sections but it's a minor issue for 32. With elf64-x86-64-freebsd there is a big non-readable area between .eh_frame and .tdata. This leads to segfaulting when running the garbage collector. I don't know any portable/official solution to this but observed that _progname is always the first symbol in .data for 32/64 bit. The boehm collector is installing a signal handler and tries to read from _end upwards until it fails. I've appended objdump section headers.
Comment #1 by code — 2011-01-25T11:35:56Z
Created attachment 878 elf32-i386-freebsd
Comment #2 by braddr — 2011-05-22T22:19:02Z
Here's the change I'm proposing for druntime, based on your previous data and from inspection of current binaries. So far, testing looks promising: diff --git a/src/rt/memory.d b/src/rt/memory.d index ccf3c57..b32dfab 100644 --- a/src/rt/memory.d +++ b/src/rt/memory.d @@ -202,8 +202,19 @@ private { extern __gshared { - int etext; - int _end; + size_t etext; + size_t _end; + } + } + version (X86_64) + { + extern (C) + { + extern __gshared + { + size_t _deh_end; + size_t __progname; + } } } } @@ -237,7 +248,8 @@ void initStaticDataGC() } else version( FreeBSD ) { - gc_addRange( &etext, cast(size_t) &_end - cast(size_t) &etext ); + gc_addRange( &etext, cast(size_t) &_deh_end - cast(size_t) &etext ); + gc_addRange( &__progname, cast(size_t) &_end - cast(size_t) &__progname ); } else version( Solaris ) {
Comment #3 by braddr — 2011-05-22T22:19:37Z
*** Issue 6008 has been marked as a duplicate of this issue. ***
Comment #4 by code — 2011-06-02T21:34:19Z
Why is it that etext -> _deh_end is scanned? Can readonly sections be the only root of dynamic memory pointers? I'm also unsure about the TLS sections, will investigate this.
Comment #5 by braddr — 2011-06-02T21:46:14Z
(In reply to comment #4) > Why is it that etext -> _deh_end is scanned? Can readonly sections be the only > root of dynamic memory pointers? I'm also unsure about the TLS sections, will > investigate this. I tried to be as conservative as I could with removing ranges from what's being scanned on every other platform.