[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Topics about GNUstep/libobjc2
From: |
David Chisnall |
Subject: |
Re: Topics about GNUstep/libobjc2 |
Date: |
Tue, 25 Oct 2016 16:52:28 +0100 |
This should now be fixed:
https://github.com/gnustep/libobjc2/commit/6df23377a02f187e0df8cb359175fb274b34aae1
It turns out that I’d previously got some code that was slightly wrong for this
and then disabled it…
It needs a lot more testing, but I really should push out the 1.9 release soon
as there are a load of improvements since the last one.
David
> On 25 Oct 2016, at 15:28, David Chisnall <theraven@sucs.org> wrote:
>
> Hi,
>
> It would help if the reduced test case compiled, but adding -march=native
> seems to fix that. It would also help if it were something a bit more
> minimal, but from what you’ve sent me:
>
> The crash happens in [CalcFactor evaluate], which simply returns the
> ResultType ivar itsValue. Clang is emitting sse instructions for this,
> assuming that the ivar is correctly 128-bit aligned. The offset is 48, so it
> is aligned within the object, but the 64-bit header makes it unaligned again.
>
> Here is a reduced test case that demonstrates the problem:
>
> #include <objc/runtime.h>
> #include <stdint.h>
> #include <assert.h>
> typedef int v4si __attribute__ ((vector_size (16)));
> @interface Foo
> {
> Class isa;
> v4si var;
> }
> - (void)check;
> + (id)new;
> @end
> @implementation Foo
> + (id)new
> {
> return class_createInstance(self, 0);
> }
> - (void)check
> {
> size_t addr = (size_t)&var;
> assert(addr & 15 == 0);
> }
> @end
>
> int main(void)
> {
> [[Foo new] check];
> }
>
> It appears that we’re not taking the offset into account correctly. I
> thought I’d fixed this, but apparently I haven’t. I’ll take a look now.
>
> David
>
>> On 25 Oct 2016, at 14:47, Dr. Rolf Jansen <rj@obsigna.com> wrote:
>>
>> Hi David,
>>
>> Attached to this message you will find a .zip-Archive with the stripped down
>> test case. It contains a FreeBSD Makefile and a .xcodeproj-package.
>>
>> It should build on FreeBSD against libobjc2 (ports) and Mac OS X (native
>> libobjs) out of the box. On Mac OS X it should run fine and it would crash
>> on FreeBSD.
>>
>> If you uncomment the #pragma pack() directives in CalcObject.h it builds and
>> runs fine also on FreeBSD 11-RELEASE-p1.
>>
>> Best regards
>>
>> Rolf
>>
>>> Am 25.10.2016 um 06:55 schrieb David Chisnall <theraven@sucs.org>:
>>>
>>> Hi Rolf,
>>>
>>> From your code snippets, it looks as if it should work and you’ve probably
>>> found either a compiler or runtime bug. If you can put together a reduced
>>> test case (ideally something that doesn’t depend on anything other than
>>> libobjc) I’ll take a look.
>>>
>>> David
>>>
>>>> On 24 Oct 2016, at 23:38, Dr. Rolf Jansen <rj@obsigna.com> wrote:
>>>>
>>>> Hi David,
>>>>
>>>> many thanks for the reply.
>>>>
>>>> Does this mean, that it is not advised to use arbitrary C structs as
>>>> Objective-C instance variables?
>>>>
>>>> The code is more than 10 years old, and at that time I started learning
>>>> Objective-C, and I heavily intermixed C data structures and algorithms
>>>> into a hollow OOP construct. It is a calculator engine with more than
>>>> 10000 lines of code.
>>>>
>>>> The code (without #pragma pack, and -O1,-O2,-O3, or -Ofast) crashes
>>>> consistently on FreeBSD when accessing one instance variable indicated
>>>> below from within the respective object.
>>>>
>>>> ...
>>>>
>>>> typedef struct
>>>> {
>>>> ErrorFlags flag;
>>>> unsigned begin, count;
>>>> char *field;
>>>> } ErrorRecord;
>>>>
>>>> typedef struct ResultType
>>>> {
>>>> ResultTypeFlags f;
>>>> unsigned n;
>>>> boolean b;
>>>> long long i;
>>>> long double r;
>>>> long double complex z;
>>>> struct ResultType *v;
>>>> char *s;
>>>> ErrorRecord e;
>>>> } ResultType;
>>>>
>>>> @interface CalcObject : MyObject
>>>> {
>>>> boolean isPercent;
>>>> TokenPtr itsToken;
>>>> Precedence itsPrecedence;
>>>> OpKind itsOpKind;
>>>> CalcObject *itsParent;
>>>> Calculator *itsCalculator;
>>>> }
>>>>
>>>> ...
>>>> - many instance methods;
>>>> ...
>>>>
>>>> @end
>>>>
>>>>
>>>> @interface CalcFactor : CalcObject
>>>> {
>>>> ResultType itsValue; <<<<<<<<<<<< accessing this one gives Bus Error
>>>> }
>>>>
>>>> ...
>>>> - some more instance methods;
>>>> ...
>>>>
>>>> @end
>>>>
>>>>
>>>> Questions:
>>>>
>>>> As said already, on Mac OS X this code does not crash with Apple's
>>>> non-fragile ABI. Is this only by coincidence and other similar constructs
>>>> may crash? Or, may I continue to use my 10000 line of code, without a
>>>> major rewrite?
>>>>
>>>> Likewise on FreeBSD, is it safe to rely on the magic of #pragma pack(8) or
>>>> is my code too fragil for the non-fragil ABI?
>>>>
>>>> AFAIK, 8 byte struct packing/padding is standard for 64bit architectures
>>>> and 4 byte packing/padding for 32bit architectures. Isn't it possible to
>>>> do this reliable for C structs included as Objective-C instance variables?
>>>>
>>>> Best regards
>>>>
>>>> Rolf
>>>>
>>>>> Am 24.10.2016 um 17:09 schrieb David Chisnall
>>>>> <David.Chisnall@cl.cam.ac.uk>:
>>>>>
>>>>> Hi Rolf,
>>>>>
>>>>> With the non-fragile ABI, it isn’t safe to assume that classes have the
>>>>> same layout as C structs. This works with the fragile ABI, because the
>>>>> compiler is entirely responsible for layout there. It sounds as if
>>>>> #pragma pack is removing some padding that the ABI mandates for C
>>>>> structs, but which the Objective-C runtime is not adding.
>>>>>
>>>>> David
>>>>>
>>>>>> On 24 Oct 2016, at 17:52, Dr. Rolf Jansen <rj@obsigna.com> wrote:
>>>>>>
>>>>>> Would it be OK to discuss on this list topics about Objective-C
>>>>>> development involving clang + GNUstep/libobjc2, but almost nothing else
>>>>>> from GNUstep?
>>>>>>
>>>>>> I constructed my own root class having only the bare basic methods that
>>>>>> are needed by a quite old project, that I revamped for inclusion into a
>>>>>> new plain C project. My class/code is working well on FreeBSD 11.0
>>>>>> RELEASE-p1 (amd64) when compiled with clang 3.8 (system) with -O0 or -Os
>>>>>> and linked against libobjc2 1.8.1 (ports). Once compiled with any other
>>>>>> optimization mode, it crashes (Bus Error) when accessing a certain
>>>>>> instance variable struct.
>>>>>>
>>>>>> It is working well on Mac OS X 11.12 when compiled in any -O mode with
>>>>>> my root class and linked against the native ObjC runtime. It is almost
>>>>>> always working on FreeBSD 11 in any -O mode when using NSObject as the
>>>>>> root class and linked against libobjc2 1.8.1 and gnustep-base (ports),
>>>>>> although, I saw 2 random crashes.
>>>>>>
>>>>>> After some debugging I found a workaround. Once I add a #pragma pack(8)
>>>>>> directive at the top of the headers that declare my class hierarchy +
>>>>>> all the C structs that are used throughout, the code with my root class
>>>>>> works well on FreeBSD 11 when compiled in any -O mode -- a pack(4) does
>>>>>> work as well.
>>>>>>
>>>>>> It is still possible that something is wrong with my code. However,
>>>>>> after these many experiments, I tend to assume that the Objective-C
>>>>>> runtime and the compiler sometimes disagree on correct packing/alignment
>>>>>> of instance variables in instantiated objects. I can't tell, though, if
>>>>>> the runtime or the compiler is responsible for this.
>>>>>>
>>>>>> In the case that it is appropriate to discuss this further on this list,
>>>>>> I am ready to send more information. If this is not the appropriate
>>>>>> list, then please may I ask for advise on which location this topic may
>>>>>> be discussed.
>>>>>>
>>>>>> The #pragma pack(8) does neither cost anything nor is it a very ugly
>>>>>> hack, so perhaps, it isn't even worth to discuss this issue furthermore,
>>>>>> given that clang 4.0 may be out soon.
>>>>>>
>>>>>> Best regards
>>>>>>
>>>>>> Rolf
>>
>> <BareObjC.zip>
>
>
> _______________________________________________
> Discuss-gnustep mailing list
> Discuss-gnustep@gnu.org
> https://lists.gnu.org/mailman/listinfo/discuss-gnustep