All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: recent SIGBUS/SIGSEGV mips kernel bug
       [not found]                     ` <87r5fksxby.fsf_-_@maguirefamily.org>
@ 2010-10-20 16:38                       ` David Daney
  2010-10-20 21:31                         ` Camm Maguire
  0 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-10-20 16:38 UTC (permalink / raw)
  To: Camm Maguire; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

On 10/20/2010 08:22 AM, Camm Maguire wrote:
> Greetings!  Recent mips (aka gabrielli sid) appears to have a new
> SIGBUS/SIGSEGV bug.  Briefly, attempted writes to pages mprotected
> read-only occasionally pass a SIGBUS instead of SIGSEGV to the
> sigaction handler.  In such an instance, the code of the siginfo
> structure is 128, and the fault address is not filled in.  This
> behavior appears to hinge on writing from the floating point registers
> into the protected memory.
>

What processor is it running on?  Specifically does it have hardware 
floating point, or are the floating point instructions being emulated in 
the kernel?

It is conceivable that it is an FPU emulator bug.

David Daney


> strace:
>
> 30717 mprotect(0x2f59000, 4096, PROT_READ|PROT_EXEC) = 0
> 30717 mprotect(0x2f5a000, 745472, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 mprotect(0x3010000, 323584, PROT_READ|PROT_EXEC) = 0
> 30717 mprotect(0x305f000, 548864, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 mprotect(0x30e5000, 1220608, PROT_READ|PROT_EXEC) = 0
> 30717 mprotect(0x320f000, 53559296, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 mprotect(0x6523000, 53739520, PROT_READ|PROT_EXEC) = 0
> 30717 mprotect(0x9863000, 60375040, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 mprotect(0x6523000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 --- SIGSEGV (Segmentation fault) @ 0 (0) ---  /* good */
> 30717 mprotect(0x31fb000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 rt_sigreturn(0xdc5e80)            = -1 EPERM (Operation not permitted)
> 30717 --- SIGSEGV (Segmentation fault) @ 0 (0) ---  /* good */
> 30717 mprotect(0x9862000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
> 30717 rt_sigreturn(0xdc5e80)            = -1 EBADF (Bad file descriptor)
> 30717 --- SIGBUS (Bus error) @ 0 (0) ---  /* bad handler call */
>
> Here are the gdb details:
>
> (gdb) frame 28
> #28 0x004a3e98 in memprotect_handler (sig=10, code=2140765848,
>      scp=0x7f997f18, addr=0xfdb6c0 "\b") at sgbc.c:1687
> 1687	  segmentation_catcher(0);
> (gdb) p faddr
> $1 = 0x0
> (gdb) p/x *((siginfo_t *)code )
> $2 = {si_signo = 0xa, si_code = 0x80, si_errno = 0x0, __pad0 = 0x7f997e98,
>    _sifields = {_pad = {0x0, 0x0, 0x7f997eb4, 0x7f997fd4, 0x2167b80,
>        0x233c5b8, 0xde5e80, 0xbbec80, 0x65f8a80, 0x7f997ed0, 0x4951a8,
>        0xbbec80, 0xffffffff, 0x7f997ee0, 0x495170, 0xbbec80, 0x65f8a48,
>        0x7f997ef0, 0x4951a8, 0xbbec80, 0xffffffff, 0x7f997f00, 0x495170,
>        0xbbec80, 0x31ecc48, 0x7f997f10, 0xfdead4, 0x7f997f18, 0x454ebc},
>      _kill = {si_pid = 0x0, si_uid = 0x0}, _timer = {si_tid = 0x0,
>        si_overrun = 0x0, si_sigval = {sival_int = 0x7f997eb4,
>          sival_ptr = 0x7f997eb4}}, _rt = {si_pid = 0x0, si_uid = 0x0,
>        si_sigval = {sival_int = 0x7f997eb4, sival_ptr = 0x7f997eb4}},
>      _sigchld = {si_pid = 0x0, si_uid = 0x0, si_status = 0x7f997eb4,
>        si_utime = 0x7f997fd4, si_stime = 0x2167b80}, _sigfault = {
>        si_addr = 0x0}, _sigpoll = {si_band = 0x0, si_fd = 0x0}}}
> (gdb) up
> #29<signal handler called>
> (gdb) up
> #30 0x004484e8 in fSaset1 (x=0x29b5930, i=0, val=0x2d8d870) at array.c:231
> 231	      (x->lfa.lfa_self[i]) = Mlf(val);
> (gdb) p/x x->lfa.lfa_self
> $3 = 0x9861ff0
> (gdb) disassemble
>     0x004484d8<+1352>:	lwc1	$f0,12(v1)
>     0x004484dc<+1356>:	move	at,at
>     0x004484e0<+1360>:	lwc1	$f1,8(v1)
>     0x004484e4<+1364>:	move	at,at
> =>  0x004484e8<+1368>:	swc1	$f0,4(v0)
>     0x004484ec<+1372>:	swc1	$f1,0(v0)
> (gdb) i reg v1
> v1: 0x2d8d870
> (gdb) i reg f1
> f1:  0x3fa2056c flt: 1.26579046
> (gdb) i reg f0
> f0:  0x8f1afe4f flt: -7.64176427e-30   dbl: 0.035197632283140316
> (gdb) i reg v0
> v0: 0x9861ff0
>
> How should this be filed?
>
> Take care,

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: recent SIGBUS/SIGSEGV mips kernel bug
  2010-10-20 16:38                       ` recent SIGBUS/SIGSEGV mips kernel bug David Daney
@ 2010-10-20 21:31                         ` Camm Maguire
  2010-10-21 16:19                           ` David Daney
  0 siblings, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-10-20 21:31 UTC (permalink / raw)
  To: David Daney; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

Greetings!

Does this suffice?

(sid)camm@gabrielli:~/maxima-5.22.1/tests$ uname -a
Linux gabrielli 2.6.35.4-dsa-octeon #1 SMP Fri Sep 17 21:15:34 UTC 2010 mips64 GNU/Linux
(sid)camm@gabrielli:~/maxima-5.22.1/tests$ cat /proc/cpuinfo
system type		: CUST_WSX16 (CN3860p3.X-500-EXP)
processor		: 0
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1001.60
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 1
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.91
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 2
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 3
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.90
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 4
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 5
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 6
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 7
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.90
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 8
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 9
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 10
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.90
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 11
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.88
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 12
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 13
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.89
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 14
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.90
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

processor		: 15
cpu model		: Cavium Octeon V0.3
BogoMIPS		: 1000.90
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 32
extra interrupt vector	: yes
hardware watchpoint	: yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb]
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available

(sid)camm@gabrielli:~/maxima-5.22.1/tests$ 

Take care,

David Daney <ddaney@caviumnetworks.com> writes:

