Autor Thema: wie ladet ihr binarys  (Gelesen 7361 mal)

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« am: 17. June 2006, 18:08 »
hi!
ich bekomm es einfach nicht hin die binary korrekt zu laden es geht bei mir nur waenn der stack nicht manipuliert wird... koennt ihr mir eventl beispielcode zeigen wie ihr das macht?

waer super nett danke

mfg noob!!!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #1 am: 17. June 2006, 21:38 »
Anmerkung: auto_array is ne Eigenproduktion ala std::auto_ptr nur für arrays. Ansonsten übernehm ich keine garantie für garnix :) Hab diese Version noch nicht getestet


// Elf.hpp
class elf
{
public:
/*! The constructor
*\param[in] start address of the beginning of the elf file
*\param[in] size the size of the memory location */
elf(void *start, unsigned int s);
/*! Is it a valid elf file? */
bool valid();
/*! Returns the size of the process image
*\return size of the process image */
unsigned int imageSize();
/*! Create the process image */
char *createProcessImage();
/*! Returns the entry point
*\return address of the entry point */
inline unsigned long entryPoint(){if (pHeader == 0)return 0;return pHeader->entry;}
private:
/*! The elf header */
struct header
{
unsigned char id[16];
unsigned short type;
unsigned short machine;
unsigned int version;
unsigned int entry;
unsigned int programHeader;
unsigned int sectionHeader;
unsigned int flags;
unsigned short headerSize;
unsigned short programHeaderSize;
unsigned short programHeaderCount;
unsigned short sectionHeaderSize;
unsigned short sectionHeaderCount;
unsigned short iStringTable;
}__attribute__((packed));

/*! The elf programm header */
struct programHeader
{
unsigned int type;
unsigned int offset;
unsigned int vAddress;
unsigned int pAddress;
unsigned int fileSize;
unsigned int memorySize;
unsigned int flags;
unsigned int align;
}__attribute__((packed));

/*! Program Header entry flags */
enum
{
PH_FLAG_EXECUTE = 0x01,
PH_FLAG_WRITE = 0x02,
PH_FLAG_READ = 0x04,
};

/*! Pointer to the elf header */
elf::header *pHeader;
/*! Size of the elf file */
unsigned int size;
/*! Pointer to the elf program header table */
elf::programHeader *pProgHeader;
};

//Elf.cpp

#include <elf.hpp>
#include <cstring>
#include <iostream>
using namespace std;

elf::elf(void *start, unsigned int s)
: pHeader(reinterpret_cast<header*>(start)), size(s)
{
pProgHeader = reinterpret_cast<programHeader*>(reinterpret_cast<unsigned int>(start) + pHeader->programHeader);
}
bool elf::valid()
{
if (pHeader == 0)return false;

// Check elf header id
if (pHeader->id[0] != 0x7F ||
pHeader->id[1] != 'E' ||
pHeader->id[2] != 'L' ||
pHeader->id[3] != 'F')
return false;
// Is 32bit elf?
if (pHeader->id[4] != 1)return false;
// LSB byte encoding?
if (pHeader->id[5] != 1)return false;
// version?
if (pHeader->id[6] != 1)return false;
// executable elf?
if (pHeader->type != 2)return false;
// i386 machine?
if (pHeader->machine != 3)return false;
// version?
if (pHeader->version != 1)return false;
return true;
}
unsigned int elf::imageSize()
{
unsigned int imgSize = 0;

// Go trough the program header
for (unsigned int i = 0;i < pHeader->programHeaderCount;i++)
{
programHeader *p = (programHeader*)((unsigned int)pProgHeader + i * pHeader->programHeaderSize);
if (p->type == 0)continue;
else if (p->type == 1)
{
imgSize += p->memorySize;
if ((p->memorySize % p->align) != 0)imgSize += p->align - (p->memorySize % p->align);
}
else if (p->type == 2 || p->type == 3)return 0;
else continue;
}
return imgSize;
}
char *elf::createProcessImage()
{
auto_array<char> memory(new char[imageSize()]);

// Go through the sections
for (unsigned int i = 0;i < pHeader->programHeaderCount;i++)
{
elf::programHeader *p = (elf::programHeader*)(reinterpret_cast<unsigned int>(pProgHeader) + i * pHeader->programHeaderSize);

if (p->type == 0)continue;
else if (p->type == 1)
{
unsigned int index = p->pAddress - 0x400000;

if (p->fileSize > p->memorySize)
{
cerr << "elf: invalid program header" << endl;
memory.reset();
break;
}

memcpy( &memory.get()[index],
&reinterpret_cast<char*>(pHeader)[p->offset],
p->fileSize);
memset( &memory.get()[index + p->fileSize],
0,
p->memorySize - p->fileSize);
}
else if (p->type == 2 || p->type == 3 || p->type == 4 || p->type == 5 || p->type == 6)
{
cerr << "elf: unsupported program header type (" << p->type << ")" << endl;
memory.reset();
break;
}
else
{
cout << "elf: unknown program header type (" << p->type << ")" << endl;
continue;
}
}

return memory.release();
}
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 18. June 2006, 18:42 »
danke fuer deine antwort mich intressiert aber eher wie ihr das macht mit dem stack sichern und den stack dann wieder zurueckspielen das funkt naemlich bei mir nicht!!

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #3 am: 18. June 2006, 19:13 »
Zitat von: noob
danke fuer deine antwort mich intressiert aber eher wie ihr das macht mit dem stack sichern und den stack dann wieder zurueckspielen das funkt naemlich bei mir nicht!!


