Forum: Mikrocontroller und Digitale Elektronik [C] Was bewirkt diese Zeile?


von Harry L. (Gast)


Lesenswert?

Moin,

kann mir jemand von euch "C" Spezies erklären, was diese Zeile bewirkt?
1
const char AppName[]  __attribute__((section(".Copyright"))) = APP_NAME "\0" "Version " APP_VERSION "\0" APP_COMPANY;

von Dr. Sommer (Gast)


Lesenswert?

Vermutlich sollen vorher APP_NAME, APP_VERSION und APP_COMPANY als 
Makros für Stringliterale definiert werden. Diese werden mit 0-Bytes als 
Trennzeichen zusammengehängt und in ein char-Array ("String") 
geschrieben. Dieses Array wird in die Linker Input Section ".Copyright" 
geschrieben, welche dann vom Linkerscript an eine bestimmte Position im 
Speicher gelegt werden kann.

von Harry L. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Dieses Array wird in die Linker Input Section ".Copyright"

Und was bewirkt das? Einfachere Handhabung? Aufruf?

von Dr. Sommer (Gast)


Lesenswert?

Harry L. schrieb:
> Und was bewirkt das? Einfachere Handhabung? Aufruf?

Kann man nicht pauschal beantworten. Möglicherweise soll so ermöglicht 
werden, dass man die entsprechende Stelle im Programmspeicher (Flash?) 
des Systems auslesen kann um die Programmversion zu ermitteln. Quasi als 
Embedded Äquivalent des Eigenschaften-Dialogs von .exe-Dateien im 
Windows Explorer. Ohne die extra Section würde der Linker das Array 
"irgendwo" in den Speicher packen und man würde es nicht so leicht 
finden.

von Harry L. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Harry L. schrieb:
>> Und was bewirkt das? Einfachere Handhabung? Aufruf?
>
> Kann man nicht pauschal beantworten. Möglicherweise soll so ermöglicht
> werden, dass man die entsprechende Stelle im Programmspeicher (Flash?)
> des Systems auslesen kann um die Programmversion zu ermitteln. Quasi als
> Embedded Äquivalent des Eigenschaften-Dialogs von .exe-Dateien im
> Windows Explorer. Ohne die extra Section würde der Linker das Array
> "irgendwo" in den Speicher packen und man würde es nicht so leicht
> finden.

Verstehe den Sinn nicht so ganz. Dafür hat man doch extra sein Array 
(AppName[])

von PPB (Gast)


Lesenswert?

Wenn das in einer extra section liegt, kann der Optimizer erkennen ob es 
verwendet wird oder nicht und dementsprechend rauskicken oder nicht.

von Dr. Sommer (Gast)


Lesenswert?

Harry L. schrieb:
> Verstehe den Sinn nicht so ganz. Dafür hat man doch extra sein Array
> (AppName[])

Wenn du nur den Controller vor der Nase hast oder auch nur eine binäre 
Flash-Image-Datei ("ROM") ohne Header, aber keine ELF-Datei (selbst der 
Source Code hilft hier nur bedingt) hast du keine Ahnung, wo im Flash 
der Linker das Array abgelegt hat. Daher kannst du von außerhalb des 
Programms (z.B. per Hex-Editor) das Array nur schwer finden und lesen.

PPB schrieb:
> Wenn das in einer extra section liegt, kann der Optimizer erkennen
> ob es
> verwendet wird oder nicht und dementsprechend rauskicken oder nicht.
Dazu würde man aber eher nicht das "section"-Attribut nutzen sondern die 
-fdata-sections Option.

von Nop (Gast)


Lesenswert?

Harry L. schrieb:

> Verstehe den Sinn nicht so ganz. Dafür hat man doch extra sein Array
> (AppName[])

Und jetrzt hast Du noch irgendein Configprogramm z.B. unter Windows, mit 
dem man die Firmware einspielen kann. Woran erkennt man jetzt die 
Firmware-Version? Kann man über den Dateinamen des Bin/Hexfiles machen 
und hoffen, daß der Dateiname auch wirklich immer den Inhalt richtig 
wiedergibt.

