Кошерно ли? Мне нужно в обработчике узнать, вызван ли данный SIGSEGV переполнением стека. Обработчик работает на альтернативном стеке. Берем из контекста ESP и EIP, узнаем по этой паре страницу, к которой случился доступ, а затем два раза mprotect на нее - узнаем атрибуты, затем выставляем staus quo.
Стоит Gentoo 2004.2. Хочу ядро обновить до 2.6.10-r6. Что говорить emerge? Скачал gentoo-sources-2.6.10-r6.ebuild, но что с ним делать? И, насколько я понимаю, оно захочет еще и linux26-headers-2.6.10-r6, но такого зверя вообще не существует...
Собственно, subj.
Если сделать такую библиотеку:
#include <stdio.h>
#include <stdlib.h>
void * operator new(size_t n)
{
printf("operator new(%d)\n",n);
return malloc(n);
}
void operator delete(void* p)
{
printf("operator delete(%X)\n",p);
return free(p);
}
class my_struct {
char data[0x10000];
};
my_struct *mystr = new my_struct;
extern "C" {
extern void Cleanup () {
printf("cleaning up...\n");
delete mystr;
}
}
загрузить, поработать и выгрузить ее dlopen/dlsym/dlclose, операторы
new/delete заиспользуются вовсе не мои перегруженные, а стандартные.
как же быть, если мне позарез нужно перегрузить new/delete в моей
конкретной библиотеке?
Да, а в обычных екзешниках все мои new/delete работают...
Вот такая проблема - нужно _всегда_ ловить stack overflow, причем нативный код может быть получен не только с помощью gcc, а как угодно, хоть самописный на ассемблере. Я посмотрел в info libc, там сказано, что сигнал SIGILL _может_ бросаться в случае переполнения стека. Не уточняется, что значит - может. Всегда ли он бросается, и всегда ли именно SIGILL, и именно с параметром ILL_BADSTK?
Есть ли вообще готовые методы ловли ситуации переполнения стека?
В виндах есть флаг FILE_FLAG_DELETE_ON_CLOSE, передаваемый в вызов CreateFile - новосозданный файл удаляется при завершении процесса. Как лучше сделать то же самое в линуксе?
Замечено, что при интенсивном расходе памяти via malloc & mmap память выделяется фактически начиная с 0x80000000 и забивается примерно до 0xC00000000, после чего очередной вызов mmap обламывается. Почему же выделение не происходит в первом гиге?
Ни разу не приходилось... Есть редхатовый gcc в SRPM. Если сказать rpm --install на него, оно развернет в /usr/src/packages/SOURCES файл gcc-3.2-7....tar.bz2 и кучу patch-файлов. И все. Вопрос такой: а как же это все правильно скомпилировать, и чтобы все патчи правильно приложились?
Hello All!
Я вот наткнулся на странную проблему, может быть, кто-нибудь знает, в
чем дело... Итак:
1) есть исходник shared library с инициализатором _init:
-------- mydll.c -----------------------------------
#include <dlfcn.h>
static void *myhandle;
void _init() {
myhandle = dlopen("/lib/libc.so.6", RTLD_LAZY);
}
----------------------------------------------------
компилируется так:
gcc -Wall mydll.c -nostdlib -shared -o libmydll.so -ldl
2) есть программулина, которая грузит эту lybmydll.so:
-------- test.c ------------------------------------
#include <dlfcn.h>
#include <stdio.h>
int main() {
char libname[] = "libmydll.so";
void *lib = dlopen(libname, RTLD_LAZY);
if(!lib) {
printf("Cannot open library: %s\n", dlerror());
return 1;
}
printf("OK!\n");
return 0;
}
----------------------------------------------------
Компилируем программулину так:
gcc -g -c test.c -o test.o
gcc -g -o test test.o -ldl
Запускаем:
bash$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
bash$ ./test
OK!
Все работает. А вот теперь внимание - компилируем по-другому:
gcc -g -c test.c -o test.o
gcc -g -o test test.o -static -lc -ldl
Запускаем:
bash$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
bash$ ./test
Segmentation fault
Таким образом, при вызове dlopen из инициализатора все работает, если
екзешник собран динамическим, а если статически - все падает... Без
вызова dlopen опять-таки все в порядке.
Крэш происходит в динамическом загрузчике (/lib/ld-2.3.2.so). Где -
непонятно, собирать и инсталлить все хозяйство с отладкой слишком
опасно :(
В чем может быть дело?
Заранее спасибо!
Вчера в одной приладе увидел вот такой код с комментарием (но без
каких-либо дополнительных разъяснений):
/* Open fake stdin, stdout, stderr - just in case */
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);
Вопрос такой: зачем такое делается? Какое отношение имеют стандартные
каналы к /dev/null? Почему не сохраняются результирующие дескрипторы?
Заранее спасибо за информацию :)
Ситуация примерно следующая. Есть мультитредовое приложение, работает
под NPTL only (LinuxThreads меня не интересует). На сигнал SIGRT_3
навешивается некоторое действие. При этом выставляется флаг sigaction
SA_RESTART. Один из потоков приложения садится на poll. Вся прилада
обрабатывает сетевые http-запросы (для их генерации я использую Apache
Benchmark, ab).
Так вот, через некоторое время очередной вызов poll возвращает -1,
errno = EINTR, и в логе strace случается такая запись:
Вот что интересно (может быть, вопрос совсем глупый, прошу сильно не
пинать, если так): какие правила линковки к shared library, если на
нее есть некоторое количество симлинков? Например, в RH8 есть такие
файлы:
/usr/lib/libz.so -> /usr/lib/libz.so.1.2.1.1
/usr/lib/libz.so.1 -> /usr/lib/libz.so.1.2.1.1
/usr/lib/libz.so.1.2.1.1
Спрашивается, что пропишется в executable, рожденный gcc-ом с
подключеной libz?
Проверка:
====ztest.c====
int main() {return 0;}
==============
$ gcc ztest.c -o ztest -lz
$ ldd ./ztest
libz.so.1 => /usr/lib/libz.so.1 (0x00726000)
libc.so.6 => /lib/tls/libc.so.6 (0x005de000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x005c5000)
objdump показываетс, что в секции NEEDED действительно прописано "libz.so.1".
Почему именно ".so.1"?
В новых дистрибах появилась новая версия libz (1.2.1, насколько я
понимаю). Появляется симлинк libz.so.2, и пропадает симлинк libz.so.
Так что если программа залинкована на libz.so, то скорее всего
работать она не будет. Опять же: как будет использоваться эта
libz.so.2, если со старых программ на нее нет ссылки? Или libz.so.1=>
libz.so.2?
Так вот вопрос: как компилятор опереляет, к какому симлинку линковать?
Заранее большое спасибо за объяснения.
Ситуация следующая. Запускаем на ядре 2.6.5 или младше на i386
такую программку:
#include <stdio.h>
#include <sys/mman.h>
int main() {
while(1) {
void *p = mmap(NULL,0x100000,PROT_READ |PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
if(p==(void*)-1)
break;
printf("p = %X\n", p);
}
return 0;
}
Она заканчивает работу на последнем возвращенном адресе 0xBFE2F000,
что меньше 3-гигабайтного предела.
Запускаем ту же самую прогу на ядре 2.6.8. Последний адрес равен 0xFED00000,
что больше 3-гигабайтного предела.
Проблема в следующем: я никак не могу найти в ChangeLog-ах ядра
запись, указывающую на фикс, позволяющий адресоваться дальше 3 Gb.
Куда смотреть, чтобы понять, что вообще изменилось?
Подскажите, плз. Заранее спасибо...
Меня жутко раздражает такая странная особенность мозиллы, проявляющаяся,
как ни странно, только на сайте LOR: когда я создаю сообщение (или
отвечаю на чье-то), пользуясь своим зарегистрированным ником, мой пароль
и логин запоминается, а когда я снова создаю сообщение, он опять
запоминается, с тем же логином! Так что, при открытии любой страницы
форума LOR, вылазит мозилловское окошко, в котором написано "выберите
логин" и выбор из двух строк:
jek_
jek_
Если я махну рукой и никак не разбирусь с password менеджером, в этой
таблице появится еще одна точно такая же запись. И так далее. Это
окошко вылазит КАЖДЫЙ раз при открытии КАЖДОЙ новой LOR-ской страницы и ужасно
раздражает. Приходится каждый раз после добавления сообщения лезть в
password manager и удалять там лишнюю запись. Или вообще пользоваться
логином anonymous.
Скажите, это только у меня руки криво растут, или это мозилловский баг?
Или, может, с LOR-ом косяк?
Thanks in advance...
Вот, нужно мне :) Поэтому единственное, что приходит в голову - написать фуфловую новость, чтобы так проникнуть в этот самый список. Можно ли это сделать как-нибудь более честно?
У меня неожиданно возникла проблема: программа в main, сразу после
начала выполнения, выполняет fork-exec, предварительно установив
для себя размер стека 900'000 байт. Все прекрасно работало на многих
системах - RH8,9, Mandrake8,9.2,10, Fedora2. Но вдруг обнаружилось,
что на Fedora1 происходит SIGSEGV сразу после exec. Backtrace в
отладчике отсутствовал, текущая функция - _dl_sysinfo_int80.
Запускаемая программа даже не начинала исполняться (во
всяком случае, до ее main-а управление не доходило). Ничего не
помогало, пока я не догадался подкрутить rlimit для стека. Стоило
сделать его 2'000'000 байт, и все стало замечательно работать.
Повторюсь - это только на Fedora2. Вот и вопрос: в чему тут может
быть дело? Я хочу поковырять сорцы glibc от FC2, но вопрос несколько
более принципиальный - как управлять стеком? Какой остаток его будет
достаточен для fork-exec?
Господа, я занимаюсь поделкой некоего подобия отладчика, и наткнулся
на одну неприятную проблему. Отлаживается многопотоковое приложение.
События типа breakpoint-ов и сигналов ловяться с помощью ptrace. Все
вроде бы прекрасно работает, но иногда вдруг в одном из потоков
отлаживаемого приложения случается сигнал SIGTRAP, и все мои проверки
на тип события проваливаются - SIGTRAP вызван не breakpoint-ом и не
каким-то сигналом. Процесс этот останавливается всгда в одном и том
же месте, а именно - в функции __pthread_sigsuspend. Код там такой:
libpthread.so$.__pthread_sigsuspend:
4002FA20 push ebp
4002FA21 mov ebp, esp
4002FA23 mov eax, dword ptr [ebp+08H]
4002FA26 mov ecx, 000000008H
4002FA2B push ebx
4002FA2C mov ebx, eax
4002FA2E mov eax, 0000000B3H
---> 4002FA33 int 0FFFFFF80H
4002FA35 pop ebx
4002FA36 pop ebp
4002FA37 ret
Стоп происходит в месте, отмеченном "--->".
Системный вызов с номером 0xb3 == 179 - это rt_sigsuspend.
Вот собственно и вопрос - почему rt_sigsuspend генерирует SIGTRAP?
Причем не под отладчиком никакого SIGTRAP никогда не летит, прилада
прекрасно работает.
Если этот сигнал просто проигнорировать, не отдавая процессу,
отлаживаемая программа повисает. Если отдать, то соответствующий
поток умрет и так же все накроется. Получается безвыходное положение,
так что нужно понять, отчего возникает этот сигнал.
Может быть, кто-нибудь занимался чем-то подобным? Буду весьма
благодарен за любую помощь.
У меня случается очень странная ситуация. Есть мультитредовая программа, работающая под LinuxThreads (NPTL не обсуждается). В ней есть обработчик Ctrl-C (SIGINT). Из этого обработчика зовется сначала pthread_cancel() для некоторых тредов, а затем exit(). Main-тред что-то печатает в цикле, и в это время пользователь нажимает Ctrl-C. В моем случае SIGINT всегда обрабатывается в main треде - это видно по PID-у. Вопреки всем ожиданиям, после вызова exit() main продолжает работу, которая была прервана по Ctrl-C! Все остальные потоки, кроме менеджера, умирают. То есть лог выглядит примерно так:
[pid 13801] Starting...
Running the runner 1
The runner 1 is working
The runner 1 is working
[pid 13801] The main thread is working
The runner 1 is working
The runner 1 is working
[pid 13801] The main thread is working
[pid 13801] SIGINT caught
[pid 13801] Killing threads... done
[pid 13801] calling exit...
[pid 13801] The main thread is working
[pid 13801] The main thread is working
[pid 13801] The main thread is working
[pid 13801] The main thread is working
[pid 13801] The main thread is working
Как же такое может быть?? У меня, честно говоря, ум за разум заходит... :(
Столкнулся с такой проблемой: моя программа (A), время от времени вызывающая другую приладу (B), работает некоторое время, а потом случается следующее: она пытается в очередной раз вызвать B, но та падает, - статус fork->waitpid() говорит о том, что эта прилада B свалилась по сигналу SIGILL (то есть выполняется предикат WIFSIGNALED && WTERMSIG == SIGILL). Причем до вызова ее main(), похоже, дело даже не доходит.
Самое странно то, что, когда я попытался получить core файл и установил ulimit -Sc в unlimited, все заработало и работает прекрасно! Стоит сделать ulimit -Sc 0, как опять начинает случаться тот же глюк.