Fork me on GitHub Fork me on GitHub

uninformativ.de

GNU, Linux, Shell und Co.

Assembler: Calling Conventions und Syscalls bei 32 und 64 Bit

Pingu-Avatar

05.04.2013, 18:40:40

Ein Funktionsaufruf in C sieht nicht spektakulär aus:

retval = foo(arg, bla, blubb);

Auf Assembler-Ebene gibt es zwar das Instruktionspaar „call“ und „ret“, mit denen man komfortabel in eine andere Stelle im Code und zurück springen kann. Aber einen festen Mechanismus, wie man dabei Parameter übergeben kann, gibt es nicht. Deswegen muss man sich auf einen sinnvollen Weg einigen – und das regeln die Calling Conventions.

Diese Konvention unterscheidet sich nicht nur von Betriebssystem zu Betriebssystem, sondern bei GNU/Linux auch zwischen 32 und 64 Bit. Zusätzlich muss man unterscheiden, ob es sich um einen Syscall handelt, ich also direkt mit dem Kernel spreche, oder ob es einfach nur ein Codesprung im Userland ist. Für ersteres gibt der Kernel ein Interface vor und ein Syscall ist auch etwas grundsätzlich anderes als ein Funktionsaufruf – auch wenn im highlevel C-Code beide Dinge gleich wirken mögen (Fußnote: Es sieht nur an der Oberfläche gleich aus, weil die libc alles kapselt). Im Userland könnte ich aber in meinem eigenen Code theoretisch machen, was ich möchte. Spätestens dann, wenn mein Code mit dem anderer Leute interagieren soll (prominentes Beispiel libc), muss ich mich aber auch hier an die Konvention halten.

Im Folgenden jeweils für 32 und 64 Bit die Calling Conventions für das Userland und der Syscall-Mechanismus. Andere Systeme als GNU/Linux werden nicht betrachtet. Gedacht unter anderem als Merkzettel für mich.

[…]

Lizenz-Foo

Pingu-Avatar

05.03.2013, 22:05:30

In Anbetracht des Unsinns, der ohnehin generell und momenten beim sogenannten „Leistungsschutzrecht“ passiert, verkünde ich hiermit, dass die Inhalte (Texte, Bilder, …) dieser Webseite analog zu den jüngsten Code-Projekten als PIZZA-WARE veröffentlicht sind:

Im Klartext heißt das: „Setz’ ’ne Quellenangabe. Darüberhinaus: Mach’, was du willst. Die Pizza ist optional.“

Ich bin eigentlich ziemlich müde, darüber nachzudenken, was unter welcher Lizenz steht. Eigentlich möchte ich, wenn ich irgendwas interessantes finde, am liebsten damit machen, was auch immer ich will. Texte in beliebigen Längen zitieren, Bilder und Musik weiterverarbeiten, an Code schrauben und so weiter. Wenn etwas besonders toll ist, dann schicke ich ein Dankeschön zurück – in welcher Form auch immer. In unzähligen Fällen funktioniert das auch prächtig und durch die vielen freien Inhalte wurde mein Leben drastisch vereinfacht und verbessert.

Analog soll das mit dem Kram, den ich veröffentliche, auch gemacht werden können. Nach meinem Verständnis ist sowas wie PIZZA-WARE das offenste und freiste, was nach deutschem Recht möglich ist. Sollte es etwas geben, das noch weniger Widerstand als PIZZA-WARE erzeugt (eine Quellenangabe setzt ein anständiger Mensch von sich aus und alle anderen kümmert es eh nicht), dann immer her damit.

Ich bin ein Freund des Copyleft, aber es ist mir zu kompliziert geworden. Es gibt zu viele verschiedene Formen davon, manche harmonieren, andere nicht. Und im beruflichen Kontext habe ich schon das eine oder andere Tool nicht verwenden können dürfen, weil die Lizenz irgendeine Form des Copyleft erforderte. Die Folge war dann, dass ich etwas minderwertiges verwenden oder den Code nochmal selbst schreiben musste. Ätzend.

Wenn jemand mein Zeug verwenden will, dann soll er das nach Lust und Laune tun können, ohne über Lizenzmüll nachdenken zu müssen. Wozu habe ich es sonst online gestellt? Wie wertvoll das, was ich so rausblase, tatsächlich ist, sei dahingestellt – es geht hier ums Prinzip. :-)

