develooper Front page | perl.perl5.porters | Postings from July 2009

Re: [perl #60574] sv_upgrade() loses 64-bit alignment, causing SIGBUS on sparc

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
July 17, 2009 12:44
Subject:
Re: [perl #60574] sv_upgrade() loses 64-bit alignment, causing SIGBUS on sparc
Message ID:
20090717194440.GJ60303@plum.flirble.org
On Mon, Nov 17, 2008 at 08:52:28PM +0200, Niko Tyni wrote:
> On Mon, Nov 17, 2008 at 03:44:18PM +0000, Nicholas Clark wrote:
> > On Sun, Nov 16, 2008 at 08:17:17PM +0200, Niko Tyni wrote:
> > > On Sun, Nov 16, 2008 at 05:15:36PM +0000, Nicholas Clark wrote:
> > > > On Sun, Nov 16, 2008 at 04:16:14AM -0800, Niko Tyni wrote:
> > > > 
> > > > > As seen in <http://bugs.debian.org/505415>, calling sv_chop() or otherwise
> > > > > upgrading an SV can result in an unaligned 64-bit access on the sparc
> > > > > architecture.
> > > 
> > > > What is __alignof__(XPVIV) and sizeof(XPVIV) on the same system?
> > > 
> > > 8 and 24.
> > 
> > whereas __alignof__(xpv_allocated) and sizeof(xpv_allocated) are 8 and 4,
> > and __alignof__(xpviv_allocated) and sizeof(xpviv_allocated) are 12 and 4?
> 
> The other way around, otherwise right.
> 
> XPV:             alignof: 8 sizeof: 16
> xpv_allocated:   alignof: 4 sizeof: 8
> XPVIV:           alignof: 8 sizeof: 24
> xpviv_allocated: alignof: 4 sizeof: 12
>  
> > If so, that would explain a lot, and it's my fault.
> 
> Looking forward to the explanation :)
> 
> Thanks for your work,

Sorry for the delay. Does change 69ba284b5e077075f1211a1053a11dae403648fd
fix it? It's currently in blead, but it should be suitable to merge to
maint-5.10. It replaces the *_allocated structs with a construction using
STRUCT_OFFSET().

I don't have access to sparc Debian, but I do have limited acces to sparc
Solaris 9 (with gcc). On that, running the appended script I see

bash-2.05$ ./perl -Ilib align.pl >align.c && gcc -Wall -o align align.c && ./align
XPV                                                     16      8
xpv_allocated                                           8       4
sizeof(XPV) - STRUCT_OFFSET(XPV, xpv_cur)               8

XPVIV                                                   24      8
xpviv_allocated                                         12      4
sizeof(XPVIV) - STRUCT_OFFSET(XPVIV, xpv_cur)           16

XPVAV                                                   32      8
xpvav_allocated                                         20      4
sizeof(XPVAV) - STRUCT_OFFSET(XPVAV, xav_fill)          24

XPVHV                                                   32      8
xpvhv_allocated                                         20      4
sizeof(XPVHV) - STRUCT_OFFSET(XPVHV, xhv_fill)          24

XPVCV                                                   64      8
xpvcv_allocated                                         56      4
sizeof(XPVCV) - STRUCT_OFFSET(XPVCV, xpv_cur)           56

XPVFM                                                   64      8
xpvfm_allocated                                         56      4
sizeof(XPVFM) - STRUCT_OFFSET(XPVFM, xpv_cur)           56

XPVIO                                                   88      8
xpvio_allocated                                         76      4
sizeof(XPVIO) - STRUCT_OFFSET(XPVIO, xpv_cur)           80

regexp                                                  96      8
struct regexp_allocated                                 88      4
sizeof(regexp) - STRUCT_OFFSET(regexp, xpv_cur)         88

bash-2.05$ 

                                               sizeof() ^       ^ __alignof__()

So I think the new way preserves the alignment constraint.

If I've got this right, I'll explain further if necessary. I'm not committing
to an explanation yet, as I don't know if I'm right.

Nicholas Clark

#!perl -w
use strict;

print <<'EOH';
#include "EXTERN.h"
#include "perl.h"

int main() {
EOH

my %first = (
	     XPVAV => 'xav_fill',
	     XPVHV => 'xhv_fill',
	    );

my @types = qw(XPV XPVIV XPVAV XPVHV XPVCV XPVFM);
push @types, qw(XPVIO regexp) if $] >= 5.011;

foreach my $raw (@types) {
    foreach my $struct (map {$_, "\L$_\E_allocated"} $raw) {
	$struct = "struct $struct" if $struct eq 'regexp_allocated';
	print qq{printf("%-48s\\t%d\t%d\\n", "$struct"};
	print ", $_($struct)" foreach qw(sizeof __alignof__);
	print ")\n;";
    }
    my $first = $first{$raw} || 'xpv_cur';
    my $new = "sizeof($raw) - STRUCT_OFFSET($raw, $first)";
    print qq{printf("%-48s\\t%d\\n\\n", "$new", $new);\n};
}

print <<'EOH';
    return 0;
}
EOH

__END__

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About