Meinst du nun wie man Software-Multitasking macht oder wie man Binaries lädt? Oder meinst du was ganz anderes?
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 19. June 2006, 13:11 »
nee nur wie man binarys laedt!!!

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #5 am: 19. June 2006, 21:54 »
Zitat von: noob
nee nur wie man binarys laedt!!!
Wie wie man binarys läd? An einer Adresse laden und dahinspringen. oder was?

bitmaster
In the Future everyone will need OS-64!!!

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 20. June 2006, 06:41 »
Oder alternative

Binary laden. Processstructur anlegen und entsprechend manipulieren ( einsprungadresse im stack hinterlegen, Register vorinitallisieren ) die Processstructur dem sceduler übergeben, und hoven das er ihn auch ausführt.

ich hab das damals so gemacht, da der Processkontext auf dem Stack gesichert war. danach bin ich relativ einfach mit nem push all und iret, oder wars ret in den process gesprungen.


gruss

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 20. June 2006, 08:17 »
tja das mitn laden hab ich schon hinbekommen ich komm auch wieder zurueck in den kernel aber ich hab noch ein problem und zwar ich will im kernel wieder so weitermachen wie ich aufgehoert habe... dazu muesste ich den ganzen stack an irgendeine addresse laden... bzw irgendwie die register sichern... und das bekomm ich einfachnicht hin...

danke
noob

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 20. June 2006, 08:56 »
Hi

Im rm kannst du das über den stack und iret machen. Trit ein interrupt (z.B. der des Timers der für den sceduler verantwortlich ist ) auf, werden ja zunindest mal die wichtigsten register auf dem Stack gesichert (PC, SW),  danach wurde dann mein sceduler ausgeführt. als erstes sichert der noch die restlichen register mit auf den stack. Danach wurde bei mir der Stack ausgetauscht entweder duch den für den kernel, oder deneiner anderen Task  und dann entsprechend rückwärtz wieder abgebaut. Register zurück, und dann nen iret um wieder die task fortzusetzen, die vorher mal angehalten wurde.

im PM gibts glaub genau für sowas schon passende befehle, die den registersatz wechseln,

gruss

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 20. June 2006, 11:29 »
@termite kannst du mir eventl deinen code zeigen? waer super nett danke!!!

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 20. June 2006, 11:50 »
Tut mir leid. der existiert leider nicht mehr. Ist irgend wann mal beim aufräumen verschitt gegangen. kann aber daheim mal noch mal schauen ob im ASM - Script darüber was drinsteht

gruss

nooooooooos

  • Beiträge: 734
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 20. June 2006, 17:59 »
Ich könnte dir vieleicht da auch helfen. Was willst denn du genau sehen?

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 20. June 2006, 21:20 »
super noooooooos also was mich genau intressiert:

