2012-04-03 11 views
6

Tôi đang phát triển cho một nền tảng nhúng và tôi đang gặp khó khăn khi tìm cách liên kết thư viện được chia sẻ động. Tôi đang sử dụng định dạng tệp bFLT và tôi không có quyền kiểm soát nơi thư viện thực thi và thư viện được chia sẻ được tải.Mã độc lập vị trí, thư viện chia sẻ và mã veneers - làm cho chúng hoạt động cùng nhau

Trình tải của tôi tải đúng thư viện được chia sẻ và thực thi vào bộ nhớ và sửa đổi GOT thực thi tại thời gian chạy để liên kết với thư viện được chia sẻ.

Tôi có thể thực hiện thành công địa chỉ của hàm và tôi biết chính xác là từ việc tháo mã tại vị trí đó. Tuy nhiên, nếu tôi cố gắng gọi hàm, toàn bộ sự cố sẽ bị treo.

Tắt GCC thêm 'mã vơ nia' khi gọi các hàm thư viện được chia sẻ và lấy đường vòng khi hàm được gọi và không thực sự phân nhánh đến địa chỉ của hàm. Địa chỉ mà các chi nhánh veneer mã không được định vị lại chính xác bởi vì nó không hiển thị trong danh sách các vị trí di chuyển trong tệp nhị phân thực thi.

Các tháo của veneer trông như thế này:

000008d0 <__library_call_veneer>: 
8d0: e51ff004 ldr pc, [pc, #-4] ; 8d4 <__library_call_veneer+0x4> 
8d4: 03000320 .word 0x03000320 ; This address isn't correctly relocated! 

Nhược bằng tôi lấy địa chỉ của hàm và đặt nó vào một con trỏ hàm (do đó, qua mặt 'mã veneer') và gọi nó, thư viện được chia sẻ hoạt động hoàn hảo.

Vì vậy, ví dụ:

#define DIRECT_LIB_CALL(x, args...) do { \ 
     typeof(x) * volatile tmp = x; \ 
     tmp(#args); \ 
    } while (0) 

DIRECT_LIB_CALL(library_call); /* works */ 
library_call(); /* crashes */ 

Có cách nào để một trong hai, nói với GCC để không tạo ra một veneer mã và chi nhánh trực tiếp đến địa chỉ nằm ở GOT hoặc bằng cách nào đó làm cho địa chỉ các chi nhánh đang veneer hiển thị trong danh sách các địa điểm để thực hiện?

+0

Bạn có khai báo các nguyên mẫu của thư viện bằng extern C không? –

+0

Tôi đang biên soạn dưới C để extern "C" sẽ được thừa sẽ không? – tangrs

+1

Veneers cần nhiều hơn hoặc ít hơn trên các hệ thống ARM, làm cho veneer là điều đúng đắn cần làm. Tuy nhiên, không cập nhật địa chỉ không ... Nhìn vào định dạng tệp của bạn, http://docs.blackfin.uclinux.org/doku.php?id=toolchain:executable_file_formats và http://docs.blackfin.uclinux.org /doku.php?id=toolchain:creating_libraries xuất hiện. Có vẻ như bạn có thể có ID thư viện được chia sẻ xung đột hoặc bạn có thể muốn sửa đổi cờ liên kết của mình (như được giải thích ở đó). Xin lỗi không thể giúp được nhiều hơn nữa –

Trả lời

2

Tôi đã tìm thấy giải pháp cho sự cố này. Nó không phải là phương pháp tốt nhất hoặc sạch nhất nhưng nó thực hiện công việc trong trường hợp của tôi.

Tôi đã tận dụng tùy chọn --wrap trong trình liên kết để chuyển hướng các ký hiệu đến __wrap_symbol. Với điều này, tôi thiết lập một kịch bản awk tự động tạo ra các tập tin ASM tải một địa chỉ di chuyển đúng vào máy tính. Mọi cuộc gọi thư viện sẽ được chuyển hướng đến mã này. Về cơ bản những gì tôi đã làm là tạo ra những đoạn mã của riêng tôi. Kể từ khi veneer mã được tạo ra đã không được tham chiếu, nó chỉ đơn giản là đã được tối ưu hóa đi.

Ngoài ra, tôi phải đặt veneers của tôi trong phần .data vì mọi thứ trong phần .text không được định vị lại chính xác. Kể từ đó, nền tảng tôi đang làm việc trên không phân biệt giữa mã và dữ liệu nhiều, công việc hacky này hoạt động.

Here's a link cho dự án Tôi đang nghiên cứu nơi bạn có thể tra cứu chi tiết cụ thể.

+0

Công việc tốt. Tôi sẽ gửi một yêu cầu tính năng cho các tác giả SDK homebrew để thêm hỗ trợ veneer thích hợp ... đó là một điều khá cơ bản cho nền tảng ARM vì những hạn chế của phân nhánh ... –