2010-01-30 38 views
8

Tôi đang cố gắng tự động giải quyết typedef trong các dự án tùy ý C++ hoặc C.Giải quyết typedefs trong C và C++

Vì một số typedef được xác định trong tệp tiêu đề hệ thống (ví dụ uint32), tôi hiện đang cố gắng đạt được điều này bằng cách chạy bộ tiền xử lý gcc trên tệp mã của tôi rồi quét các tệp đã xử lý trước cho typedef. Sau đó tôi có thể thay thế typedefs trong các tệp mã của dự án.

Tôi tự hỏi, nếu có cách khác, có lẽ là cách đơn giản hơn, tôi bị thiếu. Bạn có thể nghĩ về một?

Lý do, tại sao tôi muốn thực hiện việc này: Tôi đang trích xuất các chỉ số mã từ các dự án C/C++ bằng các công cụ khác nhau. Các số liệu dựa trên phương pháp. Sau khi trích xuất các số liệu, tôi phải hợp nhất dữ liệu, được tạo bởi các công cụ khác nhau. Vấn đề là, một trong những công cụ giải quyết typedef và những công cụ khác thì không. Nếu có typedefs được sử dụng cho các kiểu tham số của các phương thức, tôi có các chỉ số ánh xạ tới các tên phương thức khác nhau, mà thực sự đang đề cập đến cùng một phương thức trong mã nguồn.

Hãy suy nghĩ về phương pháp này trong mã nguồn: int test(uint32 par1, int par2)
Sau khi chạy công cụ của tôi, tôi có số liệu, ánh xạ tới một phương thức có tên int test(uint32 par1, int par2) và một số số liệu của tôi được ánh xạ tới int test(unsigned int par1, int par2).

+5

Bạn cũng có thể cung cấp một số thông tin về lý do bạn cần xóa các typedef này khỏi mã của bạn không? Có lẽ, điều đó sẽ giúp trong việc đề xuất một giải pháp. – Jay

Trả lời

5

Nếu bạn không quan tâm đến việc xác định nơi chúng được xác định, bạn có thể sử dụng objdump để kết xuất bảng biểu tượng C++ để phân giải typedef.

lorien$ objdump --demangle --syms foo 

foo:  file format mach-o-i386 

SYMBOL TABLE: 
00001a24 g  1e SECT 01 0000 .text dyld_stub_binding_helper 
00001a38 g  1e SECT 01 0000 .text _dyld_func_lookup 
... 
00001c7c g  0f SECT 01 0080 .text foo::foo(char const*) 
... 

đoạn này là từ định nghĩa cấu trúc sau:

typedef char const* c_string; 
struct foo { 
    typedef c_string ntcstring; 
    foo(ntcstring s): buf(s) {} 
    std::string buf; 
}; 

này yêu cầu bạn phải biên dịch tất cả mọi thứ và nó sẽ chỉ hiển thị các biểu tượng trong thực thi kết quả để có một vài hạn chế.Các tùy chọn khác là để có mối liên kết đổ một bản đồ biểu tượng. Đối với các công cụ GNU, hãy thêm -Wl,-map-Wl,name trong đó name là tên của tệp cần tạo (xem lưu ý). Cách tiếp cận này không làm hỏng tên, nhưng với một công việc nhỏ bạn có thể đảo ngược kỹ thuật quy ước mangling của trình biên dịch. Đầu ra từ đoạn mã trước sẽ bao gồm nội dung như sau:

0x00001CBE 0x0000005E [ 2] __ZN3fooC2EPKc 
0x00001D1C 0x0000001A [ 2] __ZN3fooC1EPKc 

Bạn có thể giải mã chúng bằng cách sử dụng đặc điểm C++ ABI. Một khi bạn cảm thấy thoải mái với cách làm việc này, các mangling table đi kèm với ABI trở nên vô giá. Các nguồn gốc trong trường hợp này là:

<mangled-name>   ::= '_Z' <encoding> 
<encoding>    ::= <name> <bare-function-type> 
    <name>     ::= <nested-name> 
    <nested-name>  ::= 'N' <source-name> <ctor-dtor-name> 'E' 
     <source-name>  ::= <number> <identifier> 
     <ctor-dtor-name> ::= 'C2' # base object constructor 
    <bare-function-type> ::= <type>+ 
     <type>    ::= 'P' <type> # pointer to 
     <type>   ::= <cv-qualifier> <type> 
      <cv-qualifier> ::= 'K' # constant 
      <type>  ::= 'c' # character 

