Tôi muốn tạo một tệp mà tôi có thể tải vào bộ nhớ (ví dụ: mmap
) và sau đó chuyển đến đầu bộ nhớ đó để chạy mã. Lý tưởng nhất, tôi muốn tùy chọn làm cho mã có thể relocatable (có thể không hiệu quả) hoặc chỉ định một địa chỉ rõ ràng rằng mã dự kiến sẽ được tải tại (đó là một cơn đau), nhưng một trong hai có lẽ sẽ hoạt động tự mình làm tốt.Cách tạo gcc chỉ tạo mã máy có thể được tải trực tiếp vào bộ nhớ và được thực thi?
Trả lời
Bạn có thể thực hiện việc này nhưng bạn sẽ cần thực hiện định dạng tệp đối tượng. Cụ thể, lệnh objcopy
có thể chuyển đổi tệp thi hành thành tệp nhị phân "phẳng" (tùy thuộc vào nền tảng đích của bạn). Có lẽ một cái gì đó như thế này:
gcc -o test test.c
objcopy -O binary test test.bin
Xem man objcopy
trên nền tảng của bạn để biết thêm chi tiết.
+1, tôi biết có cái gì đó đã làm điều này .Bạn có biết tôi có cần tải cái này tại một địa chỉ cụ thể không? –
Có, bạn sẽ. Đó sẽ là địa chỉ mà người liên kết được yêu cầu liên kết tại. Lưu ý rằng bạn thường không thấy tệp kiểm soát của liên kết, vì vậy bạn có thể không biết địa điểm đó ở đâu .... – RBerteig
Tôi sẽ tìm tệp kiểm soát ở đâu? –
Bạn muốn biết về tiện ích objcopy
, thường có sẵn cùng với GCC. Nó là một thành phần của gói công cụ binutils, thành viên dễ thấy nhất trong số đó là trình liên kết, ld
.
Quá trình này là bạn biên dịch (các) tệp nguồn của bạn và liên kết chúng như thường lệ. Điều đó cung cấp cho bạn một tệp thực thi đã hoàn tất trong định dạng nhị phân elf (hoặc một dạng nhị phân phụ thuộc vào nền tảng khác). Sau đó, bạn sử dụng objcopy để chuyển đổi tệp thực thi thành hình ảnh nhị phân phẳng. Điều này hữu ích nhất khi chuẩn bị mã chạy từ ROM, nơi bạn muốn đảm bảo rằng bạn đang sử dụng thư viện thời gian chạy C phù hợp cho nền tảng đích của bạn, và có thể cần tùy chỉnh tệp tập lệnh liên kết cũng như cung cấp mã khởi động thời gian chạy C của riêng bạn.
Nếu mục tiêu của bạn là lấy thứ gì đó giống như tệp .so, được tải vào quy trình hiện có, hãy lưu ý rằng một số công việc của trình tải thư viện được chia sẻ thực sự kết thúc liên kết trong tệp .so đề cập đến địa chỉ trong tệp thực thi chính (hoặc các tệp .so khác) được giải quyết khi tải. Sử dụng objcopy sẽ không làm điều đó, và do đó nó có thể là khó khăn cho các chức năng nạp theo cách này để sử dụng đúng thư viện thời gian chạy C hiện tại của bạn và các đối tượng nó duy trì như các tập tin mở.
Bất kể mục tiêu của bạn là gì, bạn sẽ cần phải nắm quyền kiểm soát của trình liên kết để xác định vị trí nhị phân của bạn tại địa chỉ đã biết. Để làm điều đó, bạn sẽ cần phải tạo một kịch bản liên kết. Tài liệu cho ngôn ngữ kịch bản nằm trong the binutils manual. Bạn sẽ chủ yếu quan tâm đến các phần ".tiếp theo *" và có thể trong phần ".rodata *" nếu bạn dự định có bất kỳ biến toàn cầu được khởi tạo nào. Trên thực tế sắp xếp cho khởi tạo đó là trái như là một bài tập cho người đọc.
Nhìn chung, đây chỉ là đỉnh của một tảng băng trôi rất lớn. Tôi muốn đề nghị dành một chút thời gian với một trình biên dịch chéo để xem những thứ này được sử dụng như thế nào trong thực tế. Các cộng đồng AVR và MSP430 sử dụng GCC, có sự tham gia tích cực và phần cứng rẻ tiền (và thậm chí cả nguồn mở) để bắt đầu.
không phải đây là tệp đối tượng? – aaronasterling
không, ít nhất, các tệp đối tượng chứa thông tin về những biểu tượng mà chúng xuất (để sử dụng bởi trình liên kết) –
Bất kỳ lý do cụ thể nào mà bạn không muốn sử dụng thư viện dll/shared thay vào đó? Có một * rất nhiều cạm bẫy với các tệp nhị phân thô. – snemarch