Git: Wie sah eine Datei damals aus?

Pingu-Avatar

24.02.2013, 11:39:03

Dieses Problem habe ich öfter: Ich will eine Datei aus einem Repo wieder in den Zustand bringen, in dem sie zu einem bestimmten Datum war. Daher will ich einmal sauber aufschreiben, wie das geht – und wie nicht.

Was man beim Suchen im Netz zuerst findet, ist etwas wie:

$ git checkout 'master@{2013-02-03 13:00}'              # Leider beides
$ git show 'master@{2013-02-03 13:00}:$dateiname'       # irreführend!

Klingt verlockend, ist aber leider nicht notwendigerweise korrekt. Das @-Konstrukt schaut nämlich im Reflog (siehe Git Book, Git Ready) nach, also in einem Log, das aufzeichnet, wann sich welche Referenz wie bewegt hat. Zum einen ist diese Information lokal, es geht also darum, wann sich mein master-Branch bewegt hat. Das hat nicht unbedingt etwas mit den Timestamps von Commits zu tun. Zum anderen sind die Reflogs zeitlich beschränkt, sie verfallen normalerweise nach 90 Tagen und beginnen ohnehin erst zum Zeitpunkt des Repo-Clones.

Der korrekte Weg ist, in der History einen Commit zu finden, der sich möglichst nahe am gewünschten Datum befindet. Git speichert bei jedem Commit einen vollen Snapshot des Repos. In einem Commit-Objekt ist dazu ein Verweis auf ein Tree-Objekt hinterlegt. Ein Tree ist vergleichbar mit einem Verzeichnis auf Dateisystemebene, er enthält Verweise auf Blobs (Dateien) oder weitere Trees. In einem Tree sind Verweise auf alle Dateien hinterlegt, auch jene, die sich mit diesem Commit gar nicht geändert haben. Habe ich meinen Commit in zeitlicher Nähe gefunden, kann ich also den zugehörigen Tree auslesen und dort den Verweis auf den gewünschten Blob finden.

Grafisch sieht das so aus:

inline thumbnail

Ich will in folgendem Beispiel herausfinden, wie meine „~/.vimrc“ zum Zeitpunkt dieses Screenshots aussah:

$ pwd
/home/void/work/dotfiles

$ git log -n 1 --until='2012-06-04 16:02'
commit ee68d8a5ca8aced4933b7b390f0366c14ad4c037
Author: Ich <bla@example.invalid>
Date:   Mon Jun 4 15:39:13 2012 +0200

    mpd: Playlists.

Da ist mein Commit. Auf welchen Tree verweist er?

$ git cat-file -p ee68d8a
tree 14f538d3f751056f26b000a6b2854d6e286eff74
parent 2f3feb641bca890766cba576980367f45281de38
author Ich <bla@example.invalid> 1338817153 +0200
committer Ich <bla@example.invalid> 1338817153 +0200

mpd: Playlists.

Jetzt felt nur noch der Hash des Blobs meiner „.vimrc“:

$ git cat-file -p 14f538d | grep vimrc
100644 blob deed2a8e7312d22ca969280a57da58aaebf32ab0    .vimrc

Da ist er. Das kann ich mir nun anschauen, das ist die Datei zum gewünschten Zeitpunkt:

$ git cat-file -p deed2a8

Sich auf diese Weise durch die Commits zu hangeln, ist etwas aufwändig, allerdings durchaus interessant, wenn man verstehen will, wie Git intern arbeitet. Will ich schnell zum Ziel, dann gibt es einen Abkürzung, sobald ich den Hash des gewünschten Commits kenne:

$ git show ee68d8a:.vimrc

Und mit einer Befehlssubstitution kann man nun noch die Suche nach dem Commit-Hash hinzufügen, sodass sich die ganze Aktion auf folgenden Befehl reduzieren lässt:

$ git show $(git rev-list -n 1 --until='2012-06-04 16:02' master):.vimrc

Sollte man das täglich brauchen, lohnt sich eine Shell-Funktion.

Nichtverfehlbare Ziele

Pingu-Avatar

06.01.2013, 16:46:50

Ich benutze für meinen dwm den noborder-Patch. Der hat zur Folge, dass, wenn man nur ein einzelnes Fenster im tile-Layout anzeigt, dieses gar keinen Rahmen mehr hat. Da ich außerdem meine Statusbar am unteren Bildschirmrand habe, fängt das Fenster links oben bei der Koordinate (0, 0) an.