Lưu ý: nó trông giống như GNU thay đổi các đối số ld vì vậy bạn có thể muốn kiểm tra thủ công địa phương của bạn (man ld) để đảm bảo rằng các lệnh thế hệ tập tin bản đồ là -mapfilename trong phiên bản của bạn. Trong các phiên bản gần đây, use -Wl,-M and redirect stdout to a file.

+0

Khi tôi cố gắng chạy trình biên dịch của tôi như thế này: 'g ++ foo.cpp -Wl, -map -Wl, mapname' Tôi nhận được lỗi'/usr/bin/ld: chế độ mô phỏng không được công nhận: ap Mô phỏng được hỗ trợ: elf_i386 i386linux' . Tôi có sử dụng thông số chính xác không? (Phiên bản g ++: 4.4.2 20091208 (prerelease), phiên bản ld: 2.20.0.20091101) – Customizer

+0

Tôi đã cập nhật câu trả lời của mình. Phiên bản cục bộ của tôi vẫn ở 4.0.1 và có vẻ như các đối số đã thay đổi. Hãy thử 'g ++ foo.cpp -Wl, -M> foo.map'. –

+1

Chương trình C++ filt có thể được sử dụng để khử các tên. – Tronic

2

GCC-XML có thể giúp giải quyết typedefs, bạn phải làm theo các loại-id của <Typedef> yếu tố cho đến khi bạn giải quyết chúng vào một yếu tố <FundamentalType>, <Struct> hoặc <Class>.

Để thay thế typedef trong dự án của bạn, bạn có vấn đề cơ bản hơn: bạn không thể tìm kiếm và thay thế đơn giản vì bạn phải tôn trọng phạm vi tên - hãy nghĩ đến ví dụ: typedefs chức năng cục bộ, bí danh không gian tên hoặc using chỉ thị.

Tùy thuộc vào những gì bạn đang thực sự cố gắng đạt được, phải có cách tốt hơn.

Cập nhật: Thực tế, trong bối cảnh dữ liệu số liệu cố định, thay thế cho tên tệp bằng gcc-xml sẽ hoạt động tốt nếu nó hỗ trợ mã cơ sở của bạn.

+0

Tôi không chắc chắn, nhưng tôi nghĩ GCC-XML thực sự không tích cực phát triển nữa. Phiên bản chính thức cuối cùng, theo trang web, từ năm 2004. Và nếu tôi nhớ lại chính xác, phiên bản CVS chỉ dựa trên phiên bản 3.x của gcc. Tôi không thực sự biết, nếu điều đó quan trọng, mặc dù. Hmm, không gian tên. Chưa nghĩ về điều đó, thành thật mà nói. Điều đó làm phức tạp vấn đề ... – Customizer

+0

Tôi nghĩ bạn có nghĩa là thay thế các loại trong nguồn, điều đó sẽ trở nên phức tạp hơn. Tuy nhiên, nếu bạn chỉ cần sửa dữ liệu số liệu chứ không phải nguồn, gcc-xml phải đủ nếu nó hỗ trợ mã cơ sở của bạn. –

+0

Trên thực tế, tôi nghĩ rằng các dự án, tôi đang phân tích, tất cả nên được compilable bởi một gcc v. 3.x. Vì vậy, điều này có thể làm việc. – Customizer

3

Bạn có thể sử dụng Clang (trình biên dịch LLVM C/C++ front-end) để phân tích cú pháp mã theo cách bảo toàn thông tin trên typedef và thậm chí cả macro. Nó có một API C++ rất đẹp để đọc dữ liệu sau khi mã nguồn được đọc vào AST (cây cú pháp trừu tượng). http://clang.llvm.org/

Nếu bạn đang tìm kiếm một chương trình đơn giản đã giải quyết cho bạn (thay vì API lập trình Clang), tôi nghĩ bạn không may mắn vì tôi chưa bao giờ thấy một thứ như vậy.

+0

Tôi nghĩ clangs C++ parser chưa hoàn thành? –

+0

Việc tạo mã là khá không đầy đủ, nhưng nó có thể đã xử lý hầu hết thư viện chuẩn, cũng như nhiều thư viện bên ngoài. Trình phân tích cú pháp hoàn chỉnh hơn, nhưng thậm chí nó vẫn còn thiếu một vài thứ (vì vậy bạn không thể sử dụng nó, ví dụ như với Boost Spirit.Qi). Tuy nhiên, tôi nghĩ rằng nó có thể là lựa chọn tốt nhất có sẵn cho những gì Customizer đang yêu cầu. – Tronic

+0

API trông thực sự tuyệt vời. Tôi khá tò mò để thử nó khi nó trở nên ổn định. –

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