Как сделать так, чтобы компилятор не оставлял имена функций в библиотеке, если это не нужно? Недавно скомпилировал библиотеку для серверной защиты и вскрыл ее текстовым редактором, и сразу нашел имена всех используемых функций. Проблема в том, что их в релизе быть не должно. Почему-то компилятор оставляет имена функций, несмотря на отсутствие отладочной информации и то, что эти функции не выставлены в экспорт.
Mika0x65 Не помогло. Применял strip со всеми возможными параметрами, бесполезно. В итоге в .so остается перечень функций и глобальных переменных, в той же секции, что и расшаренные функции, при этом имена расшаренных хранятся в обычном формате, а нерасшаренных - _ZX$name$v, где X - цифра от 1 до 16, может повторяться, как в _Z4ratev
Zlyden А эти переменные объявлены как static? В Linux все, что не static попадает в секции '.symtab'/'.dynsym'.
Нет, не статичные. Объявил static, и они из списка пропали. А вот с функциями мне пока ничего не удалось, пробовал по-разному. Если это поможет: .o компилируются с параметрами -pipe -m32 -O2 -fPIC -fomit-frame-pointer -ffast-math -falign-loops=2 -falign-jumps=2 -falign-functions=2 -fno-strict-aliasing -fstrength-reduce -I../sdks .so компилируются с параметрами -pipe -m32 -O2 -fPIC -fomit-frame-pointer -ffast-math -falign-loops=2 -falign-jumps=2 -falign-functions=2 -fno-strict-aliasing -fstrength-reduce -shared -m32
Zlyden С -фиями static не работает? Должен быть тот же эффект: //Not visible static int f() { return 0; } //Visible int g() { return 0; } И где именно видны эти ф-ии? В таблице символов после strip?
Тоже недавно разбирался с этой проблемой, только как я понял надо убрать лишнее из so ака dll, а не либы (.a \ .lib в винде). Чтобы экспортировать только нужные символы в шаред либу (и отбрасывался мертвый код) длжны соблюдаться несколько условий, если одно не выполнено - молча не заработает, делается примерно так: g++ -O2 -Wl,-x,-gc-sections,-retain-symbols-file=syms -fpic -shared -fdata-sections -ffunction-sections -o out.so input.cpp где syms - файл в котором через строчку указываются экспортируемые символы (аналог .def в винде) если линковать другие либы, то как они собраны тоже будет влиять и может навалиться мусора от них (причем даже если их не видно в экспорте не значит что их нет) Вобщем все это крайне не порадовало, весь линукс (все дистрибутивы) собран фактически криво и мертвый код не удаляется. Сам линкер мутный и добиться результата было сложно и до конца так и не добился.
Mika0x65 Пробовал объявлять функции со static, единственное отличие - вместо _ZX$name$v теперь пишется _ZLX$name$v. Натравил на него readelf, выяснил, что это секция .dynstr (естественно, ее удаление при помощи strip ни к чему хорошему не приведет). Что меня удивило, так обнаружение в том же файле восьми секций debug_*, хотя компилировал без -g (осмотрел Makefile). Сейчас попробовал отладить с этой "релизной" библиотекой - все признаки дебаг-информации, даже бряки на нерасшаренные функции ставятся. Все перепроверил, скомпилировал вручную (обычно компилировал при помощи make) командами без необязательных параметров, дебаг информация пропала, имена остались. Опытным путем нашел, что дебаг-информация появляется от параметра -ffast-math. semen Спасибо, но ваш метод не помог
Zlyden Странно, только что собрал delme.c: Код (Text): int f() { return 0; } static int g() { return 0; } Собирал вот так: 'cc delme.c -ffast-math -shared', затем 'strip a.out'. objdump -T: Код (Text): a.out: file format elf32-i386 DYNAMIC SYMBOL TABLE: 00000000 w DF *UND* 00000023 GLIBC_2.0 __deregister_frame_info 00000000 w D *UND* 00000000 __gmon_start__ 000004cc g DF .fini 00000000 Base _fini 00000000 w DF *UND* 0000003a GLIBC_2.0 __register_frame_info 000015f4 g D *ABS* 00000000 Base __bss_start 0000160c g D *ABS* 00000000 Base _end 0000046c g DF .text 0000000a Base f 000015f4 g D *ABS* 00000000 Base _edata 00000000 w DF *UND* 0000015a GLIBC_2.1.3 __cxa_finalize 000002d0 g DF .init 00000000 Base _init Т.е. ф-ия g() в .dynsym не попала. Код (Text): $ cc -v Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.6/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,f77 --disable-libgcj --host=i386-redhat-linux Thread model: posix gcc version 3.4.6 20060404 (Red Hat 3.4.6-4) А если собрать минимальный тестовый пример, то g() все равно остается?
gcc предустановленный. Код (Text): Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) Mika0x65 В .dynsym у меня ее и так нет, она присутствует в .dynstr. Скомпилировал пример через gcc, все как положено, g на выходе в .dynstr отсутствует. Забыл сказать, что я собираю через g++.
Zlyden .dynstr -- просто секция, куда скидываются все строки, принадлежащие .dynsym (может не только ей, точно не знаю). Т.е. какой-то символ из .dynsym ссылается на эту строку. Вопрос в том, почему он туда вообще попал, если ф-ия объявлена как static. Не понял два момента: 1. Это происходит всегда, если собирать с помощью g++ (и на тестовом примере тоже)? 2. Это происходит и в случае gcc, но не происходит на тестовом примере?
Mika0x65 Большое спасибо, разобрался. Дело в том, все эти функции были в отдельном .cpp, а когда я их перебросил в main, они сразу из списка исчезли (естественно, при помощи static). А что касается вопросов, то всегда итог одинаковый, хоть с gcc, хоть g++. Единственная разница - формат имен этих функций разный (при gcc $name$, а g++ _ZX$name$v)
Zlyden Странно, что оно вообще собралось -- static также ограничивает область видимости ф-ии файлом, в котором она определена. Т.е. если main находится в другом файле, то эти ф-ии просто не будут видны из него. Поэтому подозреваю, что в .dynsym символ попадал как неопределенный.