Я только что прочитал о проекте LLVM и что его можно использовать для статического анализа на кодах C/С++ с использованием анализатора Clang, который является интерфейсом LLVM. Я хотел знать, можно ли извлекать все обращения к памяти (переменные, локальные, а также глобальные) в исходном коде с помощью LLVM.
Есть ли встроенная библиотека в LLVM, которую я мог бы использовать для извлечения этой информации. Если нет, предложите мне, как писать функции, чтобы сделать то же самое (существующий исходный код, ссылка, учебник, пример...) Из того, что я подумал, я должен сначала преобразовать исходный код в LLVM bc, а затем применить его для анализа, но точно не знаю, как это сделать.
Я попытался выяснить, какой IR я должен использовать для своей цели (Дерево синтаксиса абстрактного текста (AST) или промежуточное представление LLVM SSA (IR).), но не мог понять, какой из них использовать. Вот что я пытаюсь сделать. Учитывая любую программу C/С++ (например, приведенную ниже), я пытаюсь вставить вызовы в какую-либо функцию до и после каждой инструкции, которая читает/записывает в/из памяти. Например, рассмотрим приведенную ниже программу на С++ (Account.cpp)
#include <stdio.h>
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 <stdio.h>
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, было бы очень сложно получить сопоставление 1:1 между моей оригинальной программой и инструментальным IR. Итак, можно ли отразить изменения, внесенные в ИК (из-за инструментария) в исходную программу.
Чтобы начать работу с пропуском LLVM и как сделать это самостоятельно, я рассмотрел пример прохода, который добавляет проверки времени выполнения к нагрузкам и хранилищам LLVM IR, пропускную способность (хранение) хранилища SAFECode (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.