Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-09

crash in lazbuild only on powerpc 64bit

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mattias Gaertner

Hi,

I was not able to reproduce the crash in a simple program. So I'm asking for help to create a good bug report.

The crash happens in lazbuild only on powerpc 64bit Linux with fpc 2.6.0 and fpc 2.7.1. It works on Linux 32+64bit intel+amd and powerpc 32bit OS X with any fpc.

The crashing line looks pretty common:

IncludePath:=OnGetIncludePath(FullDir,false);

OnGetIncludePath is a property:

TOnGetIncludePath = function(const Directory: string; UseCache: boolean): string of object;
property OnGetIncludePath: TOnGetIncludePath read fOnGetIncludePath write fOnGetIncludePath;

Calling the method directly does not crash.
Comparing the property and the address gives true:

writeln('This gives true=',OnGetIncludePath = @CodeToolBoss.GetIncludePathForDirectory);

Here is the assembler of the line

# [1514] IncludePath:=OnGetIncludePath(FullDir,false); ld r3,152(r1)
ld r3,184(r3)
ld r5,184(r1)
addi r4,r1,200
li r6,0
ld r7,152(r1)
ld r30,176(r7)
ld r31,0(r30)
std r2,40(r1)
mtctr r31
ld r2,8(r30)
ld r11,16(r30)
bctrl
ld r2,40(r1)

And here is the assembler of the working call:

# [1512] IncludePath:=CodeToolBoss.GetIncludePathForDirectory(FullDir); ld r5,184(r1)
addi r4,r1,200
lis r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@highesta ori r3,r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@highera sldi r3,r3,32
oris r3,r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@ha
ld r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@l(r3)
li r6,1
bl CODETOOLMANAGER_TCODETOOLMANAGER_$__GETINCLUDEPATHFORDIRECTORY$ANSISTRING$BOOLEAN$$ANSISTRING nop

Mattias

Mattias Gaertner
to Mattias Gaertner
Show quoted text 54 lines
Hi, I was not able to reproduce the crash in a simple program. So I'm asking for help to create a good bug report. The crash happens in lazbuild only on powerpc 64bit Linux with fpc 2.6.0 and fpc 2.7.1. It works on Linux 32+64bit intel+amd and powerpc 32bit OS X with any fpc. The crashing line looks pretty common: IncludePath:=OnGetIncludePath(FullDir,false); OnGetIncludePath is a property: TOnGetIncludePath = function(const Directory: string; UseCache: boolean): string of object; property OnGetIncludePath: TOnGetIncludePath read fOnGetIncludePath write fOnGetIncludePath; Calling the method directly does not crash. Comparing the property and the address gives true: writeln('This gives true=',OnGetIncludePath = @CodeToolBoss.GetIncludePathForDirectory); Here is the assembler of the line # [1514] IncludePath:=OnGetIncludePath(FullDir,false); ld r3,152(r1) ld r3,184(r3) ld r5,184(r1) addi r4,r1,200 li r6,0 ld r7,152(r1) ld r30,176(r7) ld r31,0(r30) std r2,40(r1) mtctr r31 ld r2,8(r30) ld r11,16(r30) bctrl ld r2,40(r1) And here is the assembler of the working call: # [1512] IncludePath:=CodeToolBoss.GetIncludePathForDirectory(FullDir); ld r5,184(r1) addi r4,r1,200 lis r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@highesta ori r3,r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@highera sldi r3,r3,32 oris r3,r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@ha ld r3,(U_CODETOOLMANAGER_CODETOOLBOSS)@l(r3) li r6,1 bl CODETOOLMANAGER_TCODETOOLMANAGER_$__GETINCLUDEPATHFORDIRECTORY$ANSISTRING$BOOLEAN$$ANSISTRING nop

I created a bug report.

http://bugs.freepascal.org/view.php?id=22958

Mattias

Jonas Maebe
to Mattias Gaertner: I was not able to reproduce the crash in a simple program. So I'm asking for help to…

Mattias Gaertner wrote on Sun, 23 Sep 2012:

Show quoted text 5 lines
Calling the method directly does not crash. Comparing the property and the address gives true: writeln('This gives true=',OnGetIncludePath = @CodeToolBoss.GetIncludePathForDirectory);

The result of such an expression is unpredictable on Linux/ppc64 and on AIX. The reason is that on those platforms, procedure variables are actually pointers to a descriptor (their ABI requires this). This descriptor is 3 pointer large and contains the address of the routine to be called, the value of the TOC pointer (r2) and the value of a nested frame pointer (r11; unused by FPC). It's possible to have an arbitrarily large number of different descriptors for the same routine in a program, although the linker will try to merge them as much as possible.

That may also be related to main problem in your code, although the fact that the descriptors match suggests that it isn't.

