comp.lang.ada
 help / color / mirror / Atom feed
From: Hyung-Hwan Chung <hyunghwan.chung@gmail.com>
Subject: Re: GNAT Allocation of a very large record
Date: Wed, 14 Aug 2013 18:06:14 -0700 (PDT)
Date: 2013-08-14T18:06:14-07:00	[thread overview]
Message-ID: <0a76f2be-4254-4641-8fa9-844aebacc545@googlegroups.com> (raw)
In-Reply-To: <12ebc074-b545-4528-af28-48864d90d049@googlegroups.com>

On Thursday, August 15, 2013 5:08:32 AM UTC+9, Anh Vo wrote:
> On Wednesday, August 14, 2013 12:32:10 PM UTC-7, Per Sandberg wrote:
> 
> > Tried 4 different GCC:s and one failed:
> > 
> > gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) x86 ok 
> > gcc 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC) x86_64 ok 
> > gcc 4.7.3 20130318 for GNAT Pro 7.2.0w (20130317) (GCC) x86_64 ok 
> > gcc 4.4.5 (Debian 4.4.5-8) arm (raspberry-pi) fail
> 
> It works fine with GNAT-GPL-2013 on Windows and GNATPro 7.1.1 on Red Hat x86.
>  
> A. Vo


I tried gcc 4.4.7 20120313 (Red Hat 4.4.7-2) (GCC) x86_64 and it seemed to work find originally.  Soon later, I wanted to confirm this at a slightly lower-level and realized that it gave me the illusion that it worked.

It raised the STORAGE_ERROR exception. But the key here is that how it was raised.

Strace reveals that there was a segmentation fault. You can guess that the program catches SIGSEGV from rt_sigaction (SIGSEGV,...) at the beginning.

$ strace ./x1
--<snip>--
rt_sigaction(SIGSEGV, {0x41ac90, [], SA_RESTORER|SA_STACK|SA_RESTART|SA_NODEFER|SA_SIGINFO, 0x7fd6ba93a920}, NULL, 8) = 0
fstat(2, {st_mode=S_IFREG|0664, st_size=2182, ...}) = 0
fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(4, 2), ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(4, 2), ...}) = 0
brk(0)                                  = 0xd23000
brk(0xd44000)                           = 0xd44000
write(1, "1. Kind: POINTER_OBJECT Size:  1"..., 34) = 34
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
brk(0xd65000)                           = 0xd65000
write(1, "2. Allocation Failed\n", 21)  = 21
exit_group(0)                           = ?
 
Ltrace reveals that the second attempt to 'new' that translated to malloc eventually requested 16 bytes only. You can also print the Pointer_Object_Record'Max_Size_In_Storage_Elements from within the program. I used ltrace to see the real value  passed to the malloc function. This comes down to the overflow/wrap-around issue.

$ ltrace ./x1
-- <snip> --
malloc(104)                                      = 0x18cd010
memcpy(0x7fff0c80a6d0, "1. Kind: ", 9)           = 0x7fff0c80a6d0
memcpy(0x7fff0c80a6d9, "POINTER_OBJECT", 14)     = 0x7fff0c80a6d9
memcpy(0x7fff0c80a6e7, " Size: ", 7)             = 0x7fff0c80a6e7
memcpy(0x7fff0c80a6ee, " 10", 3)                 = 0x7fff0c80a6ee
memcpy(0x6302a8, "1. Kind: POINTER_OBJECT Size:  1"..., 33) = 0x6302a8
memcpy(0x7fff0c80a790, "1. Kind: POINTER_OBJECT Size:  1"..., 33) = 0x7fff0c80a790
fwrite("1. Kind: POINTER_OBJECT Size:  1"..., 34, 1, 0x7f630f8ad780) = 1
malloc(16)                                       = 0x18cd080
--- SIGSEGV (Segmentation fault) ---
malloc(64)                                       = 0x18ee010
-- <snip> --

The assembly listing for the 'new' allocation part is shown here. It was produced with the command 'gcc -S x1.adb'. You can see that it initializes the record after memory allocation. I assume that __gnat_malloc contains the check for the actual malloc failure. For this case, malloc was given 16 so I'm sure it has reached the part after 'call __gnat_malloc'. The line 'movq $0, 16(%rax)' violates the memory access for the first time as it's accessing beyond the 16 byte block allocated. I believe that the line is for 'Class => Null'. If it carried on, it would execute the code after the label .L53 starting from a few lines above it in a loop for 'Pointer_Slot => (others => null)'. That would also violate the memory access.

     --<snip>--
     call __gnat_malloc
     movb $0, (%rax)
     movq -840(%rbp), %rdx
     movq %rdx, 8(%rax)
     movzbl    1(%rax), %edx
     andl $-8, %edx
     movb %dl, 1(%rax)
     movzbl    1(%rax), %edx
     andl $-9, %edx
     movb %dl, 1(%rax)
     movzbl    1(%rax), %edx
     andl $15, %edx
     movb %dl, 1(%rax)
     movq $0, 16(%rax) 
     movq -840(%rbp), %rdx
     movq %rdx, %rcx
     testq     %rcx, %rcx
     jle  .L52
     movl $1, %edx
.L53:
     movq %rdx, %rbx
     addq $1, %rbx
     movq $0, 8(%rax,%rbx,8)
     cmpq %rdx, %rcx
     je   .L52
     addq $1, %rdx
     jmp  .L53
     --<snip>--

Valgrind fails more miserably with this program. Any comments?

Thanks again,
Hyung-Hwan

  reply	other threads:[~2013-08-15  1:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-14  3:50 GNAT Allocation of a very large record hyunghwan.chung
2013-08-14 19:32 ` Per Sandberg
2013-08-14 20:08   ` Anh Vo
2013-08-15  1:06     ` Hyung-Hwan Chung [this message]
2013-08-15  8:59 ` Georg Bauhaus
2013-08-15 14:27 ` Robert A Duff
2013-08-16  1:18   ` Hyung-Hwan Chung
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox