vsyscall
-
hi,
bei mir gehts so:
#include <stdio.h> int pid; int main(int argc, char **argv) { __asm__("movl $20, %eax\n" "call 0xffffe400\n" "movl %eax, pid\n"); printf("pid is %d\n", pid); return 0; }
gcc -o test test.c
./test
pid is 2640Was für Fehlermeldungen hast du denn?
Gruss blurb^2
-
blurb schrieb:
Was für Fehlermeldungen hast du denn?
"Speicherzugriffsfehler" (Ich weiß ich hätte Kubuntu mal auf englisch installieren sollen)
EDIT: Mit "call *%gs:0x18\n" ist übrigends genau das selbe.
EDIT2: Was für eine Kernel version hast du denn ? Meine ist 2.6.12-9-386
-
Bei mir kommt da auch ein Segfault.
-
#include <stdio.h> int pid; int main(int argc, char **argv) { __asm__("movl $20, %eax\n" "call *%gs:0x10\n" "movl %eax, pid\n"); printf("pid is %d\n", pid); return 0; }
$ ./test pid is 7718 $ uname -a Linux triphoenix 2.6.15 #2 PREEMPT Sun Feb 12 23:18:38 CET 2006 i686 AMD Athlon(tm) XP 2100+ AuthenticAMD GNU/Linux
Es tut so. Auf http://sources.redhat.com/ml/gdb/2003-04/msg00153.html findet sich auch der Grund dafür und warum es bei manchen mit dem hier stehenden ging und bei manchen nicht:
%gs:0x10 is a location that has been initialized to a kernel-supplied special entry point address. In the current kernels, that address is always 0xffffe000. But that is not part of the ABI, which is why it's indirect instead of a literal "call 0xffffe000". The kernel supplies the actual entry point address to libc at startup time, and nothing in the kernel-user interface prevents it from using a different address in each process if it chose to.
-
TriPhoenix schrieb:
"call *%gs:0x10\n"
Danke, das funktioniert. Merkwürderigerweise ist der Inhalt von gs:0x10 aber 0xffffe400
Naja egal, Hauptsache ist es funktioniert.
-
Die Adresse ist ansich ja auch die richtige. Das Problem liegt bei dem Call mit Adresse ganz woanders, nämlich im Compiler/Assembler. Schau dir etwa mit objdump -d mal an, was wirklich dnan in deiner main-Funktion steht, bei mir kommt ein relativer Sprung raus, weil 0xffffe400 als relative Adresse interpretiert wird. Vielleicht ein Bug, vieleicht absicht im neuen gcc/gas?
80483b0: b8 14 00 00 00 mov $0x14,%eax 80483b5: e8 fc e3 ff ff call 80467b6 <_init-0x1ae2> 80483ba: a3 ec 95 04 08 mov %eax,0x80495ec
Aber per *%gs:0x10 bist du auch flexibler, da sich die tatsächliche Adresse ja ändern kann, die glibc aber dorthin immerhin die Adresse schreibt (wäre nur interessant zu wissen, wie stabil diese Konvention der glibc ist).
Interessant wäre noch welche Compilerversion/Assembler-Versionen bei nichtfunktionierendem und funktionierendem call 0xffffe400 waren. Ich habe für nicht-funktionierend:
as --version => 2.16.1
gcc --version => 3.4.5
-
TriPhoenix schrieb:
Die Adresse ist ansich ja auch die richtige. Das Problem liegt bei dem Call mit Adresse ganz woanders, nämlich im Compiler/Assembler. Schau dir etwa mit objdump -d mal an, was wirklich dnan in deiner main-Funktion steht.
Hmm, ich sehe auch einen relativen Sprung.
TriPhoenix schrieb:
Interessant wäre noch welche Compilerversion/Assembler-Versionen bei nichtfunktionierendem und funktionierendem call 0xffffe400 waren.
gcc: 4.0.2 (prerelease)
gas: 2.16.1TriPhoenix schrieb:
Wäre nur interessant zu wissen, wie stabil diese Konvention der glibc ist.
Mich würde mal interessieren woher libc diese Adresse weiß. Ich dachte erst, dass %gs vom Kernel selbst gesetzt wird, darum habe ich ein kleines Test-Programm geschreiben:
char hello[] = "Hallo Welt !\n"; int size = sizeof(hello)/sizeof(char); void _start (void) { // print __asm__( "movl size, %edx \n" "leal hello, %ecx \n" "movl $1, %ebx \n" "movl $4, %eax \n" "call *%gs:0x10 \n" "movl $0, %ebx \n" "movl $1, %eax \n" "call *%gs:0x10 \n" ); }
und mit
gcc -o test test.c -nostdlib
compiliert, aber da bekomme ich wieder einen seg. fault.
-
Die Adresse ist ansich ja auch die richtige. Das Problem liegt bei dem Call mit Adresse ganz woanders, nämlich im Compiler/Assembler. Schau dir etwa mit objdump -d mal an, was wirklich dnan in deiner main-Funktion steht, bei mir kommt ein relativer Sprung raus, weil 0xffffe400 als relative Adresse interpretiert wird. Vielleicht ein Bug, vieleicht absicht im neuen gcc/gas?
Hmm, anscheined liegt es doch nicht am Compiler, bei mir steht nähmlich folgendes:
80480ad: e8 fc e3 ff ff call 80464ae <_start-0x1be6>
Es eine andere realtive Adresse als bei dir, obwohl der bytecode (oder wie heißt es in Assembler?) gleich ist. Es sieht also so aus. als ob objdump einfach die relative Adresse darstellt. Ich hab also folgendes ausprobiert:
"movl 0xffffe400, %esi \n" "call *%esi \n"
und es funktioniert auch nicht....
-
[quote="Byte"]
Hmm, anscheined liegt es doch nicht am Compiler, bei mir steht nähmlich folgendes:
80480ad: e8 fc e3 ff ff call 80464ae <_start-0x1be6>
Es eine andere realtive Adresse als bei dir, obwohl der bytecode (oder wie heißt es in Assembler?) gleich ist. Es sieht also so aus. als ob objdump einfach die relative Adresse darstellt.
Das ist derslebe relative Sprung. Bei dir liegt nur der Sprungbefehl woanders und daher ist das Ziel auch woanders. In beiden Fällen (bei dir und bei mir) wird 0xffffe400 nicht als Adresse, sondern als relativer Versatz aufgefasst.
%gs:0x10 wird in der Tat von der glibc gesetzt, nicht vom Kernel.
"movl 0xffffe400, %esi \n" "call *%esi \n"
und es funktioniert auch nicht....
Schreib mal "movl $0xffffe400, %esi", dann klappt das auch
Dein Code lädt den Wert, der an Stelle 0xffffe400 im Speicher steht nach %esi, nicht etwa 0xffffe400 selber (jaja, die liebe AT&T-Syntax...).
-
TriPhoenix schrieb:
Das ist derslebe relative Sprung. Bei dir liegt nur der Sprungbefehl woanders und daher ist das Ziel auch woanders. In beiden Fällen (bei dir und bei mir) wird 0xffffe400 nicht als Adresse, sondern als relativer Versatz aufgefasst.
Ich meine ja nur das in beiden Fällen der Hexwert gleich ist, nämlich e8 fc e3 ff ff, dann müsste eigendlich auch der Assembler code der dahinter steht gleich sein oder nicht ?
TriPhoenix schrieb:
%gs:0x10 wird in der Tat von der glibc gesetzt, nicht vom Kernel.
Aber ich frage mich noch immer, woher die den Wert für gs hat. Werde mir den Code vielleicht noch mal ansehen.
TriPhoenix schrieb:
Schreib mal "movl $0xffffe400, %esi", dann klappt das auch
Dein Code lädt den Wert, der an Stelle 0xffffe400 im Speicher steht nach %esi, nicht etwa 0xffffe400 selber (jaja, die liebe AT&T-Syntax...).
Opps.. mit der AT&T-Syntax habe ich mich immer noch nicht so recht angefreundet.
-
Byte schrieb:
TriPhoenix schrieb:
Das ist derslebe relative Sprung. Bei dir liegt nur der Sprungbefehl woanders und daher ist das Ziel auch woanders. In beiden Fällen (bei dir und bei mir) wird 0xffffe400 nicht als Adresse, sondern als relativer Versatz aufgefasst.
Ich meine ja nur das in beiden Fällen der Hexwert gleich ist, nämlich e8 fc e3 ff ff, dann müsste eigendlich auch der Assembler code der dahinter steht gleich sein oder nicht ?
Nein bei nem relativen Sprung eben nicht. 0xffffe400 heißt "rufe das auf, was von hier auf 0x1c00 Bytes hinter mir liegt", und dann hängt die dargestellte Zieladresse davon ab, wo ich bin.
TriPhoenix schrieb:
%gs:0x10 wird in der Tat von der glibc gesetzt, nicht vom Kernel.
Aber ich frage mich noch immer, woher die den Wert für gs hat. Werde mir den Code vielleicht noch mal ansehen.
Viel Spaß, ich habe es für ne Viertelstunde versucht, habe mich in komischen headerdateien zwischen Makros, #ifdefs und ähnlichem verheddert und den Spaß dran verloren *G* Soviel habe ich rausgefunden: %gs enthält eine Threadlokale Struktur, in dieser Struktur ist das für uns interessante Element "sysinfo". Es wird wohl in der Datei sysdeps/generic/dl-sysdep.c geholt. Es kommt aus einem _dl_auxv und an dem Punkt darfst du dann
Verrat mal, wies weitergeht