2009-10-29 24 views
7

Trên Windows, một số đối số được truyền cho constructor DllMain:Linux: Cách lấy tên đầy đủ của đối tượng được chia sẻ vừa tải từ hàm tạo?

BOOL WINAPI DllMain( 
    __in HINSTANCE hinstDLL, 
    __in DWORD fdwReason, 
    __in LPVOID lpvReserved 
); 

Từ hinstDLL Tôi có thể lấy tên đầy đủ hồ sơ của DLL bản thân sử dụng GetModuleFileName():

LPTSTR str = new TCHAR[256]; 
int libNameLength = GetModuleFileName(hinstDLL, str, 256); 
delete[] str; 

Trong ví dụ này ở trên, str bây giờ chứa tên đầy đủ của DLL vừa nạp, ví dụ: C: \ Windows \ System32 \ MyFile.dll.

Trên Linux, không có đối số được truyền cho các nhà xây dựng đối tượng chia sẻ:

void `__attribute__` ((constructor)) on_load(void); 

Làm thế nào để có được tên đầy đủ của DLL trong trường hợp này? Thêm tín dụng nếu giải pháp của bạn hoạt động trên Mac, quá. :-)

+0

Tôi không biết rằng có một cách hay. Câu hỏi của tôi trong các tình huống như thế này là "Tại sao bạn muốn biết?". Bằng cách lùi lại một cấp độ, bạn có thể thấy có một con đường dẫn đến mục tiêu thực sự của bạn mà không cần thực hiện bước mà hiện đang chặn bạn. – Omnifarious

+0

Câu hỏi hay. Tôi muốn biết, bởi vì tôi đang phát triển một CSP và một mô-đun PKCS # 11 (các tệp DLL) cả hai đều cần phải xác minh tính toàn vẹn của riêng chúng khi chúng được nạp. Cả hai tập tin DLL được tải bởi hệ điều hành, do đó, điểm vào của tôi là constructor. Hiện tại, ý tưởng tốt nhất tôi có để xác minh tính toàn vẹn của tệp DLL là tính toán giá trị băm của tệp DLL trong hàm tạo và sau đó gửi băm đó đến máy chủ trung tâm có thể xác minh tính chính xác của băm. Tuy nhiên, tôi cần tên tập tin của DLL để có thể tính toán băm. –

Trả lời

3

Tôi nghĩ rằng chức năng dladdr có thể làm những gì bạn muốn. Từ trang người đàn ông:

Hàm dladdr() lấy con trỏ hàm và cố gắng phân giải tên và tệp nơi đặt nó. Thông tin được lưu trữ trong cơ cấu Dl_info:

typedef struct { 
    const char *dli_fname; /* Pathname of shared object that 
           contains address */ 
    void  *dli_fbase; /* Address at which shared object 
           is loaded */ 
    const char *dli_sname; /* Name of nearest symbol with address 
           lower than addr */ 
    void  *dli_saddr; /* Exact address of symbol named 
           in dli_sname */ 
} Dl_info; 

Nếu không có biểu tượng phù hợp với addr có thể được tìm thấy, sau đó dli_snamedli_saddr được thiết lập để NULL.

dladdr() trả về 0 do lỗi và không phải thành công.

Vì vậy, bạn chỉ cần cung cấp cho nó một con trỏ hàm (giống như địa chỉ của bản thân hàm tạo), và nó sẽ cung cấp cho bạn tên tệp và một loạt thông tin khác. Dưới đây là một số mẫu mã:

#define _GNU_SOURCE 
#include <dlfcn.h> 
#include <stdio.h> 

__attribute__((constructor)) 
void on_load(void) { 
    Dl_info dl_info; 
    dladdr(on_load, &dl_info); 
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname); 
} 

EDIT: Có vẻ như chức năng này tồn tại trên OS X cũng vậy, với cùng một ngữ nghĩa.

+0

Câu trả lời hay, cảm ơn bạn rất nhiều! –

+0

Vâng, tôi rất vui vì cách mà cả hai chúng tôi nghĩ không phải là câu trả lời đúng. :-) – Omnifarious

+0

Phương pháp này không hoạt động trên Android: 'dli_fname' chỉ chứa tên tệp chứ không phải đường dẫn đầy đủ. – 18446744073709551615

1

Một cách cực kỳ xấu xí và kinh khủng để thực hiện việc này là xem qua/proc/pid/maps và tìm bản đồ bao gồm địa chỉ của hàm on_load đang được thực thi.

+1

Tôi bắt đầu đi xuống con đường này ngày hôm qua, và tôi đã không loại bỏ nó * hoàn toàn *, bởi vì nó hiện là giải pháp khả thi duy nhất mà tôi biết. Tuy nhiên, nó cũng làm ớn lạnh cột sống của tôi. –

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