<short summary of the patch>
authorCamm Maguire <camm@debian.org>
Sun, 13 Nov 2022 12:55:14 +0000 (12:55 +0000)
committerCamm Maguire <camm@debian.org>
Sun, 13 Nov 2022 12:55:14 +0000 (12:55 +0000)
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

Gbp-Pq: Name Version_2_6_13pre26

configure
configure.in
h/elf32_mips_reloc.h
h/elf32_mips_reloc_special.h
o/nsocket.c

index 9b7e3183fef0c0bb5751b2d84d7766c97f371b7e..c92f0e3d7d6da545bba91bdac8a574c305e5d007 100755 (executable)
--- a/configure
+++ b/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*)
index d81e9fdeb0b7d4d07e8206096a506b476478ddba..85d4dfbad02981d8f73ba655eb45fb733f29d84d 100644 (file)
@@ -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*)
index c1b10398b04995cf7f45bd4054612baab65744ad..629f2f5448103d4dcc15860ff4a8fc545dfe24e2 100644 (file)
@@ -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);
     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);
index df400089807b6f2e7f0354bb8814d41cae69aebc..9f94f06f10d567180b5a543dfa63f286771d5857 100644 (file)
@@ -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,Shdr *sece,Sym *sym1,Sym *syme,const char
 
   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,Shdr *sece,Sym *sym1,Sym *syme,const char
   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;
   
 }
index 45f6daff3b62a001579d92407cd4fd648efaeb8a..9fc7360fca18cc3330d24769e3ff568461c25b32 100644 (file)
@@ -645,11 +645,11 @@ getCharGclSocket(object strm, object block)
       { 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;