Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  3 1177
Hei, jeg har drevet å lekt meg litt med dynamic linking in runtime o.l. i C og bestemt meg for å ta dette et skritt lengere ved å selv skrive en implementasjon av dette, for å lære mer om hvordan maskinkoden behandles. Dette er bare for læringens skyld, jeg skal ikkje bytte ut dl[addr/close/error/sym] med min egen implementasjon bare så det er sagt.

Jeg har skrevet en enkel "library" som jeg har kompilert til en objekt fil, koden i denne "librarien" ser slik ut:

Kode

#include <stdio.h>

int something ( )
{
  printf ( "Hello World!\n" );

  return 0x7F;
}
Jeg har også fått til å laste denne object filen inn til minnet med kjøre tillatelse, videre så har jeg også funnet funksjonen "something ( )" i object koden å laget en funksjons pointer til den, funksjonen starter på addresse 0x41 i forhold til starten av det allokerte minne.

Kode

something = ( int ( * )( ))( mcode + 0x41 );
Men når jeg kaller funksjonen ved hjelp av funksjons pointeren, så kjører den koden og returnerer verdien 0x7F som forventet, men den printf-delen ser ut til å utebli, jeg får ingen "Hello World!\n" output i terminalen som forventet.

Jeg har også forsket nærmere på dette ved å bruke objdump som gir meg følgende:

Kode

Contents of section .text:
  554889e5 bf000000 00e80000 0000b87f  UH..............
  0000005d c3                                      ...].
Contents of section .rodata:
  48656c6c 6f20576f 726c6421 00            Hello World!.
Jeg har unlatt .comment section og .eh_frame med vilje siden disse ikkje ser ut til å ha noe med selve kjøringen av koden å gjøre. Og jeg har også prøvd å "clean'e" objekt filen ved å fjerne alt annet enn .text delen og .rodata, men da krasjet bare programmet, å fjerne unødvendig data fra objekt filen og kun laste inn .text delen har fungert tidligere når jeg ikkje har hatt data i .rodata delen.

Hvis jeg disassembler object filen så blir den som følgende:

Kode

push %rbp
mov %rsp, %rbp
mov $0x0, %edi
callq e <something+0xe>
mov $0x7F, %eax
pop %rbp
retq
Kan noen forklare meg hvorfor printf ( ) ikkje ser ut til å få "Hello World!" som argument? Eller at den hele funksjonen kallet uteblir? Det skal også nevnes at mine assembly kunnskaper er nokså begrenset.
(Regner med at det er shared objects du leker med)

Og hvordan opprettet du objektfilene dine? Når du begynner med offsets inn i minnet så er du på ganske tynn is. Offset vil være avhengig av arkitektur og compiler, så jeg ville heller tatt en titt på eksemplene her:

http://www.javahotchocolate.com/tutorials/so.html

Der er noen simple eksempler som bruker printf. Legg spesielt merke til -fPIC.

Edit: Så vidt jeg ser så caster du funksjonen til en int-peker-returnerende funksjon som tar ingen parametere.
Sist endret av Dyret; 8. desember 2013 kl. 21:39.
War room
0xFF's Avatar
Trådstarter Donor
Sitat av Dyret Vis innlegg
(Regner med at det er shared objects du leker med)

Og hvordan opprettet du objektfilene dine? Når du begynner med offsets inn i minnet så er du på ganske tynn is. Offset vil være avhengig av arkitektur og compiler, så jeg ville heller tatt en titt på eksemplene her:

http://www.javahotchocolate.com/tutorials/so.html

Der er noen simple eksempler som bruker printf. Legg spesielt merke til -fPIC.

Edit: Så vidt jeg ser så caster du funksjonen til en int-peker-returnerende funksjon som tar ingen parametere.
Vis hele sitatet...
Disse blir kompilert med GCC.

Kode

gcc -Wall -Werror -fpic -c -o object.o object.c
gcc -shared -o libobject.so object.o
Nei, jeg caster ikkje til en int-peker-returnerende funksjon som tar ingen parametere, det hadde sett slik ut:

Kode

something = ( int * ( * )( ))( mcode + 0x41 );
Det jeg caster til er en funksjon-pointer som tar ingen argumenter og som returnerer int.
▼ ... noen uker senere ... ▼
Jeg har også forsket nærmere på dette ved å bruke objdump som gir meg følgende:

Kode

Contents of section .text:
  554889e5 bf000000 00e80000 0000b87f  UH..............
  0000005d c3                                      ...].
Contents of section .rodata:
  48656c6c 6f20576f 726c6421 00            Hello World!.
Hvis jeg disassembler object filen så blir den som følgende:

Kode

push %rbp
mov %rsp, %rbp
mov $0x0, %edi
callq e <something+0xe>
mov $0x7F, %eax
pop %rbp
retq
Kan noen forklare meg hvorfor printf ( ) ikkje ser ut til å få "Hello World!" som argument? Eller at den hele funksjonen kallet uteblir? Det skal også nevnes at mine assembly kunnskaper er nokså begrenset.
Vis hele sitatet...

Er her linking kommer inn i bildet, som kan skje direkte eller indirekte ettersom en kompilerer for PIC eller ikke. I linking informasjonen ligger det referanser til hvor i .text etc det ligger pekere, og hva dem skal peke til. Et generelt eksempel (med tilfeldige tall)

Kode

.code
00 05 10 30 ff 00 00 10 f0 30 10 50 10 50
.rodata
3a 3a 3a 00 30 10


linking:
.code, offset 5, symbol "printf"
når denne her så lastes inn i RAM, så ser den først slik ut

Kode

.code
00 05 10 30 ff XX XX XX XX 30 10 50 10 50
XX XX XX XX  <- her legges adressen til printf til (og når det står et tall her  fra før, så kan en lage offset inn i et symbol)