Как найти функцию 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. Поэтому я совершенно уверен, что моя собственная основная функция действительна.

у вас есть идеи, что может быть не так? В настоящее время у меня нет идей о том, как найти и удалить основную функцию rogue.

спасибо,

Эдриан

EDIT: как я только что узнал, я сделал ошибку при поиске файлов файлов со строкой " это автоматически сгенерированный." Я только что нашел несколько десятков файлов с той же строкой, все принадлежащие FreeImage, одной из сторонних библиотек, которые я использую. Таким образом, проблема, похоже, связана с FreeImage, но я все еще не уверен, как действовать, поскольку я скомпилировал Freeimage как библиотеку с вложенным файлом macOS makefile и включил только библиотеку. Я попытаюсь восстановить более новую версию FreeImage и посмотреть, исправила ли это мою проблему.

10 ответов


может ли это быть инициализатор для статического объекта, который терпит неудачу до вызова main ()?


у вас есть несколько основных в двоичной? Попробуйте использовать nm на нем. (это не должно быть возможно как ld не будет связываться с дубликатами, но перейдите в динамические библиотеки и найдите _main есть)

nm a.out | grep -5 _main

это должно дать 5 строк до и после _main найдено в двоичном a.out

если у вас есть несколько, см. окружающие символы для подсказок, в каких частях они находятся...

следующий шаг может быть сделать то же самое на каждом динамический lib, который используется. Для получения списка используемых динамических библиотек используйте otool

otool -L a.out

Я не уверен, как найти другой, но вы можете указать свою собственную точку входа явно и сделать другой неиспользуемой. Вы можете использовать GNU linker ld - e возможность установить точку входа.

-e запись

--entry=запись

использовать запись в качестве явного символа для начала выполнения программа, а не точка входа по умолчанию. Если нет sym- бол с именем entry, компоновщик попытается разобрать запись как число, и используйте это как адрес записи (номер будет интерпретироваться в базе 10; вы можете использовать ведущий 0x для базы 16 или ведущий 0 на основание 8).

для будущих читателей, если у вас есть эта проблема в Windows. Эквивалентный параметр компоновщика -/запись.


вы пытались запустить исполняемый файл через nm? Это может дать вам некоторые подсказки. Я бы не подумал, что можно связать программу с более чем одной глобально видимой функцией с именем main() Не уверен, как это успевает случиться.


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


быстрый Хак:

readelf -s -w my_bin_file > temp.txt

открыть temp.txt, поиск main (с функцией FUNC в одном столбце) Поднимитесь, пока не найдете первый столбец файла-это файл со ссылкой main.

edit: это работает только на GNU Unix вкусов и друзей. OS X использует формат Mach-O, а не ELF.


Я знаю, что в C вы можете иметь другую точку входа, вызываемую перед основной функцией, это может быть идея. Код обычно выглядит так :

void __attribute__ ((constructor)) my_main(void);

возможно, вы можете найти что-то подобное в своем коде.

В C также существуют различные способы поймать основную функцию и вызвать ее после" реальной " основной. Некоторые библиотеки потоков имеют такие хаки, чтобы "подготовить" среду, планировщик и тому подобное.

Это не действительно полезно, но это может объяснить, почему ваш main не вызывается вообще.

надеюсь, что это помогает!


еще одно замечание.

WxWidgets также определяют свои собственные main

С здесь

Как и во всех программах должна быть "основная функция". Под wxWidgets main реализован этот макрос, который создает экземпляр приложения и запускает программу.

IMPLEMENT_APP(MyApp)


похоже, у вас может быть файл с именем b44ExpLogTable.cpp скомпилирован в вашу двоичную или некоторую библиотеку thirdpart. Похоже, что эта небольшая программа должна генерировать таблицу exp (), но каким-то образом импортируется в ваш проект (ы)

посмотреть этой и в источники FreeImage


создать файл карте. Большинство программ на самом деле не начинаются с main. Mapfile из GCC должен сообщить вам адрес __start или __executable_start, который вы должны иметь возможность взломать и пройти, чтобы увидеть, что вызывает выход вашей программы.