Я только что прочитал о проекте LLVM и о том, что его можно использовать для статического анализа кодов C/C++ с помощью анализатора Clang, который является передней частью LLVM. Я хотел узнать, возможно ли извлечь все обращения к памяти (переменные, как локальные, так и глобальные) в исходном коде с помощью LLVM.
Есть ли какая-нибудь встроенная библиотека в LLVM, которую я мог бы использовать для извлечения этой информации. Если нет, пожалуйста, подскажите, как написать функции для этого (существующий исходный код, ссылка, учебник, пример...). Из того, что я думал, это то, что я сначала конвертирую исходный код в LLVM bc, а затем использую его для анализа, но не знаю точно, как это сделать.
Я пытался выяснить, какой IR я должен использовать для своей цели (абстрактное синтаксическое дерево (AST) Clang или промежуточное представление (IR) SSA LLVM. ), но так и не смог понять, какой из них использовать. Вот что я пытаюсь сделать. В любой программе на C/C++ (как в приведенной ниже) я пытаюсь вставить вызовы некоторых функций до и после каждой инструкции, которая читает/пишет в/из памяти. Для примера рассмотрим нижеприведенную программу на C++ (Account.cpp)
#include
class Account {
int balance;
public:
Account(int b) {
balance = b;
}
int read() {
int r;
r = balance;
return r;
}
void deposit(int n) {
balance = balance + n;
}
void withdraw(int n) {
int r = read();
balance = r - n;
}
};
int main () {
Account* a = new Account(10);
a->deposit(1);
a->withdraw(2);
delete a;
}
Итак, после инструментализации моя программа должна выглядеть так:
#include
class Account {
int balance;
public:
Account(int b) {
balance = b;
}
int read() {
int r;
foo();
r = balance;
foo();
return r;
}
void deposit(int n) {
foo();
balance = balance + n;
foo();
}
void withdraw(int n) {
foo();
int r = read();
foo();
foo();
balance = r - n;
foo();
}
};
int main () {
Account* a = new Account(10);
a->deposit(1);
a->withdraw(2);
delete a;
}
где foo() может быть любой функцией, например, получить текущее системное время или увеличить счетчик... и так далее. Я понимаю, что для вставки функций, подобных вышеуказанным, мне нужно сначала получить IR, а затем запустить инструментальный проход на IR, который вставит такие вызовы в IR, но я не очень понимаю, как этого добиться. Пожалуйста, подскажите на примерах, как это сделать.
Также я понимаю, что после компиляции программы в IR, будет очень сложно получить 1:1 отображение между моей оригинальной программой и инструментальным IR. Итак, возможно ли отразить изменения, сделанные в IR (из-за инструментария), в оригинальной программе.
Для того, чтобы начать разбираться с LLVM pass и как сделать его самостоятельно, я посмотрел пример pass, который добавляет проверки во время выполнения к загрузкам и сохранениям LLVM IR, SAFECode's load/store instrumentation pass (http://llvm.org/viewvc/llvm-project/safecode/trunk/include/safecode/LoadStoreChecks.h?view=markup и http://llvm.org/viewvc/llvm-project/safecode/trunk/lib/InsertPoolChecks/LoadStoreChecks.cpp?view=markup). Но я не смог понять, как запустить этот проход. Пожалуйста, дайте мне шаги, как запустить этот проход в какой-нибудь программе, скажем, в вышеприведенном Account.cpp.