was funkt bei mir:
 + also ich kann meinen interrupthandler installieren und das funkt auch
 + ich kann die binary an einen bestimmten platz im speicher laden und dahin springen
 + ich kann mit hilfe des interrupts auch wieder zurueckspringen in den kernel
 
nur dann tut der kernel seine arbeit nicht mehr richtig weil der stack im arsch ist... was mich nun intressiert wie kann ich den stack und alle register an ne bestimmte stelle im speicher komplett sichern und wie kann ich den dann im interrupthandler dann wiederherstellen.

also nochmal was ich will und was noch nicht funkt

installiere interrupthandler ---- funkt
speichere stack und register an eine stelle im arbeinsspeicher ----- FUNKT NICHT
springe in externe binary ------- funkt
springe wieder zurueck in den kernel mit hilfe des interrupts ----- funkt
stelle stack wider her ------- FUNKT NICHT
fahre im kernel wie gewohnt weiter --- FUNKT NICHT

bitmaster

  • Troll
  • Beiträge: 1 138
    • Profil anzeigen
    • OS-64 = 64 Bit Operating System
Gespeichert
« Antwort #13 am: 20. June 2006, 21:54 »
Zitat
weil der stack im arsch ist
und
Zitat
was mich nun intressiert wie kann ich den stack und alle register an ne bestimmte stelle im speicher komplett sichern und wie kann ich den dann im interrupthandler dann wiederherstellen
Also vom a**** wo hin? ^^

bitmaster
In the Future everyone will need OS-64!!!

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 20. June 2006, 22:34 »
Hi

was mich wundert, was macht dein kernel, das er einen eigenen stack braucht? wieso kehrst du mittels eines interrupts aus deinem program zurück? ist es damit beendet oder läuft es noch weiter?

Ich nehm mal an, das hier ggf schon grundlegende probleme existieren. Das einrichten einer neuen Task geschieht bereits von einer task aus. ( auch wenn es die bisher einzigste deines systems ist ) Diese task richtet eine neue Verwaltungsstrucktur für eine Task ein, initallisiert die dort eingetragenen register, stackpointer, .... anschliesend, wird diese strucktur in die zentralle verwaltungstruktur eingetragen. Der sceduler arbeitet auf der Zentrallen verwaltungsstruktur. er kann eigentlich erstmal ohne eigene n registersatz und stack aus. Seine einzige aufgabe ist es, die registerwerte der aktuellen task in der dazugehöhrenden struktur zu sichern, die nächste task zu suchen, die register anhand der Verwaltungsstruktur zu rekonstruieren und sich anschliessend selbst zu beenden. damit wird die neue task gestartet/fortgesetzt und zwar genau an der stelle, wo sie unterbrochen wurde.

was du dazu brauchst
1. eine verwaltungsstrucktur für deine tasks. in der registerwerte, Prioritäten, stackpointer, taskstatus, ... gesichert werden
2. eine funktion, die die in einer Verwaltungsstruktur hinterlegten registerwerte, stackpointer wieder herstellt. anschliesend die task wieder ausführt.
3. eine funktion die die register in einer verwaltunsstrucktur sichert
4. eine interupthandler / sceduler, der ohne den stack zu manipulieren, die funktion 3 aufruft, die nächste taks sucht, und funktion 2 aufruft.

eine möglichkeit die mir einfällt, währe, den stack zu missbrauchen, wen der sceduler zuschlägt, werden ja bektanlicherweise IP, CS und PSW auf dem stack gesichert. man könnte jetzt die restlichen register eins nach dem anderen mit auf dem stack sichern, bis alle register gesichert sind. ( den SP muss man nicht sichern, da wir mit dem ja was anderes vorhaben ) danach kann man dann den SP in der dazugehörigen struktur aktuallisieren.

jetzt kann man sich einen neuen sp besorgen, fals man irgendwelchen hässlichen komlexen sachen vorhat, oder versuchen ohne stack auszukommen. der nächste schritt ist dann die nächste task struktur zu ermitteln. Wie ist mal egal, hat man sie gefunden, wird der stack pointer der dazugehörigen strucktur geladen, anschliessend die register in umgekehrter reihenfolge vom stack geholt ( wir erinnern und, wie haben sie ja irgendwann mal so abgelegt ) und zum schluss verbleiben nur noch IP, CS und PSW auf dem stack, die dann mit einem RET / IRET vom stack verschwinden und gleichzeitig die task wieder zu leben erwecken.

