Не удается найти точку входа программы в проекте C++

У меня есть проект C++ в Ubuntu 12.04. Для запуска проекта make файлу требуются следующие файлы:

1-Все файлы .cpp

2-Все файлы .h

3-три общие библиотеки.

Проект полностью функционален и соответствует заявленным характеристикам. Доступны все необходимые файлы .cpp и .h. Проблема в том, что ни в одном из исходных файлов нет функции main(), а точка входа в программу находится в одной из трех разделяемых библиотек. Моя работа состоит в том, чтобы выяснить конвейер выполнения программы, и без основного файла я не могу этого сделать. Я не могу запустить проект в любой среде IDE (например, в eclipse), потому что основная функция недоступна.

Вопрос: Подскажите, пожалуйста, как найти точку входа в программу?

P.S. Буду рад предоставить любую информацию или материалы, которые могут вам понадобиться для решения моей проблемы.

Изменить: файл CMakeLists.txt доступен здесь.

Изменить 2: файл build.sh доступен здесь.


person zindarod    schedule 31.03.2014    source источник
comment
У вас не может быть исполняемого файла без main. Можно немного расширить поиск. Попробуйте grep -RIi main * или что-то подобное в главном каталоге проекта.   -  person Kiril Kirov    schedule 31.03.2014
comment
Вы можете попробовать nm в общих библиотеках и посмотреть, есть ли в них файл main. Кроме того, может быть, в заголовке есть макрос, который расширяется до main? Вы тоже искали main в заголовках?   -  person Shahbaz    schedule 31.03.2014
comment
@KirilKirov Поверьте мне, я проверяю каждый файл в проекте вручную и с помощью grep.   -  person zindarod    schedule 31.03.2014
comment
@VisaisRacism Да, действительно. Я проверяю все исходные файлы, файлы .cpp и .h.   -  person zindarod    schedule 31.03.2014
comment
@Zindarod - Хорошо, если в исходных/заголовочных файлах ничего нет, проверьте, какие объектные файлы или библиотеки используются в makefile, main может быть в каком-то другом месте (не уверен, что это возможно, но я не вижу причин не быть). Для динамических библиотек может быть полезно ldd executable (перечисляет все динамические библиотеки, используемые исполняемым файлом).   -  person Kiril Kirov    schedule 31.03.2014
comment
@KirilKirov У меня есть список всех файлов .so, необходимых для проекта. Проблема в том, что я не знаю, как искать в них main().   -  person zindarod    schedule 31.03.2014
comment
Подключите отладчик и пройдитесь по стеку вызовов, пока не найдете main?   -  person JoeG    schedule 01.04.2014
comment
@JoeGauterin Сделал nm и нашел main в одном из файлов .so. Теперь нужно найти способ декомпилировать файл .so.   -  person zindarod    schedule 01.04.2014


Ответы (3)


Чтобы найти точку входа, просмотрите каждый общий объект с помощью:

nm $library | egrep "T main$"

Библиотека с main() выведет что-то вроде

090d8ab0 T main

Очень полезный способ визуализации дерева выполнения - запустить:

valgrind --tool=callgrind ./my_executable -arg -arg ....

(вы можете прервать выполнение досрочно, нажав Ctrl+C)

Это выведет файл callgrind.<pid>. Чтобы визуализировать это, запустите kcachegrind callgrind.<pid>.


Вам понадобится valgrind:

sudo apt-get install valgrind

и kcachegrind

sudo apt-get install kcachegrind
person GreenScape    schedule 02.04.2014
comment
Спасибо за ответ. Я уже нашел общий объект, содержащий функцию main(). Теперь проблема в том, как найти конвейер выполнения из main(). Я попробую ваше предложение и сообщу вам о результатах. - person zindarod; 02.04.2014
comment
Большое спасибо за предложение valgrind. Возможно, я не верну исходный код main(), но это наиболее близкая вещь без необходимости дизассемблирования машинного кода. - person zindarod; 02.04.2014

Создайте его с параметром отладки -g и войдите в программу с помощью отладчика, такого как gdb (или cgdb, или ddd). Однако вам понадобятся любые подходящие библиотеки отладочных библиотек.

Если не считать этого, немного поиграйте с кодом. Попробуйте поместить операторы printf или cout, которые печатают внутренние переменные в любых функциях, которые кажутся важными, и посмотрите, каков статус программы и как часто они вызываются. Если main скрыто в библиотеке, возможно, где-то есть другая функция, которая ведет себя как main для целей API, предоставляемого любой библиотекой, имеющей настоящий main.

Какова документация API для ваших библиотек? (это школьный проект?). Звучит странно иметь скрытый main и ничего о нем не говорить.

person Sveltely    schedule 01.04.2014

Если вы используете систему сборки (CMake, SCons, ...), вполне возможно, что система сборки также генерирует некоторые файлы, и один из них может содержать метод main(). Мы используем эту методологию, когда генерируем основную функцию, чтобы создавать экземпляры классов для библиотек, которые были специально выбраны в CMake-gui.

