2009-05-02 9 views
3

Die Umgebung ist Solaris auf 32bit SPARC, aber ich denke, das ist ein allgemeineres Problem mit dynamischem Linking und/oder positionsunabhängigem Code.Wie beziehe ich mich auf eine globale Variable in einer dynamisch verbundenen Bibliothek?

Ich habe ein Assembly-Programm, das ich als positionsunabhängigen Code kompiliere und dynamisch mit einem C-Programm verknüpfe. Es funktioniert gut, außer dass ich auf keinen Speicher verweisen kann, der von dem Assembly-Programm aus dem Assembly-Programm reserviert wird. Springen innerhalb des Assembly-Programms funktioniert gut.

Ich möchte nur innerhalb des Assembly-Programms zu lesen und in den Speicher schreiben, aber jedes Mal, wenn ich versuche, bekomme ich Segmentierung Fehler.

Ich schrieb dieses Prüfprogramm dieses Problem

.section ".data" 
    .global foo 
foo: .word 1 
    .section ".text" 
    .global testprog 
testprog: 
    save %sp, -(92+4), %sp 
    sethi %hi(foo), %o0 ! set foo, %o0 
    or %o0, %lo(foo), %o0 
    call print_int 
    nop 
    ret 
    restore 
resultierende

ich diese kompilieren, um mit

als -K PIC -b die

und dlopen zu debuggen .so in C

dlhandle = dlopen(obj_file, RTLD_NOW) 
dl_testprog = dlsym(dlhandle, "testprog") 

Wenn ich dl_testprog() rufe, druckt es "4". Es wird auch "4" gedruckt, wenn ich versuche, die Adresse von testprog oder print_int zu drucken. Springen zu einem Label und alles andere funktioniert gut. Bei der Demontage wird foo durch 0x0 ersetzt, so wie es sein sollte.

Muss ich durch _GLOBAL_OFFSET_TABLE_ oder etwas gehen, um in meinem eigenen Speicher innerhalb des Assembly-Programms schreiben zu können? Wenn ja, wie mache ich das? Alles, was ich versuchte, führte zu einem Segfault, und ich konnte keinen sehr guten Weg finden, dies zu tun (was mich zu der Annahme verleitet, dass Sie das nicht tun sollten. Ist das nicht das Linkers-Problem?) .

Antwort

1

Ja, ich glaube, Sie müssen durch GOT gehen, um private Daten zu adressieren. Siehe Abschnitt 9.2 here. Obwohl NASM ein x86-Assembler ist, sollten die allgemeinen Prinzipien auch auf SPARC/Solaris dieselben sein.

Auch AT & T-Assembler verwenden normalerweise '@got' -Syntax, um die Verschiebung anzugeben. BEKAM. Die genauen Details werden in Ihrem Assembler-Handbuch beschrieben, d. H. Die Syntaxdetails von NASM funktionieren nicht mit dem Assembler von Solaris.

2

Gelöst wurde es durch den Code, den der C-Compiler für PIC ausgibt, was ich von Anfang an hätte tun sollen, anstatt Handbücher und zufällige Webseiten zu lesen.

Vielleicht war es offensichtlich, aber in der Tat reale Adresse eines Objekts in PIC (mindestens 32b SPARC) ist (_GLOBAL_OFFSET_TABLE_ + PC + object). Und die Konvention besteht darin, die GOT-Adresse zu Beginn einer Funktion auf% 17 zu berechnen. Die Details sind here, außer wie% l7 tatsächlich berechnet wird.

addpc: 
    add %o7, %l7, %l7 ! %o7 == addr of call == PC 
    retl 
    nop 
testprog: 
    sethi %hi(_GLOBAL_OFFSET_TABLE_-8), %l7 ! -8 = distance from call addpc 
    add %l7, %lo(_GLOBAL_OFFSET_TABLE_-4), %l7 
    call addpc ! add PC to %l7 
    nop 
+0

+1 suchen sie nach dem Montag Ausgang :-) C (half mir ein paar Jahren viel vor einem echten schnellen und optimierten Interrupt-Handler auf m68k zu schreiben. Ich begann es nur in C, um den ASM-Ausgang und optimierte griff es ... ohne Programmierung Assembler für m68k vor diesem Projekt). – mmmmmmmm