Poka¿ wyniki od 1 do 3 z 3

Temat: O tym, jak napisaæ prosty kompilator asemblera po linuksem

  1. #1

    Domy¶lnie O tym, jak napisaæ prosty kompilator asemblera po linuksem

    Wstêp

    Swego czau obmy¶li³em prosty asembler, do którego by³ kompilowany inny jêzyk. Ten aembler by³ wykonywany przez maszynê wirtualn±. Teraz piszê kompilator tego asemblera do pliku wykonywalnego, napisany jest w C, pod Linuksem.


    Przedstawiê tu pokrótce, jak to dzia³a, gdy¿ temat te wydaje mi siê do¶æ ciekawy, a te¿ ma³o popularny. Kod jest w pocz±tkowej fazie i ma³o jest tam do analizowania, a jednocze¶nie IMHO jest na tyle dobry, ¿e dalsze rzeczy bêdzie w miarê ³atwo dodaæ.


    Potrzebne bêd± nam nastêpuj±ce oprogramowanie oraz wiedza z zakresu:

    • podstawy asemblera, C, Makefile
    • Linux z pakietami libelfg0 oraz libelfg0-dev
    • git (by ¶ci±gn±æ kod z repozytorium)
    • objdump



    Projekt mo¿na ¶ci±gn±æ pomocy git'a klonuj±c repozytorium:


    Kod:
    git clone git@github.com:RobertGawron/l33tlang.git
    Mo¿liwo¶ci kompilatora


    No na razie nie ma tego du¿o:

    • obs³uga przerwania, które koñczy dzia³anie programu
    • dodawanie
    • odk³adanie na stos
    • procedury (których póki co nie mo¿na wywo³ywaæ)



    Teoria


    Pliki wykonywalne w Linuksie oparte s± o pliki ELF, jest to do¶æ stary standard, powszechny w ¶rodowiskach Uniksowych. Ka¿dy taki plik jest plikiem binarnym, tzn. Nie otworzymy go zwyk³ym edytorem tekstu (vim, emacs), lecz musimy skorzystaæ z wyspecjalizowanego programu, który potrafi go odczytaæ I przedstawiæ nam o nim (tzn. o pliku) informacje. Takie narzêdzia to m.in. readelf oraz objdump, ja wykorzysta³em ten drugi. O tym, jak go wykorzystaæ powiem pó¼niej.


    Plik ELF sk³ada siê z sekcji, informacje w nich zawarte s± ze sob± powi±zane, najwa¿niejsze z nich to:

    • symtab – tablica symboli, s³u¿y m.in. Do tego, by wskazac, w którym miejcu zaczynaj± siê procedury, nazwy tych funkcji zawarte s± w strtab
    • strtab – powi±zana z symtab, nazwy procedur
    • text – instrukcje do wykonania dla procesora

    Toolchain



    W skrócie to pisanie takiego kodu u mie dzia³a tak: kompilujê kompilator, odpalam makefile, który tym kompilowanym kmpilatorem kompiluje plik asemblera. Ta kompilacja przebiega pod okiem valgrinda, bym wiedzia³, czy s± wycieki pamiêci. Skompilowany plik wynikowy sprawdzam objdumpem (sekcje z rozkazami dla procesor), linkujê (ld – standardowy linker) sprawdzaj±c czy nie ma b³êdów linkwania, a na koñcu wykonujê (sprawdzaj±c czy program siê nie rozsypie.


    By przeprpwadziæ te czynno¶ci trzeba ucruchomiæ makefile, w katalogu /dist/Debug/GNU-Linux-x86 Ma on postaæ:
    Kod:
    all:
            valgrind ./nativecompiler ./hello-*
            objdump -D foo.o 
            ld -s -o foo ./foo.o  -lelf -I/lib/ld-linux.so.2 
            ./foo
    Plik asemblera ma postaæ:
    Kod:
    main:
        push 5
        push 3
        add
        call foo
        int 0
        int 2
        ret
    foo:
        ret
    bar:
        ret
    A wynik jest taki:
    Kod:
    rgawron@foo:/opt/l33tlang/NativeCompiler/dist/Debug/GNU-Linux-x86$ make
    valgrind ./nativecompiler ./hello-*
    ==13616== Memcheck, a memory error detector.
    ==13616== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
    ==13616== Using LibVEX rev 1804, a library for dynamic binary translation.
    ==13616== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
    ==13616== Using valgrind-3.3.0-Debian, a dynamic binary instrumentation framework.
    ==13616== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
    ==13616== For more details, rerun with: -v
    ==13616==
    call foo
     ; call is not implmented
    ==13616==
    ==13616== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 1)
    ==13616== malloc/free: in use at exit: 352 bytes in 1 blocks.
    ==13616== malloc/free: 14 allocs, 13 frees, 2,164 bytes allocated.
    ==13616== For counts of detected errors, rerun with: -v
    ==13616== searching for pointers to 1 not-freed blocks.
    ==13616== checked 69,732 bytes.
    ==13616==
    ==13616== LEAK SUMMARY:
    ==13616==    definitely lost: 0 bytes in 0 blocks.
    ==13616==      possibly lost: 0 bytes in 0 blocks.
    ==13616==    still reachable: 352 bytes in 1 blocks.
    ==13616==         suppressed: 0 bytes in 0 blocks.
    ==13616== Rerun with --leak-check=full to see details of leaked memory.
    objdump -D foo.o
    
    foo.o:     file format elf32-i386
    
    Disassembly of section .text:
    
    00000000 <_start>:
       0:   55                      push   %ebp
       1:   89 e5                   mov    %esp,%ebp
       3:   68 05 00 00 00          push   $0x5
       8:   68 03 00 00 00          push   $0x3
       d:   59                      pop    %ecx
       e:   5b                      pop    %ebx
       f:   01 cb                   add    %ecx,%ebx
      11:   90                      nop
      12:   b8 01 00 00 00          mov    $0x1,%eax
      17:   cd 80                   int    $0x80
      19:   c9                      leave
      1a:   c3                      ret
    
    0000001b <foo>:
      1b:   55                      push   %ebp
      1c:   89 e5                   mov    %esp,%ebp
      1e:   c9                      leave
      1f:   c3                      ret
    
    00000020 <bar>:
      20:   55                      push   %ebp
      21:   89 e5                   mov    %esp,%ebp
      23:   c9                      leave
      24:   c3                      ret
    ld -s -o foo ./foo.o  -lelf -I/lib/ld-linux.so.2
    ./foo
    make: *** [all] Error 8
    Pytanie na znajomo¶æ asma+linuka, czy Error, który pojawia siê na koñcu to b³±d czy nie? :)


    Kod


    Ca³o¶c napisana jest w sposób obiektowy, w C, je¶li siê z tym nie spotkali¶cie, to mo¿e to wygl±daæ trochê dziwnie :) Jakby¶cie chcieli o tym wiêcej poczytaæ, to tutaj jest d³u¿sza notka o programowaniu zorientowanym obiektowo w C.


    Obiekt world tworzy ¶rodowisko dla naszego parsera (nom, on te¿ powinien byæ bardziej obiektowo napisany, to swoj± drog±).


    Parser, po koleii pobiera linijki z pliku z asemblerem, a ka¿d± z nich parsuje (tzn maj±c string “push 33”, probuje zrozumieæ, ¿e ma od³o¿yæ na stos 33, ¿e ma takie co¶ ma w³a¶cie skompilowaæ). Moje za³o¿enie by³o takie, by kompilacja ka¿dej linijki pliku asemblera wymaga³a wczytania, posiadania informacji tylko tej linijce, by nie trzeba by³o sprawdzaæ, co jest linijkê wcze¶niej, lub pó¼niej.


    Obs³uga przerwañ asemblera, generowanie odpowiadaj±cego im kodu znajdje siê wpliku interrupts.c.


    Do obs³ugi plików ELF wykorzysta³em gotow± bibliotekê (napisan± w C) o nazwie libelf. AFAIK ma³o jest o niej dokumentacji, lecz do¶c ciekawym linkiem jest ten tutorial.

    Biblioteka ta jest ona do¶æ toporna w ob³udze, masê rzeczy trzeba ustawiæ rêcznie, dlatego obudowa³em j± w swój zestaw funkcji (wzoruj± siê na powy¿szym linku), dziêki czemu pisz±æ inne fragmêty kompilatora nie musia³em sie przejmowaæ niskopoziomowymi detalami. Ta czê¶c jest te¿ napisana nieobiektowo.


    W ca³ym kodzie czêsto przekazujê funkcjê jako argument inne funkcje, tworze tablice funkcji etc, jest to rozwi±zanie znacznie czytelniejsze, ni¿ siermiê¿ne drabinki if-else. W przysz³o¶ci poprawiê to I zamiast zwyk³ych tablic zastosujê struktury.
    Ostatnio edytowane przez RobertG ; 23-02-2010 o 23:45

  2. #2

    Domy¶lnie

    Notka by³a zbyt d³uga na jeden post, wiêc tu jest ci±g dalszy:

    Dokumentacja


    Ogólna znajduje siê na stonie projektu.
    Dokumentacja techniczn± mo¿na wygenerowaæ doxygenem (o ile macie zainstalowanego), jest do tego dopisana osobna regu³ka w Makefile, wiêc wystarczy odpaliæ:
    Kod:
    make docs
    dokumentacja znajduje siê w katalogu html.



    Rzeczy do zrobienia

    Jest ca³a masa b³êdów, niedoróbek, np pusta linia w pliku asemblera wywala kompilator Nied³ugo skoñczê wreszcie pisaæ wywo³ywanie funkcji bo ju¿ mam to wstêpnie przeanalizowane. U¿ycie w asemblerze liczb dziesiêtnych zamiast szesnastkowych to by³ epic fail..


    Plany na przysz³o¶æ

    wielow±tkowo¶æ


    W razie pytañ, uwag i sugestii piszcie.

  3. #3
    Dawni Moderatorzy Avatar grzonu
    Do³±czy³
    26-12-2006
    Sk±d
    Gdansk, Poland, Poland
    Posty
    1 392

    Domy¶lnie

    Bardzo dobrze ze cos takiego powstaje
    Pisz dalej bo warto zobaczyc efekty koncowe
    Filmy online---Grzonu Blog

    1) Moje gg to nie pomoc techniczna w obsludze keyloggerow!!! Na gg i pw pomagam tylko w kwestiach organizacyjnych forum. Masz problem to pisz na forum.
    2) Nie zajmuje sie malware a uprzedzajac pytanie "czemu?" - bo taki mam kaprys!

Uprawnienia

  • Nie mo¿esz zak³adaæ nowych tematów
  • Nie mo¿esz pisaæ wiadomo¶ci
  • Nie mo¿esz dodawaæ za³±czników
  • Nie mo¿esz edytowaæ swoich postów
  •