Blob Blame Raw
Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 gcl (2.6.12-20) unstable; urgency=medium
 .
   * Version_2_6_13pre25
Author: Camm Maguire <camm@debian.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- gcl-2.6.12.orig/configure
+++ gcl-2.6.12/configure
@@ -4435,7 +4435,6 @@ case $use in
 #			if test "$enable_debug" != "yes" ; then TO2FLAGS="-O" ; fi
 			;;
 		mips*)
-			TCFLAGS="$TCFLAGS -mplt"
 #			if test "$enable_debug" != "yes" ; then TO3FLAGS="-O0" ; fi #FIXME needed asof gcc 4.6.2
 			;;
 		ia64*)
--- gcl-2.6.12.orig/configure.in
+++ gcl-2.6.12/configure.in
@@ -640,7 +640,6 @@ case $use in
 #			if test "$enable_debug" != "yes" ; then TO2FLAGS="-O" ; fi
 			;;
 		mips*)
-			TCFLAGS="$TCFLAGS -mplt"
 #			if test "$enable_debug" != "yes" ; then TO3FLAGS="-O0" ; fi #FIXME needed asof gcc 4.6.2
 			;;
 		ia64*)
--- gcl-2.6.12.orig/h/elf32_mips_reloc.h
+++ gcl-2.6.12/h/elf32_mips_reloc.h
@@ -4,7 +4,12 @@
       add_val(where,~0L,s+a-(ul)got);
       break;
     case R_MIPS_26:
-      add_val(where,MASK(26),(s+a)>>2);
+      if (((s+a)>>28)!=(((ul)where)>>28)) {
+	gote=got+sym->st_size-1;
+	massert(!write_26_stub(s+a,got,gote));
+	store_val(where,MASK(26),((ul)gote)>>2);
+      } else
+        add_val(where,MASK(26),(s+a)>>2);
       break;
     case R_MIPS_32:
       add_val(where,~0L,s+a);
@@ -19,7 +24,10 @@
     case R_MIPS_CALL16:
       gote=got+sym->st_size-1;
       store_val(where,MASK(16),((void *)gote-(void *)got));
-      *gote=s;
+      if (s>=ggot && s<ggote) {
+        massert(!write_stub(s,got,gote));
+      } else
+        *gote=s;
       break;
     case R_MIPS_HI16:
       if (sym->st_other) s=gpd=(ul)got-(sym->st_other==2 ? 0 : (ul)where);
--- gcl-2.6.12.orig/h/elf32_mips_reloc_special.h
+++ gcl-2.6.12/h/elf32_mips_reloc_special.h
@@ -1,9 +1,88 @@
-static ul gpd; static Rel *hr;
+#include <page.h>
+
+static ul gpd,ggot,ggote,can_gp; static Rel *hr;
+
+typedef struct {
+  ul addr_hi,addr_lo,jr,nop;
+} mips_26_tramp;
+
+static int
+write_26_stub(ul s,ul *got,ul *gote) {
+
+  static mips_26_tramp t1={(0xf<<26)|(0x0<<21)|(0x19<<16),   /*lui t9*/
+			   (0xe<<26)|(0x19<<21)|(0x19<<16),  /*ori t9,t9 */
+			   0x03200008,                       /*jr t9*/
+			   0x00200825};                      /*mv at,at */;
+  mips_26_tramp *t=(void *)gote;
+
+  *t=t1;
+  t->addr_hi|=s>>16;
+  t->addr_lo|=s&0xffff;
+
+  return 0;
+
+}
+
+typedef struct {
+  ul entry,addr_hi,addr_lo,lw,jr,lwcan;
+} call_16_tramp;
+
+static int
+write_stub(ul s,ul *got,ul *gote) {
+
+  static call_16_tramp t1={0,
+			   (0xf<<26)|(0x0<<21)|(0x19<<16),   /*lui t9*/
+			   (0xe<<26)|(0x19<<21)|(0x19<<16),  /*ori t9,t9 */
+			   (0x23<<26)|(0x19<<21)|(0x19<<16), /*lw t9,(0)t9*/
+			   0x03200008,                       /*jr t9*/
+                           /*stub addresses need veneer setting gp to canonical*/
+			   (0x23<<26)|(0x1c<<21)|(0x1c<<16)};/*lw gp,(0)gp*/
+  call_16_tramp *t=(void *)gote++;
+
+  *t=t1;
+  *got=can_gp;
+
+  t->entry=(ul)gote;
+  t->addr_hi|=s>>16;
+  t->addr_lo|=s&0xffff;
+
+  return 0;
+
+}
 
 static int
 find_special_params(void *v,Shdr *sec1,Shdr *sece,const char *sn,
 		    const char *st1,Sym *ds1,Sym *dse,Sym *sym,Sym *syme) {
   
+  Shdr *sec;
+  ul *q,gotsym=0,locgotno=0,stub,stube;
+  void *p,*pe;
+
+  massert(sec=get_section(".dynamic",sec1,sece,sn));
+  for (p=(void *)sec->sh_addr,pe=p+sec->sh_size;p<pe;p+=sec->sh_entsize) {
+    q=p;
+    if (q[0]==DT_MIPS_GOTSYM)
+      gotsym=q[1];
+    if (q[0]==DT_MIPS_LOCAL_GOTNO)
+      locgotno=q[1];
+    if (q[0]==DT_PLTGOT)
+      can_gp=q[1]+0x7ff0;
+
+  }
+  massert(gotsym && locgotno && can_gp);
+
+  massert(sec=get_section(".MIPS.stubs",sec1,sece,sn));
+  stub=sec->sh_addr;
+  stube=sec->sh_addr+sec->sh_size;
+
+  massert(sec=get_section(".got",sec1,sece,sn));
+  ggot=sec->sh_addr+locgotno*sec->sh_entsize;
+  ggote=sec->sh_addr+sec->sh_size;
+
+  for (ds1+=gotsym,sym=ds1;sym<dse;sym++)
+    if (!sym->st_value || (sym->st_value>=stub && sym->st_value<stube))
+      sym->st_value=ggot+(sym-ds1)*sec->sh_entsize;
+
   return 0;
 
 }
