2013-09-05 14 views
10

Ich habe weit und breit für das, wie dies zu tun ist, und haben es versäumt, mit einer Antwort zu kommen.Linker-Skript - Platzieren eines Abschnitts am Ende einer Speicherregion

Mein Speicher-Layout ist wie folgt:

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

Am Ende des Stapels ich den Haufen legen. Was aufwächst und der Stapel ist ein vollständig absteigender Stapel für den ARM-Chip, den ich benutze.

Nun, was ich tun möchte, ist ein einzelner Abschnitt, nennen wir es .persist, in meinen RAM-Speicher. Ich möchte, dass es am Ende des RAM residiert, und ich möchte dies in mein Linker-Skript einprogrammieren. Diese .persist Abschnittsgröße wird jedoch nicht von mir definiert, sondern vom Compiler anhand der darin enthaltenen Symbole berechnet.

Bis jetzt habe ich keine gute Möglichkeit, es zu tun. Da ich die RAM-Startadresse und GRÖSSE kenne, wäre es trivial zu berechnen, wohin der Abschnitt gehen soll, wenn ich die Abschnittsgröße kenne. Doch nach the GNU linker documentation (pg 74) es scheint, dass:

SIZEOF (Abschnitt) Gibt die Größe in Bytes des benannten Abschnitt, wenn dieser Abschnitt zugeordnet ist. Wenn der Abschnitt bei der Auswertung nicht zugeordnet wurde, meldet der Linker einen Fehler.

so kann ich die Größe des Abschnitts im Linker-Skript nicht erarbeiten (da ich die Größe berechnen möchte, BEVOR ich es platziere/zuteile).

Kennt jemand einen guten Weg, dies zu tun?

+0

hatte ich das gleiche Problem. Hilft dir das? http://StackOverflow.com/a/19348569/911550 – parvus

+0

Es ist eine Teillösung, aber nicht das, was ich möchte. Es ist immer noch der nächste, dem irgendjemand sonst helfen wollte. Vielen Dank! – nonsensickle

Antwort

0

was ich tun möchte, ist ein einzelner Abschnitt, nennen wir es .persist, in meinen RAM-Speicher. Ich möchte, dass es am Ende des RAM residiert, und ich möchte dies in mein Linker-Skript einprogrammieren.

Linkers Skript hat spezielle Variable Location Counter genannt, die die aktuelle Adresse zu modifizieren erlaubt, und als solche die Größe oder die Adresse eines Abschnitts oder Symbol, die durch Lücken oder Löcher in dem Adressraum zu schaffen.

+0

Ja, ich bin mir dessen bewusst. Sie haben verpasst, was ich gesagt habe über den Operator 'SIZEOF', der Ihnen die Größe des Abschnitts ** nicht vorgibt, bis ** Sie * ihn * setzen. Ich muss die Größe des Abschnitts ** vor ** Ich lege es für die Arbeit. – nonsensickle

+0

Die einzige Problemumgehung wäre, wenn ich den Abschnitt platzieren könnte, die Größe bekommen und es dann verschieben und es woanders verschieben könnte ... – nonsensickle

0

Sie können Abschnitte an bestimmten Stellen erzwingen.

Zum Beispiel in dieser Dokumentation Linkers Red Hat GNU page, können Sie den .data Abschnitt definieren an der Adresse starten 0x8000000:

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

Ja, mir ist das bewusst. Dies erlaubt mir jedoch nicht, meinen Abschnitt so zu speichern, dass er * an einer bestimmten Adresse endet. Ich möchte die Größe meiner Sektion bekommen, subtrahiere sie von einer Adresse, die mir eine Ergebnisadresse gibt und lege sie dann an die Ergebnisadresse. Auf diese Weise kann ich meine Sektion, die eine variable Größe hat, ** am Ende ** meines RAM-Speicherblocks platzieren. Ich fand das nicht möglich und darum geht es in der Frage. – nonsensickle

5

konnte ich ähnliche, etwas zu erreichen, indem ein zweistufiger Prozess Verknüpfung machen . Zuerst kompiliere ich den betreffenden Abschnitt in eine eigene Objektdatei. In meinem Fall hatte ich einen Metadatenabschnitt, der aus einer Assemblydatei generiert wurde. gcc -c kompiliert die Quelle in Objektdateien, verbindet sie jedoch nicht.

gcc -c metadata.s -o metadata.o 

Sie können auch Ihr ganzes Programm bauen, dann mit objcopy nur den betreffenden Bereich extrahieren.

Jetzt baue ich und verbinde den Rest des Programms, und fügen Sie die Objektdatei unter die Linker-Eingabe.

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

Der Linker liest den Abschnitt .metadata aus der Objektdatei, und ich kann seine Größe in der Linker-Skript verweisen.

+0

Es ist lange her, seit ich das letzte Mal an diesem Projekt gearbeitet habe, aber deine Antwort scheint ihr am nächsten zu liegen. Ich werde es überprüfen müssen, bevor Sie es als richtig markieren, aber jetzt +1. – nonsensickle

0

hatte ich ein ähnliches Problem ich es auf diese Weise

/* 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

Obwohl ich dies in Erwägung zog, stellt sich die Frage nach der Platzierung eines Abschnitts am Ende von RAM, so dass das letzte Byte dieses Abschnitts die '_ram_end' Adresse einnimmt. Von dem, was ich sehen kann, platzieren Sie den Stapel am Ende des Widders und der Stapel belegt einfach alle verbleibenden Bytes. Ich möchte dies mit einem Abschnitt machen, der im Gegensatz zum Stapel eine statische Größe hat, die nicht von den Größen der anderen Abschnitte abhängt. In diesem Beispiel belegt Ihr Stack den gesamten verbleibenden Arbeitsspeicher im RAM. – nonsensickle