В голом металлическом проекте C / C ++ я использую GCC-рычажного встроен (в настоящее время самый последний 4.9-2015-q2).
По некоторым причинам я должен избегать использования некоторых функций, таких как некоторые из stdio et cetera (не хочу использовать ретаргетинг или полухостинг).
Кроме того, я использую FreeRtos с heap_4.c и имел, например, malloc()
перенаправлен прямо на pvPortMalloc()
как это:
void* malloc(size_t s) {
return pvPortMalloc(s);
}
Поэтому я не хочу, чтобы какие-либо части кода управления кучей инструментария были в моем двоичном файле.
Теперь есть несколько ситуаций, которые разработчик моей команды хотел использовать, например. printf()
который косвенно ссылается _malloc_r()
(и еще немного), и на самом деле довольно сложно выяснить, откуда на него ссылаются и где исправить.
(Использование printf()
это просто пример здесь. В моем проекте есть пользовательская реализация printf (), которая печатает напрямую в uart без использования stdio. Но есть и другие случаи, например, Тип информации демангелинга,…)
В настоящее время у меня есть ситуация, когда мой проект (который содержит около 200 исходных файлов c и c ++) хорошо компилируется без ссылок _malloc_r()
любым способом — пока я строю с GCC 4,8.
Но при строительстве с GCC 4,9, Я вижу нежелательные ссылки на _malloc_r
и еще немного.
Может ли быть инструмент командной строки для анализа моего эльфийского файла, чтобы выяснить, откуда ссылаются конкретные функции?
Изменить 2015-07-20:
_malloc_r
внутри моего кода.Далее я узнаю, что есть __gnu_cxx::__snprintf_lite()
который ссылается на полный удар iostream
который я не хочу в своем коде. это __gnu_cxx::__snprintf_lite()
используется некоторыми исключениями gcc
stl
реализация (например, ссылка на __throw_out_of_range_fmt()
). (Да, мой код использует std::map
). Мой способ избавиться от iostream
должен был просто предоставить свой собственный __gnu_cxx::__snprintf_lite()
как это (имея свой маленький след vsnprintf
):
namespace __gnu_cxx {
int __snprintf_lite(char* buf, size_t bufsize, const char* fmt, va_list ap) {
return vsnprintf(buf, bufsize, fmt, ap);
}
}
Это можно проверить, просмотрев исходники библиотеки gcc-4.9 (например, src/gcc/libstdc++-v3/src/c++11/snprintf_lite.cc
).
Это пример для выяснения ссылок на _exit
в статически скомпилированной программе:
/* hello.c */
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
write(1, "Hello\n", 6);
_exit(0);
}
Скомпилируйте это:
$ gcc hello.c -static -g
Узнайте адрес _exit
:
$ nm a.out | grep " _exit"000000000040f760 T _exit
Разбирать с objdump -d -j .text
, grep
для адреса _exit
, cut
адрес из линии и передать его addr2line
:
$ objdump -d -j .text a.out | grep 40f760 | cut -c 1-8 | addr2line -e a.out -f
oom
dl-tls.o:?
main
/home/m/hello.c:8
__run_exit_handlers
??:?
??
??:0
_Exit
??:?
_dl_non_dynamic_init
??:?
abort
??:?
do_lookup_x
dl-lookup.o:?
_dl_relocate_object
??:?
_dl_signal_error
??:?
dl_open_worker
dl-open.o:?
_dl_close_worker.part.0
dl-close.o:?
_dl_start_profile
??:?
Результат:
функции oom
, main
, __run_exit_handlers
… сделать ссылку на функцию _exit
,
Я не уверен, правильно ли я вас понял, но, похоже, вы хотите избежать использования некоторых конкретных функций в вашем проекте. Как насчет простого отравления идентификаторов функций?
Этот код не может скомпилировать (намеренно) для printf
:
#define printf FORBIDDEN
int main(int argc, char *argv[]) {
printf("Test");
}
со следующей ошибкой:
Untitled.cpp:11:3: error: no matching function for call to 'FORBIDDEN'
printf("Test");
^~~~~~
Untitled.cpp:3:16: note: expanded from macro 'printf'
#define printf FORBIDDEN
^~~~~~~~~
Так что порядок объявления и переопределения не имеет значения. Вам не нужно знать все функции, которые вызывают запрещенные функции:
#define printf FORBIDDEN
// this in included file:
void otherfunc() {
printf("I fail.");
}
// eof included file
int main(int argc, char *argv[]) {
otherfunc();
}
Пераф использует собственный malloc.h, где вы можете отменить или переопределить _malloc_r
Что-то похожее:
extern _PTR malloc _PARAMS ((size_t));
#ifdef __CYGWIN__
#undef _malloc_r
#define _malloc_r(r, s) malloc (s)
#else
extern _PTR _malloc_r _PARAMS ((struct _reent *, size_t));
#endif
Посмотрите на Крючки-для-таНос тоже
Библиотека GNU C позволяет вам изменять поведение malloc, realloc и
бесплатно, указав соответствующие функции подключения. Вы можете использовать эти крючки
чтобы помочь вам отлаживать программы, которые используют динамическое распределение памяти, для
пример.Переменные хука объявлены в malloc.h.
Еще один совет — использование LD_PRELOAD Что такое трюк LD_PRELOAD?