> On 10/20/2010 08:22 AM, Camm Maguire wrote:
>> Greetings!  Recent mips (aka gabrielli sid) appears to have a new
>> SIGBUS/SIGSEGV bug.  Briefly, attempted writes to pages mprotected
>> read-only occasionally pass a SIGBUS instead of SIGSEGV to the
>> sigaction handler.  In such an instance, the code of the siginfo
>> structure is 128, and the fault address is not filled in.  This
>> behavior appears to hinge on writing from the floating point registers
>> into the protected memory.
>>
>
> What processor is it running on?  Specifically does it have hardware
> floating point, or are the floating point instructions being emulated
> in the kernel?
>
> It is conceivable that it is an FPU emulator bug.
>
> David Daney
>
>
>> strace:
>>
>> 30717 mprotect(0x2f59000, 4096, PROT_READ|PROT_EXEC) = 0
>> 30717 mprotect(0x2f5a000, 745472, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 mprotect(0x3010000, 323584, PROT_READ|PROT_EXEC) = 0
>> 30717 mprotect(0x305f000, 548864, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 mprotect(0x30e5000, 1220608, PROT_READ|PROT_EXEC) = 0
>> 30717 mprotect(0x320f000, 53559296, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 mprotect(0x6523000, 53739520, PROT_READ|PROT_EXEC) = 0
>> 30717 mprotect(0x9863000, 60375040, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 mprotect(0x6523000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 --- SIGSEGV (Segmentation fault) @ 0 (0) ---  /* good */
>> 30717 mprotect(0x31fb000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 rt_sigreturn(0xdc5e80)            = -1 EPERM (Operation not permitted)
>> 30717 --- SIGSEGV (Segmentation fault) @ 0 (0) ---  /* good */
>> 30717 mprotect(0x9862000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
>> 30717 rt_sigreturn(0xdc5e80)            = -1 EBADF (Bad file descriptor)
>> 30717 --- SIGBUS (Bus error) @ 0 (0) ---  /* bad handler call */
>>
>> Here are the gdb details:
>>
>> (gdb) frame 28
>> #28 0x004a3e98 in memprotect_handler (sig=10, code=2140765848,
>>      scp=0x7f997f18, addr=0xfdb6c0 "\b") at sgbc.c:1687
>> 1687	  segmentation_catcher(0);
>> (gdb) p faddr
>> $1 = 0x0
>> (gdb) p/x *((siginfo_t *)code )
>> $2 = {si_signo = 0xa, si_code = 0x80, si_errno = 0x0, __pad0 = 0x7f997e98,
>>    _sifields = {_pad = {0x0, 0x0, 0x7f997eb4, 0x7f997fd4, 0x2167b80,
>>        0x233c5b8, 0xde5e80, 0xbbec80, 0x65f8a80, 0x7f997ed0, 0x4951a8,
>>        0xbbec80, 0xffffffff, 0x7f997ee0, 0x495170, 0xbbec80, 0x65f8a48,
>>        0x7f997ef0, 0x4951a8, 0xbbec80, 0xffffffff, 0x7f997f00, 0x495170,
>>        0xbbec80, 0x31ecc48, 0x7f997f10, 0xfdead4, 0x7f997f18, 0x454ebc},
>>      _kill = {si_pid = 0x0, si_uid = 0x0}, _timer = {si_tid = 0x0,
>>        si_overrun = 0x0, si_sigval = {sival_int = 0x7f997eb4,
>>          sival_ptr = 0x7f997eb4}}, _rt = {si_pid = 0x0, si_uid = 0x0,
>>        si_sigval = {sival_int = 0x7f997eb4, sival_ptr = 0x7f997eb4}},
>>      _sigchld = {si_pid = 0x0, si_uid = 0x0, si_status = 0x7f997eb4,
>>        si_utime = 0x7f997fd4, si_stime = 0x2167b80}, _sigfault = {
>>        si_addr = 0x0}, _sigpoll = {si_band = 0x0, si_fd = 0x0}}}
>> (gdb) up
>> #29<signal handler called>
>> (gdb) up
>> #30 0x004484e8 in fSaset1 (x=0x29b5930, i=0, val=0x2d8d870) at array.c:231
>> 231	      (x->lfa.lfa_self[i]) = Mlf(val);
>> (gdb) p/x x->lfa.lfa_self
>> $3 = 0x9861ff0
>> (gdb) disassemble
>>     0x004484d8<+1352>:	lwc1	$f0,12(v1)
>>     0x004484dc<+1356>:	move	at,at
>>     0x004484e0<+1360>:	lwc1	$f1,8(v1)
>>     0x004484e4<+1364>:	move	at,at
>> =>  0x004484e8<+1368>:	swc1	$f0,4(v0)
>>     0x004484ec<+1372>:	swc1	$f1,0(v0)
>> (gdb) i reg v1
>> v1: 0x2d8d870
>> (gdb) i reg f1
>> f1:  0x3fa2056c flt: 1.26579046
>> (gdb) i reg f0
>> f0:  0x8f1afe4f flt: -7.64176427e-30   dbl: 0.035197632283140316
>> (gdb) i reg v0
>> v0: 0x9861ff0
>>
>> How should this be filed?
>>
>> Take care,
>
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: recent SIGBUS/SIGSEGV mips kernel bug
  2010-10-20 21:31                         ` Camm Maguire
@ 2010-10-21 16:19                           ` David Daney
  2010-10-21 16:32                             ` Camm Maguire
  2010-10-21 17:29                             ` David Daney
  0 siblings, 2 replies; 21+ messages in thread
From: David Daney @ 2010-10-21 16:19 UTC (permalink / raw)
  To: Camm Maguire; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

On 10/20/2010 02:31 PM, Camm Maguire wrote:
> Greetings!
>
> Does this suffice?
>
> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ uname -a
> Linux gabrielli 2.6.35.4-dsa-octeon #1 SMP Fri Sep 17 21:15:34 UTC 2010 mips64 GNU/Linux
> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ cat /proc/cpuinfo
> system type		: CUST_WSX16 (CN3860p3.X-500-EXP)
> processor		: 0
> cpu model		: Cavium Octeon V0.3
[...]

Hah!  I have those things piled up all around me.

No guarantees, but I will try to reproduce it.  If I can reproduce it, 
it should be easy to fix.

David Daney

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: recent SIGBUS/SIGSEGV mips kernel bug
  2010-10-21 16:19                           ` David Daney
@ 2010-10-21 16:32                             ` Camm Maguire
  2010-10-21 17:29                             ` David Daney
  1 sibling, 0 replies; 21+ messages in thread
From: Camm Maguire @ 2010-10-21 16:32 UTC (permalink / raw)
  To: David Daney; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

Greetings!

David Daney <ddaney@caviumnetworks.com> writes:

> On 10/20/2010 02:31 PM, Camm Maguire wrote:
>> Greetings!
>>
>> Does this suffice?
>>
>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ uname -a
>> Linux gabrielli 2.6.35.4-dsa-octeon #1 SMP Fri Sep 17 21:15:34 UTC 2010 mips64 GNU/Linux
>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ cat /proc/cpuinfo
>> system type		: CUST_WSX16 (CN3860p3.X-500-EXP)
>> processor		: 0
>> cpu model		: Cavium Octeon V0.3
> [...]
>
> Hah!  I have those things piled up all around me.
>
> No guarantees, but I will try to reproduce it.  If I can reproduce it,
> it should be easy to fix.
>
> David Daney
>

Thanks so much!  Please keep me posted.

Take care,

>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: recent SIGBUS/SIGSEGV mips kernel bug
  2010-10-21 16:19                           ` David Daney
  2010-10-21 16:32                             ` Camm Maguire
@ 2010-10-21 17:29                             ` David Daney
  2010-10-21 19:07                               ` Camm Maguire
                                                 ` (2 more replies)
  1 sibling, 3 replies; 21+ messages in thread
From: David Daney @ 2010-10-21 17:29 UTC (permalink / raw)
  To: David Daney
  Cc: Camm Maguire, debian-mips, Frederick Isaac, gcl-devel, linux-mips

On 10/21/2010 09:19 AM, David Daney wrote:
> On 10/20/2010 02:31 PM, Camm Maguire wrote:
>> Greetings!
>>
>> Does this suffice?
>>
>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ uname -a
>> Linux gabrielli 2.6.35.4-dsa-octeon #1 SMP Fri Sep 17 21:15:34 UTC
>> 2010 mips64 GNU/Linux
>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ cat /proc/cpuinfo
>> system type : CUST_WSX16 (CN3860p3.X-500-EXP)
>> processor : 0
>> cpu model : Cavium Octeon V0.3
> [...]
>
> Hah! I have those things piled up all around me.
>
> No guarantees, but I will try to reproduce it. If I can reproduce it, it
> should be easy to fix.
>

Definitely a kernel bug.  Consider this program:

------------8<--------sigbus.c-------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/mman.h>

int main(int argc, char *argv[])
{
   int pgsize;
   float *p1;
   float *p2;
   int r;

   pgsize = getpagesize();

   p1 = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

   if (p1 == MAP_FAILED) {
     perror("mmap p1 failed");
     exit(1);
   }

   p2 = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

   if (p2 == MAP_FAILED) {
     perror("mmap p2 failed");
     exit(1);
   }

   *p1 = 2.5;
   *p2 = 3.5;

   r = mprotect(p1, pgsize, PROT_READ);
   if (r) {
     perror("mprotect p1 failed");
     exit(1);
   }

   r = mprotect(p2, pgsize, PROT_READ);
   if (r) {
     perror("mprotect p2 failed");
     exit(1);
   }

   *p2 = *p1;

   asm volatile("" ::: "memory");

   puts("All done!");

   exit(0);
}
------------8<-----------------------

$ mips64-octeon-linux-gnu-gcc -Wall -mhard-float -march=mips64 -O3 -o 
sigbus sigbus.c
$ mips64-octeon-linux-gnu-objdump -d sigbus > sigbus.dis

The float copy '*p2 = *p1;' dissassembles as:

    120000b30:	c6400000 	lwc1	$f0,0(s2)
    120000b34:	e6000000 	swc1	$f0,0(s0)

When run on an FPU-less system I get:

~ # ./sigbus
Bus error

When run on my x86_64 workstation:

$ ./sigbus
Segmentation fault (core dumped)

I will fix this kernel bug.

David Daney

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: recent SIGBUS/SIGSEGV mips kernel bug
  2010-10-21 17:29                             ` David Daney
@ 2010-10-21 19:07                               ` Camm Maguire
  2010-10-25 20:11                               ` Camm Maguire
  2010-10-25 21:32                               ` gdb for mips64 Camm Maguire
  2 siblings, 0 replies; 21+ messages in thread
From: Camm Maguire @ 2010-10-21 19:07 UTC (permalink / raw)
  To: David Daney; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

Greetings!

David Daney <ddaney@caviumnetworks.com> writes:

> On 10/21/2010 09:19 AM, David Daney wrote:
>> On 10/20/2010 02:31 PM, Camm Maguire wrote:
>>> Greetings!
>>>
>>> Does this suffice?
>>>
>>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ uname -a
>>> Linux gabrielli 2.6.35.4-dsa-octeon #1 SMP Fri Sep 17 21:15:34 UTC
>>> 2010 mips64 GNU/Linux
>>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ cat /proc/cpuinfo
>>> system type : CUST_WSX16 (CN3860p3.X-500-EXP)
>>> processor : 0
>>> cpu model : Cavium Octeon V0.3
>> [...]
>>
>> Hah! I have those things piled up all around me.
>>
>> No guarantees, but I will try to reproduce it. If I can reproduce it, it
>> should be easy to fix.
>>
>
> Definitely a kernel bug.  Consider this program:
>
> ------------8<--------sigbus.c-------
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
>
> #include <sys/mman.h>
>
> int main(int argc, char *argv[])
> {
>   int pgsize;
>   float *p1;
>   float *p2;
>   int r;
>
>   pgsize = getpagesize();
>
>   p1 = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
> 	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
>   if (p1 == MAP_FAILED) {
>     perror("mmap p1 failed");
>     exit(1);
>   }
>
>   p2 = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
> 	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
>   if (p2 == MAP_FAILED) {
>     perror("mmap p2 failed");
>     exit(1);
>   }
>
>   *p1 = 2.5;
>   *p2 = 3.5;
>
>   r = mprotect(p1, pgsize, PROT_READ);
>   if (r) {
>     perror("mprotect p1 failed");
>     exit(1);
>   }
>
>   r = mprotect(p2, pgsize, PROT_READ);
>   if (r) {
>     perror("mprotect p2 failed");
>     exit(1);
>   }
>
>   *p2 = *p1;
>
>   asm volatile("" ::: "memory");
>
>   puts("All done!");
>
>   exit(0);
> }
> ------------8<-----------------------
>
> $ mips64-octeon-linux-gnu-gcc -Wall -mhard-float -march=mips64 -O3 -o 
> sigbus sigbus.c
> $ mips64-octeon-linux-gnu-objdump -d sigbus > sigbus.dis
>
> The float copy '*p2 = *p1;' dissassembles as:
>
>    120000b30:	c6400000 	lwc1	$f0,0(s2)
>    120000b34:	e6000000 	swc1	$f0,0(s0)
>
> When run on an FPU-less system I get:
>
> ~ # ./sigbus
> Bus error
>
> When run on my x86_64 workstation:
>
> $ ./sigbus
> Segmentation fault (core dumped)
>
> I will fix this kernel bug.
>

Great!  Thanks!  If you have time to drop a quick note when done, that
would be awesome.

Separately, do you know where I can find pre-built gdb binaries for
mips64, i.e. to debug -mabi=64?  I'm assuming that is the 'official
one' going foward.  (I have an account on the gcc compile farm.)

Thanks so much!

> David Daney
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: recent SIGBUS/SIGSEGV mips kernel bug
  2010-10-21 17:29                             ` David Daney
  2010-10-21 19:07                               ` Camm Maguire
@ 2010-10-25 20:11                               ` Camm Maguire
  2010-10-25 21:32                               ` gdb for mips64 Camm Maguire
  2 siblings, 0 replies; 21+ messages in thread
From: Camm Maguire @ 2010-10-25 20:11 UTC (permalink / raw)
  To: David Daney; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

Greetings, and thanks so much for this and the kernel fix!

I've committed a little test which hopefully will enable trapping
these signals when the kernel fix is in place:

--- o/sgbc.c	1 Oct 2010 19:15:40 -0000	1.9.4.1.2.12.6.1.2.1.6.4
+++ o/sgbc.c	25 Oct 2010 19:46:35 -0000
@@ -1146,10 +1146,6 @@
   memset(b1,32,2*p);
   memset(b2,0,p);
   memprotect_test_address=(void *)(((unsigned long)b1+p-1) & ~(p-1));
-  if (mprotect(memprotect_test_address,p,PROT_READ_EXEC)) {
-    memprotect_result=memprotect_cannot_protect;
-    return -1;
-  }
   sa.sa_sigaction=(void *)memprotect_handler_test;
   sa.sa_flags=MPROTECT_ACTION_FLAGS;
   if (sigaction(SIGSEGV,&sa,&sao)) {
@@ -1161,6 +1157,29 @@
     memprotect_result=memprotect_sigaction;
     return -1;
   }
+  { /* mips kernel bug test -- SIGBUS with no faddr when floating point is emulated. */
+    float *f1=(void *)memprotect_test_address,*f2=(void *)b2;
+  
+    if (mprotect(memprotect_test_address,p,PROT_READ_EXEC)) {
+      memprotect_result=memprotect_cannot_protect;
+      return -1;
+    }
+    memprotect_result=memprotect_bad_return;
+    *f1=*f2;
+    if (memprotect_result==memprotect_bad_return)
+      memprotect_result=memprotect_no_signal;
+    if (memprotect_result!=memprotect_none) {
+      sigaction(SIGSEGV,&sao,NULL);
+      sigaction(SIGBUS,&saob,NULL);
+      return -1;
+    }
+    memprotect_handler_invocations=0;
+
+  }
+  if (mprotect(memprotect_test_address,p,PROT_READ_EXEC)) {
+    memprotect_result=memprotect_cannot_protect;
+    return -1;
+  }
   memprotect_result=memprotect_bad_return;
   memset(memprotect_test_address,0,p);
   if (memprotect_result==memprotect_bad_return)

This seems to work, but if you see any shortcomings, please let me
know.

Thanks so much again!

David Daney <ddaney@caviumnetworks.com> writes:

> On 10/21/2010 09:19 AM, David Daney wrote:
>> On 10/20/2010 02:31 PM, Camm Maguire wrote:
>>> Greetings!
>>>
>>> Does this suffice?
>>>
>>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ uname -a
>>> Linux gabrielli 2.6.35.4-dsa-octeon #1 SMP Fri Sep 17 21:15:34 UTC
>>> 2010 mips64 GNU/Linux
>>> (sid)camm@gabrielli:~/maxima-5.22.1/tests$ cat /proc/cpuinfo
>>> system type : CUST_WSX16 (CN3860p3.X-500-EXP)
>>> processor : 0
>>> cpu model : Cavium Octeon V0.3
>> [...]
>>
>> Hah! I have those things piled up all around me.
>>
>> No guarantees, but I will try to reproduce it. If I can reproduce it, it
>> should be easy to fix.
>>
>
> Definitely a kernel bug.  Consider this program:
>
> ------------8<--------sigbus.c-------
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
>
> #include <sys/mman.h>
>
> int main(int argc, char *argv[])
> {
>   int pgsize;
>   float *p1;
>   float *p2;
>   int r;
>
>   pgsize = getpagesize();
>
>   p1 = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
> 	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
>   if (p1 == MAP_FAILED) {
>     perror("mmap p1 failed");
>     exit(1);
>   }
>
>   p2 = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
> 	    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
>   if (p2 == MAP_FAILED) {
>     perror("mmap p2 failed");
>     exit(1);
>   }
>
>   *p1 = 2.5;
>   *p2 = 3.5;
>
>   r = mprotect(p1, pgsize, PROT_READ);
>   if (r) {
>     perror("mprotect p1 failed");
>     exit(1);
>   }
>
>   r = mprotect(p2, pgsize, PROT_READ);
>   if (r) {
>     perror("mprotect p2 failed");
>     exit(1);
>   }
>
>   *p2 = *p1;
>
>   asm volatile("" ::: "memory");
>
>   puts("All done!");
>
>   exit(0);
> }
> ------------8<-----------------------
>
> $ mips64-octeon-linux-gnu-gcc -Wall -mhard-float -march=mips64 -O3 -o 
> sigbus sigbus.c
> $ mips64-octeon-linux-gnu-objdump -d sigbus > sigbus.dis
>
> The float copy '*p2 = *p1;' dissassembles as:
>
>    120000b30:	c6400000 	lwc1	$f0,0(s2)
>    120000b34:	e6000000 	swc1	$f0,0(s0)
>
> When run on an FPU-less system I get:
>
> ~ # ./sigbus
> Bus error
>
> When run on my x86_64 workstation:
>
> $ ./sigbus
> Segmentation fault (core dumped)
>
> I will fix this kernel bug.
>
> David Daney
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* gdb for mips64
  2010-10-21 17:29                             ` David Daney
  2010-10-21 19:07                               ` Camm Maguire
  2010-10-25 20:11                               ` Camm Maguire
@ 2010-10-25 21:32                               ` Camm Maguire
  2010-10-25 21:45                                 ` David Daney
  2 siblings, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-10-25 21:32 UTC (permalink / raw)
  To: David Daney; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

Greetings!  Can gdb be made to work on mips64?

(gdb) r
Starting program: /home/camm/gcl-2.6.8pre/unixport/saved_pre_gcl 
/home/wingsun/develop/build/gdb/gdb-6.8/gdb/mips-tdep.c:603: internal-error: bad register size
A problem internal to GDB has been detected,
further debugging may prove unreliable.

Take care,
-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: gdb for mips64
  2010-10-25 21:32                               ` gdb for mips64 Camm Maguire
@ 2010-10-25 21:45                                 ` David Daney
  2010-10-26 12:47                                   ` Maciej W. Rozycki
  2010-10-26 14:47                                   ` gdb for mips64 Camm Maguire
  0 siblings, 2 replies; 21+ messages in thread
From: David Daney @ 2010-10-25 21:45 UTC (permalink / raw)
  To: Camm Maguire; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

On 10/25/2010 02:32 PM, Camm Maguire wrote:
> Greetings!  Can gdb be made to work on mips64?
>

You have to have a 64-bit toolchain.

Then something like this (untested):

CC='mips64-linux-gnu -mabi=64' configure --host=mips64-linux 
--target=mips64-linux.

I don't think a 32-bit gdb can debug 64-bit processes :-(.

David Daney


> (gdb) r
> Starting program: /home/camm/gcl-2.6.8pre/unixport/saved_pre_gcl
> /home/wingsun/develop/build/gdb/gdb-6.8/gdb/mips-tdep.c:603: internal-error: bad register size
> A problem internal to GDB has been detected,
> further debugging may prove unreliable.
>
> Take care,

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: gdb for mips64
  2010-10-25 21:45                                 ` David Daney
@ 2010-10-26 12:47                                   ` Maciej W. Rozycki
  2010-10-26 17:19                                     ` David Daney
  2010-10-26 14:47                                   ` gdb for mips64 Camm Maguire
  1 sibling, 1 reply; 21+ messages in thread
From: Maciej W. Rozycki @ 2010-10-26 12:47 UTC (permalink / raw)
  To: David Daney
  Cc: Camm Maguire, debian-mips, Frederick Isaac, gcl-devel, linux-mips

On Mon, 25 Oct 2010, David Daney wrote:

> I don't think a 32-bit gdb can debug 64-bit processes :-(.

 And it should (assuming ptrace(2) gets things right) -- if what you say 
is true, then it's a bug rather than a deliberate design decision.  To add 
some irony, MIPS GDB is always 64-bit internally.

> > (gdb) r
> > Starting program: /home/camm/gcl-2.6.8pre/unixport/saved_pre_gcl
> > /home/wingsun/develop/build/gdb/gdb-6.8/gdb/mips-tdep.c:603: internal-error:
> > bad register size
> > A problem internal to GDB has been detected,
> > further debugging may prove unreliable.

 Try a newer version though -- GDB 7.2 has been out for a (short) while 
now.  You're missing 2.5 years of development.  If still unsuccessful with 
a pristine release from ftp.gnu.org, then file a bug report at 
http://sourceware.org/gdb/bugs/.

  Maciej

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: gdb for mips64
  2010-10-25 21:45                                 ` David Daney
  2010-10-26 12:47                                   ` Maciej W. Rozycki
@ 2010-10-26 14:47                                   ` Camm Maguire
  2010-10-26 20:12                                     ` [Gcl-devel] " Camm Maguire
  1 sibling, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-10-26 14:47 UTC (permalink / raw)
  To: David Daney; +Cc: debian-mips, Frederick Isaac, gcl-devel, linux-mips

Greetings!

David Daney <ddaney@caviumnetworks.com> writes:

> On 10/25/2010 02:32 PM, Camm Maguire wrote:
>> Greetings!  Can gdb be made to work on mips64?
>>
>
> You have to have a 64-bit toolchain.
>
> Then something like this (untested):
>
> CC='mips64-linux-gnu -mabi=64' configure --host=mips64-linux
> --target=mips64-linux.
>
> I don't think a 32-bit gdb can debug 64-bit processes :-(.
>

Thanks.

Why doesn't _IO_getc get a stub on mips64, like say _setjmp?

readelf -a saved_ansi_gcl |grep  IO_getc
  2812: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@GLIBC_2.0 (2)
 15315: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@@GLIBC_2.0
readelf -a saved_ansi_gcl |grep  setjmp
  2159: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@GLIBC_2.0 (2)
 15978: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@@GLIBC_2.0
 
Is there anything I can do about this?

Take care,

> David Daney
>
>
>> (gdb) r
>> Starting program: /home/camm/gcl-2.6.8pre/unixport/saved_pre_gcl
>> /home/wingsun/develop/build/gdb/gdb-6.8/gdb/mips-tdep.c:603: internal-error: bad register size
>> A problem internal to GDB has been detected,
>> further debugging may prove unreliable.
>>
>> Take care,
>
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: gdb for mips64
  2010-10-26 12:47                                   ` Maciej W. Rozycki
@ 2010-10-26 17:19                                     ` David Daney
  2010-11-01 16:24                                       ` mips and ADDR_NO_RANDOMIZE Camm Maguire
  0 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-10-26 17:19 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Camm Maguire, debian-mips, Frederick Isaac, gcl-devel, linux-mips

On 10/26/2010 05:47 AM, Maciej W. Rozycki wrote:
> On Mon, 25 Oct 2010, David Daney wrote:
>
>> I don't think a 32-bit gdb can debug 64-bit processes :-(.
>
>   And it should (assuming ptrace(2) gets things right) -- if what you say
> is true, then it's a bug rather than a deliberate design decision.  To add
> some irony, MIPS GDB is always 64-bit internally.
>
>>> (gdb) r
>>> Starting program: /home/camm/gcl-2.6.8pre/unixport/saved_pre_gcl
>>> /home/wingsun/develop/build/gdb/gdb-6.8/gdb/mips-tdep.c:603: internal-error:
>>> bad register size
>>> A problem internal to GDB has been detected,
>>> further debugging may prove unreliable.
>
>   Try a newer version though -- GDB 7.2 has been out for a (short) while
> now.  You're missing 2.5 years of development.  If still unsuccessful with
> a pristine release from ftp.gnu.org, then file a bug report at
> http://sourceware.org/gdb/bugs/.
>

After more though, I think you may have to configure with 
--enable-64-bit-bfd for a 32-bit gdb to work on 64-bit processes. 
Although I have not actually tested that.  In the past, I have just 
built a native 64-bit gdb.

David Daney

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Gcl-devel] Re: gdb for mips64
  2010-10-26 14:47                                   ` gdb for mips64 Camm Maguire
@ 2010-10-26 20:12                                     ` Camm Maguire
  2010-10-28 10:50                                       ` Maciej W. Rozycki
  0 siblings, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-10-26 20:12 UTC (permalink / raw)
  To: David Daney; +Cc: linux-mips, debian-mips, gcl-devel

Greetings!  

Camm Maguire <camm@maguirefamily.org> writes:

> Thanks.
>
> Why doesn't _IO_getc get a stub on mips64, like say _setjmp?
>
> readelf -a saved_ansi_gcl |grep  IO_getc
>   2812: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@GLIBC_2.0 (2)
>  15315: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@@GLIBC_2.0
> readelf -a saved_ansi_gcl |grep  setjmp
>   2159: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@GLIBC_2.0 (2)
>  15978: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@@GLIBC_2.0
>  
> Is there anything I can do about this?
>

A little more info here.  Latest toolchain on the gcc compile farm
does provide a stub, but the slightly older gentoo on a sicortex
machine does not.  Clearly not too much to worry about unless you
might know of an easy workaround.

Take care,
-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Gcl-devel] Re: gdb for mips64
  2010-10-26 20:12                                     ` [Gcl-devel] " Camm Maguire
@ 2010-10-28 10:50                                       ` Maciej W. Rozycki
  2010-10-28 21:28                                         ` Camm Maguire
  0 siblings, 1 reply; 21+ messages in thread
From: Maciej W. Rozycki @ 2010-10-28 10:50 UTC (permalink / raw)
  To: Camm Maguire; +Cc: David Daney, linux-mips, debian-mips, gcl-devel

On Tue, 26 Oct 2010, Camm Maguire wrote:

> > Why doesn't _IO_getc get a stub on mips64, like say _setjmp?
> >
> > readelf -a saved_ansi_gcl |grep  IO_getc
> >   2812: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@GLIBC_2.0 (2)
> >  15315: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@@GLIBC_2.0
> > readelf -a saved_ansi_gcl |grep  setjmp
> >   2159: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@GLIBC_2.0 (2)
> >  15978: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@@GLIBC_2.0
> >  
> > Is there anything I can do about this?
> >
> 
> A little more info here.  Latest toolchain on the gcc compile farm
> does provide a stub, but the slightly older gentoo on a sicortex
> machine does not.  Clearly not too much to worry about unless you
> might know of an easy workaround.

 Can you quote what `ld --version' says on the affected system?

 It *might* be a linker bug, though the exact circumstances may be 
complicated as I have n64 MIPS64 binaries as old as from mid 2005 with a 
stub for _IO_getc() correctly installed.  Nobody should be using any older 
binutils, especially with the MIPS64 target as 64-bit support for MIPS was 
quite immature back then.  I suggest that you switch to binutils 2.20.1; 
version 2.21 is due out in a couple of weeks too.

 A legitimate cause for a stub to be omitted by the linker are pointer 
references to the function in question as in this case the symbol has to 
be fully resolved for pointer comparison to produce reliable results.  It 
could be that one version of GCC produces code that looks to the linker as 
if referring to the symbol this way (i.e. the object files presented to 
the linker contain relocations normally used for data references rather 
than function calls associated with the symbol in question).  You can 
determine if that is the case by running `objdump -r' on the program's 
object files used in the final link and checking if there are any GOT 
relocations (that'll be a part of their names, e.g. R_MIPS_GOT_PAGE) 
against _IO_getc.  Again, that *might* be a GCC bug then.

 That said the only impact from a missing stub is a small program startup 
performance penalty as lazy binding cannot be applied to this single 
symbol only and the symbol has to be fully resolved at startup.

  Maciej

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Gcl-devel] Re: gdb for mips64
  2010-10-28 10:50                                       ` Maciej W. Rozycki
@ 2010-10-28 21:28                                         ` Camm Maguire
  2010-10-29  7:47                                           ` Maciej W. Rozycki
  0 siblings, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-10-28 21:28 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: David Daney, linux-mips, debian-mips, gcl-devel

"Maciej W. Rozycki" <macro@linux-mips.org> writes:

> On Tue, 26 Oct 2010, Camm Maguire wrote:
>
>> > Why doesn't _IO_getc get a stub on mips64, like say _setjmp?
>> >
>> > readelf -a saved_ansi_gcl |grep  IO_getc
>> >   2812: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@GLIBC_2.0 (2)
>> >  15315: 0000000000000000   472 FUNC    GLOBAL DEFAULT  UND _IO_getc@@GLIBC_2.0
>> > readelf -a saved_ansi_gcl |grep  setjmp
>> >   2159: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@GLIBC_2.0 (2)
>> >  15978: 00000001204b9b40    32 FUNC    GLOBAL DEFAULT  UND _setjmp@@GLIBC_2.0
>> >  
>> > Is there anything I can do about this?
>> >
>> 
>> A little more info here.  Latest toolchain on the gcc compile farm
>> does provide a stub, but the slightly older gentoo on a sicortex
>> machine does not.  Clearly not too much to worry about unless you
>> might know of an easy workaround.
>
>  Can you quote what `ld --version' says on the affected system?
>

ld --version
GNU ld (GNU Binutils) 2.18
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.


>  It *might* be a linker bug, though the exact circumstances may be 
> complicated as I have n64 MIPS64 binaries as old as from mid 2005 with a 
> stub for _IO_getc() correctly installed.  Nobody should be using any older 
> binutils, especially with the MIPS64 target as 64-bit support for MIPS was 
> quite immature back then.  I suggest that you switch to binutils 2.20.1; 
> version 2.21 is due out in a couple of weeks too.
>
>  A legitimate cause for a stub to be omitted by the linker are pointer 
> references to the function in question as in this case the symbol has to 
> be fully resolved for pointer comparison to produce reliable results.  It 
> could be that one version of GCC produces code that looks to the linker as 
> if referring to the symbol this way (i.e. the object files presented to 
> the linker contain relocations normally used for data references rather 
> than function calls associated with the symbol in question).  You can 
> determine if that is the case by running `objdump -r' on the program's 
> object files used in the final link and checking if there are any GOT 
> relocations (that'll be a part of their names, e.g. R_MIPS_GOT_PAGE) 
> against _IO_getc.  Again, that *might* be a GCC bug then.

Yep:

File: gcl_readline.o
0000000000000928 R_MIPS_GOT_DISP   _IO_getc

int rl_getc_em(FILE *f) {
	static char *line = NULL;
	static int linepos = 0;
	int r;
	
	if (f!=stdin || !isatty(fileno(f)) ) return getc(f);
....

>
>  That said the only impact from a missing stub is a small program startup 
> performance penalty as lazy binding cannot be applied to this single 
> symbol only and the symbol has to be fully resolved at startup.
>

This comment was very helpful.  I had implemented a stub at the end of
each loaded .o file to read the main stub, discern the got entry, read
it, and jump.  Now I skip the stub reading step and use the gotsym and
locgotno from the .dynamic section and the dyn_symtab entries to
compute the got offset.  I can now handle symbols with 0 initial
value.

Thanks so much!

>   Maciej
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Gcl-devel] Re: gdb for mips64
  2010-10-28 21:28                                         ` Camm Maguire
@ 2010-10-29  7:47                                           ` Maciej W. Rozycki
  2010-10-29 15:52                                             ` Camm Maguire
  0 siblings, 1 reply; 21+ messages in thread
From: Maciej W. Rozycki @ 2010-10-29  7:47 UTC (permalink / raw)
  To: Camm Maguire; +Cc: David Daney, linux-mips, debian-mips, gcl-devel

On Thu, 28 Oct 2010, Camm Maguire wrote:

> >  Can you quote what `ld --version' says on the affected system?
> >
> 
> ld --version
> GNU ld (GNU Binutils) 2.18
> Copyright 2007 Free Software Foundation, Inc.
> This program is free software; you may redistribute it under the terms of
> the GNU General Public License version 3 or (at your option) a later version.
> This program has absolutely no warranty.

 OK, they should be good I believe, as should be any version newer than 
2.16-ish (I'd have to get at the ChangeLogs to recall exactly when usable 
support for the new ABIs went in), but I suggest an upgrade to the current 
version at your convenience anyway.

> >  A legitimate cause for a stub to be omitted by the linker are pointer 
> > references to the function in question as in this case the symbol has to 
> > be fully resolved for pointer comparison to produce reliable results.  It 
> > could be that one version of GCC produces code that looks to the linker as 
> > if referring to the symbol this way (i.e. the object files presented to 
> > the linker contain relocations normally used for data references rather 
> > than function calls associated with the symbol in question).  You can 
> > determine if that is the case by running `objdump -r' on the program's 
> > object files used in the final link and checking if there are any GOT 
> > relocations (that'll be a part of their names, e.g. R_MIPS_GOT_PAGE) 
> > against _IO_getc.  Again, that *might* be a GCC bug then.
> 
> Yep:
> 
> File: gcl_readline.o
> 0000000000000928 R_MIPS_GOT_DISP   _IO_getc
> 
> int rl_getc_em(FILE *f) {
> 	static char *line = NULL;
> 	static int linepos = 0;
> 	int r;
> 	
> 	if (f!=stdin || !isatty(fileno(f)) ) return getc(f);
> ....

 OK, so that does look like a problem with GCC as this piece of code only 
takes the address of getc() (that is #defined to _IO_getc() in <stdio.h>) 
for the purpose of making a function call.  An R_MIPS_CALL16 relocation 
should therefore be used here instead.

 Would you care to quote the GCC version causing this and get an assembly 
output of the surrounding code (say +/-5 instructions from the 
relocation), preferably one generated by GCC along the lines of:

$ gcc -S -dp <other_options_needed_here> gcl_readline.c

(you can just copy and paste the invocation line quoted by `make' and 
substitute "-c" for "-S -dp" (and gcl_readline.o for gcl_readline.s, if 
applicable) leaving the rest of options intact), but if that turns out too 
difficult, then:

$ objdump -dr gcl_readline.o

might be good enough.

> >  That said the only impact from a missing stub is a small program startup 
> > performance penalty as lazy binding cannot be applied to this single 
> > symbol only and the symbol has to be fully resolved at startup.
> >
> 
> This comment was very helpful.  I had implemented a stub at the end of
> each loaded .o file to read the main stub, discern the got entry, read
> it, and jump.  Now I skip the stub reading step and use the gotsym and
> locgotno from the .dynamic section and the dyn_symtab entries to
> compute the got offset.  I can now handle symbols with 0 initial
> value.

 Hmm, what you're doing sounds odd to me -- are you trying to gather some 
sort of statistics about lazy binding calls or what?  There may be 
functionality to cover this kind of processing already available in ld.so.  
Also once the program has been loaded the dynamic linker will have already 
resolved any strong symbol references and you shouldn't be seeing any that 
still has a null value (that does not apply to weak references that may 
remain unsatisfied).

 Also note that if you're doing stuff manually like this, then you may 
have to take the GOT model used (traditional GOT, xGOT, multi-GOT) into 
account.

> Thanks so much!

 You are welcome!

  Maciej

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Gcl-devel] Re: gdb for mips64
  2010-10-29  7:47                                           ` Maciej W. Rozycki
@ 2010-10-29 15:52                                             ` Camm Maguire
  2010-10-30 12:39                                               ` Maciej W. Rozycki
  0 siblings, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-10-29 15:52 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: David Daney, linux-mips, debian-mips, gcl-devel

[-- Attachment #1: Type: text/plain, Size: 5685 bytes --]

Greetings!

"Maciej W. Rozycki" <macro@linux-mips.org> writes:

> On Thu, 28 Oct 2010, Camm Maguire wrote:
>
>> >  Can you quote what `ld --version' says on the affected system?
>> >
>> 
>> ld --version
>> GNU ld (GNU Binutils) 2.18
>> Copyright 2007 Free Software Foundation, Inc.
>> This program is free software; you may redistribute it under the terms of
>> the GNU General Public License version 3 or (at your option) a later version.
>> This program has absolutely no warranty.
>
>  OK, they should be good I believe, as should be any version newer than 
> 2.16-ish (I'd have to get at the ChangeLogs to recall exactly when usable 
> support for the new ABIs went in), but I suggest an upgrade to the current 
> version at your convenience anyway.

OK, this isn't my machine, but good to know.

>
>> >  A legitimate cause for a stub to be omitted by the linker are pointer 
>> > references to the function in question as in this case the symbol has to 
>> > be fully resolved for pointer comparison to produce reliable results.  It 
>> > could be that one version of GCC produces code that looks to the linker as 
>> > if referring to the symbol this way (i.e. the object files presented to 
>> > the linker contain relocations normally used for data references rather 
>> > than function calls associated with the symbol in question).  You can 
>> > determine if that is the case by running `objdump -r' on the program's 
>> > object files used in the final link and checking if there are any GOT 
>> > relocations (that'll be a part of their names, e.g. R_MIPS_GOT_PAGE) 
>> > against _IO_getc.  Again, that *might* be a GCC bug then.
>> 
>> Yep:
>> 
>> File: gcl_readline.o
>> 0000000000000928 R_MIPS_GOT_DISP   _IO_getc
>> 
>> int rl_getc_em(FILE *f) {
>> 	static char *line = NULL;
>> 	static int linepos = 0;
>> 	int r;
>> 	
>> 	if (f!=stdin || !isatty(fileno(f)) ) return getc(f);
>> ....
>
>  OK, so that does look like a problem with GCC as this piece of code only 
> takes the address of getc() (that is #defined to _IO_getc() in <stdio.h>) 
> for the purpose of making a function call.  An R_MIPS_CALL16 relocation 
> should therefore be used here instead.
>
>  Would you care to quote the GCC version causing this and get an assembly 
> output of the surrounding code (say +/-5 instructions from the 
> relocation), preferably one generated by GCC along the lines of:
>
> $ gcc -S -dp <other_options_needed_here> gcl_readline.c
>
> (you can just copy and paste the invocation line quoted by `make' and 
> substitute "-c" for "-S -dp" (and gcl_readline.o for gcl_readline.s, if 
> applicable) leaving the rest of options intact), but if that turns out too 
> difficult, then:
>
> $ objdump -dr gcl_readline.o
>
> might be good enough.
>

OK see attachment below.


>> >  That said the only impact from a missing stub is a small program startup 
>> > performance penalty as lazy binding cannot be applied to this single 
>> > symbol only and the symbol has to be fully resolved at startup.
>> >
>> 
>> This comment was very helpful.  I had implemented a stub at the end of
>> each loaded .o file to read the main stub, discern the got entry, read
>> it, and jump.  Now I skip the stub reading step and use the gotsym and
>> locgotno from the .dynamic section and the dyn_symtab entries to
>> compute the got offset.  I can now handle symbols with 0 initial
>> value.
>
>  Hmm, what you're doing sounds odd to me -- are you trying to gather some 
> sort of statistics about lazy binding calls or what?  There may be 
> functionality to cover this kind of processing already available in ld.so.  
> Also once the program has been loaded the dynamic linker will have already 
> resolved any strong symbol references and you shouldn't be seeing any that 
> still has a null value (that does not apply to weak references that may 
> remain unsatisfied).
>

Its simple but rather unconventional.  GCL is a lisp system.  It loads
compiled object files at runtime into memory, and executes therefrom.
It can then save the expanded memory image to disk via unexec for
later execution on the same or different machines.  Compiled code can
reference symbols in external shared libraries.  These must be
directed toward some trampoline in the initial final-linked
executable, as otherwise the address loaded might not be valid in a
later execution.  On mips, GCL adds a little stub to load the global
got address from a local got table appended to the .o file, then to
load the contents of this address, and then jump.  GCL ensures that
LD_BIND_NOW is set at runtime via pushing the environment and execve()
on startup.  On other systems, where .plt entries are available, GCL
sets the address to the .plt which takes care of everything.  This is
much cleaner as it requires no little machine-specific assembly.

In the cvs version of GCL, such external calls are made through a C
pointer, which is redirected at startup to the correct address via
dlsym().  A little faster, and makes the loader a little simpler.

We tried to do this via bfd_get_relocated_section_contents, but the
coverage here was very spotty.

>  Also note that if you're doing stuff manually like this, then you may 
> have to take the GOT model used (traditional GOT, xGOT, multi-GOT) into 
> account.
>

Thankfully thus far this has not proved necessary.  But ia64 and hppa
are the only targets yet unimplemented, so who knows.

Take care,

>> Thanks so much!
>
>  You are welcome!
>
>   Maciej
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

[-- Attachment #2: att --]
[-- Type: application/octet-stream, Size: 44120 bytes --]

 # gcc -S -dp -mips3 -mabi=64  -Wall -DVOL=volatile -fsigned-char -pipe -fPIC -O3 -fomit-frame-pointer  -I/rootl/usr/local/downloads/gcln1/o -I../h -I../gcl-tk gcl_readline.c
</local/downloads/gcln1/o -I../h -I../gcl-tk gcl_readline.c
 # ls -lrt |tail
ls -lrt |tail
-rw-r--r-- 1 root   root    40834 Oct 28 10:52 new_init.c
-rw-r--r-- 1 root   root    73104 Oct 28 10:52 new_init.o
-rw-r--r-- 1 root   root     7768 Oct 28 10:52 gcllib.a
-rw-r--r-- 1 root   root   168368 Oct 28 10:52 cmpinclude.h
-rw-r--r-- 1 root   root    25608 Oct 28 17:56 sfasl.o
-rw-r--r-- 1 freddy freddy  12448 Oct 29 12:15 gcl_readline.d
-rw-r--r-- 1 root   root       60 Oct 29 12:15 gcl_readline.ini
-rw-r--r-- 1 root   root    12760 Oct 29 12:15 gcl_readline.o
-rw-r--r-- 1 root   root    12501 Oct 29 12:15 gcl_readline.c
-rw-r--r-- 1 root   root    41579 Oct 29 12:16 gcl_readline.s
 # objdump -r gcl_readline.o |grep IO_getc
objdump -r gcl_readline.o |grep IO_getc
0000000000000928 R_MIPS_GOT_DISP   _IO_getc
 # cat gcl_readline.s
cat gcl_readline.s
	.file	1 "gcl_readline.c"
	.section .mdebug.abi64
	.previous
	.abicalls
	.text
	.align	2
	.align	3
	.ent	siLreadline_off
	.type	siLreadline_off, @function
siLreadline_off:
	.frame	$sp,0,$31		# vars= 0, regs= 0/0, args= 0, gp= 0
	.mask	0x00000000,0
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	lui	$3,%hi(%neg(%gp_rel(siLreadline_off)))	 # 30	*movdi_64bit/2	[length = 4]
	daddu	$3,$3,$25	 # 31	*adddi3/1	[length = 4]
	daddiu	$3,$3,%lo(%neg(%gp_rel(siLreadline_off)))	 # 32	*lowdi	[length = 4]
	ld	$2,%got_disp(readline_on)($3)	 # 24	load_gotdi	[length = 4]
	j	$31	 # 28	return	[length = 4]
	sw	$0,0($2)	 # 12	*movsi_internal/5	[length = 4]

	.set	macro
	.set	reorder
	.end	siLreadline_off
	.section	.rodata.str1.8,"aMS",@progbits,1
	.align	3
.LC0:
	.ascii	"TERM\000"
	.align	3
.LC1:
	.ascii	"GCL\000"
	.align	3
.LC2:
	.ascii	"dumb\000"
	.align	3
.LC3:
	.ascii	"READLINE-ON\000"
	.align	3
.LC4:
	.ascii	"READLINE-OFF\000"
	.text
	.align	2
	.align	3
	.globl	gcl_init_readline_function
	.ent	gcl_init_readline_function
	.type	gcl_init_readline_function, @function
gcl_init_readline_function:
	.frame	$sp,32,$31		# vars= 0, regs= 4/0, args= 0, gp= 0
	.mask	0x90030000,-8
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	daddiu	$sp,$sp,-32	 # 112	*adddi3/2	[length = 4]
	sd	$28,16($sp)	 # 114	*movdi_64bit/5	[length = 4]
	lui	$28,%hi(%neg(%gp_rel(gcl_init_readline_function)))	 # 131	*movdi_64bit/2	[length = 4]
	daddu	$28,$28,$25	 # 132	*adddi3/1	[length = 4]
	daddiu	$28,$28,%lo(%neg(%gp_rel(gcl_init_readline_function)))	 # 133	*lowdi	[length = 4]
	ld	$4,%got_page(.LC0)($28)	 # 107	load_gotdi	[length = 4]
	ld	$25,%call16(getenv)($28)	 # 10	load_calldi	[length = 4]
	sd	$17,8($sp)	 # 115	*movdi_64bit/5	[length = 4]
	sd	$16,0($sp)	 # 116	*movdi_64bit/5	[length = 4]
	sd	$31,24($sp)	 # 113	*movdi_64bit/5	[length = 4]
	jal	$25	 # 11	call_value_internal/1	[length = 4]
	daddiu	$4,$4,%got_ofst(.LC0)	 # 9	*lowdi	[length = 4]

	move	$16,$2	 # 12	*movdi_64bit/1	[length = 4]
	ld	$2,%got_page(.LC1)($28)	 # 108	load_gotdi	[length = 4]
	ld	$4,%got_disp(rl_readline_name)($28)	 # 109	load_gotdi	[length = 4]
	ld	$3,%got_page(rl_completion)($28)	 # 110	load_gotdi	[length = 4]
	daddiu	$2,$2,%got_ofst(.LC1)	 # 16	*lowdi	[length = 4]
	sd	$2,0($4)	 # 17	*movdi_64bit/5	[length = 4]
	ld	$2,%got_disp(rl_attempted_completion_function)($28)	 # 111	load_gotdi	[length = 4]
	ld	$25,%call16(isatty)($28)	 # 25	load_calldi	[length = 4]
	daddiu	$3,$3,%got_ofst(rl_completion)	 # 93	*lowdi	[length = 4]
	sd	$3,0($2)	 # 22	*movdi_64bit/5	[length = 4]
	move	$4,$0	 # 24	*movdi_64bit/2	[length = 4]
	jal	$25	 # 26	call_value_internal/1	[length = 4]
	ld	$17,%got_page(n.12486)($28)	 # 106	load_gotdi	[length = 4]

	beq	$2,$0,.L12	 # 29	*branch_zerodi	[length = 4]
	ld	$4,%got_page(.LC3)($28)	 # 102	load_gotdi	[length = 4]

	ld	$5,%got_page(.LC2)($28)	 # 105	load_gotdi	[length = 4]
	ld	$25,%call16(strcmp)($28)	 # 38	load_calldi	[length = 4]
	move	$4,$16	 # 35	*movdi_64bit/1	[length = 4]
	beq	$16,$0,.L6	 # 32	*branch_zerodi	[length = 4]
	daddiu	$5,$5,%got_ofst(.LC2)	 # 37	*lowdi	[length = 4]

	jal	$25
	nop
	 # 39	call_value_internal/1	[length = 8]
	bne	$2,$0,.L13	 # 41	*branch_zerodi	[length = 4]
	ld	$2,%got_disp(readline_on)($28)	 # 104	load_gotdi	[length = 4]

	.align	3
.L4:
	ld	$4,%got_page(.LC3)($28)	 # 102	load_gotdi	[length = 4]
.L12:
	ld	$5,%got_page(siLreadline_on)($28)	 # 103	load_gotdi	[length = 4]
	lw	$2,%got_ofst(n.12486)($17)	 # 52	extendsidi2/2	[length = 4]
	ld	$25,%call16(make_si_function_internal)($28)	 # 61	load_calldi	[length = 4]
	daddiu	$4,$4,%got_ofst(.LC3)	 # 58	*lowdi	[length = 4]
	bne	$2,$0,.L10	 # 53	*branch_zerosi	[length = 4]
	daddiu	$5,$5,%got_ofst(siLreadline_on)	 # 60	*lowdi	[length = 4]

	jal	$25
	nop
	 # 62	call_value_internal/1	[length = 8]
	ld	$4,%got_page(.LC4)($28)	 # 100	load_gotdi	[length = 4]
	ld	$5,%got_page(siLreadline_off)($28)	 # 101	load_gotdi	[length = 4]
	ld	$25,%call16(make_si_function_internal)($28)	 # 68	load_calldi	[length = 4]
	daddiu	$4,$4,%got_ofst(.LC4)	 # 65	*lowdi	[length = 4]
	jal	$25	 # 69	call_value_internal/1	[length = 4]
	daddiu	$5,$5,%got_ofst(siLreadline_off)	 # 67	*lowdi	[length = 4]

	li	$3,1			# 0x1	 # 72	*movsi_internal/2	[length = 4]
	sw	$3,%got_ofst(n.12486)($17)	 # 73	*movsi_internal/5	[length = 4]
.L10:
	ld	$31,24($sp)	 # 120	*movdi_64bit/4	[length = 4]
	ld	$28,16($sp)	 # 121	*movdi_64bit/4	[length = 4]
	ld	$17,8($sp)	 # 122	*movdi_64bit/4	[length = 4]
	ld	$16,0($sp)	 # 123	*movdi_64bit/4	[length = 4]
	j	$31	 # 125	return_internal	[length = 4]
	daddiu	$sp,$sp,32	 # 124	*adddi3/2	[length = 4]

	.align	3
.L6:
	ld	$2,%got_disp(readline_on)($28)	 # 104	load_gotdi	[length = 4]
.L13:
	li	$3,1			# 0x1	 # 46	*movsi_internal/2	[length = 4]
	b	.L4	 # 134	jump	[length = 4]
	sw	$3,0($2)	 # 47	*movsi_internal/5	[length = 4]

	.set	macro
	.set	reorder
	.end	gcl_init_readline_function
	.section	.rodata.str1.8
	.align	3
.LC5:
	.ascii	"GCL is not being run from a terminal\000"
	.align	3
.LC6:
	.ascii	"Controlling terminal is not readline capable\000"
	.text
	.align	2
	.align	3
	.ent	siLreadline_on
	.type	siLreadline_on, @function
siLreadline_on:
	.frame	$sp,16,$31		# vars= 0, regs= 2/0, args= 0, gp= 0
	.mask	0x90000000,-8
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	daddiu	$sp,$sp,-16	 # 84	*adddi3/2	[length = 4]
	sd	$28,0($sp)	 # 86	*movdi_64bit/5	[length = 4]
	lui	$28,%hi(%neg(%gp_rel(siLreadline_on)))	 # 105	*movdi_64bit/2	[length = 4]
	daddu	$28,$28,$25	 # 106	*adddi3/1	[length = 4]
	daddiu	$28,$28,%lo(%neg(%gp_rel(siLreadline_on)))	 # 107	*lowdi	[length = 4]
	ld	$25,%call16(isatty)($28)	 # 9	load_calldi	[length = 4]
	sd	$31,8($sp)	 # 85	*movdi_64bit/5	[length = 4]
	jal	$25	 # 10	call_value_internal/1	[length = 4]
	move	$4,$0	 # 8	*movdi_64bit/2	[length = 4]

	ld	$4,%got_page(.LC0)($28)	 # 83	load_gotdi	[length = 4]
	ld	$25,%call16(getenv)($28)	 # 28	load_calldi	[length = 4]
	move	$5,$0	 # 19	*movdi_64bit/2	[length = 4]
	bne	$2,$0,.L15	 # 13	*branch_zerodi	[length = 4]
	daddiu	$4,$4,%got_ofst(.LC0)	 # 27	*lowdi	[length = 4]

	ld	$4,%got_page(.LC5)($28)	 # 81	load_gotdi	[length = 4]
	daddiu	$4,$4,%got_ofst(.LC5)	 # 18	*lowdi	[length = 4]
.L22:
	ld	$25,%got_disp(FEerror)($28)	 # 78	load_gotdi	[length = 4]
	ld	$28,0($sp)	 # 99	*movdi_64bit/4	[length = 4]
	ld	$31,8($sp)	 # 98	*movdi_64bit/4	[length = 4]
	jr	$25	 # 49	sibcall_internal/1	[length = 4]
	daddiu	$sp,$sp,16	 # 100	*adddi3/2	[length = 4]

	.align	3
.L15:
	jal	$25
	nop
	 # 29	call_value_internal/1	[length = 8]
	ld	$5,%got_page(.LC2)($28)	 # 80	load_gotdi	[length = 4]
	ld	$25,%call16(strcmp)($28)	 # 38	load_calldi	[length = 4]
	move	$4,$2	 # 35	*movdi_64bit/1	[length = 4]
	beq	$2,$0,.L17	 # 32	*branch_zerodi	[length = 4]
	daddiu	$5,$5,%got_ofst(.LC2)	 # 37	*lowdi	[length = 4]

	jal	$25
	nop
	 # 39	call_value_internal/1	[length = 8]
	ld	$4,%got_page(.LC6)($28)	 # 79	load_gotdi	[length = 4]
	move	$5,$0	 # 47	*movdi_64bit/2	[length = 4]
	beq	$2,$0,.L22	 # 41	*branch_zerodi	[length = 4]
	daddiu	$4,$4,%got_ofst(.LC6)	 # 46	*lowdi	[length = 4]

.L17:
	ld	$2,%got_disp(readline_on)($28)	 # 77	load_gotdi	[length = 4]
	li	$3,1			# 0x1	 # 55	*movsi_internal/2	[length = 4]
	sw	$3,0($2)	 # 56	*movsi_internal/5	[length = 4]
	ld	$31,8($sp)	 # 90	*movdi_64bit/4	[length = 4]
	ld	$28,0($sp)	 # 91	*movdi_64bit/4	[length = 4]
	j	$31	 # 93	return_internal	[length = 4]
	daddiu	$sp,$sp,16	 # 92	*adddi3/2	[length = 4]

	.set	macro
	.set	reorder
	.end	siLreadline_on
	.align	2
	.align	3
	.ent	rl_completion
	.type	rl_completion, @function
rl_completion:
	.frame	$sp,0,$31		# vars= 0, regs= 0/0, args= 0, gp= 0
	.mask	0x00000000,0
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	lui	$3,%hi(%neg(%gp_rel(rl_completion)))	 # 38	*movdi_64bit/2	[length = 4]
	daddu	$3,$3,$25	 # 39	*adddi3/1	[length = 4]
	daddiu	$3,$3,%lo(%neg(%gp_rel(rl_completion)))	 # 40	*lowdi	[length = 4]
	ld	$5,%got_page(rl_completion_words_new)($3)	 # 34	load_gotdi	[length = 4]
	ld	$25,%got_disp(rl_completion_matches)($3)	 # 35	load_gotdi	[length = 4]
	jr	$25	 # 16	sibcall_value_internal/1	[length = 4]
	daddiu	$5,$5,%got_ofst(rl_completion_words_new)	 # 14	*lowdi	[length = 4]

	.set	macro
	.set	reorder
	.end	rl_completion
	.align	2
	.align	3
	.ent	rl_completion_words_new
	.type	rl_completion_words_new, @function
rl_completion_words_new:
	.frame	$sp,224,$31		# vars= 128, regs= 11/0, args= 0, gp= 0
	.mask	0xd0ff0000,-16
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	daddiu	$sp,$sp,-224	 # 739	*adddi3/2	[length = 4]
	sd	$28,192($sp)	 # 742	*movdi_64bit/5	[length = 4]
	lui	$28,%hi(%neg(%gp_rel(rl_completion_words_new)))	 # 831	*movdi_64bit/2	[length = 4]
	daddu	$28,$28,$25	 # 832	*adddi3/1	[length = 4]
	sd	$20,160($sp)	 # 746	*movdi_64bit/5	[length = 4]
	sd	$31,208($sp)	 # 740	*movdi_64bit/5	[length = 4]
	sd	$fp,200($sp)	 # 741	*movdi_64bit/5	[length = 4]
	sd	$23,184($sp)	 # 743	*movdi_64bit/5	[length = 4]
	sd	$22,176($sp)	 # 744	*movdi_64bit/5	[length = 4]
	sd	$21,168($sp)	 # 745	*movdi_64bit/5	[length = 4]
	sd	$19,152($sp)	 # 747	*movdi_64bit/5	[length = 4]
	sd	$18,144($sp)	 # 748	*movdi_64bit/5	[length = 4]
	sd	$17,136($sp)	 # 749	*movdi_64bit/5	[length = 4]
	sd	$16,128($sp)	 # 750	*movdi_64bit/5	[length = 4]
	daddiu	$28,$28,%lo(%neg(%gp_rel(rl_completion_words_new)))	 # 833	*lowdi	[length = 4]
	bne	$5,$0,.L26	 # 10	*branch_zerodi	[length = 4]
	move	$20,$4	 # 3	*movdi_64bit/1	[length = 4]

	ld	$2,%got_disp(sSAreadline_prefixA)($28)	 # 738	load_gotdi	[length = 4]
	ld	$22,%got_page(pref.12253)($28)	 # 736	load_gotdi	[length = 4]
	ld	$21,%got_page(prefl.12245)($28)	 # 737	load_gotdi	[length = 4]
	ld	$3,0($2)	 # 21	*movdi_64bit/4	[length = 4]
	li	$2,13			# 0xd	 # 661	*movsi_internal/2	[length = 4]
	sd	$0,%got_ofst(pref.12253)($22)	 # 15	*movdi_64bit/5	[length = 4]
	ld	$4,8($3)	 # 22	*movdi_64bit/4	[length = 4]
	sw	$0,%got_ofst(prefl.12245)($21)	 # 18	*movsi_internal/5	[length = 4]
	lbu	$3,0($4)	 # 23	*zero_extendqisi2/2	[length = 4]
	beq	$3,$2,.L28	 # 25	*branch_equalitysi	[length = 4]
	move	$17,$0	 # 28	*movdi_64bit/2	[length = 4]

	move	$18,$0	 # 29	*movdi_64bit/2	[length = 4]
.L30:
	ld	$25,%call16(strchr)($28)	 # 81	load_calldi	[length = 4]
	move	$4,$20	 # 79	*movdi_64bit/1	[length = 4]
	jal	$25	 # 82	call_value_internal/1	[length = 4]
	li	$5,58			# 0x3a	 # 80	*movdi_64bit/2	[length = 4]

	beq	$2,$0,.L35	 # 86	*branch_zerodi	[length = 4]
	move	$19,$2	 # 83	*movdi_64bit/1	[length = 4]

	move	$4,$20	 # 90	*movdi_64bit/1	[length = 4]
	move	$17,$2	 # 97	*movdi_64bit/1	[length = 4]
	sd	$0,%got_ofst(pref.12253)($22)	 # 93	*movdi_64bit/5	[length = 4]
	sw	$0,%got_ofst(prefl.12245)($21)	 # 96	*movsi_internal/5	[length = 4]
.L37:
	beq	$17,$4,.L91	 # 122	*branch_equalitydi	[length = 4]
	li	$2,13	 # 658	*movqi_internal/2	[length = 4]

	ld	$25,%call16(find_package)($28)	 # 164	load_calldi	[length = 4]
	dsubu	$3,$17,$4	 # 159	subdi3	[length = 4]
	sd	$0,0($sp)	 # 149	*movdi_64bit/5	[length = 4]
	sb	$2,0($sp)	 # 155	*movqi_internal/4	[length = 4]
	li	$2,1	 # 657	*movhi_internal/2	[length = 4]
	sd	$0,16($sp)	 # 151	*movdi_64bit/5	[length = 4]
	sd	$0,32($sp)	 # 153	*movdi_64bit/5	[length = 4]
	sd	$4,24($sp)	 # 158	*movdi_64bit/5	[length = 4]
	sh	$2,16($sp)	 # 157	*movhi_internal/4	[length = 4]
	sw	$3,32($sp)	 # 160	truncdisi2/2	[length = 4]
	sd	$0,8($sp)	 # 150	*movdi_64bit/5	[length = 4]
	jal	$25	 # 165	call_value_internal/1	[length = 4]
	move	$4,$sp	 # 163	*movdi_64bit/1	[length = 4]

.L88:
	ld	$5,%got_page(package.12246)($28)	 # 730	load_gotdi	[length = 4]
	move	$16,$2	 # 691	*movdi_64bit/1	[length = 4]
	beq	$16,$0,.L92	 # 174	*branch_zerodi	[length = 4]
	sd	$2,%got_ofst(package.12246)($5)	 # 168	*movdi_64bit/5	[length = 4]

.L46:
	ld	$3,%got_page(package.12246)($28)	 # 727	load_gotdi	[length = 4]
	ld	$2,32($16)	 # 185	*movdi_64bit/4	[length = 4]
	move	$18,$0	 # 191	*movdi_64bit/2	[length = 4]
	sd	$16,%got_ofst(package.12246)($3)	 # 182	*movdi_64bit/5	[length = 4]
	ld	$3,%got_page(use.12247)($28)	 # 728	load_gotdi	[length = 4]
	beq	$17,$0,.L50	 # 188	*branch_zerodi	[length = 4]
	sd	$2,%got_ofst(use.12247)($3)	 # 186	*movdi_64bit/5	[length = 4]

	lb	$2,1($17)	 # 196	*extendqisi2/2	[length = 4]
	xori	$2,$2,0x3a	 # 197	*mips.md:2123/2	[length = 4]
	sltu	$2,$2,1	 # 200	*seq_si	[length = 4]
	andi	$18,$2,0x00ff	 # 201	*zero_extendqidi2/1	[length = 4]
.L50:
	ld	$2,%got_page(internal.12243)($28)	 # 725	load_gotdi	[length = 4]
	ld	$3,%got_page(ftext.12251)($28)	 # 726	load_gotdi	[length = 4]
	daddiu	$4,$19,1	 # 213	*adddi3/2	[length = 4]
	sw	$18,%got_ofst(internal.12243)($2)	 # 205	*movsi_internal/5	[length = 4]
	beq	$19,$0,.L93	 # 210	*branch_zerodi	[length = 4]
	sd	$20,%got_ofst(ftext.12251)($3)	 # 208	*movdi_64bit/5	[length = 4]

.L53:
	lb	$2,0($4)	 # 222	*extendqisi2/2	[length = 4]
	ld	$3,%got_page(wtext.12252)($28)	 # 721	load_gotdi	[length = 4]
	ld	$25,%call16(strlen)($28)	 # 235	load_calldi	[length = 4]
	xori	$2,$2,0x3a	 # 594	*mips.md:2123/2	[length = 4]
	sltu	$2,$2,1	 # 595	*seq_si	[length = 4]
	dsll	$2,$2,32	 # 719	*ashldi3	[length = 4]
	dsrl	$2,$2,32	 # 720	*lshrdi3	[length = 4]
	daddu	$4,$4,$2	 # 597	*adddi3/1	[length = 4]
	jal	$25	 # 236	call_value_internal/1	[length = 4]
	sd	$4,%got_ofst(wtext.12252)($3)	 # 231	*movdi_64bit/5	[length = 4]

	ld	$3,%got_page(len.12242)($28)	 # 722	load_gotdi	[length = 4]
	sw	$2,%got_ofst(len.12242)($3)	 # 238	truncdisi2/2	[length = 4]
	ld	$2,%got_page(tp.12248)($28)	 # 723	load_gotdi	[length = 4]
	sd	$16,%got_ofst(tp.12248)($2)	 # 241	*movdi_64bit/5	[length = 4]
	ld	$2,%got_page(i.12241)($28)	 # 724	load_gotdi	[length = 4]
	beq	$18,$0,.L56	 # 246	*branch_zerodi	[length = 4]
	sw	$0,%got_ofst(i.12241)($2)	 # 244	*movsi_internal/5	[length = 4]

	ld	$2,48($16)	 # 249	*movdi_64bit/4	[length = 4]
	ld	$4,%got_page(base.12249)($28)	 # 718	load_gotdi	[length = 4]
	lw	$3,64($16)	 # 253	extendsidi2/2	[length = 4]
	sd	$2,%got_ofst(base.12249)($4)	 # 251	*movdi_64bit/5	[length = 4]
.L58:
	ld	$2,0($2)	 # 270	*movdi_64bit/4	[length = 4]
	ld	$17,%got_page(l.12250)($28)	 # 715	load_gotdi	[length = 4]
	ld	$4,%got_page(size.12244)($28)	 # 716	load_gotdi	[length = 4]
	sd	$2,%got_ofst(l.12250)($17)	 # 271	*movdi_64bit/5	[length = 4]
	sw	$3,%got_ofst(size.12244)($4)	 # 267	*movsi_internal/5	[length = 4]
	ld	$2,%got_disp(Cnil_body)($28)	 # 713	load_gotdi	[length = 4]
.L101:
	beq	$16,$2,.L60	 # 283	*branch_equalitydi	[length = 4]
	ld	$3,%got_page(pref.12253)($28)	 # 708	load_gotdi	[length = 4]

	ld	$2,%got_page(internal.12243)($28)	 # 707	load_gotdi	[length = 4]
	ld	$17,%got_page(l.12250)($28)	 # 712	load_gotdi	[length = 4]
	ld	$22,%got_ofst(pref.12253)($3)	 # 291	*movdi_64bit/4	[length = 4]
	lw	$2,%got_ofst(internal.12243)($2)	 # 288	extendsidi2/2	[length = 4]
	ld	$3,%got_page(prefl.12245)($28)	 # 710	load_gotdi	[length = 4]
	sd	$2,112($sp)	 # 670	*movdi_64bit/5	[length = 4]
	lw	$16,%got_ofst(prefl.12245)($3)	 # 300	extendsidi2/2	[length = 4]
	ld	$2,%got_page(len.12242)($28)	 # 709	load_gotdi	[length = 4]
	ld	$3,%got_page(wtext.12252)($28)	 # 711	load_gotdi	[length = 4]
	lw	$23,%got_ofst(len.12242)($2)	 # 294	extendsidi2/2	[length = 4]
	ld	$fp,%got_ofst(wtext.12252)($3)	 # 296	*movdi_64bit/4	[length = 4]
.L62:
	ld	$3,%got_page(size.12244)($28)	 # 697	load_gotdi	[length = 4]
	ld	$4,%got_page(base.12249)($28)	 # 698	load_gotdi	[length = 4]
	lw	$20,%got_ofst(size.12244)($3)	 # 513	extendsidi2/2	[length = 4]
	ld	$21,%got_ofst(base.12249)($4)	 # 516	*movdi_64bit/4	[length = 4]
	ld	$8,%got_ofst(l.12250)($17)	 # 438	*movdi_64bit/4	[length = 4]
.L100:
	lbu	$2,0($8)	 # 439	*zero_extendqisi2/2	[length = 4]
	beql	$2,$0,.L98	 # 440	*branch_zerosi	[length = 4]
	ld	$6,16($8)	 # 309	*movdi_64bit/4	[length = 4]

	ld	$5,%got_page(i.12241)($28)	 # 706	load_gotdi	[length = 4]
	lw	$2,%got_ofst(i.12241)($5)	 # 445	extendsidi2/2	[length = 4]
.L99:
	addiu	$2,$2,1	 # 447	*addsi3_extended/2	[length = 4]
	beq	$20,$2,.L74	 # 451	*branch_equalitysi	[length = 4]
	sw	$2,%got_ofst(i.12241)($5)	 # 449	*movsi_internal/5	[length = 4]

	dsll	$2,$2,3	 # 457	*ashldi3	[length = 4]
	daddu	$2,$2,$21	 # 458	*adddi3/1	[length = 4]
	ld	$4,0($2)	 # 459	*movdi_64bit/4	[length = 4]
	ld	$3,%got_page(l.12250)($28)	 # 705	load_gotdi	[length = 4]
	sd	$4,%got_ofst(l.12250)($3)	 # 460	*movdi_64bit/5	[length = 4]
	ld	$8,%got_ofst(l.12250)($17)	 # 776	*movdi_64bit/4	[length = 4]
	lbu	$2,0($8)	 # 777	*zero_extendqisi2/2	[length = 4]
	bne	$2,$0,.L99	 # 778	*branch_zerosi	[length = 4]
	lw	$2,%got_ofst(i.12241)($5)	 # 445	extendsidi2/2	[length = 4]

	ld	$6,16($8)	 # 309	*movdi_64bit/4	[length = 4]
.L98:
	daddiu	$7,$sp,40	 # 311	*adddi3/2	[length = 4]
	daddiu	$9,$6,64	 # 312	*adddi3/2	[length = 4]
	.align	3
.L64:
	ld	$2,0($6)	 # 314	*movdi_64bit/4	[length = 4]
	ld	$3,8($6)	 # 315	*movdi_64bit/4	[length = 4]
	ld	$4,16($6)	 # 316	*movdi_64bit/4	[length = 4]
	ld	$5,24($6)	 # 317	*movdi_64bit/4	[length = 4]
	daddiu	$6,$6,32	 # 322	*adddi3/2	[length = 4]
	sd	$2,0($7)	 # 318	*movdi_64bit/5	[length = 4]
	sd	$3,8($7)	 # 319	*movdi_64bit/5	[length = 4]
	sd	$4,16($7)	 # 320	*movdi_64bit/5	[length = 4]
	sd	$5,24($7)	 # 321	*movdi_64bit/5	[length = 4]
	bne	$6,$9,.L64	 # 324	*branch_equalitydi	[length = 4]
	daddiu	$7,$7,32	 # 323	*adddi3/2	[length = 4]

	ld	$2,0($6)	 # 325	*movdi_64bit/4	[length = 4]
	sd	$2,0($7)	 # 326	*movdi_64bit/5	[length = 4]
	ld	$3,8($8)	 # 331	*movdi_64bit/4	[length = 4]
	ld	$19,64($sp)	 # 327	*movdi_64bit/4	[length = 4]
	lw	$18,72($sp)	 # 328	extendsidi2/2	[length = 4]
	beq	$22,$0,.L65	 # 334	*branch_zerodi	[length = 4]
	sd	$3,%got_ofst(l.12250)($17)	 # 332	*movdi_64bit/5	[length = 4]

	slt	$2,$18,$16	 # 338	*slt_si	[length = 4]
	bne	$2,$0,.L100	 # 339	*branch_zerosi	[length = 4]
	ld	$8,%got_ofst(l.12250)($17)	 # 438	*movdi_64bit/4	[length = 4]

	ld	$25,%call16(strncasecmp)($28)	 # 345	load_calldi	[length = 4]
	move	$4,$22	 # 342	*movdi_64bit/1	[length = 4]
	move	$5,$19	 # 343	*movdi_64bit/1	[length = 4]
	jal	$25	 # 346	call_value_internal/1	[length = 4]
	move	$6,$16	 # 344	*movdi_64bit/1	[length = 4]

	bne	$2,$0,.L100	 # 348	*branch_zerodi	[length = 4]
	ld	$8,%got_ofst(l.12250)($17)	 # 438	*movdi_64bit/4	[length = 4]

	daddu	$19,$19,$16	 # 352	*adddi3/1	[length = 4]
	subu	$18,$18,$16	 # 355	*subsi3_extended	[length = 4]
.L65:
	slt	$2,$18,$23	 # 359	*slt_si	[length = 4]
	bne	$2,$0,.L100	 # 360	*branch_zerosi	[length = 4]
	ld	$8,%got_ofst(l.12250)($17)	 # 438	*movdi_64bit/4	[length = 4]

	ld	$25,%call16(strncasecmp)($28)	 # 366	load_calldi	[length = 4]
	move	$4,$fp	 # 363	*movdi_64bit/1	[length = 4]
	move	$5,$19	 # 364	*movdi_64bit/1	[length = 4]
	jal	$25	 # 367	call_value_internal/1	[length = 4]
	move	$6,$23	 # 365	*movdi_64bit/1	[length = 4]

	bne	$2,$0,.L100	 # 369	*branch_zerodi	[length = 4]
	ld	$8,%got_ofst(l.12250)($17)	 # 438	*movdi_64bit/4	[length = 4]

	ld	$16,%got_page(ftext.12251)($28)	 # 692	load_gotdi	[length = 4]
	ld	$25,%call16(malloc)($28)	 # 380	load_calldi	[length = 4]
	ld	$17,%got_page(c.12263)($28)	 # 693	load_gotdi	[length = 4]
	ld	$4,%got_ofst(ftext.12251)($16)	 # 375	*movdi_64bit/4	[length = 4]
	dsubu	$4,$fp,$4	 # 376	subdi3	[length = 4]
	daddiu	$4,$4,1	 # 377	*adddi3/2	[length = 4]
	jal	$25	 # 381	call_value_internal/1	[length = 4]
	daddu	$4,$18,$4	 # 379	*adddi3/1	[length = 4]

	ld	$3,%got_page(wtext.12252)($28)	 # 694	load_gotdi	[length = 4]
	ld	$5,%got_ofst(ftext.12251)($16)	 # 389	*movdi_64bit/4	[length = 4]
	ld	$25,%call16(memcpy)($28)	 # 399	load_calldi	[length = 4]
	ld	$6,%got_ofst(wtext.12252)($3)	 # 391	*movdi_64bit/4	[length = 4]
	move	$4,$2	 # 396	*movdi_64bit/1	[length = 4]
	sd	$2,%got_ofst(c.12263)($17)	 # 386	*movdi_64bit/5	[length = 4]
	jal	$25	 # 400	call_value_internal/1	[length = 4]
	dsubu	$6,$6,$5	 # 398	subdi3	[length = 4]

	ld	$6,%got_page(wtext.12252)($28)	 # 695	load_gotdi	[length = 4]
	ld	$2,%got_ofst(ftext.12251)($16)	 # 406	*movdi_64bit/4	[length = 4]
	ld	$3,%got_ofst(c.12263)($17)	 # 409	*movdi_64bit/4	[length = 4]
	ld	$4,%got_ofst(wtext.12252)($6)	 # 405	*movdi_64bit/4	[length = 4]
	ld	$25,%call16(memcpy)($28)	 # 417	load_calldi	[length = 4]
	move	$5,$19	 # 415	*movdi_64bit/1	[length = 4]
	dsubu	$4,$4,$2	 # 407	subdi3	[length = 4]
	daddu	$4,$4,$3	 # 414	*adddi3/1	[length = 4]
	jal	$25	 # 418	call_value_internal/1	[length = 4]
	move	$6,$18	 # 416	*movdi_64bit/1	[length = 4]

	ld	$2,%got_page(wtext.12252)($28)	 # 696	load_gotdi	[length = 4]
	ld	$5,%got_ofst(c.12263)($17)	 # 422	*movdi_64bit/4	[length = 4]
	ld	$4,%got_ofst(ftext.12251)($16)	 # 426	*movdi_64bit/4	[length = 4]
	ld	$3,%got_ofst(wtext.12252)($2)	 # 424	*movdi_64bit/4	[length = 4]
	daddu	$2,$18,$5	 # 428	*adddi3/1	[length = 4]
	dsubu	$3,$3,$4	 # 427	subdi3	[length = 4]
	daddu	$2,$2,$3	 # 429	*adddi3/1	[length = 4]
	sb	$0,0($2)	 # 430	*movqi_internal/4	[length = 4]
	ld	$31,208($sp)	 # 754	*movdi_64bit/4	[length = 4]
	ld	$fp,200($sp)	 # 755	*movdi_64bit/4	[length = 4]
	ld	$28,192($sp)	 # 756	*movdi_64bit/4	[length = 4]
	ld	$23,184($sp)	 # 757	*movdi_64bit/4	[length = 4]
	ld	$22,176($sp)	 # 758	*movdi_64bit/4	[length = 4]
	ld	$21,168($sp)	 # 759	*movdi_64bit/4	[length = 4]
	ld	$20,160($sp)	 # 760	*movdi_64bit/4	[length = 4]
	ld	$19,152($sp)	 # 761	*movdi_64bit/4	[length = 4]
	ld	$18,144($sp)	 # 762	*movdi_64bit/4	[length = 4]
	ld	$17,136($sp)	 # 763	*movdi_64bit/4	[length = 4]
	ld	$16,128($sp)	 # 764	*movdi_64bit/4	[length = 4]
	move	$2,$5	 # 530	*movdi_64bit/1	[length = 4]
	j	$31	 # 766	return_internal	[length = 4]
	daddiu	$sp,$sp,224	 # 765	*adddi3/2	[length = 4]

.L26:
	ld	$6,%got_page(tp.12248)($28)	 # 714	load_gotdi	[length = 4]
	ld	$16,%got_ofst(tp.12248)($6)	 # 278	*movdi_64bit/4	[length = 4]
	bne	$16,$0,.L101	 # 279	*branch_zerodi	[length = 4]
	ld	$2,%got_disp(Cnil_body)($28)	 # 713	load_gotdi	[length = 4]

.L60:
	move	$5,$0	 # 521	*movdi_64bit/2	[length = 4]
.L95:
	ld	$31,208($sp)	 # 783	*movdi_64bit/4	[length = 4]
	ld	$fp,200($sp)	 # 784	*movdi_64bit/4	[length = 4]
	ld	$28,192($sp)	 # 785	*movdi_64bit/4	[length = 4]
	ld	$23,184($sp)	 # 786	*movdi_64bit/4	[length = 4]
	ld	$22,176($sp)	 # 787	*movdi_64bit/4	[length = 4]
	ld	$21,168($sp)	 # 788	*movdi_64bit/4	[length = 4]
	ld	$20,160($sp)	 # 789	*movdi_64bit/4	[length = 4]
	ld	$19,152($sp)	 # 790	*movdi_64bit/4	[length = 4]
	ld	$18,144($sp)	 # 791	*movdi_64bit/4	[length = 4]
	ld	$17,136($sp)	 # 792	*movdi_64bit/4	[length = 4]
	ld	$16,128($sp)	 # 793	*movdi_64bit/4	[length = 4]
	move	$2,$5	 # 781	*movdi_64bit/1	[length = 4]
	j	$31	 # 795	return_internal	[length = 4]
	daddiu	$sp,$sp,224	 # 794	*adddi3/2	[length = 4]

	.align	3
.L74:
	ld	$2,%got_page(use.12247)($28)	 # 703	load_gotdi	[length = 4]
	ld	$6,112($sp)	 # 673	*movdi_64bit/4	[length = 4]
	ld	$3,%got_ofst(use.12247)($2)	 # 468	*movdi_64bit/4	[length = 4]
	ld	$4,8($3)	 # 474	*movdi_64bit/4	[length = 4]
	ld	$3,16($3)	 # 469	*movdi_64bit/4	[length = 4]
	sd	$4,%got_ofst(use.12247)($2)	 # 475	*movdi_64bit/5	[length = 4]
	ld	$4,%got_page(tp.12248)($28)	 # 704	load_gotdi	[length = 4]
	beq	$6,$0,.L76	 # 477	*branch_zerodi	[length = 4]
	sd	$3,%got_ofst(tp.12248)($4)	 # 471	*movdi_64bit/5	[length = 4]

	ld	$2,48($3)	 # 480	*movdi_64bit/4	[length = 4]
	ld	$6,%got_page(base.12249)($28)	 # 702	load_gotdi	[length = 4]
	lw	$4,64($3)	 # 484	extendsidi2/2	[length = 4]
	sd	$2,%got_ofst(base.12249)($6)	 # 482	*movdi_64bit/5	[length = 4]
.L78:
	ld	$2,0($2)	 # 504	*movdi_64bit/4	[length = 4]
	ld	$6,%got_page(size.12244)($28)	 # 699	load_gotdi	[length = 4]
	sw	$0,%got_ofst(i.12241)($5)	 # 501	*movsi_internal/5	[length = 4]
	sd	$2,%got_ofst(l.12250)($17)	 # 505	*movdi_64bit/5	[length = 4]
	ld	$2,%got_disp(Cnil_body)($28)	 # 700	load_gotdi	[length = 4]
	bne	$3,$2,.L62	 # 508	*branch_equalitydi	[length = 4]
	sw	$4,%got_ofst(size.12244)($6)	 # 498	*movsi_internal/5	[length = 4]

	b	.L95	 # 835	jump	[length = 4]
	move	$5,$0	 # 800	*movdi_64bit/2	[length = 4]

	.align	3
.L76:
	ld	$2,56($3)	 # 490	*movdi_64bit/4	[length = 4]
	lw	$4,68($3)	 # 494	extendsidi2/2	[length = 4]
	ld	$6,%got_page(base.12249)($28)	 # 701	load_gotdi	[length = 4]
	b	.L78	 # 837	jump	[length = 4]
	sd	$2,%got_ofst(base.12249)($6)	 # 492	*movdi_64bit/5	[length = 4]

.L56:
	ld	$2,56($16)	 # 259	*movdi_64bit/4	[length = 4]
	lw	$3,68($16)	 # 263	extendsidi2/2	[length = 4]
	ld	$6,%got_page(base.12249)($28)	 # 717	load_gotdi	[length = 4]
	b	.L58	 # 839	jump	[length = 4]
	sd	$2,%got_ofst(base.12249)($6)	 # 261	*movdi_64bit/5	[length = 4]

.L28:
	lw	$16,32($4)	 # 39	extendsidi2/2	[length = 4]
	ld	$18,24($4)	 # 35	*movdi_64bit/4	[length = 4]
	ld	$25,%call16(memchr)($28)	 # 46	load_calldi	[length = 4]
	sw	$16,%got_ofst(prefl.12245)($21)	 # 41	*movsi_internal/5	[length = 4]
	sd	$18,%got_ofst(pref.12253)($22)	 # 37	*movdi_64bit/5	[length = 4]
	move	$4,$18	 # 43	*movdi_64bit/1	[length = 4]
	li	$5,58			# 0x3a	 # 44	*movdi_64bit/2	[length = 4]
	jal	$25	 # 47	call_value_internal/1	[length = 4]
	move	$6,$16	 # 45	*movdi_64bit/1	[length = 4]

	beq	$2,$0,.L30	 # 49	*branch_zerodi	[length = 4]
	move	$17,$0	 # 52	*movdi_64bit/2	[length = 4]

	lb	$3,1($2)	 # 60	*extendqisi2/2	[length = 4]
	move	$17,$2	 # 57	*movdi_64bit/1	[length = 4]
	daddiu	$4,$2,1	 # 59	*adddi3/2	[length = 4]
	li	$2,58			# 0x3a	 # 660	*movsi_internal/2	[length = 4]
	beql	$3,$2,.L33	 # 62	*branch_equalitysi	[length = 4]
	daddiu	$4,$17,2	 # 65	*adddi3/2	[length = 4]

.L33:
	dsubu	$2,$4,$18	 # 72	subdi3	[length = 4]
	sll	$2,$2,0	 # 73	truncdisi2/1	[length = 4]
	subu	$2,$16,$2	 # 74	subsi3	[length = 4]
	sw	$2,%got_ofst(prefl.12245)($21)	 # 75	*movsi_internal/5	[length = 4]
	b	.L30	 # 841	jump	[length = 4]
	sd	$4,%got_ofst(pref.12253)($22)	 # 69	*movdi_64bit/5	[length = 4]

.L91:
	lb	$3,1($17)	 # 126	*extendqisi2/2	[length = 4]
	li	$2,58			# 0x3a	 # 127	*movsi_internal/2	[length = 4]
	beql	$3,$2,.L97	 # 128	*branch_equalitysi	[length = 4]
	ld	$2,%got_disp(sLApackageA)($28)	 # 733	load_gotdi	[length = 4]

	ld	$2,%got_disp(keyword_package)($28)	 # 732	load_gotdi	[length = 4]
	b	.L88	 # 843	jump	[length = 4]
	ld	$2,0($2)	 # 139	*movdi_64bit/4	[length = 4]

.L35:
	bne	$17,$0,.L37	 # 103	*branch_zerodi	[length = 4]
	move	$4,$18	 # 118	*movdi_64bit/1	[length = 4]

	ld	$2,%got_disp(sLApackageA)($28)	 # 735	load_gotdi	[length = 4]
	ld	$5,%got_page(package.12246)($28)	 # 734	load_gotdi	[length = 4]
	ld	$3,0($2)	 # 109	*movdi_64bit/4	[length = 4]
	ld	$4,8($3)	 # 110	*movdi_64bit/4	[length = 4]
	move	$16,$4	 # 690	*movdi_64bit/1	[length = 4]
	bne	$16,$0,.L46	 # 804	*branch_zerodi	[length = 4]
	sd	$4,%got_ofst(package.12246)($5)	 # 111	*movdi_64bit/5	[length = 4]

.L92:
	ld	$2,%got_disp(user_package)($28)	 # 729	load_gotdi	[length = 4]
	b	.L46	 # 845	jump	[length = 4]
	ld	$16,0($2)	 # 178	*movdi_64bit/4	[length = 4]

.L93:
	b	.L53	 # 847	jump	[length = 4]
	move	$4,$20	 # 218	*movdi_64bit/1	[length = 4]

.L97:
	ld	$3,0($2)	 # 132	*movdi_64bit/4	[length = 4]
	b	.L88	 # 849	jump	[length = 4]
	ld	$2,8($3)	 # 133	*movdi_64bit/4	[length = 4]

	.set	macro
	.set	reorder
	.end	rl_completion_words_new
	.align	2
	.align	3
	.globl	rl_ungetc_em
	.ent	rl_ungetc_em
	.type	rl_ungetc_em, @function
rl_ungetc_em:
	.frame	$sp,32,$31		# vars= 0, regs= 4/0, args= 0, gp= 0
	.mask	0x90030000,-8
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	daddiu	$sp,$sp,-32	 # 67	*adddi3/2	[length = 4]
	sd	$28,16($sp)	 # 69	*movdi_64bit/5	[length = 4]
	lui	$28,%hi(%neg(%gp_rel(rl_ungetc_em)))	 # 88	*movdi_64bit/2	[length = 4]
	daddu	$28,$28,$25	 # 89	*adddi3/1	[length = 4]
	daddiu	$28,$28,%lo(%neg(%gp_rel(rl_ungetc_em)))	 # 90	*lowdi	[length = 4]
	ld	$2,%got_disp(stdin)($28)	 # 66	load_gotdi	[length = 4]
	sd	$17,8($sp)	 # 70	*movdi_64bit/5	[length = 4]
	sd	$16,0($sp)	 # 71	*movdi_64bit/5	[length = 4]
	sd	$31,24($sp)	 # 68	*movdi_64bit/5	[length = 4]
	ld	$3,0($2)	 # 11	*movdi_64bit/4	[length = 4]
	move	$17,$4	 # 3	*movdi_64bit/1	[length = 4]
	ld	$25,%call16(fileno)($28)	 # 16	load_calldi	[length = 4]
	move	$16,$5	 # 4	*movdi_64bit/1	[length = 4]
	beq	$3,$5,.L108	 # 12	*branch_equalitydi	[length = 4]
	move	$4,$5	 # 15	*movdi_64bit/1	[length = 4]

.L103:
	ld	$25,%got_disp(ungetc)($28)	 # 65	load_gotdi	[length = 4]
	ld	$28,16($sp)	 # 83	*movdi_64bit/4	[length = 4]
	move	$4,$17	 # 28	*movdi_64bit/1	[length = 4]
	move	$5,$16	 # 29	*movdi_64bit/1	[length = 4]
	ld	$31,24($sp)	 # 82	*movdi_64bit/4	[length = 4]
	ld	$17,8($sp)	 # 84	*movdi_64bit/4	[length = 4]
	ld	$16,0($sp)	 # 85	*movdi_64bit/4	[length = 4]
	jr	$25	 # 31	sibcall_value_internal/1	[length = 4]
	daddiu	$sp,$sp,32	 # 86	*adddi3/2	[length = 4]

	.align	3
.L108:
	jal	$25
	nop
	 # 17	call_value_internal/1	[length = 8]
	ld	$25,%call16(isatty)($28)	 # 21	load_calldi	[length = 4]
	jal	$25	 # 22	call_value_internal/1	[length = 4]
	move	$4,$2	 # 20	*movdi_64bit/1	[length = 4]

	beq	$2,$0,.L103	 # 25	*branch_zerodi	[length = 4]
	andi	$3,$17,0x00ff	 # 39	*zero_extendqisi2/1	[length = 4]

	ld	$2,%got_page(rl_ungetc_em_char)($28)	 # 64	load_gotdi	[length = 4]
	sw	$3,%got_ofst(rl_ungetc_em_char)($2)	 # 40	*movsi_internal/5	[length = 4]
	ld	$31,24($sp)	 # 75	*movdi_64bit/4	[length = 4]
	move	$2,$17	 # 49	*movdi_64bit/1	[length = 4]
	ld	$28,16($sp)	 # 76	*movdi_64bit/4	[length = 4]
	ld	$17,8($sp)	 # 77	*movdi_64bit/4	[length = 4]
	ld	$16,0($sp)	 # 78	*movdi_64bit/4	[length = 4]
	j	$31	 # 80	return_internal	[length = 4]
	daddiu	$sp,$sp,32	 # 79	*adddi3/2	[length = 4]

	.set	macro
	.set	reorder
	.end	rl_ungetc_em
	.align	2
	.align	3
	.globl	rl_putc_em
	.ent	rl_putc_em
	.type	rl_putc_em, @function
rl_putc_em:
	.frame	$sp,64,$31		# vars= 0, regs= 8/0, args= 0, gp= 0
	.mask	0x903f0000,-8
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	daddiu	$sp,$sp,-64	 # 164	*adddi3/2	[length = 4]
	sd	$28,48($sp)	 # 166	*movdi_64bit/5	[length = 4]
	lui	$28,%hi(%neg(%gp_rel(rl_putc_em)))	 # 192	*movdi_64bit/2	[length = 4]
	daddu	$28,$28,$25	 # 193	*adddi3/1	[length = 4]
	daddiu	$28,$28,%lo(%neg(%gp_rel(rl_putc_em)))	 # 194	*lowdi	[length = 4]
	ld	$2,%got_disp(stdout)($28)	 # 163	load_gotdi	[length = 4]
	sd	$17,8($sp)	 # 171	*movdi_64bit/5	[length = 4]
	sd	$16,0($sp)	 # 172	*movdi_64bit/5	[length = 4]
	sd	$31,56($sp)	 # 165	*movdi_64bit/5	[length = 4]
	sd	$21,40($sp)	 # 167	*movdi_64bit/5	[length = 4]
	sd	$20,32($sp)	 # 168	*movdi_64bit/5	[length = 4]
	sd	$19,24($sp)	 # 169	*movdi_64bit/5	[length = 4]
	sd	$18,16($sp)	 # 170	*movdi_64bit/5	[length = 4]
	ld	$3,0($2)	 # 11	*movdi_64bit/4	[length = 4]
	move	$16,$5	 # 4	*movdi_64bit/1	[length = 4]
	beq	$3,$5,.L122	 # 12	*branch_equalitydi	[length = 4]
	move	$17,$4	 # 3	*movdi_64bit/1	[length = 4]

.L110:
	ld	$25,%got_disp(_IO_putc)($28)	 # 155	load_gotdi	[length = 4]
	ld	$28,48($sp)	 # 176	*movdi_64bit/4	[length = 4]
	move	$4,$17	 # 118	*movdi_64bit/1	[length = 4]
	move	$5,$16	 # 119	*movdi_64bit/1	[length = 4]
	ld	$31,56($sp)	 # 175	*movdi_64bit/4	[length = 4]
	ld	$21,40($sp)	 # 177	*movdi_64bit/4	[length = 4]
	ld	$20,32($sp)	 # 178	*movdi_64bit/4	[length = 4]
	ld	$19,24($sp)	 # 179	*movdi_64bit/4	[length = 4]
	ld	$18,16($sp)	 # 180	*movdi_64bit/4	[length = 4]
	ld	$17,8($sp)	 # 181	*movdi_64bit/4	[length = 4]
	ld	$16,0($sp)	 # 182	*movdi_64bit/4	[length = 4]
	jr	$25	 # 121	sibcall_value_internal/1	[length = 4]
	daddiu	$sp,$sp,64	 # 183	*adddi3/2	[length = 4]

	.align	3
.L122:
	ld	$25,%call16(fileno)($28)	 # 16	load_calldi	[length = 4]
	jal	$25	 # 17	call_value_internal/1	[length = 4]
	move	$4,$5	 # 15	*movdi_64bit/1	[length = 4]

	ld	$25,%call16(isatty)($28)	 # 21	load_calldi	[length = 4]
	jal	$25	 # 22	call_value_internal/1	[length = 4]
	move	$4,$2	 # 20	*movdi_64bit/1	[length = 4]

	beq	$2,$0,.L110	 # 25	*branch_zerodi	[length = 4]
	li	$2,13			# 0xd	 # 29	*movsi_internal/2	[length = 4]

	beq	$17,$2,.L113	 # 30	*branch_equalitysi	[length = 4]
	li	$2,10			# 0xa	 # 33	*movsi_internal/2	[length = 4]

	beq	$17,$2,.L113	 # 34	*branch_equalitysi	[length = 4]
	ld	$18,%got_page(current_length.12377)($28)	 # 158	load_gotdi	[length = 4]

	ld	$19,%got_page(allocated_length.12376)($28)	 # 159	load_gotdi	[length = 4]
	lw	$5,%got_ofst(current_length.12377)($18)	 # 55	extendsidi2/2	[length = 4]
	lw	$3,%got_ofst(allocated_length.12376)($19)	 # 58	extendsidi2/2	[length = 4]
	addiu	$2,$5,2	 # 56	*addsi3/2	[length = 4]
	slt	$2,$3,$2	 # 59	*sgt_si	[length = 4]
	bne	$2,$0,.L123	 # 60	*branch_zerosi	[length = 4]
	ld	$20,%got_page(rl_putc_em_line)($28)	 # 156	load_gotdi	[length = 4]

.L117:
	lw	$2,%got_ofst(current_length.12377)($18)	 # 102	extendsidi2/2	[length = 4]
	ld	$3,%got_ofst(rl_putc_em_line)($20)	 # 104	*movdi_64bit/4	[length = 4]
	addiu	$4,$2,1	 # 108	*addsi3_extended/2	[length = 4]
	daddu	$5,$3,$4	 # 112	*adddi3/1	[length = 4]
	daddu	$2,$2,$3	 # 105	*adddi3/1	[length = 4]
	sb	$17,0($2)	 # 106	*movqi_internal/4	[length = 4]
	sw	$4,%got_ofst(current_length.12377)($18)	 # 110	*movsi_internal/5	[length = 4]
	b	.L110	 # 195	jump	[length = 4]
	sb	$0,0($5)	 # 113	*movqi_internal/4	[length = 4]

.L113:
	ld	$2,%got_page(allocated_length.12376)($28)	 # 161	load_gotdi	[length = 4]
	ld	$3,%got_page(current_length.12377)($28)	 # 162	load_gotdi	[length = 4]
	lw	$4,%got_ofst(allocated_length.12376)($2)	 # 42	extendsidi2/2	[length = 4]
	blez	$4,.L110	 # 43	*branch_zerosi	[length = 4]
	sw	$0,%got_ofst(current_length.12377)($3)	 # 39	*movsi_internal/5	[length = 4]

	ld	$2,%got_page(rl_putc_em_line)($28)	 # 160	load_gotdi	[length = 4]
	ld	$3,%got_ofst(rl_putc_em_line)($2)	 # 47	*movdi_64bit/4	[length = 4]
	b	.L110	 # 197	jump	[length = 4]
	sb	$0,0($3)	 # 48	*movqi_internal/4	[length = 4]

.L123:
	sll	$5,$5,1	 # 64	*ashlsi3	[length = 4]
	ld	$25,%call16(realloc)($28)	 # 75	load_calldi	[length = 4]
	ld	$21,%got_ofst(rl_putc_em_line)($20)	 # 71	*movdi_64bit/4	[length = 4]
	addiu	$5,$5,16	 # 66	*addsi3_extended/2	[length = 4]
	sw	$5,%got_ofst(allocated_length.12376)($19)	 # 68	*movsi_internal/5	[length = 4]
	jal	$25	 # 76	call_value_internal/1	[length = 4]
	move	$4,$21	 # 73	*movdi_64bit/1	[length = 4]

	bne	$2,$0,.L117	 # 82	*branch_zerodi	[length = 4]
	sd	$2,%got_ofst(rl_putc_em_line)($20)	 # 80	*movdi_64bit/5	[length = 4]

	ld	$25,%call16(free)($28)	 # 87	load_calldi	[length = 4]
	jal	$25	 # 88	call_internal/1	[length = 4]
	move	$4,$21	 # 86	*movdi_64bit/1	[length = 4]

	sw	$0,%got_ofst(allocated_length.12376)($19)	 # 91	*movsi_internal/5	[length = 4]
	b	.L110	 # 199	jump	[length = 4]
	sw	$0,%got_ofst(current_length.12377)($18)	 # 94	*movsi_internal/5	[length = 4]

	.set	macro
	.set	reorder
	.end	rl_putc_em
	.align	2
	.align	3
	.globl	rl_getc_em
	.ent	rl_getc_em
	.type	rl_getc_em, @function
rl_getc_em:
	.frame	$sp,64,$31		# vars= 0, regs= 7/0, args= 0, gp= 0
	.mask	0x901f0000,-16
	.fmask	0x00000000,0
	.set	noreorder
	.set	nomacro
	
	daddiu	$sp,$sp,-64	 # 217	*adddi3/2	[length = 4]
	sd	$28,40($sp)	 # 219	*movdi_64bit/5	[length = 4]
	lui	$28,%hi(%neg(%gp_rel(rl_getc_em)))	 # 273	*movdi_64bit/2	[length = 4]
	daddu	$28,$28,$25	 # 274	*adddi3/1	[length = 4]
	daddiu	$28,$28,%lo(%neg(%gp_rel(rl_getc_em)))	 # 275	*lowdi	[length = 4]
	ld	$2,%got_disp(stdin)($28)	 # 216	load_gotdi	[length = 4]
	sd	$16,0($sp)	 # 224	*movdi_64bit/5	[length = 4]
	sd	$31,48($sp)	 # 218	*movdi_64bit/5	[length = 4]
	sd	$20,32($sp)	 # 220	*movdi_64bit/5	[length = 4]
	sd	$19,24($sp)	 # 221	*movdi_64bit/5	[length = 4]
	sd	$18,16($sp)	 # 222	*movdi_64bit/5	[length = 4]
	sd	$17,8($sp)	 # 223	*movdi_64bit/5	[length = 4]
	ld	$17,0($2)	 # 10	*movdi_64bit/4	[length = 4]
	beq	$17,$4,.L144	 # 11	*branch_equalitydi	[length = 4]
	move	$16,$4	 # 3	*movdi_64bit/1	[length = 4]

	move	$4,$16	 # 27	*movdi_64bit/1	[length = 4]
.L143:
	ld	$25,%got_disp(_IO_getc)($28)	 # 208	load_gotdi	[length = 4]
	ld	$28,40($sp)	 # 247	*movdi_64bit/4	[length = 4]
	ld	$31,48($sp)	 # 246	*movdi_64bit/4	[length = 4]
	ld	$20,32($sp)	 # 248	*movdi_64bit/4	[length = 4]
	ld	$19,24($sp)	 # 249	*movdi_64bit/4	[length = 4]
	ld	$18,16($sp)	 # 250	*movdi_64bit/4	[length = 4]
	ld	$17,8($sp)	 # 251	*movdi_64bit/4	[length = 4]
	ld	$16,0($sp)	 # 252	*movdi_64bit/4	[length = 4]
	jr	$25	 # 116	sibcall_value_internal/1	[length = 4]
	daddiu	$sp,$sp,64	 # 253	*adddi3/2	[length = 4]

	.align	3
.L144:
	ld	$25,%call16(fileno)($28)	 # 15	load_calldi	[length = 4]
	jal	$25
	nop
	 # 16	call_value_internal/1	[length = 8]
	ld	$25,%call16(isatty)($28)	 # 20	load_calldi	[length = 4]
	jal	$25	 # 21	call_value_internal/1	[length = 4]
	move	$4,$2	 # 19	*movdi_64bit/1	[length = 4]

	beql	$2,$0,.L143	 # 24	*branch_zerodi	[length = 4]
	move	$4,$16	 # 27	*movdi_64bit/1	[length = 4]

	ld	$2,%got_page(rl_ungetc_em_char)($28)	 # 214	load_gotdi	[length = 4]
	li	$19,-1			# 0xffffffffffffffff	 # 38	*movsi_internal/2	[length = 4]
	lw	$18,%got_ofst(rl_ungetc_em_char)($2)	 # 37	extendsidi2/2	[length = 4]
	beq	$18,$19,.L128	 # 39	*branch_equalitysi	[length = 4]
	ld	$20,%got_page(line.12405)($28)	 # 213	load_gotdi	[length = 4]

	sw	$19,%got_ofst(rl_ungetc_em_char)($2)	 # 45	*movsi_internal/5	[length = 4]
.L130:
	move	$2,$18	 # 172	*movdi_64bit/1	[length = 4]
.L148:
	ld	$31,48($sp)	 # 228	*movdi_64bit/4	[length = 4]
	ld	$28,40($sp)	 # 229	*movdi_64bit/4	[length = 4]
	ld	$20,32($sp)	 # 230	*movdi_64bit/4	[length = 4]
	ld	$19,24($sp)	 # 231	*movdi_64bit/4	[length = 4]
	ld	$18,16($sp)	 # 232	*movdi_64bit/4	[length = 4]
	ld	$17,8($sp)	 # 233	*movdi_64bit/4	[length = 4]
	ld	$16,0($sp)	 # 234	*movdi_64bit/4	[length = 4]
	j	$31	 # 236	return_internal	[length = 4]
	daddiu	$sp,$sp,64	 # 235	*adddi3/2	[length = 4]

.L128:
	ld	$2,%got_ofst(line.12405)($20)	 # 53	*movdi_64bit/4	[length = 4]
	beq	$2,$0,.L145	 # 54	*branch_zerodi	[length = 4]
	ld	$2,%got_disp(readline_on)($28)	 # 212	load_gotdi	[length = 4]

	ld	$16,%got_page(linepos.12406)($28)	 # 207	load_gotdi	[length = 4]
.L149:
	ld	$4,%got_ofst(line.12405)($20)	 # 126	*movdi_64bit/4	[length = 4]
.L150:
	lw	$5,%got_ofst(linepos.12406)($16)	 # 124	extendsidi2/2	[length = 4]
	daddu	$2,$5,$4	 # 127	*adddi3/1	[length = 4]
	lb	$3,0($2)	 # 128	*extendqidi2/2	[length = 4]
	bne	$3,$0,.L138	 # 129	*branch_zerodi	[length = 4]
	ld	$25,%call16(free)($28)	 # 134	load_calldi	[length = 4]

	jal	$25	 # 135	call_internal/1	[length = 4]
	li	$18,10			# 0xa	 # 148	*movdi_64bit/2	[length = 4]

	ld	$2,%got_page(line.12405)($28)	 # 205	load_gotdi	[length = 4]
	sw	$0,%got_ofst(linepos.12406)($16)	 # 141	*movsi_internal/5	[length = 4]
	sd	$0,%got_ofst(line.12405)($2)	 # 138	*movdi_64bit/5	[length = 4]
	ld	$2,%got_disp(rl_line_buffer)($28)	 # 206	load_gotdi	[length = 4]
	ld	$2,0($2)	 # 144	*movdi_64bit/4	[length = 4]
	bnel	$2,$0,.L130	 # 145	*branch_zerodi	[length = 4]
	sb	$0,0($2)	 # 153	*movqi_internal/4	[length = 4]

	b	.L148	 # 276	jump	[length = 4]
	move	$2,$18	 # 172	*movdi_64bit/1	[length = 4]

.L145:
	li	$3,1			# 0x1	 # 199	*movsi_internal/2	[length = 4]
	lw	$4,0($2)	 # 59	extendsidi2/2	[length = 4]
	beq	$4,$3,.L146	 # 61	*branch_equalitysi	[length = 4]
	ld	$16,%got_disp(stdout)($28)	 # 210	load_gotdi	[length = 4]

	b	.L143	 # 278	jump	[length = 4]
	move	$4,$17	 # 114	*movdi_64bit/1	[length = 4]

.L138:
	addiu	$2,$5,1	 # 162	*addsi3/2	[length = 4]
	move	$18,$3	 # 160	*movdi_64bit/1	[length = 4]
	b	.L130	 # 280	jump	[length = 4]
	sw	$2,%got_ofst(linepos.12406)($16)	 # 163	*movsi_internal/5	[length = 4]

.L146:
	ld	$25,%call16(_IO_putc)($28)	 # 69	load_calldi	[length = 4]
	li	$4,13			# 0xd	 # 67	*movdi_64bit/2	[length = 4]
	jal	$25	 # 70	call_value_internal/1	[length = 4]
	ld	$5,0($16)	 # 68	*movdi_64bit/4	[length = 4]

	ld	$2,%got_page(rl_putc_em_line)($28)	 # 211	load_gotdi	[length = 4]
	ld	$25,%call16(readline)($28)	 # 75	load_calldi	[length = 4]
	jal	$25	 # 76	call_value_internal/1	[length = 4]
	ld	$4,%got_ofst(rl_putc_em_line)($2)	 # 74	*movdi_64bit/4	[length = 4]

	ld	$25,%call16(rl_putc_em)($28)	 # 85	load_calldi	[length = 4]
	ld	$5,0($16)	 # 84	*movdi_64bit/4	[length = 4]
	li	$4,13			# 0xd	 # 83	*movdi_64bit/2	[length = 4]
	jal	$25	 # 86	call_value_internal/1	[length = 4]
	sd	$2,%got_ofst(line.12405)($20)	 # 79	*movdi_64bit/5	[length = 4]

	ld	$4,%got_ofst(line.12405)($20)	 # 89	*movdi_64bit/4	[length = 4]
	beq	$4,$0,.L147	 # 90	*branch_zerodi	[length = 4]
	ld	$2,%got_disp(rl_line_buffer)($28)	 # 209	load_gotdi	[length = 4]

	lb	$2,0($4)	 # 102	*extendqisi2/2	[length = 4]
	beql	$2,$0,.L150	 # 103	*branch_zerosi	[length = 4]
	ld	$16,%got_page(linepos.12406)($28)	 # 207	load_gotdi	[length = 4]

	ld	$25,%call16(add_history)($28)	 # 107	load_calldi	[length = 4]
	jal	$25
	nop
	 # 108	call_internal/1	[length = 8]
	b	.L149	 # 282	jump	[length = 4]
	ld	$16,%got_page(linepos.12406)($28)	 # 207	load_gotdi	[length = 4]

.L147:
	ld	$3,0($2)	 # 94	*movdi_64bit/4	[length = 4]
	b	.L130	 # 284	jump	[length = 4]
	sb	$19,0($3)	 # 96	*movqi_internal/4	[length = 4]

	.set	macro
	.set	reorder
	.end	rl_getc_em
	.globl	readline_on
	.section	.bss
	.align	2
	.type	readline_on, @object
	.size	readline_on, 4
readline_on:
	.space	4
	.local	n.12486
	.comm	n.12486,4,4
	.local	c.12263
	.comm	c.12263,8,8
	.local	pref.12253
	.comm	pref.12253,8,8
	.local	wtext.12252
	.comm	wtext.12252,8,8
	.local	ftext.12251
	.comm	ftext.12251,8,8
	.local	l.12250
	.comm	l.12250,8,8
	.local	base.12249
	.comm	base.12249,8,8
	.local	tp.12248
	.comm	tp.12248,8,8
	.local	use.12247
	.comm	use.12247,8,8
	.local	package.12246
	.comm	package.12246,8,8
	.local	prefl.12245
	.comm	prefl.12245,4,4
	.local	size.12244
	.comm	size.12244,4,4
	.local	internal.12243
	.comm	internal.12243,4,4
	.local	len.12242
	.comm	len.12242,4,4
	.local	i.12241
	.comm	i.12241,4,4
	.data
	.align	2
	.type	rl_ungetc_em_char, @object
	.size	rl_ungetc_em_char, 4
rl_ungetc_em_char:
	.word	-1
	.local	rl_putc_em_line
	.comm	rl_putc_em_line,8,8
	.local	linepos.12406
	.comm	linepos.12406,4,4
	.local	line.12405
	.comm	line.12405,8,8
	.local	current_length.12377
	.comm	current_length.12377,4,4
	.local	allocated_length.12376
	.comm	allocated_length.12376,4,4

	.comm	tf,8,8

	.comm	kf,8,8

	.comm	car_or_cdr,8,8

	.comm	casefun,8,8

	.comm	sSAreadline_prefixA,8,8
	.ident	"GCC: (GNU) 4.1.2 (Gentoo 4.1.2)"
 # objdump -d gcl_readline.o |grep -5 928
objdump -d gcl_readline.o |grep -5 928
 914:	ffb10008 	sd	s1,8(sp)
 918:	dc510000 	ld	s1,0(v0)
 91c:	1224000c 	beq	s1,a0,950 <rl_getc_em+0x68>
 920:	0080802d 	move	s0,a0
 924:	0200202d 	move	a0,s0
 928:	df990000 	ld	t9,0(gp)
 92c:	dfbc0028 	ld	gp,40(sp)
 930:	dfbf0030 	ld	ra,48(sp)
 934:	dfb40020 	ld	s4,32(sp)
 938:	dfb30018 	ld	s3,24(sp)
 93c:	dfb20010 	ld	s2,16(sp)
...
 # gcc -v
gcc -v
Using built-in specs.
Target: mips64el-gentoo-linux-gnu
Configured with: /opt/sicortex/rootfs/build/var/tmp/portage/sys-devel/gcc-4.1.2/work/gcc-4.1.2/configure --prefix=/usr --bindir=/usr/mips64el-gentoo-linux-gnu/gcc-bin/4.1.2 --includedir=/usr/lib/gcc/mips64el-gentoo-linux-gnu/4.1.2/include --datadir=/usr/share/gcc-data/mips64el-gentoo-linux-gnu/4.1.2 --mandir=/usr/share/gcc-data/mips64el-gentoo-linux-gnu/4.1.2/man --infodir=/usr/share/gcc-data/mips64el-gentoo-linux-gnu/4.1.2/info --with-gxx-include-dir=/usr/lib/gcc/mips64el-gentoo-linux-gnu/4.1.2/include/g++-v4 --host=mips64el-gentoo-linux-gnu --target=mips64el-gentoo-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-nls --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-libunwind-exceptions --enable-multilib --enable-libmudflap --disable-libssp --disable-libgcj --with-abi=64 --with-arch=5kf --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu
Thread model: posix
gcc version 4.1.2 (Gentoo 4.1.2)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Gcl-devel] Re: gdb for mips64
  2010-10-29 15:52                                             ` Camm Maguire
@ 2010-10-30 12:39                                               ` Maciej W. Rozycki
  0 siblings, 0 replies; 21+ messages in thread
From: Maciej W. Rozycki @ 2010-10-30 12:39 UTC (permalink / raw)
  To: Camm Maguire; +Cc: David Daney, linux-mips, debian-mips, gcl-devel

On Fri, 29 Oct 2010, Camm Maguire wrote:

> OK see attachment below.

 Thanks.  This is the piece of code generated (I've snipped out the 
irrelevant bits:

	ld	$25,%got_disp(_IO_getc)($28)	# 208  load_gotdi	[length = 4]
	ld	$28,40($sp)	# 247  *movdi_64bit/4	[length = 4]
[...]
	jr	$25	# 116  sibcall_value_internal/1	[length = 4]
	daddiu	$sp,$sp,64	# 253  *adddi3/2	[length = 4]

As you can see this is a sibling (aka tail) call and GCC deliberately 
requests a GOT rather than a CALL reloc -- %got_disp(_IO_getc) means: 
"Give me _IO_getc with a R_MIPS_GOT_DISP reloc applied!".

 I have checked GCC sources and this is legitimate, because with the new 
ABIs the GOT pointer register ($gp aka $28) is call saved -- as you can 
see it's restored above to the value coming from the caller.  And the stub 
requires $gp to have been loaded with a pointer to the containing module's 
GOT and not (possibly) some other one.

 Here's the relevant comment from GCC:

  /* If we're generating PIC, and this call is to a global function,
     try to allow its address to be resolved lazily.  This isn't
     possible for NewABI sibcalls since the value of $gp on entry
     to the stub would be our caller's gp, not ours.  */

As this is something I had not considered before I was not aware of this 
new ABI limitation until now -- thanks for giving me the opportunity to 
get enlightened. :)

 You may not be seeing this with a newer version of GCC, because it may be 
refraining from emitting the sibling call for some reason -- essentially 
here we have a tradeoff between a one-time performance penalty at startup 
coming from the lack of the lazy stub and a per-call penalty coming from 
an extra return required if this was an ordinary call.  GCC may be able to 
assess the choice based on the likelihood of execution.  Just guessing 
though -- I'm not that much into GCC's internals ;) -- and the explanation 
may be as simple as -fno-optimize-sibling-calls sneaked in somewhere. ;)

> Its simple but rather unconventional.  GCL is a lisp system.  It loads
> compiled object files at runtime into memory, and executes therefrom.
> It can then save the expanded memory image to disk via unexec for
> later execution on the same or different machines.  Compiled code can

 Ah, that brings memories from the 1990s and the Perl's "undump" facility 
that allowed one to get executable machine code from otherwise interpreted 
code. ;)  I believe the functionality was lost with the transition from 
a.out to ELF and never revived -- for a change you seem to be doing the 
revival for Lisp, at least to some extent. :)

> reference symbols in external shared libraries.  These must be
> directed toward some trampoline in the initial final-linked
> executable, as otherwise the address loaded might not be valid in a
> later execution.  On mips, GCL adds a little stub to load the global
> got address from a local got table appended to the .o file, then to
> load the contents of this address, and then jump.  GCL ensures that
> LD_BIND_NOW is set at runtime via pushing the environment and execve()
> on startup.  On other systems, where .plt entries are available, GCL
> sets the address to the .plt which takes care of everything.  This is
> much cleaner as it requires no little machine-specific assembly.

 Interesting -- do you actually mean "compiled object files" are final 
executables (that may or may not have a PLT according to the ABI used) 
rather than .o files one would normally assume?

 Note that with current versions of the tools (GCC + binutils) you can get 
a PLT in MIPS code as an alternative as well (32-bit only; new ABIs are 
still limited to MIPS stubs only) coming from an ABI modification made for 
performance gain; I reckon -mplt is the GCC switch to request it.  I'm not 
entirely sure what the exact timeline of these changes was, but GCC 4.4 
should most certainly provide it and when it comes to binutils, as noted 
previously, you are best running the most recent version anyway.

 Still the use of PLTs would not solve the issue where a PLT would not, 
for some reason, be generated at all, such as with the LD's "-z now" 
option, or for a given function call, such as with MIPS new ABI's sibling 
calls (which I am fairly sure will be subject to the same limitation if 
ever implemented), would it?

> In the cvs version of GCL, such external calls are made through a C
> pointer, which is redirected at startup to the correct address via
> dlsym().  A little faster, and makes the loader a little simpler.

 It sounds cleaner to me if I'm getting the overall picture right here.

> Thankfully thus far this has not proved necessary.  But ia64 and hppa
> are the only targets yet unimplemented, so who knows.

 Hmm, the Itanic sounds like a problem by definition. ;)  Is anybody still 
using it anyway?  Can't comment on HP-PA.

  Maciej

^ permalink raw reply	[flat|nested] 21+ messages in thread

* mips and ADDR_NO_RANDOMIZE
  2010-10-26 17:19                                     ` David Daney
@ 2010-11-01 16:24                                       ` Camm Maguire
  2010-11-01 18:06                                         ` David Daney
  0 siblings, 1 reply; 21+ messages in thread
From: Camm Maguire @ 2010-11-01 16:24 UTC (permalink / raw)
  To: David Daney
  Cc: Maciej W. Rozycki, debian-mips, gcl-devel, Andreas Barth, linux-mips

Greetings! Executing personality() with the ADDR_NO_RANDOMIZE bit set,
and re-executing via execve, should yield a process with traditional
contiguous brk() addresses appended to the .data segment, independent
of the setting of sysctl kernel.randomize_va_space, right?  At least
this is the way the linux kernel has been working on x86 for many
years. 

The latest Debian mips kernel is not honoring this setting.  I'd like
to know if this is a kernel bug.

=============================================================================
h/unrandomize.h
=============================================================================
#include <sys/personality.h>
#include <syscall.h>
#include <unistd.h>
#include <alloca.h>
#include <errno.h>


{
  errno=0;

  {

    long pers = personality(0xffffffffUL);
    if (pers==-1) {printf("personality failure %d\n",errno);exit(-1);}
    if (!(pers & ADDR_NO_RANDOMIZE) && !getenv("GCL_UNRANDOMIZE")) {
      errno=0;
      if (personality(pers | ADDR_NO_RANDOMIZE) != -1 && personality(0xffffffffUL) & ADDR_NO_RANDOMIZE) {
	int i;
	char **n;
	for (i=0;envp[i];i++);
	n=alloca((i+2)*sizeof(*n));
	n[i+1]=0;
	n[i--]="GCL_UNRANDOMIZE=t";
	for (;i>=0;i--)
	  n[i]=envp[i];
#ifdef GCL_GPROF
	gprof_cleanup();
#endif
	errno=0;
	execve(*argv,argv,n);
	printf("execve failure %d\n",errno);
	exit(-1);
      } else {
	printf("personality change failure %d\n",errno);
	exit(-1);
      }
    }
  }
}
=============================================================================
f.c
=============================================================================
#include <stdio.h>
                    void gprof_cleanup() {};
		    int main(int argc,char * argv[],char * envp[]) {
			FILE *f;

			#include "h/unrandomize.h"

			if (!(f=fopen("conftest1","w"))) return -1;
			fprintf(f,"%u",sbrk(0));
			return 0;}
=============================================================================
./f && cat conftest1 && echo && ./f && cat conftest1
10043392
10584064
=============================================================================
strace -f ./f
=============================================================================
execve("./f", ["./f"], [/* 16 vars */]) = 0
brk(0)                                  = 0x7a4000
old_mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b938000
uname({sys="Linux", node="phrixos", ...}) = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=16547, ...}) = 0
old_mmap(NULL, 16547, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b93c000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\24s\1\0004\0\0\0"..., 512) = 512
lseek(3, 760, SEEK_SET)                 = 760
read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0\22\0\0\0", 32) = 32
fstat64(3, {st_mode=S_IFREG|0755, st_size=1594664, ...}) = 0
old_mmap(NULL, 1576560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2b948000
mprotect(0x2baac000, 49152, PROT_NONE)  = 0
old_mmap(0x2bab8000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0x2bab8000
old_mmap(0x2bac8000, 3696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2bac8000
close(3)                                = 0
set_thread_area(0x2b940ad0)             = 0
mprotect(0x2bab8000, 49152, PROT_READ)  = 0
munmap(0x2b93c000, 16547)               = 0
personality(0xffffffff /* PER_??? */)   = 0
personality(0x40000 /* PER_??? */)      = 0
personality(0xffffffff /* PER_??? */)   = 262144
execve("./f", ["./f"], [/* 17 vars */]) = 0
brk(0)                                  = 0x670000
old_mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ba70000
uname({sys="Linux", node="phrixos", ...}) = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=16547, ...}) = 0
old_mmap(NULL, 16547, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ba74000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\24s\1\0004\0\0\0"..., 512) = 512
lseek(3, 760, SEEK_SET)                 = 760
read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0\22\0\0\0", 32) = 32
fstat64(3, {st_mode=S_IFREG|0755, st_size=1594664, ...}) = 0
old_mmap(NULL, 1576560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2ba80000
mprotect(0x2bbe4000, 49152, PROT_NONE)  = 0
old_mmap(0x2bbf0000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0x2bbf0000
old_mmap(0x2bc00000, 3696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2bc00000
close(3)                                = 0
set_thread_area(0x2ba78ad0)             = 0
mprotect(0x2bbf0000, 49152, PROT_READ)  = 0
munmap(0x2ba74000, 16547)               = 0
personality(0xffffffff /* PER_??? */)   = 0
brk(0)                                  = 0x670000
brk(0x694000)                           = 0x694000
open("conftest1", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
old_mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2bc04000
write(3, "6897664", 7)                  = 7
exit_group(0)                           = ?
=============================================================================
uname -a
=============================================================================
Linux phrixos 2.6.36-rc6-loongson-2f #1 Mon Oct 4 20:36:22 UTC 2010
			mips64 GNU/Linux
=============================================================================
/proc/cpuinfo
=============================================================================
system type		: lemote-fuloong-2f-box
processor		: 0
cpu model		: ICT Loongson-2 V0.3  FPU V0.1
BogoMIPS		: 528.38
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 64
extra interrupt vector	: no
hardware watchpoint	: yes, count: 0, address/irw mask: []
ASEs implemented	:
shadow register sets	: 1
core			: 0
VCED exceptions		: not available
VCEI exceptions		: not available
=============================================================================

Take care,
-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: mips and ADDR_NO_RANDOMIZE
  2010-11-01 16:24                                       ` mips and ADDR_NO_RANDOMIZE Camm Maguire
@ 2010-11-01 18:06                                         ` David Daney
  2010-11-01 18:24                                           ` Camm Maguire
  0 siblings, 1 reply; 21+ messages in thread
From: David Daney @ 2010-11-01 18:06 UTC (permalink / raw)
  To: Camm Maguire
  Cc: Maciej W. Rozycki, debian-mips, gcl-devel, Andreas Barth, linux-mips

On 11/01/2010 09:24 AM, Camm Maguire wrote:
> Greetings! Executing personality() with the ADDR_NO_RANDOMIZE bit set,
> and re-executing via execve, should yield a process with traditional
> contiguous brk() addresses appended to the .data segment, independent
> of the setting of sysctl kernel.randomize_va_space, right?  At least
> this is the way the linux kernel has been working on x86 for many
> years.
>
> The latest Debian mips kernel is not honoring this setting.  I'd like
> to know if this is a kernel bug.
>

For things like this, we need to know what kind of kernel it is.  Is it 
a 64-bit kernel running a 32-bit application?

I am going to guess that it is.

The 32-bit sys_personality wrapper in the kernel looks incorrect.  But 
It should probably still work, to set ADDR_NO_RANDOMIZE, so I don't 
really know where it is going off track yet.

Having implemented the randomization, I would like to see it work 
correctly, so I guess I will look at it.

You seem to have a certain knack for uncovering obscure bugs.

David Daney

> =============================================================================
> h/unrandomize.h
> =============================================================================
> #include<sys/personality.h>
> #include<syscall.h>
> #include<unistd.h>
> #include<alloca.h>
> #include<errno.h>
>
>
> {
>    errno=0;
>
>    {
>
>      long pers = personality(0xffffffffUL);
>      if (pers==-1) {printf("personality failure %d\n",errno);exit(-1);}
>      if (!(pers&  ADDR_NO_RANDOMIZE)&&  !getenv("GCL_UNRANDOMIZE")) {
>        errno=0;
>        if (personality(pers | ADDR_NO_RANDOMIZE) != -1&&  personality(0xffffffffUL)&  ADDR_NO_RANDOMIZE) {
> 	int i;
> 	char **n;
> 	for (i=0;envp[i];i++);
> 	n=alloca((i+2)*sizeof(*n));
> 	n[i+1]=0;
> 	n[i--]="GCL_UNRANDOMIZE=t";
> 	for (;i>=0;i--)
> 	  n[i]=envp[i];
> #ifdef GCL_GPROF
> 	gprof_cleanup();
> #endif
> 	errno=0;
> 	execve(*argv,argv,n);
> 	printf("execve failure %d\n",errno);
> 	exit(-1);
>        } else {
> 	printf("personality change failure %d\n",errno);
> 	exit(-1);
>        }
>      }
>    }
> }
> =============================================================================
> f.c
> =============================================================================
> #include<stdio.h>
>                      void gprof_cleanup() {};
> 		    int main(int argc,char * argv[],char * envp[]) {
> 			FILE *f;
>
> 			#include "h/unrandomize.h"
>
> 			if (!(f=fopen("conftest1","w"))) return -1;
> 			fprintf(f,"%u",sbrk(0));
> 			return 0;}
> =============================================================================
> ./f&&  cat conftest1&&  echo&&  ./f&&  cat conftest1
> 10043392
> 10584064
> =============================================================================
> strace -f ./f
> =============================================================================
> execve("./f", ["./f"], [/* 16 vars */]) = 0
> brk(0)                                  = 0x7a4000
> old_mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b938000
> uname({sys="Linux", node="phrixos", ...}) = 0
> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
> access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
> open("/etc/ld.so.cache", O_RDONLY)      = 3
> fstat64(3, {st_mode=S_IFREG|0644, st_size=16547, ...}) = 0
> old_mmap(NULL, 16547, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b93c000
> close(3)                                = 0
> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
> open("/lib/libc.so.6", O_RDONLY)        = 3
> read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\24s\1\0004\0\0\0"..., 512) = 512
> lseek(3, 760, SEEK_SET)                 = 760
> read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0\22\0\0\0", 32) = 32
> fstat64(3, {st_mode=S_IFREG|0755, st_size=1594664, ...}) = 0
> old_mmap(NULL, 1576560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2b948000
> mprotect(0x2baac000, 49152, PROT_NONE)  = 0
> old_mmap(0x2bab8000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0x2bab8000
> old_mmap(0x2bac8000, 3696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2bac8000
> close(3)                                = 0
> set_thread_area(0x2b940ad0)             = 0
> mprotect(0x2bab8000, 49152, PROT_READ)  = 0
> munmap(0x2b93c000, 16547)               = 0
> personality(0xffffffff /* PER_??? */)   = 0
> personality(0x40000 /* PER_??? */)      = 0
> personality(0xffffffff /* PER_??? */)   = 262144
> execve("./f", ["./f"], [/* 17 vars */]) = 0
> brk(0)                                  = 0x670000
> old_mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ba70000
> uname({sys="Linux", node="phrixos", ...}) = 0
> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
> access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
> open("/etc/ld.so.cache", O_RDONLY)      = 3
> fstat64(3, {st_mode=S_IFREG|0644, st_size=16547, ...}) = 0
> old_mmap(NULL, 16547, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ba74000
> close(3)                                = 0
> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
> open("/lib/libc.so.6", O_RDONLY)        = 3
> read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\24s\1\0004\0\0\0"..., 512) = 512
> lseek(3, 760, SEEK_SET)                 = 760
> read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0\22\0\0\0", 32) = 32
> fstat64(3, {st_mode=S_IFREG|0755, st_size=1594664, ...}) = 0
> old_mmap(NULL, 1576560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2ba80000
> mprotect(0x2bbe4000, 49152, PROT_NONE)  = 0
> old_mmap(0x2bbf0000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0x2bbf0000
> old_mmap(0x2bc00000, 3696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2bc00000
> close(3)                                = 0
> set_thread_area(0x2ba78ad0)             = 0
> mprotect(0x2bbf0000, 49152, PROT_READ)  = 0
> munmap(0x2ba74000, 16547)               = 0
> personality(0xffffffff /* PER_??? */)   = 0
> brk(0)                                  = 0x670000
> brk(0x694000)                           = 0x694000
> open("conftest1", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
> fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
> old_mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2bc04000
> write(3, "6897664", 7)                  = 7
> exit_group(0)                           = ?
> =============================================================================
> uname -a
> =============================================================================
> Linux phrixos 2.6.36-rc6-loongson-2f #1 Mon Oct 4 20:36:22 UTC 2010
> 			mips64 GNU/Linux
> =============================================================================
> /proc/cpuinfo
> =============================================================================
> system type		: lemote-fuloong-2f-box
> processor		: 0
> cpu model		: ICT Loongson-2 V0.3  FPU V0.1
> BogoMIPS		: 528.38
> wait instruction	: yes
> microsecond timers	: yes
> tlb_entries		: 64
> extra interrupt vector	: no
> hardware watchpoint	: yes, count: 0, address/irw mask: []
> ASEs implemented	:
> shadow register sets	: 1
> core			: 0
> VCED exceptions		: not available
> VCEI exceptions		: not available
> =============================================================================
>
> Take care,

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: mips and ADDR_NO_RANDOMIZE
  2010-11-01 18:06                                         ` David Daney
@ 2010-11-01 18:24                                           ` Camm Maguire
  0 siblings, 0 replies; 21+ messages in thread
From: Camm Maguire @ 2010-11-01 18:24 UTC (permalink / raw)
  To: David Daney
  Cc: Maciej W. Rozycki, debian-mips, gcl-devel, Andreas Barth, linux-mips

Greetings!

David Daney <ddaney@caviumnetworks.com> writes:

> On 11/01/2010 09:24 AM, Camm Maguire wrote:
>> Greetings! Executing personality() with the ADDR_NO_RANDOMIZE bit set,
>> and re-executing via execve, should yield a process with traditional
>> contiguous brk() addresses appended to the .data segment, independent
>> of the setting of sysctl kernel.randomize_va_space, right?  At least
>> this is the way the linux kernel has been working on x86 for many
>> years.
>>
>> The latest Debian mips kernel is not honoring this setting.  I'd like
>> to know if this is a kernel bug.
>>
>
> For things like this, we need to know what kind of kernel it is.  Is
> it a 64-bit kernel running a 32-bit application?
>

The kernel is Debian 2.6.36-rc6-loongson-2f.  Does this suffice?

> I am going to guess that it is.
>
> The 32-bit sys_personality wrapper in the kernel looks incorrect.  But
> It should probably still work, to set ADDR_NO_RANDOMIZE, so I don't
> really know where it is going off track yet.
>
> Having implemented the randomization, I would like to see it work
> correctly, so I guess I will look at it.
>

Thanks so much!

> You seem to have a certain knack for uncovering obscure bugs.
>

:-)

Take care,

> David Daney
>
>> =============================================================================
>> h/unrandomize.h
>> =============================================================================
>> #include<sys/personality.h>
>> #include<syscall.h>
>> #include<unistd.h>
>> #include<alloca.h>
>> #include<errno.h>
>>
>>
>> {
>>    errno=0;
>>
>>    {
>>
>>      long pers = personality(0xffffffffUL);
>>      if (pers==-1) {printf("personality failure %d\n",errno);exit(-1);}
>>      if (!(pers&  ADDR_NO_RANDOMIZE)&&  !getenv("GCL_UNRANDOMIZE")) {
>>        errno=0;
>>        if (personality(pers | ADDR_NO_RANDOMIZE) != -1&&  personality(0xffffffffUL)&  ADDR_NO_RANDOMIZE) {
>> 	int i;
>> 	char **n;
>> 	for (i=0;envp[i];i++);
>> 	n=alloca((i+2)*sizeof(*n));
>> 	n[i+1]=0;
>> 	n[i--]="GCL_UNRANDOMIZE=t";
>> 	for (;i>=0;i--)
>> 	  n[i]=envp[i];
>> #ifdef GCL_GPROF
>> 	gprof_cleanup();
>> #endif
>> 	errno=0;
>> 	execve(*argv,argv,n);
>> 	printf("execve failure %d\n",errno);
>> 	exit(-1);
>>        } else {
>> 	printf("personality change failure %d\n",errno);
>> 	exit(-1);
>>        }
>>      }
>>    }
>> }
>> =============================================================================
>> f.c
>> =============================================================================
>> #include<stdio.h>
>>                      void gprof_cleanup() {};
>> 		    int main(int argc,char * argv[],char * envp[]) {
>> 			FILE *f;
>>
>> 			#include "h/unrandomize.h"
>>
>> 			if (!(f=fopen("conftest1","w"))) return -1;
>> 			fprintf(f,"%u",sbrk(0));
>> 			return 0;}
>> =============================================================================
>> ./f&&  cat conftest1&&  echo&&  ./f&&  cat conftest1
>> 10043392
>> 10584064
>> =============================================================================
>> strace -f ./f
>> =============================================================================
>> execve("./f", ["./f"], [/* 16 vars */]) = 0
>> brk(0)                                  = 0x7a4000
>> old_mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b938000
>> uname({sys="Linux", node="phrixos", ...}) = 0
>> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
>> access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
>> open("/etc/ld.so.cache", O_RDONLY)      = 3
>> fstat64(3, {st_mode=S_IFREG|0644, st_size=16547, ...}) = 0
>> old_mmap(NULL, 16547, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b93c000
>> close(3)                                = 0
>> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
>> open("/lib/libc.so.6", O_RDONLY)        = 3
>> read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\24s\1\0004\0\0\0"..., 512) = 512
>> lseek(3, 760, SEEK_SET)                 = 760
>> read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0\22\0\0\0", 32) = 32
>> fstat64(3, {st_mode=S_IFREG|0755, st_size=1594664, ...}) = 0
>> old_mmap(NULL, 1576560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2b948000
>> mprotect(0x2baac000, 49152, PROT_NONE)  = 0
>> old_mmap(0x2bab8000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0x2bab8000
>> old_mmap(0x2bac8000, 3696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2bac8000
>> close(3)                                = 0
>> set_thread_area(0x2b940ad0)             = 0
>> mprotect(0x2bab8000, 49152, PROT_READ)  = 0
>> munmap(0x2b93c000, 16547)               = 0
>> personality(0xffffffff /* PER_??? */)   = 0
>> personality(0x40000 /* PER_??? */)      = 0
>> personality(0xffffffff /* PER_??? */)   = 262144
>> execve("./f", ["./f"], [/* 17 vars */]) = 0
>> brk(0)                                  = 0x670000
>> old_mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ba70000
>> uname({sys="Linux", node="phrixos", ...}) = 0
>> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
>> access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
>> open("/etc/ld.so.cache", O_RDONLY)      = 3
>> fstat64(3, {st_mode=S_IFREG|0644, st_size=16547, ...}) = 0
>> old_mmap(NULL, 16547, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ba74000
>> close(3)                                = 0
>> access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
>> open("/lib/libc.so.6", O_RDONLY)        = 3
>> read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\24s\1\0004\0\0\0"..., 512) = 512
>> lseek(3, 760, SEEK_SET)                 = 760
>> read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0\22\0\0\0", 32) = 32
>> fstat64(3, {st_mode=S_IFREG|0755, st_size=1594664, ...}) = 0
>> old_mmap(NULL, 1576560, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2ba80000
>> mprotect(0x2bbe4000, 49152, PROT_NONE)  = 0
>> old_mmap(0x2bbf0000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x160000) = 0x2bbf0000
>> old_mmap(0x2bc00000, 3696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2bc00000
>> close(3)                                = 0
>> set_thread_area(0x2ba78ad0)             = 0
>> mprotect(0x2bbf0000, 49152, PROT_READ)  = 0
>> munmap(0x2ba74000, 16547)               = 0
>> personality(0xffffffff /* PER_??? */)   = 0
>> brk(0)                                  = 0x670000
>> brk(0x694000)                           = 0x694000
>> open("conftest1", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
>> fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
>> old_mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2bc04000
>> write(3, "6897664", 7)                  = 7
>> exit_group(0)                           = ?
>> =============================================================================
>> uname -a
>> =============================================================================
>> Linux phrixos 2.6.36-rc6-loongson-2f #1 Mon Oct 4 20:36:22 UTC 2010
>> 			mips64 GNU/Linux
>> =============================================================================
>> /proc/cpuinfo
>> =============================================================================
>> system type		: lemote-fuloong-2f-box
>> processor		: 0
>> cpu model		: ICT Loongson-2 V0.3  FPU V0.1
>> BogoMIPS		: 528.38
>> wait instruction	: yes
>> microsecond timers	: yes
>> tlb_entries		: 64
>> extra interrupt vector	: no
>> hardware watchpoint	: yes, count: 0, address/irw mask: []
>> ASEs implemented	:
>> shadow register sets	: 1
>> core			: 0
>> VCED exceptions		: not available
>> VCEI exceptions		: not available
>> =============================================================================
>>
>> Take care,
>
>
>
>
>

-- 
Camm Maguire			     		    camm@maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2010-11-01 18:25 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <E1OwbkA-0006gv-Bi@localhost.m.enhanced.com>
     [not found] ` <4C93993E.7030008@caviumnetworks.com>
     [not found]   ` <8762y49k1k.fsf@maguirefamily.org>
     [not found]     ` <4C93D86D.5090201@caviumnetworks.com>
     [not found]       ` <87fwx4dwu5.fsf@maguirefamily.org>
     [not found]         ` <4C97D9A1.7050102@caviumnetworks.com>
     [not found]           ` <87lj6te9t1.fsf@maguirefamily.org>
     [not found]             ` <4C9A8BC9.1020605@caviumnetworks.com>
     [not found]               ` <4C9A9699.6080908@caviumnetworks.com>
     [not found]                 ` <87pqvbs7oa.fsf@maguirefamily.org>
     [not found]                   ` <4CB88D2C.8020900@caviumnetworks.com>
     [not found]                     ` <87r5fksxby.fsf_-_@maguirefamily.org>
2010-10-20 16:38                       ` recent SIGBUS/SIGSEGV mips kernel bug David Daney
2010-10-20 21:31                         ` Camm Maguire
2010-10-21 16:19                           ` David Daney
2010-10-21 16:32                             ` Camm Maguire
2010-10-21 17:29                             ` David Daney
2010-10-21 19:07                               ` Camm Maguire
2010-10-25 20:11                               ` Camm Maguire
2010-10-25 21:32                               ` gdb for mips64 Camm Maguire
2010-10-25 21:45                                 ` David Daney
2010-10-26 12:47                                   ` Maciej W. Rozycki
2010-10-26 17:19                                     ` David Daney
2010-11-01 16:24                                       ` mips and ADDR_NO_RANDOMIZE Camm Maguire
2010-11-01 18:06                                         ` David Daney
2010-11-01 18:24                                           ` Camm Maguire
2010-10-26 14:47                                   ` gdb for mips64 Camm Maguire
2010-10-26 20:12                                     ` [Gcl-devel] " Camm Maguire
2010-10-28 10:50                                       ` Maciej W. Rozycki
2010-10-28 21:28                                         ` Camm Maguire
2010-10-29  7:47                                           ` Maciej W. Rozycki
2010-10-29 15:52                                             ` Camm Maguire
2010-10-30 12:39                                               ` Maciej W. Rozycki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.