Как мне найти функцию main(…) моей программы?
Вопрос
В настоящее время я портирую проект с несколькими сотнями файлов кода и зависимостями на несколько сторонних библиотек для Mac Os.Наконец-то я дошёл до того, что программа компилируется без предупреждений и ошибок, но, похоже, не выполняет мою собственную основную функцию.
Вместо этого он, похоже, выполняет какую-то другую основную функцию, которая, похоже, принадлежит третьей стороне.Эта функция записывает в консоль некоторые диагностические данные и после этого завершает работу:
(gdb) continue
Current language: auto; currently c++
//
// This is an automatically generated file.
// Do not edit.
//
const unsigned short expTable[] =
{
0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
...
0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
};
Debugger stopped.
Program exited with status value:0.
Я не могу использовать отладчик, чтобы узнать, где находится эта основная функция, потому что, хотя трассировка стека кажется верной, gdb не показывает мне правильный номер строки и имя файла для каждой записи стека (см. этот нерешённый вопрос подробности).
Поиск занял несколько минут, но не дал никаких результатов.
Мой проект использует SDL среди других библиотек, но я получил награду SDL_Main() и основные проблемы и построил свой проект на основе прекрасно работающего шаблона проекта SDL.Поэтому я совершенно уверен, что моя собственная основная функция действительна.
Есть ли у вас какие-либо идеи, что может пойти не так?В настоящее время у меня нет идей о том, как найти и удалить мошенническую основную функцию.
Спасибо,
Адриан
РЕДАКТИРОВАТЬ: Как я только что узнал, я допустил ошибку при поиске файлов со строкой «Это автоматически сгенерированный».Я только что нашел несколько десятков файлов с одной и той же строкой, принадлежащих FreeImage, одной из сторонних библиотек, которые я использую.Итак, проблема, похоже, связана с FreeImage, но я до сих пор не уверен, как действовать, поскольку я скомпилировал Freeimage как библиотеку с прилагаемым make-файлом MacOs и включил только библиотеку.Я попытаюсь пересобрать более новую версию FreeImage и посмотреть, решит ли это мою проблему.
Решение
Может ли это быть инициализатор статического объекта, который терпит неудачу до вызова вашей функции main()?
Другие советы
У вас есть несколько основных файлов в бинарном файле?Попробуйте использовать nm
в теме. (это не должно быть возможно, так как ld
не будет связываться с дубликатами, но зайдите в динамические библиотеки и найдите _main
там)
nm a.out | grep -5 _main
Это должно дать 5 строк до и после любого _main
найден в двоичном формате a.out
Если у вас их несколько, посмотрите на окружающие символы, чтобы узнать, в каких частях они находятся...
Следующим шагом может быть сделать то же самое для каждой используемой динамической библиотеки.Чтобы получить список используемых динамических библиотек, используйтеotool
otool -L a.out
Я не уверен, как найти другую, но вы можете явно указать свою собственную точку входа и сделать другую неиспользуемой.Вы можете использовать компоновщик GNU лд -e опция, чтобы установить точку входа.
-e запись
--entry=запись
Используйте запись в качестве явного символа для начала выполнения вашей программы, а не точку входа по умолчанию.Если нет символа, названного въезда, линкеров будет попытаться проанализировать запись в качестве числа и использовать его в качестве адреса входа (номер будет интерпретироваться в базе 10;Вы можете использовать ведущий 0x для базы 16 или ведущий 0 для базы 8).
Для будущих читателей, если у вас есть эта проблема в Windows.Эквивалентный вариант компоновщика: /ВХОД.
Вы пытались запустить свой исполняемый файл через nm
?Возможно, он сможет дать вам несколько подсказок.Я бы не подумал, что можно связать программу с более чем одной глобально видимой функцией с именем main()
, не знаю, как это удается.
Просмотрите файлы заголовков, которые вы включаете, и посмотрите, нет ли определения, которое переназначает main
к чему-то другому.Это старый трюк, позволяющий гарантировать, что основная функция библиотеки вызывается первой для выполнения некоторых настроек.Как правило, в конечном итоге она вызывает вашу основную функцию, ссылаясь на переопределенное значение.
Быстрый взлом:
readelf -s -w my_bin_file > temp.txt
Откройте temp.txt, найдите Main (с фанком в одном столбце). Перейдите вверх, пока не найдете столбец первого файла - это файл с связанным Main.
редактировать: Это работает только с версиями GNU Unix и их друзьями.OS X использует формат Mach-O, а не ELF.
Я знаю, что в C перед основной функцией можно вызвать другую точку входа, и это может быть идеей.Код обычно выглядит так:
void __attribute__ ((constructor)) my_main(void);
Возможно, вы сможете поискать что-то подобное в своем коде.
В C также есть разные способы перехватить функцию main и вызвать ее после «настоящей» функции main.В некоторых библиотеках потоков есть такие хаки для «подготовки» среды, планировщика и тому подобного.
Это бесполезно, но может объяснить, почему ваш main вообще не вызывается.
Надеюсь это поможет!
Еще одно замечание.
WxWidgets также определяют свои собственные main
От здесь
Как и во всех программах должна быть «основная» функция.В wxWidgets main реализован с помощью этого макроса, который создает экземпляр приложения и запускает программу.
IMPLEMENT_APP(MyApp)
Похоже, у вас может быть файл с именем b44ExpLogTable.cpp
скомпилирован в ваш двоичный файл или в стороннюю библиотеку.Похоже, что эта маленькая программа предназначена для создания таблицы exp(), но каким-то образом ее импортировали в ваши проекты.
Видеть этот и это в Источники бесплатных изображений
Создайте файл карты.Большинство программ на самом деле не запускаются с main.Файл карты из GCC должен сообщить вам адрес __start или __executable_start, который вы сможете взломать и пройти через него, чтобы увидеть, что заставляет вашу программу завершить работу.