Man kann das Config-Programm aber auch direkt im Bin/Hexfile nachgucken 
lassen, dann ist der Dateiname egal. Dazu muß das Configprogramm aber 
auch wissen, an welcher Stelle der Datei es denn gucken soll.

von DPA (Gast)


Lesenswert?

PPB schrieb:
> Wenn das in einer extra section liegt, kann der Optimizer erkennen ob es
> verwendet wird oder nicht und dementsprechend rauskicken oder nicht.

Ich glaube nicht, dass das sinn der Sache war. Vermutlich wollten die 
schon __attribute__((section(".Copyright"),used)). Ich hab mir auch 
schon überlegt, ob ich nicht ein
1
#define N_STR_CONCAT(A, B) A ## B
2
#define LINKER_NOTICE(S,X) static const char N_STR_CONCAT( NOTICE_, __LINE__) []  __attribute__((section(".meta"),used)) = "<notice>\n  <file>" __FILE__ "</file>\n  <" #S "><![CDATA[\n" X "\n  ]]></" #S ">\n<notice>\n"
3
#define LICENSE(X) LINKER_NOTICE(license, X)

Und dann in den C Dateien:
1
LICENSE(
2
  "Copyright (C) 2019 Daniel Abrecht"  "\n"
3
  "\n"
4
  "This program is free software: you can redistribute it and/or modify" "\n"
5
  "it under the terms of the GNU General Public License as published by" "\n"
6
  "the Free Software Foundation, either version 3 of the License, or" "\n"
7
  "(at your option) any later version." "\n"
8
9
  "This program is distributed in the hope that it will be useful," "\n"
10
  "but WITHOUT ANY WARRANTY; without even the implied warranty of" "\n"
11
  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" "\n"
12
  "GNU General Public License for more details." "\n"
13
14
  "You should have received a copy of the GNU General Public License" "\n"
15
  "along with this program.  If not, see <https://www.gnu.org/licenses/>." "\n"
16
);

Dann könnte ich automatisiert die online Binaries nach danach 
durchsuchen:
1
abre2@PSTNABRE201:/mnt/c/Users/abre2$ objcopy -O binary -j .meta pr /dev/stdout
2
<notice>
3
  <file>pr.c</file>
4
  <license><![CDATA[
5
Copyright (C) 2019 Daniel Abrecht
6
7
This program is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18
  ]]></license>
19
<notice>

Und den OSS Dieben sagen: Hey, du hast meinen Code genutzt, du musst das 
Programm unter der GPL veröffentlichen.

von Dr. Sommer (Gast)


Lesenswert?

DPA schrieb:
> Dann könnte ich automatisiert die online Binaries nach danach
> durchsuchen:

Hinterhältig! Baue aber noch eine "verschlüsselte"/obfuskierte Version 
des Texts ein, damit den nicht einer zufällig findet und überschreibt. 
Am Besten noch mit Prüfsumme über das ganze Binary, welche beim Start 
geprüft wird... :-)

von DPA (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Baue aber noch eine "verschlüsselte"/obfuskierte Version
> des Texts ein, damit den nicht einer zufällig findet und überschreibt.

Eine UUID in einem Headerfile einbauen, oder eine Signatur mit einem 
Abstandpattern oder so, währe wohl noch OK.

> Am Besten noch mit Prüfsumme über das ganze Binary, welche beim Start
> geprüft wird...

Davon halte ich nichts. Ich bin ein strickter Gegner von DRM. Sowas 
führt nur zu Problemen, und schränkt auf technische weise die Rechte von 
Leuten ein, die sie Gesetzeswegen eigentlich gehabt hätten. Abgesehen 
davon, das sowas für das, was es gedacht war, nie funktioniert. Ich hab 
sogar noch irgendwo einen vorbereiteten Initiativtext herumliegen, um 
alle derartigen aktiv einschränkenden technischen Massnahmen in der 
Schweiz zu verbieten, hatte aber noch keine Zeit, das organisatorische 
durchzuplanen und die Initiative effektiv zu starten. Die Freiheiten 
aller natürlichen Personen zu Maximieren ist ein Grundsatz hinter vieler 
meiner Entscheidungen.

von Nop (Gast)


Lesenswert?

Dr. Sommer schrieb:

> Am Besten noch mit Prüfsumme über das ganze Binary, welche beim Start
> geprüft wird... :-)

