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
What steps will reproduce the problem?
GNU ld exports the symbol _end to mark the address of the end of the data sections. This
can be used as a way to programmatically get at the start of the heap (see
http://stackoverflow.com/questions/3565232/how-to-programmatically-get-the-address-of-the-heap-on-linux).
If a shared library wrapped with cgo is expecting _end to exist, the address of _end
appears to be relocated.
An example:
First create libfoo.so:
bash$ cat foo.h
int foo(void);
bash$ cat foo.c
#include <stdio.h>
#include <stdlib.h>
char *ppp1 = "hello world";
char ppp0[] = "hello world";
extern void *_end; /* any type would do, only its address is important */
int foo() {
void *p = calloc(10000,1);
printf( "end:%p heap:%p rodata:%p data:%p\n", &_end, p, ppp1, ppp0 );
return 0;
}
bash$ gcc -fPIC -shared foo.c -o libfoo.so
What is the expected output?
Using a gcc-compiled c program, note that end is below the heap.
bash$ cat tmp.c
#include "foo.h"
int main() {
return foo();
}
bash$ gcc tmp.c -L. -lfoo
bash$ LD_LIBRARY_PATH=. ./a.out
end:0x6009d8 heap:0x13ac010 rodata:0x7fe97df7c758 data:0x7fe97e17ca00
What do you see instead?
Using cgo, end is relocated with libfoo:
bash$ cat tmp.go
package main
/*
#cgo LDFLAGS: -L. -lfoo
#include "foo.h"
*/
import "C"
func main() {
C.foo()
}
bash$ go build tmp.go
bash$ LD_LIBRARY_PATH=. ./tmp
end:0x7f0b9486fa28 heap:0x2d61160 rodata:0x7f0b9466f758 data:0x7f0b9486fa00
Which compiler are you using (5g, 6g, 8g, gccgo)?
6g
Which operating system are you using?
Linux/amd64
Which version are you using? (run 'go version')
go1
Please provide any additional information below.
My first inclination is "libraries shouldn't do this - it sure looks like a nasty
hack". However, I've seen at least one library (that I'm not in a position to
modify) that expects this to work, and I currently can't wrap it with cgo. I wonder if
6l should be exporting all of the pseudo-magic symbols that GNU ld does, at least on
Linux. It looks like GNU ld exports at least _end, end, _edata, and __bss_start, all of
which are included as "ABSOLUTE" symbols in .dynsym and .symtab; the binaries
compiled with go build don't export any absolute symbols.
The text was updated successfully, but these errors were encountered:
I don't believe we should fix this. Programs that care about _end are
almost always
doing it to make assumptions that Go violates. For example, one common use of
_end is to then use sbrk for memory allocation, and that could easily
conflict with
memory that Go has already allocated.
What library does this?
This is not going to work in general.
If you have to work with an existing library that you can't change that refers to _end,
you will have to provide your own definition of _end that will cause the right thing to
happen. What the right thing is is going to depend entirely on how your library uses
_end. Traditional attempts to use _end as the start of the heap won't work with Go's
memory allocator.
by johnkgallagher:
The text was updated successfully, but these errors were encountered: