Xcode, LLVM 4.1, NSMutableArray, unused block in loop crashes. Why? - xcode

This is my first post. I apologize for mistakes.
I have a crash I can fix, but I don't understand why it crashes in the first place. I tried to reduce the code to the essentials to make it crash:
GCFTile *currentTile;
NSInteger repeatCount = 0;
do {
currentTile = self.remainingTilesArray[0];
if (repeatCount == 0) {
[self.remainingTilesArray removeObjectAtIndex:0];
[self.remainingTilesArray addObject:currentTile];
}
void (^myBlock)() = ^{
currentTile;
};
repeatCount++;
} while (repeatCount == 1);
I'm using Xcode 4.5.2, iOS 5, ARC. Also, it crashes only if the LLVM compiler optimization is set to "Fast" or above.
The code above will get and remove an object from an NSMutableArray, put it back, and then get another object from the array. The code above will run without crashing, but if I scan across all the elements in the array later (e.g., from a different method), then it crashes. It looks like a random memory address was added to the array (probably from the above call to addObject).
The above block should do nothing, but if I change it then there's no crash later. (E.g., empty block = no crash. Don't declare block as "myBlock" = no crash.) If I don't repeat the loop, there's no crash. If I don't add the object back, there's no crash. If I declare currentTile using __block or within the do loop, there's no crash.
I know blocks are "stack-local," but this block doesn't do anything! And it runs fine without compiler optimization.
Any idea what's going on?
EDIT (12-5-12): Someone asked for the crash log. I'm running in the simulator, so I don't know how to get that. But here's a little from the Debug Navigator:
#0 0x0140409b in objc_msgSend ()
#1 0x00010931 in __33-[GCFGame checkThatTilesAreValid]_block_invoke_0 at /Users/geoffrey2/personal/projects/Color Fever/Color Fever/GCFGame.m:54
#2 0x01cb24a5 in __NSArrayEnumerate ()
#3 0x01cb2026 in -[NSArray enumerateObjectsWithOptions:usingBlock:] ()
#4 0x01cb1f35 in -[NSArray enumerateObjectsUsingBlock:] ()
#5 0x000108f6 in -[GCFGame checkThatTilesAreValid] at /Users/geoffrey2/personal/projects/Color Fever/Color Fever/GCFGame.m:52
and the main window shows this (plus more lines):
libobjc.A.dylib`objc_msgSend:
0x140408c: movl 8(%esp), %ecx
0x1404090: movl 4(%esp), %eax
0x1404094: testl %eax, %eax
0x1404096: je 0x14040e8 ; objc_msgSend + 92
0x1404098: movl (%eax), %edx
0x140409a: pushl %edi
0x140409b: movl 8(%edx), %edi
The error is EXC_BAD_ACCESS(code=2, adddress=0x9).

Related

SceneKit : Crash with SCNReferenceNode load

I develop an AR project.
In my scene I use SCNReferenceNode to load external content.
The first time, I execute the code, everything is OK.
When I return to the homepage and reaccess to my scene, I've got a crash when I use load() for SCNReferenceNode. Crash occurs not every time. Sometimes, load() method don't crash my app. I test many things but nothing work.
Here is a part of my code when I use load() on SCNReferenceNode :
let url = Bundle.main.url(forResource: "model", withExtension: "scn", subdirectory: "map.scnassets")!
self.refNode = SCNReferenceNode(url: url)!
self.container.addChildNode(self.refNode)
self.refNode.load()
When I return on home, I try to clean my scene :
self.refNode.unload()
self.refNode = nil
But when I return in my scene (second time access), I've got a crash 'Bad Exec' :
0x1dbf6d048 <+40>: bl 0x1dbdbe374 ; C3DAnimationManagerRemoveAnimationsForObject
0x1dbdbe3ac <+56>: cbz x0, 0x1dbdbe3f8 ; <+132>
0x1a7d9562c <+100>: ldr x9, [x0]
On stack, I see 'C3DAnimationManagerRemoveAnimationsForObject' so I suppose the problem is going from an animation. I'll try to remove all actions, all loops...
I try to use Instruments(for zombies, leaks..), breakpoints but I'm to noob !!!
How can I find a solution, how can I resolve this error ?
Thanks in adavance...

Debugging neovim, buffer overflow detected by OS X 10.9 libc, in need of a better way to debug it

First of all a bit of context: I'm trying to debug an issue that's happening with neovim, I'm not sure if this also happens with plain vim, but it's not all that relevant.
Even though the reporter uses linux and I use OSX 10.9, I've been able to get "similar" behaviour by using specific compilers + flags:
When I use either gcc 4.8.2 or gcc 4.9 (dev) combined with even a little bit of optimization, fortification and stack smashing protection, neovim crashes on startup.
$ edit CMakeLists.txt
$ ... -Wall -O1 -g -g3 -ggdb -mtune=generic -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -Wextra -pedantic -Wno-unused-parameter -std=gnu99 ...
$ make clean && make cmake CMAKE_EXTRA_FLAGS="-DCMAKE_C_COMPILER=/usr/local/bin/gcc-4.8" && make
I've been trying to debug it with lldb (gdb doesn't seem to give my any symbols, even after codesigning). I've gotten as far as this:
compiled with gcc 4.9:
➜ neovim git:(fortify-and-stack-protector) ✗ lldb ./build/bin/nvim
Current executable set to './build/bin/nvim' (x86_64).
(lldb) run src/eval.c
Process 1295 launched: './build/bin/nvim' (x86_64)
Process 1295 stopped
* thread #1: tid = 0x242b4f, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff93f34866: jae 0x7fff93f34870 ; __pthread_kill + 20
0x7fff93f34868: movq %rax, %rdi
0x7fff93f3486b: jmpq 0x7fff93f31175 ; cerror_nocancel
0x7fff93f34870: ret
(lldb) bt
* thread #1: tid = 0x242b4f, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff91b6435c libsystem_pthread.dylib`pthread_kill + 92
frame #2: 0x00007fff8ce68b1a libsystem_c.dylib`abort + 125
frame #3: 0x00007fff8ce68c91 libsystem_c.dylib`abort_report_np + 181
frame #4: 0x00007fff8ce8c860 libsystem_c.dylib`__chk_fail + 48
frame #5: 0x00007fff8ce8c830 libsystem_c.dylib`__chk_fail_overflow + 16
frame #6: 0x00007fff8ce8ca7f libsystem_c.dylib`__strcpy_chk + 83
frame #7: 0x000000010002e1a6 nvim`call_user_func [inlined] add_nr_var(nr=1, name=<unavailable>, v=<unavailable>, dp=<unavailable>) + 42 at eval.c:18744
frame #8: 0x000000010002e17c nvim`call_user_func(fp=0x000000010030bd30, argcount=0, argvars=0x00007fff5fbfed80, rettv=0x00007fff5fbfef50, firstline=1, lastline=1, selfdict=0x0000000000000000) + 425 at eval.c:18455
frame #9: 0x000000010002ef33 nvim`call_func(funcname=<unavailable>, len=<unavailable>, rettv=0x00007fff5fbfef50, argcount=0, argvars=0x00007fff5fbfed80, firstline=1, lastline=1, doesrange=0x00007fff5fbfef44, evaluate=1, selfdict=0x0000000000000000) + 717 at eval.c:7363
frame #10: 0x0000000100032d1a nvim`get_func_tv(name=0x000000010030be20, len=9, rettv=0x00007fff5fbfef50, arg=0x00007fff5fbfef48, firstline=1, lastline=1, doesrange=0x00007fff5fbfef44, evaluate=1, selfdict=0x0000000000000000) + 340 at eval.c:7222
frame #11: 0x000000010003673e nvim`ex_call(eap=0x00007fff5fbff190) + 475 at eval.c:3086
frame #12: 0x000000010005634b nvim`do_cmdline(cmdline=<unavailable>, fgetline=0x00000001000494e3, cookie=0x00007fff5fbff790, flags=7) + 13602 at ex_docmd.c:2103
frame #13: 0x0000000100049d52 nvim`do_source(fname=0x000000010017bb3b, check_other=<unavailable>, is_vimrc=<unavailable>) + 1615 at ex_cmds2.c:2695
frame #14: 0x00000001001702c3 nvim`main + 251 at main.c:2009
frame #15: 0x00000001001701c8 nvim`main(argc=<unavailable>, argv=<unavailable>) + 5152 at main.c:1919
frame #16: 0x00007fff8b32d5fd libdyld.dylib`start + 1
(lldb) frame variable
(lldb) frame info
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
(lldb) frame select 7
frame #7: 0x000000010002e1a6 nvim`call_user_func [inlined] add_nr_var(nr=1, name=<unavailable>, v=<unavailable>, dp=<unavailable>) + 42 at eval.c:18744
18741 */
18742 static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)
18743 {
-> 18744 STRCPY(v->di_key, name);
18745 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18746 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
18747 v->di_tv.v_type = VAR_NUMBER;
compiled with gcc 4.8.2:
➜ neovim git:(fortify-and-stack-protector) ✗ lldb ./build/bin/nvim
Current executable set to './build/bin/nvim' (x86_64).
(lldb) rune
error: 'rune' is not a valid command.
(lldb) run
Process 3242 launched: './build/bin/nvim' (x86_64)
Process 3242 stopped
* thread #1: tid = 0x2454cb, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff93f34866: jae 0x7fff93f34870 ; __pthread_kill + 20
0x7fff93f34868: movq %rax, %rdi
0x7fff93f3486b: jmpq 0x7fff93f31175 ; cerror_nocancel
0x7fff93f34870: ret
(lldb) bt
* thread #1: tid = 0x2454cb, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff91b6435c libsystem_pthread.dylib`pthread_kill + 92
frame #2: 0x00007fff8ce68b1a libsystem_c.dylib`abort + 125
frame #3: 0x00007fff8ce68c91 libsystem_c.dylib`abort_report_np + 181
frame #4: 0x00007fff8ce8c860 libsystem_c.dylib`__chk_fail + 48
frame #5: 0x00007fff8ce8c830 libsystem_c.dylib`__chk_fail_overflow + 16
frame #6: 0x00007fff8ce8ca7f libsystem_c.dylib`__strcpy_chk + 83
frame #7: 0x000000010002a969 nvim`eval_init + 129 at eval.c:868
frame #8: 0x0000000100089ffd nvim`main(argc=1, argv=0x00007fff5fbffa58) + 140 at main.c:175
frame #9: 0x00007fff8b32d5fd libdyld.dylib`start + 1
frame #10: 0x00007fff8b32d5fd libdyld.dylib`start + 1
(lldb) frame select 7
frame #7: 0x000000010002a969 nvim`eval_init + 129 at eval.c:868
865
866 for (i = 0; i < VV_LEN; ++i) {
867 p = &vimvars[i];
-> 868 STRCPY(p->vv_di.di_key, p->vv_name);
869 if (p->vv_flags & VV_RO)
870 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
871 else if (p->vv_flags & VV_RO_SBX)
For this issue to appear, there needs to be some optimization, however this means that the compiler will inline things and throw away arguments, which is annoying and doesn't allow me to see the most important things at a glance. Would there be a combination of flags I could try that would keep the problem but allow better debuggability?
Is this likely a compiler bug? Clang seems to avoid it somehow, and GCC too when I turn off optimization.
gcc 4.8.2 and gcc 4.9 give a similar error (both times at a STRCPY) but in different locations, this worries me even more.
Where is the code for __chk_fail_overflow and __chk_overlap? They get called in strcpy_chk which I assume is the replacement of strcpy that gets inserted when compiling with -D_FORTIFY_SOURCE=2. I haven't been able to grep for it. I've grepped in this repo: https://github.com/aosm/Libc which appears to be the OSX 10.9 libc as I've tried to verify with apple's own opensource site.
How does the compiler decide what the 3rd argument to strcpy_chk is?! The original invocation to STRCPY doesn't include any size information:
.
STRCPY(v->di_key, name);
// I think gcc/clang replace this with:
__strcpy_chk(v->di_key, name, SOME_MAGIC_SIZE);
I hope some of the guru's on stack overflow could give me some tips/hints on what I should do next!
EDIT: I've been able to compile with -Og and gcc 4.8.2 and still provoke the error, hopefully this will give some more info.
So, I couldn't stop myself from digging further and finally got the idea of looking at the stack + registers when entereing the dreaded __strcpy_chk, where I found:
(lldb) register read
General Purpose Registers:
rax = 0x0000000000000057
rbx = 0x00000001001d3900 vimvars
rcx = 0x6300f1e7a96add52
rdx = 0x0000000000000001 /* this is probably the size parameter */
rdi = 0x00000001001d3919 vimvars + 25
rsi = 0x000000010016730e "count"
So gcc had deduced that the size of the dst parameter was 1, and is passing that to __strcpy_chk. So, because of the -D_FORTIFY_SOURCE=2, gcc replaces calls of well-known functions with their safe variants when it can deduce the size. Such is the case here as we'll see: the dst parameter is the vv_di.di_key field of this struct:
static struct vimvar {
char *vv_name; /* name of variable, without v: */
dictitem_T vv_di; /* value and name for key */
char vv_filler[16]; /* space for LONGEST name below!!! */
char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
}
struct dictitem_S {
typval_T di_tv; /* type and value of the variable */
char_u di_flags; /* flags (only used for variable) */
char_u di_key[1]; /* key (actually longer!) */
}
Which has size 1. Gcc of course doesn't realize that this was somehow intentional: the vv_filler flag is meant to store the actual string. Which is why the comment says actually longer. vv_filler follows immediately on di_key in the struct.
I can't really fault the compiler for this, it makes sense. Someone at the neovim project is busy rebuilding the interpreter to be a translator from VimL to lua. A "stupid" fix at the moment is to either disable source fortifying or lower it a level to -D_FORTIFY_SOURCE=1, which should stop gcc from making these assumptions. Ideally though, we'd be able to fix this while keeping -D_FORTIFY_SOURCE=2 and not regressing in performance (vimvar is of course an oft-used struct).
I have some extra questions though. Is what the vim codebase does here legal? There were some discussions on the neovim issue tracker where some commenters suggested that relying on this was entirely undefined. One argument that I found interesting was that there could be space between the end of struct dictitem_S and vv_filler (padding). The commenter argued that it was illegal (UB) to use this space. Reading the relevant C99 documents doesn't provide immediate clarity on this specific case. The struct hack is allowed, but we were not sure if it is allowed for nested structs. i.e.: the struct hack appears at the end of dictitem_S, but definitely not at the end of its containing struct (vimvar).

Symbolic exception breakpoint on -[NSRangeException raise]

Adding a symbolic breakpoint in Xcode gives you an example template of -[NSException raise]. I want to do the same thing but specifically on -[NSRangeException raise]. The reason being that I want to breakpoint only on specific array bounds exceptions, for example:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 31 beyond bounds [0 .. 30]'
Yes, I know that I can add a catch all exception breakpoint. However, I do not want to do that as I do not want to breakpoint on the many exceptions generated throughout using the app.
I've tried quite a few things based on other posts related to NSException. However, I have not found anything that works successfully as yet.
For example I tried:
This journal entry was also of interest albeit inconclusive:
Dealing with NSArray "out of bounds"
So, basically, the question is, in Xcode, how to breakpoint specifically and only on a range exception?
NSRangeException isn't a class:
grep NSRangeException /System/Library/Frameworks/Foundation.framework/Headers/NSException.h
FOUNDATION_EXPORT NSString * const NSRangeException;
Turns out, range exceptions are just NSExceptions whose name is NSRangeException, i.e.:
(lldb) b s -n objc_exception_throw
Breakpoint 2: where = libobjc.A.dylib`objc_exception_throw, address = 0x00007fff8e3c2e4a
(lldb) c
Process 58216 resuming
Process 58216 stopped
* thread #1: tid = 0x1d7f4b, function: objc_exception_throw , stop reason = breakpoint 2.1
frame #0: 0x00007fff8e3c2e4a libobjc.A.dylib`objc_exception_throw
libobjc.A.dylib`objc_exception_throw:
-> 0x7fff8e3c2e4a: pushq %rbp
0x7fff8e3c2e4b: movq %rsp, %rbp
0x7fff8e3c2e4e: pushq %r15
0x7fff8e3c2e50: pushq %r14
(lldb) bt
* thread #1: tid = 0x1d7f4b, function: objc_exception_throw , stop reason = breakpoint 2.1
frame #0: 0x00007fff8e3c2e4a libobjc.A.dylib`objc_exception_throw
frame #1: 0x00007fff841ca1df CoreFoundation`-[__NSArrayI objectAtIndex:]
frame #2: 0x0000000100000eb9 range-exception`-[Foo throwIt] at range-exception.m:14
frame #3: 0x0000000100000f27 range-exception`main at range-exception.m:22
frame #4: 0x00007fff8468d5fd libdyld.dylib`start
frame #5: 0x00007fff8468d5fd libdyld.dylib`start
(lldb) expr (NSString *) [((NSException *) $arg1) name]
(NSString *) $0 = 0x00007fff74177990 #"NSRangeException"
So you could set a breakpoint on objc_exception_throw, and write a breakpoint condition comparing the name to NSRangeException. Something like:
[(NSString *) [((NSException *) $arg1) name] isEqual: (NSString *) NSRangeException]
should do the trick.
To make a breakpoint for NSRangeException, use an Exception breakpoint. It's one of the options when you click the "+" in the breakpoint navigator. Found this info from this answer: https://stackoverflow.com/a/9718552/591487

what differs 2 function calls in a row?

Suppose you look at the stack and registers of a process which has the following code...
...
void Test()
{
for (int i = 0; i < 10; i++)
{
OneRunDontKnow();
}
}
...
You look at the stack twice exactly when the process executes the loop, and in both times the OneRunDontKnow is at the top of the stack.
Can you somehow know if OneRunDontKnow was popped out of the stack and then pushed in again or if it was never popped out?
EDIT: OneRunDontKnow can have any signature (it can also take parameters or return a value).
Probably the best way is to look at your assembled code. OneRunDontKnow() takes no parameters, so the only thing on the stack will be the instruction pointer, and other stack frame stuff, but no parameters. So find the place in the disassembly where OneRunDontKnow() should be called, and see what kind of PUSH and JMP inside the code where LOOP_ (LOOP, LOOPE, etc) is.

OSX Snow Leopard: Static and dynamic link behaving differently

I have some code structured like this:
Fixed mainline -> user code -> dependent library
These three parts can be statically linked and all is well.
Alternatively, the mainline can be turned into an executable
and the user code into a dylib, and the mainline loads the
user code with dlopen() and enters it with dlsym().
I have hundreds of test programs where this works fine, but two cases
where it fails:
Case 1: the dependent library is gmpxx (which depends on gmp).
Case 2: the dependent library is SDL
In the gmp case the dynamic program prints the correct answers by then terminates with:
flx_run(29601) malloc: *** error for object 0x7fff712ac500: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap
(gdb) bt
#0 0x00007fff8438e0b6 in __kill ()
#1 0x00007fff8442e9f6 in abort ()
#2 0x00007fff84346195 in free ()
#3 0x00000001000d3a35 in flxusr::gmp__hyphen_0::_init_ ()
Previous frame inner to this frame (gdb could not unwind past this frame)
I would guess some memory corruption is here.
In the SDL case:
~/felix>LD_LIBRARY_PATH=build/release/lib/rtl build/release/bin/flx_arun demos/sdl/sdl-1.01.03-0.dylib
frames in seconds = FPS
frames in seconds = FPS
frames in seconds = FPS
whereas
~/felix>demos/sdl/sdl-1.01.03-0
98 frames in 5.016 seconds = 19.5375 FPS
100 frames in 5.043 seconds = 19.8295 FPS
82 frames in 5.043 seconds = 16.2602 FPS
The frame rate data is formatted by
_urv20946 = ::flx::rtl::strutil::str(((double)PTF Frames / seconds ));
where
template<class T>
string str(T const &t) {
std::ostringstream x;
x << t;
return x.str();
}
noting this code is "in" a dependent library (well of course not, it is in a header file!)
Any ideas?

Resources