Das macht man doch sowieso, schon damit man erkennen kann, ob der 
FW-Upload wirklich richtig funktioniert hat. Oder ob nach vielen Jahren 
der FW-Inhalt überhaupt noch richtig ist.

von Dr. Sommer (Gast)


Lesenswert?

DPA schrieb:
> Davon halte ich nichts. Ich bin ein strickter Gegner von DRM.

Da bin ich ganz bei dir. DRM z.B. bei Blu-Rays nützt im Endeffekt 
vermutlich niemandem. Allerdings ist das hier ja kein richtiges DRM - 
wenn die Software sowieso Open Source ist, kann man Modifikationen 
vornehmen. Es soll ja nur verhindert werden, dass sie jemand entgegen 
der Open-Source-Lizenz nutzt indem er z.B. nicht auf die Verwendung 
hinweist und eben den Urheberrechts-Hinweis entfernt.

Nop schrieb:
> Das macht man doch sowieso
Im Idealfall... ;-) Leider kann z.B. der GNU ld keine Checksums 
berechnen. Das macht die Sache etwas lästiger.

von Nop (Gast)


Lesenswert?

Dr. Sommer schrieb:

> Im Idealfall... ;-) Leider kann z.B. der GNU ld keine Checksums
> berechnen. Das macht die Sache etwas lästiger.

Dafür hat man nach Jahren der Entwicklung eh ein Tool im Fundus, was das 
mit dem fertigen Hexfile macht.

von Dr. Sommer (Gast)


Lesenswert?

Nop schrieb:
> Dafür hat man nach Jahren der Entwicklung eh ein Tool im Fundus, was das
> mit dem fertigen Hexfile macht.

Ist eine Möglichkeit, finde ich aber etwas unsauber. Ist natürlich 
besser als nichts.