Eine Konsequenz davon ist zum Beispiel, dass die Tabs vom Luakit auch ganz oben am Bildschirmrand sind:

inline thumbnail

Also, die Tabs sind wirklich ganz oben. Wenn ich die Tabs also mal mit der Maus wechseln oder schließen will, dann kann ich meine Maus einfach an den oberen Bildschirmrand werfen – ich muss in y-Richtung überhaupt nicht zielen. Das spart einiges an Nerven und „Denkleistung“. Ich hab’ mal gehört, das globale Menü bei MacOS und jetzt auch Ubuntu verfolgt dieselbe Idee.

Leider gilt das für Gtk2-Programme nicht. Hier gibt es einen kleinen Rand um Menüleisten (ich habe dem Screenshot einen künstlichen, einen Pixel breiten, schwarzen Rahmen gegeben, damit man es besser sieht):

inline thumbnail

Den grauen Abstand über und links neben dem blau hinterlegen „File“ meine ich. Wenn ich also in einem Gtk2-Programm (GIMP, Audacity, Leafpad, ...) meine Maus an den oberen Bildschirmrand werfe und klicke, dann treffe ich nicht das Menü, sondern diesen komischen Rand über dem Menü. Annoying!

Das Problem lässt sich zum Glück beheben mit einem Eintrag in der ~/.gtkrc-2.0:

style "borderlessmenu" = "default"
{
	GtkMenuBar::internal-padding = 0
	GtkMenuBar::shadow-type = GTK_SHADOW_NONE
}
class "*GtkMenuBar*" style "borderlessmenu"

Dann sieht es so aus und das Menü reicht komplett bis nach oben:

inline thumbnail

In ein paar Jahren, wenn sie dann alle zu Gtk3 gewechselt sind, wird man vermutlich neu herausfinden müssen, wie das geht.

Der Firefox, den ich leider manchmal noch brauche, tanzt wie immer aus der Reihe. Um hier das Menü auch ganz nach oben zu zwingen, braucht man einen Eintrag in der userChrome.css:

menubar {
	margin-top: -1px !important;
}

Oder man schaltet das Menü einfach ganz ab. Dann sind die Tabs ganz oben (auch, wenn es nicht danach aussieht) und auch der „Firefox“-Knopf ist (ohne userChrome.css-Eintrag) direkt erreichbar – auch hier wieder ein künstlicher Pixelrand zur besseren Orientierung:

inline thumbnail

Der Passwortmanager passman

Pingu-Avatar

31.12.2012, 12:26:34

Ein Haufen Leute zahlt Geld für Passwortmanager. Die Dinger, die ein Masterpasswort haben, hinter dem dann deine ganzen echten Daten stecken. Andere benutzen den GNOME-Keyring. All sowas integriert sich aber schlecht bis gar nicht in ein einfaches Desktop-Setup.

Gestern habe ich im englischen Arch Forum einen Post von „i_love_penguins“ gelesen, in dem er passman vorgestellt hat. Das ist ein Passwortmanager in Form eines Shellskriptes. Die Daten werden von GnuPG verschlüsselt. Mit dem dmenu kann man Passwörter auswählen und das xdotool kann sie automatisch in die Felder des Browsers schreiben.

Großartig! Ich frage mich, wieso ich nicht schon früher über sowas gestolpert bin oder es gar selbst gebastelt habe. Schwer ist das ja nicht umzusetzen und es funktioniert prima.

Ich selbst verwende passman nicht direkt, weil es schlecht mit meiner bestehenden „Lösung“ funktioniert: Ich habe pro Account eine Textdatei mit den notwendigen Informationen; das ganze Zeug liegt in einem EncFS. Das hat den Vorteil, dass ich neben den eigentlichen Zugangsdaten noch direkt an Ort und Stelle weitere Informationen hinterlegen kann, zum Beispiel mit welcher E-Mail-Adresse ich mich registriert habe und so weiter. Die relevanten „bits and pieces“ habe ich dann von passman übernommen.

Aber jedem, der vielleicht noch gar keinen Passwortmanager verwendet oder nicht weiß, wie er das Problem bei einem minimalen Desktop-Setup elegant lösen könnte, sei passman als Anreiz wärmstens empfohlen. :-)