beim erzeugen einer neuen task muss man
1. IP, CS und PSW auf dem stack vorinitallisieren, so das sie bei einem ret auch richtig geladen werden, um den gewünschten code auszuführen
2. die restlichen register müssen auch auf dem stack hintelegt werden.

solltest du im sceduler einen stack brauchen, ist darauf zu achten, das dieser sich nicht ins unendliche aufbaut. ggf kann es da zu etwas verwirrenden verhalten kommen.  aber das dann bei gelegenheit bei entsprechenden problemen.

gruss

(ps ich hab zwar was im script gefunden, ich bin aber zu faul 2 seiten asm code abzutippen, und 4 seiten c code )

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #15 am: 22. June 2006, 16:57 »
oh, ich glaub ich hab eingangs wohl die Frage falsch verstanden und irgendwo elf hineininterpretiert  :oops:

Für alle die den Thread noch lesen werden: Mein obiger Code funktioniert (zumindest unter für mein OS)... hab mittlerweile multitasking wiedermal hinbekommen :D
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

noob

  • Beiträge: 63
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 25. June 2006, 13:53 »
hi!

super danke termite so wie du das gesagt hast funkts bei mir teilweise schaut euch mal meinen code an:


struct Process{
    unsigned short buf_ax;
    unsigned short buf_cx;
    unsigned short buf_dx;
    unsigned short buf_bx;
    unsigned short buf_sp;
    unsigned short buf_bp;
    unsigned short buf_si;
    unsigned short buf_di;
    unsigned short buf_ds;
    unsigned short buf_es;
} process;


int readBin(int seg, int head,int track,int startSector,int anz){

   bx = seg;                 /*segment*/
   cl = startSector;            /*sectroNumber*/
   dl = DRIVE;                  /*drive number 0 == floppy*/
   al = anz;                    /*number of sectors to read*/
   ch = track;                  /*track number*/
   dh = head;                   /*head number*/  

    asm{
        mov ah, 0x2;
        int 0x13
        setc bx
    }
   
    return bx;
}


int loadBin(char *paht){
    int seg = 0;
    int lsn = analytePath(paht);
    int i;

printf("%d\n", lsn);
   
    asm{
        mov ax, 0x4000
        mov es, ax
    }

    for(i = 0; i < 7; i++){
        readBin(seg, ((lsn) / 18) % 2, (lsn) / 36, ((lsn) % 18) +1, 1);
        seg+=512;
        lsn++;
    }

    /*save all registers*/
    process.buf_ax = ax;
    process.buf_cx = cx;
    process.buf_dx = dx;
    process.buf_bx = bx;
    process.buf_sp = sp;
    process.buf_bp = bp;
    process.buf_si = si;
    process.buf_di = di;
    process.buf_ds = ds;
    process.buf_es = es;
   
    asm {
        fcall 0x4000,0x0000
    }

    printf("_\n");

    return -1;
}

int interruptHandler(void){
    /*restore all registers*/
    ds = process.buf_ds;
    es = process.buf_es;
    ax = process.buf_ax;
    cx = process.buf_cx;
    dx = process.buf_dx;
    bx = process.buf_bx;
    sp = process.buf_sp;
    bp = process.buf_bp;
    si = process.buf_si;
    di = process.buf_di;

    printf("hallo\n");
    getKonsoleInput();

    //while(1);

   // asm{
   //     siret
   // }
}

es ist so dass ich aus einem programm das genau einen sektor gross ist wieder fabelhaft wieder zurueckspringen kann das ist kein prob aber dann funkt das diskettenzugriff nichtmehr(nachdem ich das prog ausgefuerht habe) will ich aber einprogramm ausfuerhen das 6sektoren hat gehts nicht mehr :-( bochs sagt mir dann:
Zitat von: bochs
fails bounds test


mfg noob

 

Einloggen