This is the mail archive of the
java-patches@sourceware.cygnus.com
mailing list for the Java project.
boehm-gc: data_start
- To: java-patches at sourceware dot cygnus dot com
- Subject: boehm-gc: data_start
- From: Jeff Sturm <jsturm at sigma6 dot com>
- Date: Sat, 22 Apr 2000 00:16:03 -0400
- Organization: AppNet Inc.
Some of the problems I've had with boehm-gc on Alpha may be due to the
data_start hack in libgcjdata.c. Regardless of linker options, the
data_start symbol does not appear to show up at the actual beginning of
the data segement... I am regularly seeing class variables prior to it.
(We could use GC_find_limit as an ugly fix.)
Since an actual data_start symbol is missing for some targets in glibc,
I once suggested a workaround based on /proc to find the data segment
boundaries. It was never widely adopted, and Hans didn't use it in his
code.
Here's another attempt at a general fix for data_start. It should work
on all Linux ELF targets. It doesn't have some of the same problems as
the /proc solution (i.e. requiring I/O, failing if /proc is not
mounted). This patch uses ELF program header information instead to
find the main data segment. It is loosely based on code in dyn_load.c.
It detects executables that are statically linked, falling back on the
.data symbol created by ld. I've only tested on Alpha and ia32, but it
should work on all glibc targets at least.
I haven't shown this to Hans yet; I'm just posting it for feedback. If
we can adopt it, we can also kill the libgcjdata hack in libjava.
2000-04-21 Jeff Sturm <jsturm@sigma6.com>
* gcconfig.h: Define SEARCH_FOR_DATA_START and DATASTART,
undefine LINUX_DATA_START for Alpha/Linux.
* os_dep.c (GC_init_linux_data_start): use ELF program header
to resolve GC_data_start.
Index: gcconfig.h
===================================================================
RCS file: /cvs/java/libgcj/boehm-gc/gcconfig.h,v
retrieving revision 1.10
diff -u -r1.10 gcconfig.h
--- gcconfig.h 2000/04/19 10:09:57 1.10
+++ gcconfig.h 2000/04/22 03:43:57
@@ -1050,9 +1050,10 @@
# define CPP_WORDSZ 64
# define STACKBOTTOM ((ptr_t) 0x120000000)
# ifdef __ELF__
-# define LINUX_DATA_START
# define DYNAMIC_LOADING
/* This doesn't work if the collector is in a dynamic library. */
+# define SEARCH_FOR_DATA_START
+# define DATASTART GC_data_start
# else
# define DATASTART ((ptr_t) 0x140000000)
# endif
Index: os_dep.c
===================================================================
RCS file: /cvs/java/libgcj/boehm-gc/os_dep.c,v
retrieving revision 1.10
diff -u -r1.10 os_dep.c
--- os_dep.c 2000/04/19 10:09:58 1.10
+++ os_dep.c 2000/04/22 03:43:57
@@ -144,20 +144,51 @@
#endif
#if defined(SEARCH_FOR_DATA_START)
- /* The following doesn't work if the GC is in a dynamic library. */
/* The I386 case can be handled without a search. The Alpha case */
/* used to be handled differently as well, but the rules changed */
/* for recent Linux versions. This seems to be the easiest way to */
/* cover all versions. */
ptr_t GC_data_start;
- extern char * GC_copyright[]; /* Any data symbol would do. */
+# include <elf.h>
+# include <link.h>
- void GC_init_linux_data_start()
- {
- extern ptr_t GC_find_limit();
+# pragma weak _DYNAMIC
- GC_data_start = GC_find_limit((ptr_t)GC_copyright, FALSE);
+ extern int this_data_start __asm__(".data");
+
+ void GC_init_linux_data_start() {
+ struct link_map *map = NULL;
+
+ if (_DYNAMIC) {
+ ElfW(Dyn) *dp;
+
+ for (dp = _DYNAMIC; dp->d_tag != DT_NULL; dp++) {
+ if (dp->d_tag == DT_DEBUG) {
+ map = ((struct r_debug *)(dp->d_un.d_ptr))->r_map;
+ if (map) map = map->l_next;
+ break;
+ }
+ }
+ }
+
+ if (map) {
+ struct link_map *loader = map->l_loader;
+
+ if (loader) {
+ const ElfW(Phdr) *phdr = loader->l_phdr;
+ int i;
+
+ for (i = 0; i < loader->l_phnum; i++) {
+ if (phdr[i].p_type == PT_LOAD && phdr[i].p_flags & PF_W) {
+ GC_data_start = (ptr_t)phdr[i].p_vaddr;
+ }
+ }
+ }
+ } else {
+ /* static linking, use .data */
+ GC_data_start = (ptr_t)&this_data_start;
+ }
}
#endif