Crash during objc_msg_lookup_sender (Aarch64)
Closed this issue · 8 comments
Hi,
When launching Gorm.app the app crashes. This is during an ASSIGN macro/command being used. Could it be incompatible? Is this perhaps related to the bug that was recently fixed?
Thank you,
Patryk
pinebook:~/Desktop/gnustep-build/ubuntu-16.04-clang-6.0-runtime-1.9-ARM/GNUstep-build/apps-gorm/Gorm.app$ lldb-6.0 ./Gorm
(lldb) target create "./Gorm"
Current executable set to './Gorm' (aarch64).
(lldb) run
Process 10412 launched: './Gorm' (aarch64)
2019-08-28 05:51:40.657 Gorm[10412:10412] styleoffsets ... guessing offsets
2019-08-28 05:51:40.663 Gorm[10412:10412] styleoffsets ... guessing offsets
Process 10412 stopped and restarted: thread 1 received signal: SIGCHLD
2019-08-28 05:51:42.556 Gorm[10412:10412] Bad palette selection - -1
2019-08-28 05:51:42.669 Gorm[10412:10412] Bad palette selection - -1
2019-08-28 05:51:43.054 Gorm[10412:10412] Bad palette selection - -1
Process 10412 stopped
* thread #1, name = 'Gorm', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
frame #0: 0x0000007fb61890a0 libobjc.so.4.6`objc_msg_lookup_sender + 708
libobjc.so.4.6`objc_msg_lookup_sender:
-> 0x7fb61890a0 <+708>: ldr x8, [x8]
0x7fb61890a4 <+712>: stur x8, [x29, #-0x18]
0x7fb61890a8 <+716>: ldur x8, [x29, #-0x18]
0x7fb61890ac <+720>: stur x8, [x29, #-0x50]
(lldb) up
frame #1: 0x0000007fb73d8900 libgnustep-gui.so.0.27`-[NSTableView _initDefaults](self=0x00000000011750a8, _cmd="\xeb\x1e") at NSTableView.m:2017
2014 _rowHeight = 16.0;
2015 _intercellSpacing = NSMakeSize (5.0, 2.0);
2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
-> 2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
2018 _allowsEmptySelection = YES;
2019 _allowsMultipleSelection = NO;
2020 _allowsColumnSelection = YES;
(lldb) up
frame #2: 0x0000007fb73d8d08 libgnustep-gui.so.0.27`-[NSTableView initWithFrame:](self=0x00000000011750a8, _cmd="\xaf\x1c", frameRect=(origin = (x = 0, y = 0), size = (width = 0, height = 0))) at NSTableView.m:2045
2042 if (!self)
2043 return self;
2044
-> 2045 [self _initDefaults];
2046 ASSIGN(_gridColor, [NSColor gridColor]);
2047 ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]);
2048 ASSIGN(_tableColumns, [NSMutableArray array]);
(lldb) up
frame #3: 0x0000007fb2b2f38c 3Containers`-[GormNSTableView initWithFrame:](self=0x00000000011750a8, _cmd="\xb0\x1c", aRect=(origin = (x = 0, y = 0), size = (width = 0, height = 0))) at GormNSTableView.m:112
109
110 - (id) initWithFrame: (NSRect) aRect
111 {
-> 112 self = [super initWithFrame: aRect];
113 [super setDataSource: [GormNSTableView sharedDataSource]];
114 _gormDataSource = nil;
115 // ASSIGN(_savedColor, [NSColor controlBackgroundColor]);
(lldb) up
frame #4: 0x0000007fb2b2d99c 3Containers`-[ContainersPalette finishInstantiate](self=0x0000000001124eb8, _cmd="~F") at ContainersPalette.m:119
116 contentSize = [v contentSize];
117 [v setBorderType: NSBezelBorder];
118
-> 119 tv = [[GormNSTableView alloc] initWithFrame:
120 NSZeroRect];
121
122 tc = [[NSTableColumn alloc] initWithIdentifier: @"column1"];
(lldb) up
frame #5: 0x0000007fb7deda88 libGormCore.so.1`-[GormPalettesManager loadPalette:](self=0x0000000000bd26e8, _cmd="\x92I", path=0x000000000111e238) at GormPalettesManager.m:529
526 [substituteClasses addEntriesFromDictionary: subClasses];
527 }
528
-> 529 [palette finishInstantiate];
530 window = [palette originalWindow];
531 [window setExcludedFromWindowsMenu: YES];
532
(lldb) up
frame #6: 0x0000007fb7dec0d0 libGormCore.so.1`-[GormPalettesManager init](self=0x0000000000bd26e8, _cmd="\xa3") at GormPalettesManager.m:360
357
358 for (index = 0; index < [array count]; index++)
359 {
-> 360 [self loadPalette: [array objectAtIndex: index]];
361 }
362 }
363
(lldb) up
frame #7: 0x000000000040e618 Gorm`-[Gorm palettesManager](self=0x00000000007e2d78, _cmd="\vF") at Gorm.m:1065
1062 {
1063 if (palettesManager == nil)
1064 {
-> 1065 palettesManager = [[GormPalettesManager alloc] init];
1066 }
1067 return palettesManager;
1068 }
(lldb) up
frame #8: 0x0000000000406d6c Gorm`-[Gorm init](self=0x00000000007e2d78, _cmd="\xa3") at Gorm.m:164
161 * editors and inspectors provided in the standard palettes
162 * are available.
163 */
-> 164 [self palettesManager];
165 [self pluginManager];
166
167 /*
(lldb) up
frame #9: 0x0000007fb7181288 libgnustep-gui.so.0.27`+[NSApplication sharedApplication](self=0x0000000000435908, _cmd="\xb9\e") at NSApplication.m:858
855 if (NSApp == nil)
856 {
857 /* -init sets NSApp. */
-> 858 [[self alloc] init];
859 }
860 return NSApp;
861 }
(lldb)
The ASSIGN
macro just does retain and then release of the arguments. Depending on how GNUstep is compiled, this may call the objc_retain()
and objc_release
functions, or send -retain
and -release
messages. Both should work.
I suspect that the crash is in sending the [NSMutableIndexSet indexSet]
message. I can't really tell you anything about the reason for the crash when it's without debug info (it is in C code though).
I enabled debug and it looks like it might be crashing in looking up the class for the object. That seems strange, how could that be happening?
patryk@pinebook:~/Desktop/gnustep-build/ubuntu-16.04-clang-6.0-runtime-1.9-ARM/GNUstep-build/apps-gorm/Gorm.app$ lldb-6.0 ./Gorm
(lldb) target create "./Gorm"
Current executable set to './Gorm' (aarch64).
(lldb) run
Process 31423 launched: './Gorm' (aarch64)
2019-08-30 04:50:26.492 Gorm[31423:31423] Bad palette selection - -1
2019-08-30 04:50:26.626 Gorm[31423:31423] Bad palette selection - -1
2019-08-30 04:50:27.017 Gorm[31423:31423] Bad palette selection - -1
Process 31423 stopped
* thread #1, name = 'Gorm', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
frame #0: 0x0000007fb61870a0 libobjc.so.4.6`objc_msg_lookup_sender [inlined] classForObject(obj=0x4000000000000000) at class.h:316
313 return SmallObjectClasses[(addr & OBJC_SMALL_OBJECT_MASK)];
314 }
315 }
-> 316 return obj->isa;
317 }
318
319 static inline BOOL classIsOrInherits(Class cls, Class base)
(lldb) up
frame #1: 0x0000007fb6187050 libobjc.so.4.6`objc_msg_lookup_sender [inlined] objc_msg_lookup_internal(receiver=0x0000007fffffcbe0, selector="\a", sender=0x0000000001159158) at sendmsg2.c:65
62 id sender)
63 {
64 retry:;
-> 65 Class class = classForObject((*receiver));
66 Slot_t result = objc_dtable_lookup(class->dtable, selector->index);
67 if (UNLIKELY(0 == result))
68 {
(lldb) fr va
(id *) receiver = 0x0000007fffffcbe0
(SEL) selector = "\a"
(id) sender = 0x0000000001159158
(Class) class = 0x0000000000000000
(Slot_t) result = 0x0000000000000000
(lldb) up
frame #2: 0x0000007fb6187044 libobjc.so.4.6`objc_msg_lookup_sender(receiver=0x0000007fffffcbe0, selector="\a", sender=0x0000000001159158) at sendmsg2.c:171
168 (sender->isa->info & (*receiver)->isa->info & _CLS_PLANE_AWARE),1))
169 */
170 {
-> 171 return objc_msg_lookup_internal(receiver, selector, sender);
172 }
173 // If we are in plane-aware code
174 void *senderPlaneID = *((void**)sender - 1);
(lldb) fr va
(id *) receiver = 0x0000007fffffcbe0
(SEL) selector = "\a"
(id) sender = 0x0000000001159158
(lldb) up
frame #3: 0x0000007fb73d8900 libgnustep-gui.so.0.27`-[NSTableView _initDefaults](self=0x0000000001159158, _cmd="\xeb\x1e") at NSTableView.m:2017
2014 _rowHeight = 16.0;
2015 _intercellSpacing = NSMakeSize (5.0, 2.0);
2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
-> 2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
2018 _allowsEmptySelection = YES;
2019 _allowsMultipleSelection = NO;
2020 _allowsColumnSelection = YES;
(lldb) fr v
(NSTableView *) self = 0x0000000001159158
(SEL) _cmd = "\xeb\x1e"
(id) __object = 0x4000000000000000
(lldb) up
frame #4: 0x0000007fb73d8d08 libgnustep-gui.so.0.27`-[NSTableView initWithFrame:](self=0x0000000001159158, _cmd="\xaf\x1c", frameRect=(origin = (x = 0, y = 0), size = (width = 0, height = 0))) at NSTableView.m:2045
2042 if (!self)
2043 return self;
2044
-> 2045 [self _initDefaults];
2046 ASSIGN(_gridColor, [NSColor gridColor]);
2047 ASSIGN(_backgroundColor, [NSColor controlBackgroundColor]);
2048 ASSIGN(_tableColumns, [NSMutableArray array]);
(lldb)
Hi David,
I don"t quite understand the question about whether the class is accessed via class variable or via a call into the runtime.
The memory corruption seems to be happening during
2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
I set a breakpoint in indexSet and the object seems to be allocating and initializing itself.
(lldb) run
There is a running process, kill it and restart?: [Y/n] y
Process 8385 exited with status = 9 (0x00000009)
Process 8428 launched: './Gorm' (aarch64)
2019-09-01 19:06:47.474 Gorm[8428:8428] Bad palette selection - -1
2019-09-01 19:06:47.574 Gorm[8428:8428] Bad palette selection - -1
2019-09-01 19:06:47.895 Gorm[8428:8428] Bad palette selection - -1
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = breakpoint 1.1
frame #0: 0x0000007fb73d875c libgnustep-gui.so.0.27`-[NSTableView _initDefaults](self=0x0000000001159528, _cmd="\xeb\x1e") at NSTableView.m:2016
2013 _drawsGrid = YES;
2014 _rowHeight = 16.0;
2015 _intercellSpacing = NSMakeSize (5.0, 2.0);
-> 2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
2018 _allowsEmptySelection = YES;
2019 _allowsMultipleSelection = NO;
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = breakpoint 7.1
frame #0: 0x0000007fb6648588 libgnustep-base.so.1.26`+[NSIndexSet indexSet](self=0x0000007fb6aa75c0, _cmd="\x96\x04") at NSIndexSet.m:123
120 @implementation NSIndexSet
121 + (id) indexSet
122 {
-> 123 id o = [self allocWithZone: NSDefaultMallocZone()];
124
125 o = [o init];
126 return AUTORELEASE(o);
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb66485e0 libgnustep-base.so.1.26`+[NSIndexSet indexSet](self=0x0000007fb6aa75c0, _cmd="\x96\x04") at NSIndexSet.m:125
122 {
123 id o = [self allocWithZone: NSDefaultMallocZone()];
124
-> 125 o = [o init];
126 return AUTORELEASE(o);
127 }
128
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb664861c libgnustep-base.so.1.26`+[NSIndexSet indexSet](self=0x0000007fb6aa75c0, _cmd="\x96\x04") at NSIndexSet.m:126
123 id o = [self allocWithZone: NSDefaultMallocZone()];
124
125 o = [o init];
-> 126 return AUTORELEASE(o);
127 }
128
129 + (id) indexSetWithIndex: (NSUInteger)anIndex
(lldb) fr va
(Class) self = 0x0000007fb6aa75c0
(SEL) _cmd = "\x96\x04"
(id) o = 0x0000000001161008
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb73d87cc libgnustep-gui.so.0.27`-[NSTableView _initDefaults](self=0x0000000001159528, _cmd="\xeb\x1e") at NSTableView.m:2016
2013 _drawsGrid = YES;
2014 _rowHeight = 16.0;
2015 _intercellSpacing = NSMakeSize (5.0, 2.0);
-> 2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
2018 _allowsEmptySelection = YES;
2019 _allowsMultipleSelection = NO;
(lldb) fr va
(NSTableView *) self = 0x0000000001159528
(SEL) _cmd = "\xeb\x1e"
(id) __object = nil
(lldb)
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb73d885c libgnustep-gui.so.0.27`-[NSTableView _initDefaults](self=0x0000000001159528, _cmd="\xeb\x1e") at NSTableView.m:2017
2014 _rowHeight = 16.0;
2015 _intercellSpacing = NSMakeSize (5.0, 2.0);
2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
-> 2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
2018 _allowsEmptySelection = YES;
2019 _allowsMultipleSelection = NO;
2020 _allowsColumnSelection = YES;
(lldb) fr va
(NSTableView *) self = 0x0000000001159528
(SEL) _cmd = "\xeb\x1e"
(id) __object = 0x0000000001159528
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = breakpoint 7.1
frame #0: 0x0000007fb6648588 libgnustep-base.so.1.26`+[NSIndexSet indexSet](self=0x0000007fb6aa75c0, _cmd="\x96\x04") at NSIndexSet.m:123
120 @implementation NSIndexSet
121 + (id) indexSet
122 {
-> 123 id o = [self allocWithZone: NSDefaultMallocZone()];
124
125 o = [o init];
126 return AUTORELEASE(o);
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb66485e0 libgnustep-base.so.1.26`+[NSIndexSet indexSet](self=0x0000007fb6aa75c0, _cmd="\x96\x04") at NSIndexSet.m:125
122 {
123 id o = [self allocWithZone: NSDefaultMallocZone()];
124
-> 125 o = [o init];
126 return AUTORELEASE(o);
127 }
128
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb664861c libgnustep-base.so.1.26`+[NSIndexSet indexSet](self=0x0000007fb6aa75c0, _cmd="\x96\x04") at NSIndexSet.m:126
123 id o = [self allocWithZone: NSDefaultMallocZone()];
124
125 o = [o init];
-> 126 return AUTORELEASE(o);
127 }
128
129 + (id) indexSetWithIndex: (NSUInteger)anIndex
(lldb) fr va
(Class) self = 0x0000007fb6aa75c0
(SEL) _cmd = "\x96\x04"
(id) o = 0x0000000001161028
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = step over
frame #0: 0x0000007fb73d88ac libgnustep-gui.so.0.27`-[NSTableView _initDefaults](self=0x0000000001159528, _cmd="\xeb\x1e") at NSTableView.m:2017
2014 _rowHeight = 16.0;
2015 _intercellSpacing = NSMakeSize (5.0, 2.0);
2016 ASSIGN(_selectedColumns, [NSMutableIndexSet indexSet]);
-> 2017 ASSIGN(_selectedRows, [NSMutableIndexSet indexSet]);
2018 _allowsEmptySelection = YES;
2019 _allowsMultipleSelection = NO;
2020 _allowsColumnSelection = YES;
(lldb) fr va
(NSTableView *) self = 0x0000000001159528
(SEL) _cmd = "\xeb\x1e"
(id) __object = 0x4000000000000000
(lldb) n
Process 8428 stopped
* thread #1, name = 'Gorm', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
frame #0: 0x0000007fb61870a0 libobjc.so.4.6`objc_msg_lookup_sender [inlined] classForObject(obj=0x4000000000000000) at class.h:316
313 return SmallObjectClasses[(addr & OBJC_SMALL_OBJECT_MASK)];
314 }
315 }
-> 316 return obj->isa;
317 }
318
319 static inline BOOL classIsOrInherits(Class cls, Class base)
(lldb)
So it's successfully calling -indexSet
once and then failing in the second call? It's difficult to tell, because you step over the next line (which includes three message sends and an assignment or two function calls, a message send, and an assignment, depending on how the code was compiled). Can you step into the second ASSIGN macro? Or, ideally, manually expand it so that you can see exactly what the sequence is?
The first call will probably be the first call to anything in NSMutableSet
so will install the dtable for this class. It is possible that I haven't quite fixed the stack corruption that was happening when calling from the objc_msgSend
assembly into C code (though I'd expect everything to crash if that were the case), but I'm not sure what is causing the call to objc_msg_lookup_sender
here. Is clang generating those calls instead of objc_msgSend
? I though I flipped the switch on AArch64 to make that the default, but possibly not. If this is only hitting C code, then the bug is more interesting: that code is used on all platforms, so it's not clear what the issue would be.
Were you able to triage this any further?
The only thing I tried is running Gorm on an AWS ARM instance and didn’t get a crash. So maybe the crash is a result of some incompatible library on my laptop’s Armbian distribution.... hope to track it down further.
I will reopen this or open a new ticket once I track it down further or find a simple test case.