@@ -13,9 +92,10 @@ label_got_symbols(void *v1,Shdr *sec1,Sh
 
   Rel *r;
   Sym *sym;
-  Shdr *sec;
+  Shdr *sec,*ssec;
   void *v,*ve;
   ul q;
+  struct node *a;
 
   for (q=0,sym=sym1;sym<syme;sym++) {
     const char *s=st1+sym->st_name;
@@ -29,20 +109,32 @@ label_got_symbols(void *v1,Shdr *sec1,Sh
   for (sym=sym1;sym<syme;sym++)
     sym->st_size=0;
 
-  for (*gs=0,sec=sec1;sec<sece;sec++)
-    if (sec->sh_type==SHT_REL)
+  for (*gs=1,sec=sec1;sec<sece;sec++)/*can_gp in got[0]*/
+    if (sec->sh_type==SHT_REL)/*no addend*/
       for (v=v1+sec->sh_offset,ve=v+sec->sh_size,r=v;v<ve;v+=sec->sh_entsize,r=v)
 
-	if (ELF_R_TYPE(r->r_info)==R_MIPS_CALL16||
-	    ELF_R_TYPE(r->r_info)==R_MIPS_GOT16) {
+	if (!(sym=sym1+ELF_R_SYM(r->r_info))->st_size)
 
-	  sym=sym1+ELF_R_SYM(r->r_info);
+	  switch(ELF_R_TYPE(r->r_info)) {
 
-	  if (!sym->st_size)
-	    sym->st_size=++*gs; 
+	  case R_MIPS_26:
+	    if (((ul)(pagetochar(page(heap_end))+r->r_offset))>>28) {
+	      sym->st_size=++*gs;
+	      (*gs)+=sizeof(mips_26_tramp)/sizeof(ul)-1;
+	    }
+	    break;
+	  case R_MIPS_CALL16:
+	    sym->st_size=++*gs;
+	    if (((ssec=sec1+sym->st_shndx)>=sece || !ALLOC_SEC(ssec)) &&
+		(a=find_sym_ptable(st1+sym->st_name)) &&
+		a->address>=ggot && a->address<ggote)
+	      (*gs)+=sizeof(call_16_tramp)/sizeof(ul)-1;
+	    break;
+	  case R_MIPS_GOT16:
+	    sym->st_size=++*gs;
+	    break;
+	  }
 
-	}
-  
   return 0;
   
 }
--- gcl-2.6.12.orig/o/nsocket.c
+++ gcl-2.6.12/o/nsocket.c
@@ -645,11 +645,11 @@ getCharGclSocket(object strm, object blo
       { int high;
       AGAIN:      
       /* under cygwin a too large timout like (1<<30) does not work */
-      timeout.tv_sec = (block != Ct ?  0 : 0);
+      timeout.tv_sec = 0;
       timeout.tv_usec = 10000;
       FD_ZERO(&readfds);
       FD_SET(fd,&readfds);
-      high = select(fd+1,&readfds,NULL,NULL,&timeout);
+      high = select(fd+1,&readfds,NULL,NULL,block==Ct ? NULL : &timeout);
       if (high > 0)
 	{ object bufp = SOCKET_STREAM_BUFFER(strm);
 	int n;