Jonas

Mattias Gaertner
to Jonas Maebe
Show quoted text 18 lines
Mattias Gaertner wrote on Sun, 23 Sep 2012: > Calling the method directly does not crash. > Comparing the property and the address gives true: > > writeln('This gives true=',OnGetIncludePath = > @CodeToolBoss.GetIncludePathForDirectory); The result of such an expression is unpredictable on Linux/ppc64 and on AIX. The reason is that on those platforms, procedure variables are actually pointers to a descriptor (their ABI requires this). This descriptor is 3 pointer large and contains the address of the routine to be called, the value of the TOC pointer (r2) and the value of a nested frame pointer (r11; unused by FPC). It's possible to have an arbitrarily large number of different descriptors for the same routine in a program, although the linker will try to merge them as much as possible.

Interesting.
That explains why the compiler didn't let me cast it to a pointer.

The designer casts events using the TMethod record (Data, Code). How does this work under ppc64?

That may also be related to main problem in your code, although the fact that the descriptors match suggests that it isn't.

There are some cases in the FCL and Laz sources where events are compared. But this is not one of them.

Assigning a method to a property and calling it is done at thousands of places in the Lazarus sources and is also executed many times before the crash. I don't see yet, why this place is special.

Mattias

Jonas Maebe
to Mattias Gaertner

Mattias Gaertner wrote on Mon, 24 Sep 2012:

Show quoted text 18 lines
On Mon, 24 Sep 2012 11:43:32 +0200 Jonas Maebe wrote: > > writeln('This gives true=',OnGetIncludePath = > > @CodeToolBoss.GetIncludePathForDirectory); > > The result of such an expression is unpredictable on Linux/ppc64 and > on AIX. The reason is that on those platforms, procedure variables are > actually pointers to a descriptor (their ABI requires this). This > descriptor is 3 pointer large and contains the address of the routine > to be called, the value of the TOC pointer (r2) and the value of a > nested frame pointer (r11; unused by FPC). It's possible to have an > arbitrarily large number of different descriptors for the same routine > in a program, although the linker will try to merge them as much as > possible. Interesting. That explains why the compiler didn't let me cast it to a pointer.

I doubt it. As mentioned, procedure variables are pointers to descriptions, so they're still pointers. It's just that they're not guaranteed to be unique per procedure. At the parser level, procvars are not handled differently than on other platforms iirc.

The designer casts events using the TMethod record (Data, Code). How does this work under ppc64?

Exactly the same as on other platforms. The "code" field simply contains a pointer to the descriptor instead of to the code of the routine.

Jonas

Florian Klämpfl
to Jonas Maebe: Mattias Gaertner wrote on Sun, 23 Sep 2012: The result of such an expression is…
Jonas Maebe wrote 17 lines
Mattias Gaertner wrote on Sun, 23 Sep 2012: > Calling the method directly does not crash. > Comparing the property and the address gives true: > > writeln('This gives true=',OnGetIncludePath = > @CodeToolBoss.GetIncludePathForDirectory); The result of such an expression is unpredictable on Linux/ppc64 and on AIX. The reason is that on those platforms, procedure variables are actually pointers to a descriptor (their ABI requires this). This descriptor is 3 pointer large and contains the address of the routine to be called, the value of the TOC pointer (r2) and the value of a nested frame pointer (r11; unused by FPC). It's possible to have an arbitrarily large number of different descriptors for the same routine in a program, although the linker will try to merge them as much as possible.

Do we consider procedure variables as opaque? In this case we could compare the descriptor on ppc64.

Jonas Maebe
to Florian Klämpfl
Florian Klämpfl wrote 18 lines
Am 24.09.2012 11:43, schrieb Jonas Maebe: > > Mattias Gaertner wrote on Sun, 23 Sep 2012: > >> writeln('This gives true=',OnGetIncludePath = >> @CodeToolBoss.GetIncludePathForDirectory); > > The result of such an expression is unpredictable on Linux/ppc64 and on > AIX. The reason is that on those platforms, procedure variables are > actually pointers to a descriptor (their ABI requires this). This > descriptor is 3 pointer large and contains the address of the routine to > be called, the value of the TOC pointer (r2) and the value of a nested > frame pointer (r11; unused by FPC). It's possible to have an arbitrarily > large number of different descriptors for the same routine in a program, > although the linker will try to merge them as much as possible. Do we consider procedure variables as opaque? In this case we could compare the descriptor on ppc64.

You mean the code pointers stored inside the descriptor? That would introduce other inconsistencies, like making "pointer(procvar1)pointer(procvar2)" give a potentially different result from "procvar1procvar2". gcc also behaves the same as we do right now. I'm wary of inventing our own conventions in this regard.

Jonas