3 Stimmen

Verwendung von Funktionszeigern zur Erstellung von Firmware-Patches in C?

Vor ein paar Jahren habe ich einen Blog gelesen (der Link ist inzwischen in Vergessenheit geraten) und sogar das Beispiel gesehen, wie die Funktionszeiger bei der Entwicklung des Patches für die Firmware in meiner früheren Organisation intensiv genutzt wurden.

Aber aus Sicherheitsgründen/NDA-Signatur konnte ich die Kopie des Codes nicht mitnehmen (und ich bin stolz darauf, dass ich das nicht getan und mich an bewährte Verfahren gehalten habe).

Ich habe gesehen, dass die Funktionen in einigen Namenskonventionen kodiert sind, wie zum Beispiel:

filename_func_<version>_<minor_string>(arguments,other arguments)

und ähnliche Dateien werden kodiert (Teil des Patches) und in das ROM geflasht, und wenn die Funktion aufgerufen wird, wird die Adresse der neuen Definition der Funktion vom Patch-Speicherort übernommen.

Gibt es dazu Ideen oder Details?

1voto

Jonathan Leffler Punkte 694013

Das System muss so konzipiert sein, dass dies funktioniert.

Es gibt verschiedene Aspekte, die koordiniert werden müssen:

  • Es muss eine Möglichkeit geben, die Funktionszeiger zu ändern.
  • Der Code muss die Funktionen über die Zeiger aufrufen.

Es gibt mehrere Möglichkeiten, dies im Detail zu tun, aber sie sind letztlich nur Varianten eines Themas.

/* Declaration of function pointer used to invoke the function */
extern int (*filename_func_ptr)(int arg1, char const *arg2);

/* Two versions of the function */
extern int filename_func_1_1(int arg1, char const *arg2);
extern int filename_func_1_2(int arg1, char const *arg2);

/* Definition of function pointer - pointing to version 1.1 of the function */
int (*filename_func_ptr)(int arg1, char const *arg2) = filename_func_1_1;

/* Use of function pointer */
static void some_function(void)
{
    printf("%d\n", (*filename_func_ptr)(1, "pi"));
}

Beachten Sie, dass Sie möglicherweise nie beides haben filename_func_1_1() y filename_func_1_2() in derselben Datei deklariert. Der Effekt, den ich beschreibe, ist "als ob".

Nach Parcheando, mit welchen Mitteln auch immer, ist das Ergebnis so, als hätten Sie das geschrieben:

int (*filename_func_ptr)(int arg1, char const *arg2) = filename_func_1_2;

Sie können Probleme mit dem dynamischen Laden bekommen ( dlsym() sowie dlopen() usw.), um die neuen Symbole zu erhalten. Das würde einen Dateinamen für die Bibliothek benötigen, um dynamisch zu laden, sowie eine Möglichkeit, die Funktionsnamen in Zeiger auf die richtigen Funktionen zu konvertieren.

Jede patchbare Funktion muss gleichmäßig über den Zeiger aufgerufen werden. Dies ermöglicht es Ihnen, die Funktion zu ersetzen. Überlegen Sie, ob eine dynamische (gemeinsam genutzte) Bibliothek ausreicht (weil sie wahrscheinlich einfacher ist). Wenn Sie mit Firmware arbeiten, können Sie sich diesen Luxus wahrscheinlich nicht leisten.

Sie müssen sich überlegen, wie Sie mehrere Funktionen mit unterschiedlichen Schnittstellen handhaben; werden Sie einzelne globale Variablen verwenden, wie hier gezeigt, oder einen generischen Funktionszeigertyp, der bei jedem Aufruf entsprechend gecastet werden muss, oder einen Unionstyp, oder eine Struktur, die Zeiger enthält, oder ...? Es gibt viele Möglichkeiten, die Dinge zu organisieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X