И опять же, возможно, что система сборки удаляет сгенерированные файлы из-за какой-то неясной политики, о которой подумали первоначальные разработчики, но не сказали вам. Так что поищите системные файлы сборки, посмотрите, что там происходит на самом деле.

Изменить

Итак, увидев вы CMakeLists.txt:

проверьте ${DIR_EXT}/covis/src/ci.cpp, где DIR_EXT равно SET( DIR_EXT "../ext/" CACHE PATH "Folder holding external libraries" )

Посмотрите, что там внутри, и дайте нам знать :)

Изменить2

Увидев build.sh (выполните шаги по порядку):

1. изменить

`cmake -D COMPILE_BINARY=ON ..` 

to

`cmake -D COMPILE_BINARY=ON -DCMAKE_BUILD_TYPE=Debug ..`

и добавьте тот же -DCMAKE_BUILD_TYPE=Debug к другой команде cmake.

Это создаст вашу библиотеку и исполняемый файл в режиме отладки.

2. Теперь в одном из исходных файлов C++, к которому у вас есть доступ и вы уверены, что он будет вызван (чем раньше будет вызвана функция, тем лучше), добавьте:

asm("int $0x03");

Это создаст точку останова в вашем приложении.

(Если вы не хотите использовать это, см. ниже).

3. Создайте свое приложение.

4. Запустите его через отладчик в терминале:

gdb ./myapplication <ENTER>

(это даст вам подсказку gdb)

(если вы не добавили точку останова asm сверху, введите в приглашении gdb: break filename.cpp:linenumber или break methodname, чтобы добавить точку останова gdb).

run <ENTER>

Теперь ваше приложение должно останавливаться в вашей функции, когда оно выполняется. Вы все еще находитесь в командной строке gdb, поэтому введите:

bt <ENTER>

Это распечатает обратную трассировку вашего приложения. Где-то вы должны увидеть основную функцию вместе с именем файла и номером строки.

Тем не менее, этот setnames.sh выглядит интересно, посмотрите, не делает ли он ничего смешного :)

person Ferenc Deak    schedule 01.04.2014
comment
Я сделал nm для одного из файлов .so и нашел там основной. Теперь проблема в том, что генерировать код C/C++ из ассемблерного кода очень сложно и не всегда читабельно. Теперь моя проблема заключается в том, чтобы найти способ декомпилировать файл so. - person zindarod; 01.04.2014
comment
Нет, не декомпилировать. Как вы строите? - person Ferenc Deak; 01.04.2014
comment
У меня есть файл build.sh, который запускает файл CMakeList. - person zindarod; 01.04.2014
comment
Отлично. Просмотрите файлы CMakeLists.txt и посмотрите, есть ли какие-либо файловые операции, создающие файлы, записывающие в файлы, такие как configure_file или file(write,, file(append (cmake.org/cmake/help/cmake2.6docs.html#command:file) Или опубликуйте CMakeLists.txt где-нибудь... может быть обновить вопрос. - person Ferenc Deak; 01.04.2014
comment
Пожалуйста, проверьте приведенное выше редактирование для ссылки на файл CMakeLists.txt. - person zindarod; 02.04.2014
comment
Файл ci.cpp является пустым. - person zindarod; 02.04.2014
comment
Какая??? Это потрясающе :) Можете ли вы перекомпилировать приложение с отладочной информацией? Также вы можете показать build.sh? - person Ferenc Deak; 02.04.2014
comment
У меня есть только отлаженные проекты, работающие в среде IDE (например, eclipse, VS). Этот проект построен и запущен на терминале. - person zindarod; 02.04.2014
comment
Неважно, это легко. Можете ли вы отредактировать источник приложения? - person Ferenc Deak; 02.04.2014
comment
Пожалуйста, проверьте приведенное выше редактирование для build.sh, и да, я могу редактировать исходные файлы. - person zindarod; 02.04.2014
comment
@Zindarod проверьте правки :) Кроме того, если это не работает, покажите setnames.sh - person Ferenc Deak; 02.04.2014
comment
setnames.sh txt.do/tspt. Хотя я могу собрать и запустить проект и без файла setnames.sh. - person zindarod; 02.04.2014
comment
@Zindarod хорошо, имена наборов не выглядят интересными для этой цели. Вы пробовали отладку? - person Ferenc Deak; 02.04.2014
comment
Да, но я не понимаю смысла отладки. Я точно знаю, что функция, которую я поставил в качестве точки останова, будет выполнена. Ранее я помещал команды печати в эту функцию для проверки. - person zindarod; 02.04.2014
comment
когда вы отлаживаете, вы получаете трассировку стека, которая показывает вам весь путь до основного вместе с именем файла и номерами строк. - person Ferenc Deak; 02.04.2014
comment
Пожалуйста, смотрите ответ GreenScape. Я успешно получил визуализацию трассировки стека с помощью valgrind. Спасибо за ваше время и усилия. :) - person zindarod; 02.04.2014
comment
Я рад, что вы нашли решение! - person Ferenc Deak; 02.04.2014