Ответ 1
Мне нужно найти, что режим exe/dll был построен, глядя на его заголовки.
Если по заголовкам вы имеете в виду разделы PE или ресурсы (заголовки ничего не скажут вам, и программы обычно не отправляются с заголовками разработки!), это возможно, в пределах и недопустимо. В противном случае это совершенно невозможно, если вы сами не написали программу.
Как правило, это сложно сделать надежным способом, тем более что "сборка отладки" - это упрощение Microsoft Visual Studio, которое не существует как таковое для большинства компиляторов. Например, с GCC вполне допустимо иметь оптимизированную сборку, которая, тем не менее, содержит символы отладки. Можно даже включить или отключить оптимизацию с помощью #pragma
(и изменить уровень оптимизации и даже целевую машину!) И, таким образом, оптимизировать функции (или группы функций) в неоптимизированной сборке и наоборот.
Наличие символов отладки - ваше лучшее предположение для программы, которую вы не пишете. В любом случае невозможно (не реалистично, простым, автоматическим способом) сообщать из сгенерированного двоичного файла, было ли оно оптимизировано или нет.
В разделах .debug$S
и .debug$T
содержатся символы отладки и типы отладки соответственно. Есть и другие разделы, начиная с .debug
, но они устарели. Программа, которая была построена в "режиме отладки" и которая впоследствии не была разделена, будет содержать некоторые или все эти разделы.
Используя С++ без внешних инструментов, вы захотите пропустить заглушку DOS "MZ" и заголовок PE. После этого появятся заголовки разделов, которые вы можете проанализировать. Полное документирование формата файла можно скачать здесь.
Скорее всего, чтение файла и выполнение строкового соответствия для .debug
будет таким же хорошим.
Аналогично, вы можете посмотреть VERSIONINFO или файл манифеста (они также позволяют указать, является ли программа строкой отладки), но они не являются обязательными. Вы можете написать почти все, что захотите. В то же время они еще менее надежны, чем поиск отладочных символов.
Еще один намек, ненадежный, - проверить, какие версии системных библиотек связаны с программой. Если это версия отладки, скорее всего, это была отладочная сборка. Однако можно сделать сборку релизов и по-прежнему связываться с библиотеками отладки, ничто не помешает вам это сделать.Следующее лучшее предположение заключалось бы в отсутствии вызовов функции CRT assert
(которую вы могли бы сделать с простым совпадением строк), поскольку макрос assert
(из которого он обычно вызывается) полностью разделен на построена с NDEBUG
. Нет использования этого символа, нет строки, присутствующей в двоичном файле.
К несчастью, программа, которая не имеет никаких утверждений, будет ложно идентифицирована как "сборка релиза" независимо от ее фактической сборки, и вполне возможно переопределить макрос assert
, чтобы сделать что-то совершенно другое (например, printf
a текст и продолжить). И, наконец, вы не знаете, какая статическая сторонняя библиотека, с которой вы связываетесь (которая, очевидно, уже прошла препроцессор), содержит вызовы assert
, о которых вы не знаете.
Если вы хотите проверить программу, которую вы написали самостоятельно, вы можете использовать тот факт, что оптимизатор полностью удалит вещи, которые предположительно недоступны или не используются. Может потребоваться 2-3 попытки сделать это правильно, но в основном это должно быть так же просто, как определить переменную (или экспортированную функцию, если ваш компилятор/компоновщик не экспортирует символы, которые не используются) и написания двух или трех магические значения для него из местоположения программы, недоступного. Оптимизирующий компилятор будет по крайней мере свернуть эти несколько избыточных движений в один, или, скорее всего, полностью соединить их всех.
Затем вы можете просто выполнить двоичный поиск строк для магических значений. Если они отсутствуют, это оптимизированная сборка.