Skip to content
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

gc linker does not export _end #3518

Closed
gopherbot opened this issue Apr 13, 2012 · 2 comments
Closed

gc linker does not export _end #3518

gopherbot opened this issue Apr 13, 2012 · 2 comments

Comments

@gopherbot
Copy link

by johnkgallagher:

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.
@rsc
Copy link
Contributor

rsc commented Apr 13, 2012

Comment 1:

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?

Status changed to Thinking.

@ianlancetaylor
Copy link
Contributor

Comment 2:

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.

Status changed to WorkingAsIntended.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants