2013-09-05 29 views
10

Tôi đã tìm kiếm rất xa và rộng để biết cách thực hiện điều này và không thể đưa ra câu trả lời.Trình liên kết tập lệnh - Đặt một phần ở phần cuối của vùng bộ nhớ

bố trí bộ nhớ của tôi là như sau:

Fake Address | Section 
    0  | text 
    7  | relocate 
    15  | bss 
    23  | stack 

Vào cuối Stack Tôi đặt Heap. Mà lớn lên và ngăn xếp là một ngăn xếp giảm dần đầy đủ cho chip ARM tôi đang sử dụng.

Bây giờ, những gì tôi muốn làm là đặt một phần duy nhất, hãy gọi nó là .persist, vào bộ nhớ ram của tôi. Tôi muốn nó nằm ở phần cuối của RAM và tôi muốn chương trình này vào kịch bản linker của tôi. Tuy nhiên, kích thước của phần .persist này không được định nghĩa bởi tôi nhưng được tính toán bởi trình biên dịch từ các biểu tượng mà nó chứa.

Cho đến giờ tôi chưa nghĩ ra cách tốt để làm điều đó. Vì tôi biết địa chỉ khởi động RAM và SIZE nó sẽ là tầm thường để tính toán nơi mà phần cần phải đi nếu tôi biết kích thước phần. Tuy nhiên, theo the GNU linker documentation (pg 74) có vẻ như rằng:

sizeof (phần) Trả về kích thước tính bằng byte của tên phần, nếu phần đó đã được phân bổ. Nếu phần không được phân bổ khi đánh giá phần này, trình liên kết sẽ báo cáo lỗi.

vì vậy tôi không thể làm việc với kích thước của phần trong tập lệnh trình liên kết (vì tôi muốn tính kích thước TRƯỚC KHI tôi đặt nó/phân bổ nó).

Có ai biết cách tốt để làm điều này không?

+0

Tôi có cùng một vấn đề. Điều này có giúp bạn không? http://stackoverflow.com/a/19348569/911550 – parvus

+0

Đó là một giải pháp một phần nhưng không phải là những gì tôi theo sau. Nó vẫn là người gần nhất đã đến giúp đỡ. Cảm ơn! – nonsensickle

Trả lời

0

những gì tôi muốn làm là đặt một phần, hãy gọi nó là .persist, vào bộ nhớ ram của tôi. Tôi muốn nó nằm ở phần cuối của RAM và tôi muốn chương trình này vào kịch bản linker của tôi.

Kịch bản liên kết có biến đặc biệt được gọi là Location Counter cho phép thay đổi địa chỉ hiện tại và kích thước hoặc địa chỉ của phần hoặc ký hiệu bằng cách tạo khoảng trống hoặc lỗ hổng trong không gian địa chỉ.

+0

Vâng, tôi biết điều này. Bạn đã bỏ lỡ những gì tôi đã nói sau khi về toán tử 'SIZEOF' không cho bạn kích thước của phần ** cho đến khi ** bạn * đặt nó *. Tôi cần phải nhận được kích thước của phần ** trước khi ** Tôi đặt nó để làm việc này. – nonsensickle

+0

Cách giải quyết duy nhất sẽ là nếu tôi có thể đặt phần, lấy kích thước và sau đó unplace nó và di chuyển nó ở nơi khác ... – nonsensickle

0

Bạn có thể bắt buộc các phần tại các vị trí cụ thể.

Ví dụ trong tài liệu hướng dẫn này Red Hat GNU Linker page, bạn có thể xác định phần .data để bắt đầu tại địa chỉ 0x8000000:

SECTIONS 
{ 
    . = 0x10000; 
    .text : { *(.text) } 
    . = 0x8000000; 
    .data : { *(.data) } 
    .bss : { *(.bss) } 
} 
+0

Vâng, tôi biết điều này. Tuy nhiên, điều này không cho phép tôi lưu trữ phần của tôi để nó * kết thúc tại một địa chỉ cụ thể *. Tôi muốn có được kích thước của phần của tôi, trừ nó từ một địa chỉ cho tôi một địa chỉ kết quả và sau đó đặt nó tại địa chỉ kết quả. Bằng cách này tôi có thể đặt phần của tôi, trong đó có một kích thước biến, ** ở cuối ** của khối bộ nhớ RAM của tôi. Tôi thấy điều này là không thể và đó là câu hỏi. – nonsensickle

5

tôi đã có thể hoàn thành một cái gì đó tương tự bằng cách liên kết một quá trình hai bước . Đầu tiên tôi biên dịch phần được đề cập đến tệp đối tượng của chính nó. Trong trường hợp của tôi, tôi đã có một phần siêu dữ liệu được tạo ra từ một tập tin lắp ráp. gcc -c sẽ biên dịch nguồn thành các tệp đối tượng, nhưng không liên kết chúng.

Bạn cũng có thể tạo toàn bộ chương trình, sau đó chỉ trích xuất phần được đề cập với objcopy.

gcc -c main.cc -o main.o 
objcopy --only-section=.metadata main.o metadata.o 

Bây giờ tôi tạo và liên kết phần còn lại của chương trình và bao gồm tệp đối tượng trong đầu vào của liên kết.

gcc metadata.o ../main.o -o Program.elf -T linkerscript.ld 

Trình liên kết đọc phần .metadata từ tệp đối tượng và tôi có thể tham chiếu kích thước trong tập lệnh liên kết.

+0

Đã lâu rồi tôi mới làm việc trong dự án này nhưng câu trả lời của bạn dường như là gần nhất để làm cho nó có thể. Tôi sẽ phải xác minh nó trước khi đánh dấu là chính xác nhưng bây giờ là +1. – nonsensickle

0

Tôi đã có một vấn đề tương tự tôi đã làm nó theo cách này

/* heap section */ 
.heap (NOLOAD): 
{ 
    . = ALIGN(8); 
    _sheap = .; 
    . = . + HEAP_SIZE; 
    . = ALIGN(8); 
    _eheap = .; 
} > ram 

_ram_end_ = ORIGIN(ram) + LENGTH(ram) -1 ; 
_stack_size = _ram_end_ - _eheap ; 

/* stack section */ 
.stack (NOLOAD): 
{ 
    . = ALIGN(8); 
    _sstack = .; 
    . = . + _stack_size; 
    . = ALIGN(8); 
    _estack = .; 
} > ram 

.LastSection (NOLOAD): /* for test in dump file */ 
{ 
    . = ALIGN(8); 
} > ram 
+0

Mặc dù tôi đã xem xét câu hỏi này là yêu cầu vị trí của một phần ở cuối ram sao cho byte cuối cùng của phần đó chiếm địa chỉ '_ram_end'. Từ những gì tôi có thể thấy bạn đang đặt ngăn xếp ở cuối ram và ngăn xếp đơn giản chiếm tất cả các byte còn lại. Tôi yêu cầu làm điều này với một phần mà, không giống như ngăn xếp, có kích thước tĩnh mà không phụ thuộc vào kích thước của các phần khác. Có hiệu quả, trong ví dụ này, ngăn xếp của bạn chiếm toàn bộ bộ nhớ còn lại trong RAM. – nonsensickle

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