home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
vp21beta.zip
/
LRTLSRC.RAR
/
PE2ELF
/
IMPCONVE.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
2000-08-15
|
23KB
|
637 lines
procedure naechste_seite;
begin
// !!!!! vielleicht löst es ein paar Probleme ...
inc(adressposition,4096);
end;
var
_plt_dateiposition, _plt_adressposition,
_rel_plt_dateiposition, _rel_plt_adressposition,
_got_dateiposition, _got_adressposition,
_dynamic_dateiposition, _dynamic_adressposition,
_dynsym_dateiposition, _dynsym_adressposition,
_dynsymstr_dateiposition, _dynsymstr_adressposition,
_dynsymstrhash_dateiposition, _dynsymstrhash_adressposition,
resource_dateiposition ,resource_adressposition:longint;
_plt_laenge,
_rel_plt_laenge,
_dynamic_laenge,
_dynsym_laenge,
resource_laenge,
hash_tabelle_laenge:longint;
luecke_dateiposition,luecke_adressposition,luecke_laenge,_got_laenge:longint;
procedure Speichere_in_der_DYNAMIC_Tabelle(_d_tag,_d_val:word);
begin
Inc(anzahl_dynamic_eintraege);
ReallocMem(dynamic_speicher,anzahl_dynamic_eintraege*SizeOf(Elf32_Dyn_type));
with dynamic_speicher^[anzahl_dynamic_eintraege-1] do
begin
d_tag:=_d_tag;
d_val:=_d_val;
end;
end;
(***************************************************************************)
var
symboltabelle_gefuellt:longint;
procedure Symboltabelleneintrag(const _name,_value:word;const _info:byte;const _shindex:smallword);
begin
Inc(symboltabelle_gefuellt);
ReallocMem(symboltabelle,symboltabelle_gefuellt*SizeOf(Elf32_Sym_type));
with symboltabelle^[symboltabelle_gefuellt-1] do
begin
st_name :=_name; // Stringtabellenindex
st_value :=_value; // Adressen,..
st_size :=0; // unwichtig
st_info :=_info; // bind/type
st_other :=0; // undefiniert
st_shndx :=_shindex; // auf welche Sektion bezogen
end;
end;
(***************************************************************************)
var
symbolstringtabelle_laenge:longint;
symbolstringtabelle_eintraege:longint;
_dynamic_st_index,_global_offset_table_st_index:longint;
function Speichere_in_der_SymbolStringTabelle(const sym_name:string):longint;
var
p:pointer;
begin
// hier kann noch um ein paar Byte gefeilt werden
// wenn Teilzeichenketten genutzt werden ..
Result:=symbolstringtabelle_laenge;
ReallocMem(symbolstringtabelle,symbolstringtabelle_laenge+Length(sym_name)+1);
Move(sym_name[1],symbolstringtabelle^[symbolstringtabelle_laenge],Length(sym_name));
Inc(symbolstringtabelle_laenge,Length(sym_name));
symbolstringtabelle^[symbolstringtabelle_laenge]:=#0;
Inc(symbolstringtabelle_laenge);
Inc(symbolstringtabelle_eintraege);
end;
(***************************************************************************)
(***************************************************************************)
procedure import_umrechnung;
type
pe_Import_Directory_Entry=
packed record
IMPORT_FLAGS :longint;
TIME_DATE_STAMP :longint;
MAJOR_VERSION,
MINOR_VERSION :smallword;
NAME_RVA :longint;
IMPORT_LOOKUP_TABLE_RVA :longint;
//??IMPORT_ADDRESS_TABLE_RVA:longint;
end;
temp_import_typ=
record
wo, // Aufrufer
sym_index:longint; // Index in der Symboltabelle
end;
temp_import_tabelle_typ=array[1..100000000] of temp_import_typ;
var
p,p2,off:longint;
temp_import_tabelle_z:^temp_import_tabelle_typ;
temp_import_tabelle_gefuellt:longint;
z,z2:longint;
gefunden:boolean;
plt_index_tabelle:PLongArray;
weitergerueckt:boolean;
(************************************************************************)
procedure Merke_Import(const _wo,_sym_index:longint);
begin
Inc(temp_import_tabelle_gefuellt);
ReallocMem(temp_import_tabelle_z,temp_import_tabelle_gefuellt*SizeOf(temp_import_typ));
with temp_import_tabelle_z^[temp_import_tabelle_gefuellt] do
begin
wo :=_wo ;
sym_index:=_sym_index;
end;
end;
(************************************************************************)
procedure Erzeuge_Hash_Tabelle;
type char_z=^char;
function elf_hash(const _name:char_z):longint;
// Seite 84
var
z:char_z;
g,h:longint;
begin
z:=_name;
h:=0;
while z^<>#0 do
begin
h:=(h shl 4)+Ord(z^);
Inc(z);
if g=(h and $F0000000) then
h:=h xor (g shr 24);
h:=h and (not g);
end;
end;
var
nbucket,nchain:longint;
z,wert:longint;
begin
nbucket:=symboltabelle_gefuellt; // kleiner ?
nchain :=symboltabelle_gefuellt;
// die Länge wurde schon vorher berechnet
//hash_tabelle_laenge:=4*(1+1+nbucket+nchain);
GetMem (hash_tabelle ,hash_tabelle_laenge);
FillCHar(hash_tabelle^,hash_tabelle_laenge,0);
hash_tabelle^[0]:=nbucket;
hash_tabelle^[1]:=nchain;
// Eintrag 1 ist reserviert ('')
for z:=2 to nchain do
begin
wert:=elf_hash(@symbolstringtabelle^[symboltabelle^[z-1].st_name]);
wert:=wert mod nbucket;
if hash_tabelle^[2+wert]=0 then
// leerer "Eimer" gefunden
hash_tabelle^[2+(wert mod nbucket)]:=z-1
else
begin
// voller Eimer -> Verkettung
while hash_tabelle^[2+nbucket+wert]<>0 do
wert:=hash_tabelle^[2+nbucket+wert];
hash_tabelle^[2+nbucket+wert]:=z-1;
end;
end;
end;
begin
// mit "leerer" Stringtabelle für Symbole anfangen
symbolstringtabelle:=nil;
symbolstringtabelle_eintraege:=0;
symbolstringtabelle_laenge:=0;
Speichere_in_der_SymbolStringTabelle(#0);
_dynamic_st_index :=Speichere_in_der_SymbolStringTabelle('_DYNAMIC');
_global_offset_table_st_index:=Speichere_in_der_SymbolStringTabelle('_GLOBAL_OFFSET_TABLE_');
temp_import_tabelle_gefuellt:=0;
temp_import_tabelle_z:=nil;
p:=0;
while p<pe_obj_tab[idata].physical_size do
with pe_Import_Directory_Entry(import_puffer^[p]) do
begin
if NAME_RVA=0 then
break;
DWriteLn('* '+StrPas(@import_puffer^[NAME_RVA-pe_obj_tab[idata].rva]));
// "shared object"-name als DT_NEEDED Eintrag abspeichern
Speichere_in_der_DYNAMIC_Tabelle(
DT_NEEDED,
Speichere_in_der_SymbolStringTabelle(
StrPas(@import_puffer^[NAME_RVA-pe_obj_tab[idata].rva])));
p2:=IMPORT_LOOKUP_TABLE_RVA-pe_obj_tab[idata].rva;
repeat
off:=Meml[Ofs(import_puffer^[p2])];
if off=0 then break;
Dec(off,pe_obj_tab[idata].rva);
DWriteLn('+ $'+Int2Hex(p2+pe_obj_tab[idata].rva+pe_kopf.image_base,8)+' : '+
StrPas(@import_puffer^[off+2]));
// Funktion und zu Speicherstelle merken wo sie benutzt wird
Merke_Import(
p2+pe_obj_tab[idata].rva+pe_kopf.image_base,
Speichere_in_der_SymbolStringTabelle(
StrPas(@import_puffer^[off+2])));
Inc(p2,4);
until false;
Inc(p,SizeOf(pe_Import_Directory_Entry));
end;
//******************************************************************
// jetzt ist die Anzahl der Importe bekannt
// Länge der Stringtabelle auf 32 Bit-Vielfaches bringen
Aufrunden(symbolstringtabelle_laenge,4);
// zwischen der Interpreter-Sektion und der .text-Sektion ist noch
// fast 4096 Byte Platz (Adresse und Datei)
index_:=sektionen_uebersicht[sekt_interpreter].index_;
luecke_adressposition:=sektionen_kopf[index_].sh_addr +sektionen_kopf[index_].sh_size;
luecke_dateiposition :=sektionen_kopf[index_].sh_offset+sektionen_kopf[index_].sh_size;
Aufrunden(luecke_adressposition,4);
Aufrunden(luecke_dateiposition ,4);
index_:=sektionen_uebersicht[sekt_text].index_;
luecke_laenge:=sektionen_kopf[index_].sh_addr-luecke_adressposition;
// VP erzeugt schon soetwas ähnliches wie .plt (in .code32)
// diese Einträge jmp [.idata+xyz] // $ff $25 (.idata+xyz)
// jmp [.idata+xzy]
// jmp [.idata+yxz]
// ...
// muessen später auf die GOT (Global Offset Table) verweisen
// jetzt wird erst einmal der Bereich und die Anzahl bestimmt
p2:=pe_obj_tab[code32].physical_size;
while code_puffer^[p2-2]=0 do dec(p2); (* $0040xxxx *)
z:=0;
while (code_puffer^[p2-6]=$ff) and (code_puffer^[p2-6+1]=$25) do
begin
Dec(p2,6);
Inc(z);
end;
if z<>temp_import_tabelle_gefuellt then
abbruch(#7'Error: '+Int2Str(z)+' stubs for imported functions found but '+Int2Str(temp_import_tabelle_gefuellt)+' functions imported');
// die .dynamic-Tabelle kommt nach dem Datensegment
_dynamic_adressposition:=adressposition;
_dynamic_dateiposition :=dateiposition ;
// die .dynamic-Tabelle enthält jetzt schon anzahl_dynamic_eintraege Einträge
// außerdem kommen noch hinzu:
// DT_HASH,DT_STRTAB,DT_SYMTAB,DT_STRSZ,DT_REL,DT_RELSZ,DT_RELENT,DT_NULL
_dynamic_laenge:=SizeOf(Elf32_Dyn_type)*(anzahl_dynamic_eintraege+8);
Inc(adressposition,_dynamic_laenge);
Inc(dateiposition ,_dynamic_laenge);
// die .got kommt nach .dynamic
naechste_seite;
_got_adressposition:=adressposition;
_got_dateiposition :=dateiposition ;
_got_laenge:=(3+temp_import_tabelle_gefuellt)*4;
Inc(adressposition,_got_laenge);
Inc(dateiposition ,_got_laenge);
//************************************************
// .dynsym,.dynstr,.hash,. sind nicht beschreibbar
Aufrunden(adressposition,4096);
suche_naechste_passende_adressposition;
// Symbole in der .dynsym-Tabelle:
// 1 ""
// +1 "_DYNAMIC"
// +1 "_GLOBAL_OFFSET_TABLE_"
// +temp_import_tabelle_gefuellt
_dynsym_laenge:=(3+temp_import_tabelle_gefuellt)*SizeOf(Elf32_Sym_type);
weitergerueckt:=false;
// Adresse von .dynsym festlegen
// wenn möglich in der Lücke von .interp bis .text
if _dynsym_laenge<=luecke_laenge then
begin
_dynsym_adressposition:=luecke_adressposition;
_dynsym_dateiposition :=luecke_dateiposition ;
Dec(luecke_laenge ,_dynsym_laenge);
Inc(luecke_adressposition,_dynsym_laenge);
Inc(luecke_dateiposition ,_dynsym_laenge);
end
else
begin
_dynsym_adressposition:=adressposition;
_dynsym_dateiposition :=dateiposition ;
Inc(adressposition,_dynsym_laenge);
Inc(dateiposition ,_dynsym_laenge);
weitergerueckt:=true;
end;
// Adresse von .dynstr festlegen
// wenn möglich in der Lücke von .interp bis .text
if symbolstringtabelle_laenge<=luecke_laenge then
begin
_dynsymstr_adressposition:=luecke_adressposition;
_dynsymstr_dateiposition :=luecke_dateiposition ;
Dec(luecke_laenge ,symbolstringtabelle_laenge);
Inc(luecke_adressposition,symbolstringtabelle_laenge);
Inc(luecke_dateiposition ,symbolstringtabelle_laenge);
end
else
begin
_dynsymstr_adressposition:=adressposition;
_dynsymstr_dateiposition :=dateiposition ;
Inc(adressposition,symbolstringtabelle_laenge);
Inc(dateiposition ,symbolstringtabelle_laenge);
weitergerueckt:=true;
end;
// Adresse von .hash festlegen
// Länge der Hash-Tabelle (siehe erzeuge_hash_tabelle)
hash_tabelle_laenge:=4*(1+1+2*(3+temp_import_tabelle_gefuellt));
// wenn möglich in der Lücke von .interp bis .text
if hash_tabelle_laenge<=luecke_laenge then
begin
_dynsymstrhash_adressposition:=luecke_adressposition;
_dynsymstrhash_dateiposition :=luecke_dateiposition ;
Dec(luecke_laenge ,hash_tabelle_laenge);
Inc(luecke_adressposition,hash_tabelle_laenge);
Inc(luecke_dateiposition ,hash_tabelle_laenge);
end
else
begin
_dynsymstrhash_adressposition:=adressposition;
_dynsymstrhash_dateiposition :=dateiposition ;
Inc(adressposition,hash_tabelle_laenge);
Inc(dateiposition ,hash_tabelle_laenge);
weitergerueckt:=true;
end;
_rel_plt_laenge:=temp_import_tabelle_gefuellt*SizeOf(Elf32_Rel_type);
GetMem (rel_plt_speicher ,_rel_plt_laenge);
FillChar(rel_plt_speicher^,_rel_plt_laenge,0);
// Adresse von .rel.plt festlegen
// wenn möglich in der Lücke von .interp bis .text
if _rel_plt_laenge<=luecke_laenge then
begin
_rel_plt_adressposition:=luecke_adressposition;
_rel_plt_dateiposition :=luecke_dateiposition ;
Dec(luecke_laenge ,_rel_plt_laenge);
Inc(luecke_adressposition,_rel_plt_laenge);
Inc(luecke_dateiposition ,_rel_plt_laenge);
end
else
begin
_rel_plt_adressposition:=adressposition;
_rel_plt_dateiposition :=dateiposition ;
Inc(adressposition,_rel_plt_laenge);
Inc(dateiposition ,_rel_plt_laenge);
weitergerueckt:=true;
end;
// Reseourcen passen am besten hierher:
// auch "nur Lesen" (kein Ausführen,Schreiben)
if sektionen_uebersicht[sekt_resource].vorhanden then
begin
resource_laenge:=pe_obj_tab[res].physical_size;
if resource_laenge<=luecke_laenge then
begin
resource_adressposition:=luecke_adressposition;
resource_dateiposition :=luecke_dateiposition ;
Dec(luecke_laenge ,resource_laenge);
Inc(luecke_adressposition,resource_laenge);
Inc(luecke_dateiposition ,resource_laenge);
end
else
begin
resource_adressposition:=adressposition;
resource_dateiposition :=dateiposition ;
Inc(adressposition,resource_laenge);
Inc(dateiposition ,resource_laenge);
weitergerueckt:=true;
end;
end;
// .plt ist ausführbar -> muß auf eine neue Speicherseite
if weitergerueckt then
begin
Aufrunden(adressposition,4096);
suche_naechste_passende_adressposition;
end;
// Länge der .plt-Sektion ausrechnen
// .plt hat .plt0 und plt1..plt(Anzahl Importe) Einsprungstellen
GetMem(plt_index_tabelle,4*(temp_import_tabelle_gefuellt+1));
// .plt ist kleiner als $10*(anzahl_importe+1)
GetMem (plt_speicher ,(temp_import_tabelle_gefuellt+1)*$10);
FillChar(plt_speicher^,(temp_import_tabelle_gefuellt+1)*$10,0);
_plt_laenge:=0;
// .plt0:
// push offset got[4] // $ff $35 (got+4)
// jmp got[8] // $ff $25 (got+8)
plt_index_tabelle^[0]:=_plt_laenge;
plt_speicher^[$0]:=$ff;
plt_speicher^[$1]:=$35;
longint_z(@plt_speicher^[$2])^:=_got_adressposition+4;
plt_speicher^[$6]:=$ff;
plt_speicher^[$7]:=$25;
longint_z(@plt_speicher^[$8])^:=_got_adressposition+8;
Inc(_plt_laenge,6+6);
for z:=1 to temp_import_tabelle_gefuellt do
begin
plt_index_tabelle^[z]:=_plt_laenge;
//.pltx_: (x>=1)
// push (x-1)*2 (A)
// jmp .plt0 (B)
// je 2 Varianten für (A) und (B):
// $6a shortint((x-1)*8) (A1)
// $eb shortint(.plt0-.pltx_-2-2) (B1)
// $68 longint((x-1)*8) (A2)
// $e9 longint(.plt0-.pltx_-5-5 (B2)
if (z-1)*8<=127 then
begin (* A1 *)
plt_speicher^[_plt_laenge+0]:=$6a;
plt_speicher^[_plt_laenge+1]:=(z-1)*8;
Inc(_plt_laenge,2);
end
else
begin (* A2 *)
plt_speicher^[_plt_laenge+0]:=$68;
longint_z(@plt_speicher^[_plt_laenge+1])^:=(z-1)*8;
Inc(_plt_laenge,5);
end;
if plt_index_tabelle^[0]-_plt_laenge-2>=-128 then
begin (* B1 *)
plt_speicher^[_plt_laenge+0]:=$eb;
shortint(plt_speicher^[_plt_laenge+1]):=plt_index_tabelle^[0]-_plt_laenge-2;
Inc(_plt_laenge,2);
end
else
begin (* B2 *)
plt_speicher^[_plt_laenge+0]:=$e9;
longint_z(@plt_speicher^[_plt_laenge+1])^:=plt_index_tabelle^[0]-_plt_laenge-5;
Inc(_plt_laenge,5);
end;
// entsprechende "Relokation" erzeugen
with rel_plt_speicher^[z-1] do
begin
r_offset:=_got_adressposition+(3+z-1)*4; // die ersten 3 Einträge in der GOT sind reserviert
r_info :=(z-1+3) shl 8 // die ersten 3 Einträge in der Symboltabelle sind reserviert
+R_386_JMP_SLOT;
end;
longint_z(@plt_speicher^[z*$10+$c])^:=-$10*(z+1);
end;
Aufrunden(_plt_laenge,4); // auf 32 bit ausrichten
// jetzt ist die Länge von .plt bekannt
// Suche nach freiem Adressraum
// zwischen der .text-Sektion und der nächsten Seitengrenze ist
// vielleicht noch etwas Platz (an der Adresse und in der Datei)
index_:=sektionen_uebersicht[sekt_text].index_;
luecke_adressposition:=sektionen_kopf[index_].sh_addr +sektionen_kopf[index_].sh_size;
luecke_dateiposition :=sektionen_kopf[index_].sh_offset+sektionen_kopf[index_].sh_size;
Aufrunden(luecke_adressposition,4);
Aufrunden(luecke_dateiposition ,4);
luecke_laenge:=luecke_adressposition and (4096-1);
if luecke_laenge=4096 then
luecke_laenge:=0;
// Adresse von .plt festlegen
// wenn möglich in der Lücke
if _plt_laenge<=luecke_laenge then
begin
_plt_adressposition:=luecke_adressposition;
_plt_dateiposition :=luecke_dateiposition ;
Dec(luecke_laenge ,_plt_laenge);
Inc(luecke_adressposition,_plt_laenge);
Inc(luecke_dateiposition ,_plt_laenge);
end
else
begin
_plt_adressposition:=adressposition;
_plt_dateiposition :=dateiposition ;
Inc(adressposition,_plt_laenge);
Inc(dateiposition ,_plt_laenge);
weitergerueckt:=true;
end;
// jetzt sind wichtige Adressen bekannt und die _DYNAMIC-Tabelle
// kann vervollständigt werden
// Adresse der Hash-Tabelle dem Programmlader verraten
Speichere_in_der_DYNAMIC_Tabelle(DT_HASH,_dynsymstrhash_adressposition);
// ........... Symboltabelle-Zeichenketten ...
Speichere_in_der_DYNAMIC_Tabelle(DT_STRTAB,_dynsymstr_adressposition);
// ........... Symboltabelle ...
Speichere_in_der_DYNAMIC_Tabelle(DT_SYMTAB,_dynsym_adressposition);
// Länge des Bereiches DT_STRTAB^
Speichere_in_der_DYNAMIC_Tabelle(DT_STRSZ,symbolstringtabelle_laenge);
// Adresse des "Relokationen"
Speichere_in_der_DYNAMIC_Tabelle(DT_REL,_rel_plt_adressposition);
// Gesamtlänge
Speichere_in_der_DYNAMIC_Tabelle(DT_RELSZ,_rel_plt_laenge);
// Länge eines Eintrages
Speichere_in_der_DYNAMIC_Tabelle(DT_RELENT,SizeOf(Elf32_Rel_type));
// Ende der _DYNAMIC-Tabelle
Speichere_in_der_DYNAMIC_Tabelle(DT_NULL,0);
//**********************************************************************
// neue Symboltabelle
symboltabelle:=nil;
symboltabelle_gefuellt:=0;
// Symboltabelleneintraege 0..2
// 0: "undefiniert" name,value,info,shindex
Symboltabelleneintrag(
0,
0,
0,SHN_UNDEF);
// 1: "_DYNAMIC" - Adresse von ".dynamic"
Symboltabelleneintrag(
_dynamic_st_index,
_dynamic_adressposition,
(STB_GLOBAL shl 4)+STT_OBJECT,SHN_ABS);
// 2: "_GLOBAL_OFFSET_TABLE_"
Symboltabelleneintrag(
_global_offset_table_st_index,
_got_adressposition,
(STB_GLOBAL shl 4)+STT_OBJECT,SHN_ABS);
// die ersten 3 Einträge in der Symboltabelle sind schon benutzt
// die ersten 3 Einträge in der GOT sind auch reserviert
// im .plt-Bereich sind die ersten $10 Byte schon benutzt
GetMem(got_speicher ,3*4+4*temp_import_tabelle_gefuellt);
FillChar(got_speicher^,3*4+4*temp_import_tabelle_gefuellt,0);
got_speicher^[0]:=_dynamic_adressposition;
got_speicher^[1]:=0;
got_speicher^[2]:=0;
// off=Adresse des Code32-Segmentes wo VP schon soetwas wie .plt anlegt
off:=sektionen_kopf[sektionen_uebersicht[sekt_text].index_].sh_addr;
for z:=1 to temp_import_tabelle_gefuellt do
begin
// .plt+$10*x+6 ist die Adresse die erstmal zum Programmlader springt
got_speicher^[z-1+3]:=_plt_adressposition+plt_index_tabelle^[z];
// suche den Aufruf im code32-Bereich
gefunden:=false;
for z2:=1 to temp_import_tabelle_gefuellt do
if longint_z(@code_puffer^[p2+(z2-1)*6+2])^=temp_import_tabelle_z^[z].wo then
begin
gefunden:=true;
// Code so umstricken, das jetzt auf die GOT verwiesen wird
longint_z(@code_puffer^[p2+(z2-1)*6+2])^:=_got_adressposition+(z-1+3)*4;
Symboltabelleneintrag(
temp_import_tabelle_z^[z].sym_index,
off+p2+(z2-1)*6,
(STB_GLOBAL shl 4)+STT_FUNC,SHN_UNDEF);
break; (* z2 *)
end;
if not gefunden then
Abbruch(#7'Error: caller of imported function '
+StrPas(@symbolstringtabelle^[temp_import_tabelle_z^[z].sym_index])
+' not found');
end;
Erzeuge_Hash_Tabelle;
// die temp_import_tabelle wird nicht mehr benötigt
FreeMem(temp_import_tabelle_z);
anzahl_importe:=temp_import_tabelle_gefuellt;
FreeMem(plt_index_tabelle);
end;