von DPA (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Allerdings ist das hier ja kein richtiges DRM -
> wenn die Software sowieso Open Source ist, kann man Modifikationen
> vornehmen. Es soll ja nur

Das spielt für mich ehrlich gesagt keine rolle. Ob es jetzt OpenSource 
ist oder nicht, ob es einfach zu entfernen ist oder nicht, ob es ein 
anderes Verfahren ist oder nicht, ist aus meiner Sicht völlig 
irrelevant. Solange es existiert, bereitet es Probleme. Das Argument ist 
aber nicht unbeliebt, als die W3C EME eingeführt hat, argumentierten sie 
noch es sei kein DRM, sondern nur eine Schnittstelle für DRM. Oder bei 
vielen Games mit always online DRM wird einfach behauptet, die konstante 
Verbindung sei für die Funktion und Art des Games notwendig, und deshalb 
kein DRM. Gibt sicher noch weitere Beispiele.

von Nop (Gast)


Lesenswert?

Dr. Sommer schrieb:

> Ist eine Möglichkeit, finde ich aber etwas unsauber. Ist natürlich
> besser als nichts.

Ich find's deswegen sauber, weil das mit jedem Hexfile funktioniert, und 
weil man dann auch leicht sicherstellen kann, daß die CRC-Berechnung 
wirklich übereinstimmt.

CRC-Polynom, gedreht/nicht gedreht, mit/ohne Invertierung, Auffüllung 
mit FF oder 00, CRC in welcher Endianess, und was ist, wenn Host/Target 
unterschiedliche Endianess haben. Da gibt's soviele Freiheitsgrade, daß 
man sich damit lange beschäftigen kann.

Man kann so ein Tool dann sogar ins Makefile als notwendiges Target 
setzen, und wenn es nicht da ist, wird es eben erzeugt. Daß man dessen 
Source zusammen mit dem Projekt ablegen muß, ist ja klar.

Die Alternative mit dem Linker wäre auch nicht sauberer, weil man dann 
nämlich im Sourcetext Annahmen über das Linkerverhalten machen muß, was 
oftmals eine eher wackelige Sache ist und obendrein auch noch an einen 
spezifischen Compiler gebunden.

von Dr. Sommer (Gast)


Lesenswert?

Es schränkt aber eben nur die Möglichkeit des 
Open-Source-Lizenz-Verletzers ein, die Software entgegen der Lizenz zu 
benutzen und somit die Möglichkeiten der Gesamtheit zu beschränken - in 
Summe haben also mehr Leute was davon... Aber okay, da mittels 
Sourcecode der Hinweis ohnehin trivial entfernt werden kann, ist es 
sowieso irrelevant.

von Dr. Sommer (Gast)


Lesenswert?

Nop schrieb:
> Die Alternative mit dem Linker wäre auch nicht sauberer, weil man dann
> nämlich im Sourcetext Annahmen über das Linkerverhalten machen muß

Muss man beim externen Tool aber auch. Das muss die Prüfsumme an eine 
ganz bestimmte Stelle im Binary unterbringen - typischerweise irgendwo 
zwischen Interrupt-Vektor und eigentlichem Code.
Könnte man die Prüfsumme übers Linkerscript konfigurieren, kann man da 
zentral ihre Adresse angeben. Der Sourcecode muss sowieso Annahmen über 
das Linkerscript machen, um globale Variablen zu initialisieren o.ä. Er 
könnte die Adresse der Prüfsumme als Symbol benutzen.

Das nächste Problem ist: Will man eine ELF-Datei per JTAG-Debugger 
ausführen, muss die Prüfsumme da auch irgendwo rein. Wäre praktisch, 
wenn der Linker das direkt erledigen würde! Manuell in ELF-Dateien 
rumfummeln ist auch nicht so optimal.

von Nop (Gast)


Lesenswert?

Dr. Sommer schrieb:

> Muss man beim externen Tool aber auch.

Stimmt, aber wenn man dessen Source hat, ist das ja kein Problem.

> Das muss die Prüfsumme an eine
> ganz bestimmte Stelle im Binary unterbringen - typischerweise irgendwo
> zwischen Interrupt-Vektor und eigentlichem Code.

Oder am Ende, wobei dann die aufgefüllte Binary-Länge bekannt sein muß, 
normalerweise als Konstante im Makefile. Das kriegt das Tool dann als 
CLI-Parameter und der Sourcecode per Define im Compiler-Aufruf.

> Das nächste Problem ist: Will man eine ELF-Datei per JTAG-Debugger
> ausführen, muss die Prüfsumme da auch irgendwo rein.

Stimmt, das ist nicht so schick. Solange die Prüfsumme nur zur 
Diagnostik genutzt wird, ist es egal, dann kommt eben eine Meldung. 
Ansonsten kenne ich das so, daß es irgendwo ein Debug-Define gibt, mit 
dem dann auch die Checksumme überbrückt wird. Braucht man ja eh, um z.B. 
den Watchdog abzuschalten.

Aber wenn man CRC-32 nimmt, sagt man damit ja schon aus, daß das eh 
nicht für DRM gedacht ist. Um nachzuweisen, daß der Code von einem 
selber ist, etwa für GPL-Abmahnungen bei Lizenzverletzung, würde man 
eher unschuldig aussehende Sachen irgendwo zusammenbauen. Eventuell 
Autorenname und GPL-Hinweis mit ROT-13 noch versehen.

von Dr. Sommer (Gast)


Lesenswert?

Nop schrieb:
> normalerweise als Konstante im Makefile.

Die ändert sich doch ständig, wenn man den Code ändert. Und länger als 
nötig muss man ein Image auch nicht machen...

Nop schrieb:
> Ansonsten kenne ich das so, daß es irgendwo ein Debug-Define gibt, mit
> dem dann auch die Checksumme überbrückt wird.
Ginge auch. Leider bleiben oft Debug-Images dann doch oft länger als 
gedacht auf dem Controller - man müsste zusätzlich abfragen, ob ein 
Debugger angeschlossen ist, und wenn nicht die Arbeit verweigern (geht 
beim Cortex-M zum Glück).

Nop schrieb:
> Aber wenn man CRC-32 nimmt, sagt man damit ja schon aus, daß das eh
> nicht für DRM gedacht ist.
Stimmt, guter Punkt.

von DPA (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Es schränkt aber eben nur die Möglichkeit des
> Open-Source-Lizenz-Verletzers ein

Die Anforderung ist schlicht nicht erfüllbar, so funktioniert die 
Realität nicht. Code, der die Nutzbarkeit eines Programs oder sonst was 
einschränken soll, deckt zwangsläufig nicht alle fälle ab, das ist 
schlicht nicht möglich. Beim ersten unvorhergesehenen Umstand, Fehler, 
umgekipptem Bit, etc. sagt sowas Stop, und auch wenn man das jetzt 
umgehen kann, das ist für den Nutzer erstmal ein Problem.

Ausserdem ist es auch nicht möglich, Gesetze eindeutig und alle fälle 
abdeckend zu Kodieren. Was erlaubt ist und was nicht, ist je nach 
Jurisdiktion unterschiedlich. Nicht alles was in den Lizenzen steht, 
gilt auch in allen fällen. Zudem ist die Entscheidung, was gesetzlich 
erlaubt ist und was nicht, letztendlich Sache der Gerichte, und nicht 
des Entwicklers des DRM oder der Anwendung. Das Durchsetzen von Gesetzen 
ist auch Sache des Rechtssystems, und nicht die unsere. Aus meiner sicht 
stellt es sich so dar, dass man mit DRM letztendlich das Gesetz in die 
eigene Hand nimmt, eigene Gesetze (aka. Regeln) macht, und das 
Rechtsystem umgeht. Ich kann dir ein Messer verkaufen unter der Auflage, 
du darfst damit keine Äpfel schneiden. Rechtlich gesehen ist es dann 
aber dann normalerweise trotzdem dein Messer, und du darfst trotzdem 
Äpfel damit schneiden. Du siehst das Problem? Eigeninteresse macht dich 
nicht zum Richter.

von DPA (Gast)


Lesenswert?

Dr. Sommer schrieb:
> die Software entgegen der Lizenz zu benutzen und somit die Möglichkeiten der 
Gesamtheit zu beschränken -

Das letztere folgt aber nicht aus ersterem, ganz im gegenteil.

> in Summe haben also mehr Leute was davon

Ich sehe nicht, wer davon was haben soll. Eine technische Einschränkung 
ist eine Einschränkung ist eine Einschränkung. Wenn ich als natürliche 
Person etwas nicht tun kann, ist das immer ein Minderwert, und kein 
Mehrwert.

von Nop (Gast)


Lesenswert?

DPA schrieb:
> Wenn ich als natürliche
> Person etwas nicht tun kann, ist das immer ein Minderwert, und kein
> Mehrwert.

Wenn der Entwickler vor Dir nicht die Möglichkeit hatte, sich 
Opensource-Code zu nehmen, den etwas umzubauen und ihn dann closed zu 
machen, sondern ihn ebenfalls als open freigeben MUSSTE, dann bringt das 
Dir mehr Möglichkeiten. Deswegen gibt's die GPL ja.

von DPA (Gast)


Lesenswert?

Nop schrieb:
> DPA schrieb:
>> Wenn ich als natürliche
>> Person etwas nicht tun kann, ist das immer ein Minderwert, und kein
>> Mehrwert.
>
> Wenn der Entwickler vor Dir nicht die Möglichkeit hatte, sich
> Opensource-Code zu nehmen, den etwas umzubauen und ihn dann closed zu
> machen, sondern ihn ebenfalls als open freigeben MUSSTE, dann bringt das
> Dir mehr Möglichkeiten. Deswegen gibt's die GPL ja.

Hier macht das tun Können und das Dürfen einen grossen unterschied. Ich 
kann GPL Code in nicht legaler weise verwenden, ich bin frei das zu tun. 
Ich darf es nur nicht, im Idealfall wird der Rechtsweg gegangen, und 
dann muss man eben die Konsequenzen tragen.

Andererseits kann ich den GPL Code auch rein Privat nutzen, ohne je 
irgendwas zu veröffentlichen, und es gibt nichts, dass das verbieten 
oder verhindern würde.

Das ist das Schöne am Rechtssystem. Es verhindert nicht, das man etwas 
tun kann oder könnte, dafür ist es nicht da. Unrechtmässiges hat immer 
noch Konsequenzen, aber ich bin frei, unrecht zu tun. Meine Freiheit ist 
nicht über das hinaus eingeschränkt, was erlaubt oder notwendig wäre, 
aber meine Rechte sind dennoch, soweit vertretbar, sichergestellt.

Das ist der Grund, warum es hier keinen Minderwert gibt, es gibt keine 
Einschränkung, was ich tun kann. Dennoch sind die Ansprüche aller 
sichergestellt. Jeder bekommt, was er sich ausgesucht hat.

von Stefan K. (stefan64)


Lesenswert?

Der Vorteil einer CRC und Programmgröße in einer Section am Anfang des 
Binary ist eine kürzere Programmierzeit durch den Bootloader, wenn das 
Flash nur teilweise belegt ist.
Wir verwenden solche Sections auch, um die Version des Bootloaders und 
der Anwendungsfirmware an festen Adressbereichen zu speichern. Damit 
kann z.B. die Firmware auslesen, welcher Bootloader Version im System 
vorhanden ist.

Viele Grüße, Stefan

von zitter_ned_aso (Gast)


Lesenswert?

Warum werden  die einzelnen "Strings" mit "\0" miteinander verkettet?
1
#define STR1 "eins"
2
#define STR2 "zwei"
3
#define STR3 "drei"
4
5
char str[]=STR1 "\0" STR2 "\0" STR3 "\0";
6
puts(str);

wird ja nur "eins" ausgeben. Warum nicht STR1 " " STR2 " " STR3 "\0"?

von Axel S. (a-za-z0-9)


Lesenswert?

zitter_ned_aso schrieb:
> Warum werden  die einzelnen "Strings" mit "\0" miteinander verkettet?

Damit man sie sauber voneinander trennen kann?

>
1
> puts(str);
2
>
>
> wird ja nur "eins" ausgeben.

Ja. Und? Die Strings stehen da nicht zu dem Zweck, mit puts() oder 
anderweitig ausgegeben zu werden.

> Warum nicht STR1 " " STR2 " " STR3

Weil ein Leerzeichen kein eindeutiger Trenner ist?

Das ist eine Signatur. Die hat den Zweck, daß man das Flash-Image 
automatisch zuordnen kann. Welche App da drin ist, welche Version, von 
welchem Anbieter. Für einen Menschen könnte man das einfach als 
String-Konstante in das Programm packen; die würde dann irgendwo im 
Image stehen und ein Mensch könnte sie durch scharfes Hinsehen, evtl. 
mit der Hilfe des "strings" Kommandos finden.

Aber wenn das ein Programm erledigen soll, vielleicht gar ein 
minimalistisches Programm wie ein Bootloader, dann sollte die Signatur 
besser an einer genau definierten Stelle im Image stehen. Deswegen die 
extra Memory-Sektion.

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.