It's wide known fact that in ObjC you can safely send any message to 'nil' object. Implementation turned out to be a bit more tricky than I supposed, here is code of 'libobjc':
Message will go to another receiver if system finds some value in '__objc_nilReceiver'! Moreover I found private ad-hoc function to change value of this variable without a hassle. And here is code that prints "Some"
Just interesting fact to know...
Growing Up
среда, 1 мая 2013 г.
четверг, 14 марта 2013 г.
C99 designated initializers
Note to self. Nice one!
Grabbed from here http://stackoverflow.com/a/15235225/449928
Grabbed from here http://stackoverflow.com/a/15235225/449928
среда, 13 марта 2013 г.
GDB on iOS 6.*
Using 'gdb' bundled with iOS SDK
Contents of gdb.xml:
Now copy BOTH gdb binary and gdb.xml onto device.
Contents of gdb.xml:
Now copy BOTH gdb binary and gdb.xml onto device.
суббота, 23 февраля 2013 г.
How to compile 'otool'
As a personal note.
1. Get it here: http://www.opensource.apple.com/source/cctools
2. Modify 'libstuff' Makefile to avoid 'LTO'(link time optimization) support. '-DLTO...' and 'lto.o'
3. Run 'make' inside libstuff directory
4. Run 'make' inside otool directory (don't remember exactly, may be Makefile update required as well)
otool.NEW
Error I was getting:
../lto.c:8:10: fatal error: 'llvm-c/lto.h' file not found
#include <llvm-c/lto.h>
среда, 30 января 2013 г.
Avoiding "-load-all" linker flag
Found a nice solution on how to avoid "-load-all" linker flag.
https://github.com/square/KIF/blob/master/Additions/LoadableCategory.hJust quoting here:
//
// LoadableCategory.h
// KIF
//
// Created by Karl Stenerud on 7/16/11.
// Licensed to Square, Inc. under one or more contributor license agreements.
// See the LICENSE file distributed with this work for the terms under
// which Square, Inc. licenses this file to you.
/** Make all categories in the current file loadable without using -load-all.
*
* Normally, compilers will skip linking files that contain only categories.
* Adding a call to this macro adds a dummy class, which causes the linker
* to add the file.
*
* @param UNIQUE_NAME A globally unique name.
*/
#define MAKE_CATEGORIES_LOADABLE(UNIQUE_NAME) @interface FORCELOAD_##UNIQUE_NAME @end @implementation FORCELOAD_##UNIQUE_NAME @end
воскресенье, 25 ноября 2012 г.
Правильно считаем смещение функции в Mach-O binary
Несколько более грамотный подход. Допустим удалось определить, что искомая функция начинается по адресу 0x000A36E0 (речь об i386), - самое время рассматривать Mach-O Header
Запоминаем - Fat binary, контент i386 части начинается со смещения 0x129000
Loading command на __TEXT,__text сегмент, секцию
File offset - 0x1880
Address offset - 0x2880
Итак:
i386 __TEXT,__text file offset start: 0x129000 + 0x1880 = 0x12A880
Function address offset from section start: 0xA36E0 - 0x2880 = 0xA0E60
Function file offset from start: 0x12A880+0xA0E60 = 0x1CB6E0
P.S. Все адреса и смещения вымышлены, любое совпадение с реальными - случайно (на самом деле нет)
Loading command на __TEXT,__text сегмент, секцию
Address offset - 0x2880
Итак:
i386 __TEXT,__text file offset start: 0x129000 + 0x1880 = 0x12A880
Function address offset from section start: 0xA36E0 - 0x2880 = 0xA0E60
Function file offset from start: 0x12A880+0xA0E60 = 0x1CB6E0
P.S. Все адреса и смещения вымышлены, любое совпадение с реальными - случайно (на самом деле нет)
воскресенье, 15 апреля 2012 г.
Кто меня звал ?
Наверное одна из наиболее часто используемых команд при отладке с использованием GDB это bt/backtrace/where. Этой командой можно раскрутить стек и увидеть каким образом мы пришли к текущему этапу выполнения. Достаточно знать несколько деталей работы со стеком, чтобы получить ту же самую информацию во время работы приложения.
Вызов метода в Objective-C сводится к выполнению Си функции objc_msgSend или нескольких ее вариаций. Сама функция после определения кода который нужно выполнить делает переход к нему, оставляя неизменным стек, т.о. и в выводе GDB не видно objc_msgSend.
Выполнение каждой функции начинается с помещения в стек указателя на стек фрейм предыдущей функции и сохранении фрейма стека текущей:
Указатель на stack frame хранится в регистре %ebp.
Стек растет от старших адресов к младшим, следующим образом он будет выглядеть при вызове метода -[SomeObject setObj:(NSObject*)arg1]
+------------------------+ |
| (NSObject*)arg1 | |
+------------------------+ |
| указатель на строку | \|/
| selector, "setObj:" | '
+------------------------+
| SomeObject* |
+------------------------+
| %eip, адрес возврата |
+------------------------+
| %ebp, last stack frame | <- "push %ebp", в начале функции
+------------------------+ ..
'`- "mov %esp,%ebp", %ebp указывает сюда
Таким образом в %ebp при выполнении текущей функции лежит адрес на стеке, где лежит значение %ebp от предыдущей выплоняемой функции из которой был произведен вызов текущей. Воспользовавшись знаниями выше, можно получить следующую функцию:
Вызов метода в Objective-C сводится к выполнению Си функции objc_msgSend или нескольких ее вариаций. Сама функция после определения кода который нужно выполнить делает переход к нему, оставляя неизменным стек, т.о. и в выводе GDB не видно objc_msgSend.
Выполнение каждой функции начинается с помещения в стек указателя на стек фрейм предыдущей функции и сохранении фрейма стека текущей:
push %ebp
mov %esp,%ebp
Указатель на stack frame хранится в регистре %ebp.
Стек растет от старших адресов к младшим, следующим образом он будет выглядеть при вызове метода -[SomeObject setObj:(NSObject*)arg1]
+------------------------+ |
| (NSObject*)arg1 | |
+------------------------+ |
| указатель на строку | \|/
| selector, "setObj:" | '
+------------------------+
| SomeObject* |
+------------------------+
| %eip, адрес возврата |
+------------------------+
| %ebp, last stack frame | <- "push %ebp", в начале функции
+------------------------+ ..
'`- "mov %esp,%ebp", %ebp указывает сюда
Таким образом в %ebp при выполнении текущей функции лежит адрес на стеке, где лежит значение %ebp от предыдущей выплоняемой функции из которой был произведен вызов текущей. Воспользовавшись знаниями выше, можно получить следующую функцию:
static id getSender()Вызов данной функции вернет объект из которого был произведен вызов текущего метода, а с небольшой модификацией можно получить и метод из которого был произведен вызов.
{
id result = nil;
__asm( "push %%ebx\n"
"push %%ebp\n"
"mov (%%ebp),%%ebx\n"
"mov %%ebx,%%ebp\n"
"mov (%%ebp),%%ebx\n"
"mov %%ebx,%%ebp\n"
"mov 8(%%ebp),%%ebx\n"
"mov %%ebx,%0\n"
"pop %%ebp\n"
"pop %%ebx"
:"=r"(result)
);
return result;
}
Подписаться на:
Сообщения (Atom)

