Forum: Mikrocontroller und Digitale Elektronik Checksum GNU-Linker


von Daniel_s (Gast)


Lesenswert?

Hallo zusammen

Ich möchte gerne in einem Programm zur Laufzeit verifizieren, ob ein 
Programmcode noch richtig im Flash steht. Dies würde ich gern mit einer 
Checksum über das Programmsegment machen. Nun wollte ich fragen ob es in 
der GNU-Toolchain eine Option gibt, die den Linker veranlasst an einer 
bestimmten Stelle im Programmcode diese Checksum zu schreiben. Ich bin 
für alle Anregungen dankbar.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Die Toolchain selbst nicht, aber du kannst sowas immer noch nachher
machen -- im Zweifelsfalle erst auf der Ebene der Hex-Datei.

Zweistufig geht es auch mit dem Linker: du erfindest eine eigene
section für die Prüfsumme, die du mit einem einzelnen Symbol belegst.
Im ersten Linkerdurchlauf setzt du dieses Symbol erstmal auf 0 (damit
es überhaupt belegt ist) und linkst alles zusammen.  Danach berechnest
du für den dich interessierenden Teil (text oder text + data) die
Prüfsumme und linkst das Ganze nochmal.  Diesmal gibst du die
ermittelte Prüfsumme dem Linker über die Option --defsym mit, damit
es das spezielle Symbol auf ebendiesen Wert setzt und selbigen dann
in die zugehörige section einträgt.

von Daniel_s (Gast)


Lesenswert?

Ja wenn ich das nur ein mal nach Beendigung aller Entwicklungsarbeit 
machen müsste wär das schon gut. Leider ist es Teil einer Entwicklung 
die noch nicht abgeschlossen ist und an der mehrere mitarbeiten und so 
müsste man nach jeder Änderung von Hand die Checksumme berechnen und 
eingeben.

Der Linker XLINK von IAR hat eine Option die genau das ermöglicht. 
Leider siehts bei Gnu schlecht aus. Oder täusche ich mich?

von Εrnst B. (ernst)


Lesenswert?

Warum? Jörg hat doch grad beschrieben wie das geht.

Einfach diese Schritte ins Makefile einbinden, => bei jeden neuen Build 
wird automatisch die Checksum neu berechnet und eingebunden.

von Daniel_s (Gast)


Lesenswert?

Danke Jörg für den Tip. Hab erst jetzt gesehen, dass du noch mehr 
geschrieben hattest.

Das zweistufige ist schon ganz gut. Das Problem ist halt, dass man immer 
mit einem externen Programm die CRC berechnen muss. Aber es wird wohl 
nicht anders gehen

von Daniel_s (Gast)


Lesenswert?

Ja das stimmt, in ein MAkefile könnte man das einbinden. Ich benutzte 
halt die IDE von Anglia und da gibts wohl kein makefile im eigentlichen 
Sinne. Ich schau mal ob man das zweistufige vorgehen irgentwie sonst 
einbinden kann. Sonst muss ich ein makefile machen

von Siddhartha (Gast)


Lesenswert?

Hallo zusammen

ich weiss der Thread ist schon einige Monate alt, aber da er genau das 
Thema behandelt, das mich beschäftigt, wollte ich nicht extra einen 
neuen aufmachen.

Also ich will ebenfalls beim Compilieren ganz am Ende des Codes einen 
CRC16 einfügen. Ich benutze die GNU ARM Toolchain von Yagarto.
Ich führe zuerst arm-elf-gcc aus und lasse alles kompilieren und linken. 
Ein kleines Tool, das den CRC berechnet habe ich bereits geschrieben und 
wollte dann im Makefile mit --defsym (wie oben empfohlen) den 
berechneten CRC-Wert des vorher generierten BIN-Files nochmals an den 
Linker übergeben. Doch irgendwie wird der CRC-Wert von meinem 
Linker-Script nicht angenommen bzw nicht richtig 
interpretiert/verwendet. Irgendwie habe ich das Gefühl, dass ich die 
--defsym Option falsch verstanden habe.

Die ensprechende Zeile in meinem Makefile sieht folgendermassen aus:
1
arm-elf-gcc $(LDFLAGS) -Xlinker --defsym -Xlinker CRC16=0x$(shell crc16 $(OUTFILE).bin) -n -o $(OUTFILE).elf $(OBJECTS)
2
arm-elf-objcopy --strip-debug --strip-unneeded $(OUTFILE).elf -O binary $(OUTFILE).bin

(Zwischenfrage: Wird bei solch einem Aufruf nochmals alles neu 
kompiliert oder direkt der Linker aufgerufen?)

Im Linker-Script sieht es folgendermassen aus (nur der relevante Teil):
1
...
2
__CRC_START__  = 0x03FFFE; /* 2 Bytes for Flash-Ende */
3
PROVIDE(CRC16 = 0x0000)
4
5
SECTIONS
6
{
7
    ...
8
    
9
    crc : AT( __CRC_START__)
10
    {
11
        SHORT(CRC16);
12
    } = 0xFFFFFFFF
13
14
    ...
15
}

Komischerweise steht im MAP File dann folgendes:
1
crc             0x0020adfc        0x2 load address 0x0003fffe
2
                0x0020adfc        0x2 SHORT 0x0 CRC16
3
                0x0020adfe                PROVIDE (end, .)
4
                0x0000d8ca                CRC16 = 0xd8ca

Also irgendwie kriegt er den Wert zwar, aber er interpretiert ihn direkt 
als Adresse und nicht irgendwie als Variable.

Ich wäre sehr froh, wenn mich jemand aufklären könnte, ob ich das 
Konzept mit --defsym komplett falsch verstanden habe oder ob ich einfach 
sonst einen Newbie-Fehler gemacht habe.

Danke!
Mit freundlichen Grüssen

Siddhartha

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.