2011-10-18 31 views
10

Tôi muốn viết một thẻ LLVM để có thể truy cập mọi bộ nhớ. Đây là những gì tôi đang cố gắng làm.Sử dụng mã C/C++ bằng LLVM

Với bất kỳ chương trình C/C++ nào (như được đưa ra dưới đây), tôi đang cố gắng chèn các cuộc gọi đến một số chức năng, trước và sau mỗi lệnh đọc/ghi vào/từ bộ nhớ. Ví dụ xem xét các chương trình dưới đây C++ (Account.cpp)

#include <stdio.h> 

class Account { 
int balance; 

public: 
Account(int b) 
{ 
    balance = b; 
} 
~Account(){ } 

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; 
} 

Vì vậy, sau khi đo đạc chương trình của tôi sẽ giống như thế:

#include <stdio.h> 

class Account 
{ 
    int balance; 

public: 
Account(int b) 
{ 
    balance = b; 
} 
~Account(){ } 

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; 
} 

nơi foo() có thể là bất kỳ chức năng như có được thời gian hệ thống hiện tại hoặc tăng số lượt truy cập .. v.v.

Vui lòng cho tôi ví dụ (mã nguồn, hướng dẫn, v.v.) và các bước về cách chạy. Tôi đã đọc hướng dẫn về cách làm cho một thẻ LLVM được đưa ra trên http://llvm.org/docs/WritingAnLLVMPass.html, nhưng không thể tìm ra cách viết một vượt qua cho vấn đề trên.

+0

Vâng, bạn có thể quá tải toán tử để không chỉ thực hiện các chức năng bổ sung, trừ, chuyển nhượng thực sự mà còn gọi hàm tùy chỉnh của bạn. – vishakvkt

+0

Tại sao bạn muốn thêm các chức năng này? Nếu bạn muốn gỡ lỗi chương trình của bạn có một phương pháp tốt hơn có sẵn. – tune2fs

+0

Tôi sẽ bỏ phiếu để đóng câu hỏi này dưới dạng bản sao của lưu lượng truy cập http: // stackoverflow.com/questions/7526550/instrumenting-c-c-codes-using-llvm (ý tôi là, nhìn vào tiêu đề) và tôi nhận thấy rằng bạn là tác giả của cả hai. Làm thế nào để bạn mong đợi người dùng StackOverflow để cung cấp cho bạn câu trả lời lần này rằng họ đã không cung cấp cho bạn thời gian qua (thiếu làm việc đó cho bạn, điều đó sẽ không xảy ra)? –

Trả lời

3

Hãy thử một cái gì đó như thế này: (bạn cần phải điền vào chỗ trống và thực hiện các công việc lặp iterator mặc dù thực tế rằng các mục đang được chèn)

class ThePass : public llvm::BasicBlockPass { 
    public: 
    ThePass() : BasicBlockPass() {} 
    virtual bool runOnBasicBlock(llvm::BasicBlock &bb); 
}; 
bool ThePass::runOnBasicBlock(BasicBlock &bb) { 
    bool retval = false; 
    for (BasicBlock::iterator bbit = bb.begin(), bbie = bb.end(); bbit != bbie; 
    ++bbit) { // Make loop work given updates 
    Instruction *i = bbit; 

    CallInst * beforeCall = // INSERT THIS 
    beforeCall->insertBefore(i); 

    if (!i->isTerminator()) { 
     CallInst * afterCall = // INSERT THIS 
     afterCall->insertAfter(i); 
    } 
    } 
    return retval; 
} 

Hope this helps!

+0

Bạn không nên làm điều đó trước và sau mỗi lệnh, nhưng chỉ cho 'store' và' load' cho con trỏ chính hãng (không phải là 'alloca' nội bộ có thể rút gọn). –

+0

Bạn phải trả về true từ hàm runOnBasicBlock để chỉ ra rằng các lệnh trong khối cơ bản đã được thay đổi. – ConfusedAboutCPP

8

Tôi không quen thuộc với LLVM, nhưng tôi quen thuộc hơn với GCC (và máy móc plugin của nó), vì tôi là tác giả chính của GCC MELT (một ngôn ngữ cấp cao dành riêng cho miền để mở rộng GCC, cách bạn có thể sử dụng cho vấn đề của bạn). Vì vậy, tôi sẽ cố gắng trả lời bằng các thuật ngữ chung.

Trước tiên bạn cần biết lý do bạn muốn điều chỉnh trình biên dịch (hoặc trình phân tích tĩnh). Nó là một mục tiêu đáng giá, nhưng nó có những hạn chế (đặc biệt, w.r.t. xác định lại một số toán tử hoặc các cấu trúc khác trong chương trình C++ của bạn). Điểm chính khi mở rộng một trình biên dịch (có thể là GCC hoặc LLVM hoặc cái gì khác) là bạn rất có thể sẽ xử lý tất cả các biểu diễn bên trong của nó (và bạn có thể không bỏ qua các phần của nó, trừ khi bạn có một vấn đề được xác định rất hẹp).). Đối với GCC, nó có nghĩa là xử lý hơn 100 loại Tree-s và gần 20 loại Gimple-s: trong GCC, các cây đại diện cho các toán hạng và các khai báo, và các gimple-s đại diện cho các lệnh. Lợi thế của phương pháp này là khi bạn đã thực hiện điều đó, tiện ích mở rộng của bạn sẽ có thể xử lý mọi phần mềm được trình biên dịch chấp nhận. Nhược điểm là sự phức tạp của các biểu diễn bên trong của trình biên dịch (có thể giải thích được bởi độ phức tạp của các định nghĩa của ngôn ngữ nguồn C & C++ được chấp nhận bởi các trình biên dịch, và bởi độ phức tạp của mã máy đích mà chúng tạo ra, và bởi khoảng cách ngày càng tăng giữa nguồn & ngôn ngữ đích).

Vì vậy, hack một trình biên dịch chung (có thể là GCC hoặc LLVM), hoặc một máy phân tích tĩnh (như Frama-C), là một nhiệm vụ khá lớn (hơn một tháng làm việc, không phải vài ngày). Để đối phó chỉ với một chương trình C++ nhỏ như bạn đang hiển thị, nó không phải là giá trị nó. Nhưng nó chắc chắn là giá trị nỗ lực nếu bạn đồng bằng để đối phó với các cơ sở phần mềm nguồn lớn.

Trân

Các vấn đề liên quan