| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- MODULE ELF;
- IMPORT
- BIN,
- WR := WRITER,
- CHL := CHUNKLISTS,
- LISTS,
- PE32,
- UTILS IN "./utils/UTILS.ob07",
- STRINGS IN "./strings/STRINGS.ob07";
- CONST
- EI_NIDENT = 16;
- ET_EXEC = 2;
- ET_DYN = 3;
- EM_386 = 3;
- EM_8664 = 3EH;
- ELFCLASS32 = 1;
- ELFCLASS64 = 2;
- ELFDATA2LSB = 1;
- ELFDATA2MSB = 2;
- PF_X = 1;
- PF_W = 2;
- PF_R = 4;
- TYPE
- Elf32_Ehdr = RECORD
- e_ident: ARRAY EI_NIDENT OF BYTE;
- e_type,
- e_machine: WCHAR;
- e_version,
- e_entry,
- e_phoff,
- e_shoff,
- e_flags: INTEGER;
- e_ehsize,
- e_phentsize,
- e_phnum,
- e_shentsize,
- e_shnum,
- e_shstrndx: WCHAR
- END;
- Elf32_Phdr = RECORD
- p_type,
- p_offset,
- p_vaddr,
- p_paddr,
- p_filesz,
- p_memsz,
- p_flags,
- p_align: INTEGER
- END;
- Elf32_Dyn = POINTER TO RECORD (LISTS.ITEM)
- d_tag, d_val: INTEGER
- END;
- Elf32_Sym = POINTER TO RECORD (LISTS.ITEM)
- name, value, size: INTEGER;
- info, other: CHAR;
- shndx: WCHAR
- END;
- VAR
- dynamic: LISTS.LIST;
- strtab: CHL.BYTELIST;
- symtab: LISTS.LIST;
- hashtab, bucket, chain: CHL.INTLIST;
- PROCEDURE Write16 (w: WCHAR);
- BEGIN
- WR.Write16LE(ORD(w))
- END Write16;
- PROCEDURE WritePH (ph: Elf32_Phdr);
- BEGIN
- WR.Write32LE(ph.p_type);
- WR.Write32LE(ph.p_offset);
- WR.Write32LE(ph.p_vaddr);
- WR.Write32LE(ph.p_paddr);
- WR.Write32LE(ph.p_filesz);
- WR.Write32LE(ph.p_memsz);
- WR.Write32LE(ph.p_flags);
- WR.Write32LE(ph.p_align)
- END WritePH;
- PROCEDURE WritePH64 (ph: Elf32_Phdr);
- BEGIN
- WR.Write32LE(ph.p_type);
- WR.Write32LE(ph.p_flags);
- WR.Write64LE(ph.p_offset);
- WR.Write64LE(ph.p_vaddr);
- WR.Write64LE(ph.p_paddr);
- WR.Write64LE(ph.p_filesz);
- WR.Write64LE(ph.p_memsz);
- WR.Write64LE(ph.p_align)
- END WritePH64;
- PROCEDURE NewDyn (tag, val: INTEGER);
- VAR
- dyn: Elf32_Dyn;
- BEGIN
- NEW(dyn);
- dyn.d_tag := tag;
- dyn.d_val := val;
- LISTS.push(dynamic, dyn)
- END NewDyn;
- PROCEDURE NewSym (name, value, size: INTEGER; info, other: CHAR; shndx: WCHAR);
- VAR
- sym: Elf32_Sym;
- BEGIN
- NEW(sym);
- sym.name := name;
- sym.value := value;
- sym.size := size;
- sym.info := info;
- sym.other := other;
- sym.shndx := shndx;
- LISTS.push(symtab, sym)
- END NewSym;
- PROCEDURE MakeHash (bucket, chain: CHL.INTLIST; symCount: INTEGER);
- VAR
- symi, hi, k: INTEGER;
- BEGIN
- FOR symi := 0 TO symCount - 1 DO
- CHL.SetInt(chain, symi, 0);
- hi := CHL.GetInt(hashtab, symi) MOD symCount;
- IF CHL.GetInt(bucket, hi) # 0 THEN
- k := symi;
- WHILE CHL.GetInt(chain, k) # 0 DO
- k := CHL.GetInt(chain, k)
- END;
- CHL.SetInt(chain, k, CHL.GetInt(bucket, hi))
- END;
- CHL.SetInt(bucket, hi, symi)
- END
- END MakeHash;
- PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; fini: INTEGER; so, amd64: BOOLEAN);
- CONST
- interp = 0;
- dyn = 1;
- header = 2;
- text = 3;
- data = 4;
- bss = 5;
- linuxInterpreter64 = "/lib64/ld-linux-x86-64.so.2";
- linuxInterpreter32 = "/lib/ld-linux.so.2";
- exeBaseAddress32 = 8048000H;
- exeBaseAddress64 = 400000H;
- dllBaseAddress = 0;
- DT_NULL = 0;
- DT_NEEDED = 1;
- DT_HASH = 4;
- DT_STRTAB = 5;
- DT_SYMTAB = 6;
- DT_RELA = 7;
- DT_RELASZ = 8;
- DT_RELAENT = 9;
- DT_STRSZ = 10;
- DT_SYMENT = 11;
- DT_INIT = 12;
- DT_FINI = 13;
- DT_SONAME = 14;
- DT_REL = 17;
- DT_RELSZ = 18;
- DT_RELENT = 19;
- VAR
- ehdr: Elf32_Ehdr;
- phdr: ARRAY 16 OF Elf32_Phdr;
- i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER;
- SizeOf: RECORD header, code, data, bss: INTEGER END;
- Offset: RECORD symtab, reltab, hash, strtab: INTEGER END;
- Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER;
- item: LISTS.ITEM;
- Name: ARRAY 2048 OF CHAR;
- Address: PE32.VIRTUAL_ADDR;
- BEGIN
- dynamic := LISTS.create(NIL);
- symtab := LISTS.create(NIL);
- strtab := CHL.CreateByteList();
- IF amd64 THEN
- BaseAdr := exeBaseAddress64;
- Interpreter := linuxInterpreter64
- ELSE
- BaseAdr := exeBaseAddress32;
- Interpreter := linuxInterpreter32
- END;
- IF so THEN
- BaseAdr := dllBaseAddress
- END;
- lenInterpreter := LENGTH(Interpreter) + 1;
- SizeOf.code := CHL.Length(program.code);
- SizeOf.data := CHL.Length(program.data);
- SizeOf.bss := program.bss;
- ehdr.e_ident[0] := 7FH;
- ehdr.e_ident[1] := ORD("E");
- ehdr.e_ident[2] := ORD("L");
- ehdr.e_ident[3] := ORD("F");
- IF amd64 THEN
- ehdr.e_ident[4] := ELFCLASS64
- ELSE
- ehdr.e_ident[4] := ELFCLASS32
- END;
- ehdr.e_ident[5] := ELFDATA2LSB;
- ehdr.e_ident[6] := 1;
- ehdr.e_ident[7] := 3;
- FOR i := 8 TO EI_NIDENT - 1 DO
- ehdr.e_ident[i] := 0
- END;
- IF so THEN
- ehdr.e_type := WCHR(ET_DYN)
- ELSE
- ehdr.e_type := WCHR(ET_EXEC)
- END;
- ehdr.e_version := 1;
- ehdr.e_shoff := 0;
- ehdr.e_flags := 0;
- ehdr.e_shnum := WCHR(0);
- ehdr.e_shstrndx := WCHR(0);
- ehdr.e_phnum := WCHR(6);
- IF amd64 THEN
- ehdr.e_machine := WCHR(EM_8664);
- ehdr.e_phoff := 40H;
- ehdr.e_ehsize := WCHR(40H);
- ehdr.e_phentsize := WCHR(38H);
- ehdr.e_shentsize := WCHR(40H)
- ELSE
- ehdr.e_machine := WCHR(EM_386);
- ehdr.e_phoff := 34H;
- ehdr.e_ehsize := WCHR(34H);
- ehdr.e_phentsize := WCHR(20H);
- ehdr.e_shentsize := WCHR(28H)
- END;
- SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum);
- phdr[interp].p_type := 3;
- phdr[interp].p_offset := SizeOf.header;
- phdr[interp].p_vaddr := BaseAdr + phdr[interp].p_offset;
- phdr[interp].p_paddr := phdr[interp].p_vaddr;
- phdr[interp].p_filesz := lenInterpreter;
- phdr[interp].p_memsz := lenInterpreter;
- phdr[interp].p_flags := PF_R;
- phdr[interp].p_align := 1;
- phdr[dyn].p_type := 2;
- phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz;
- phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset;
- phdr[dyn].p_paddr := phdr[dyn].p_vaddr;
- hashtab := CHL.CreateIntList();
- CHL.PushInt(hashtab, STRINGS.HashStr(""));
- NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X);
- CHL.PushInt(hashtab, STRINGS.HashStr("dlopen"));
- NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X);
- CHL.PushInt(hashtab, STRINGS.HashStr("dlsym"));
- NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X);
- IF so THEN
- item := program.exp_list.first;
- WHILE item # NIL DO
- ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name));
- CHL.PushInt(hashtab, STRINGS.HashStr(Name));
- NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X);
- item := item.next
- END;
- ASSERT(CHL.GetStr(program.data, program.modname, Name))
- END;
- symCount := LISTS.count(symtab);
- bucket := CHL.CreateIntList();
- chain := CHL.CreateIntList();
- FOR i := 1 TO symCount DO
- CHL.PushInt(bucket, 0);
- CHL.PushInt(chain, 0)
- END;
- MakeHash(bucket, chain, symCount);
- NewDyn(DT_NEEDED, CHL.PushStr(strtab, "libdl.so.2"));
- NewDyn(DT_STRTAB, 0);
- NewDyn(DT_STRSZ, CHL.Length(strtab));
- NewDyn(DT_SYMTAB, 0);
- IF amd64 THEN
- NewDyn(DT_SYMENT, 24);
- NewDyn(DT_RELA, 0);
- NewDyn(DT_RELASZ, 48);
- NewDyn(DT_RELAENT, 24)
- ELSE
- NewDyn(DT_SYMENT, 16);
- NewDyn(DT_REL, 0);
- NewDyn(DT_RELSZ, 16);
- NewDyn(DT_RELENT, 8)
- END;
- NewDyn(DT_HASH, 0);
- IF so THEN
- NewDyn(DT_SONAME, CHL.PushStr(strtab, Name));
- NewDyn(DT_INIT, 0);
- NewDyn(DT_FINI, 0)
- END;
- NewDyn(DT_NULL, 0);
- Offset.symtab := LISTS.count(dynamic) * (8 + 8 * ORD(amd64));
- Offset.reltab := Offset.symtab + symCount * (16 + 8 * ORD(amd64));
- Offset.hash := Offset.reltab + (8 + 16 * ORD(amd64)) * 2;
- Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4;
- DynAdr := phdr[dyn].p_offset + BaseAdr;
- item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr;
- item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr;
- item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr;
- item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + DynAdr;
- phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64);
- phdr[dyn].p_memsz := phdr[dyn].p_filesz;
- phdr[dyn].p_flags := PF_R;
- phdr[dyn].p_align := 1;
- offset := 0;
- phdr[header].p_type := 1;
- phdr[header].p_offset := offset;
- phdr[header].p_vaddr := BaseAdr;
- phdr[header].p_paddr := BaseAdr;
- phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz;
- phdr[header].p_memsz := phdr[header].p_filesz;
- phdr[header].p_flags := PF_R + PF_W;
- phdr[header].p_align := 1000H;
- INC(offset, phdr[header].p_filesz);
- VA := BaseAdr + offset + 1000H;
- phdr[text].p_type := 1;
- phdr[text].p_offset := offset;
- phdr[text].p_vaddr := VA;
- phdr[text].p_paddr := VA;
- phdr[text].p_filesz := SizeOf.code;
- phdr[text].p_memsz := SizeOf.code;
- phdr[text].p_flags := PF_X + PF_R;
- phdr[text].p_align := 1000H;
- ehdr.e_entry := phdr[text].p_vaddr;
- INC(offset, phdr[text].p_filesz);
- VA := BaseAdr + offset + 2000H;
- pad := (16 - VA MOD 16) MOD 16;
- phdr[data].p_type := 1;
- phdr[data].p_offset := offset;
- phdr[data].p_vaddr := VA;
- phdr[data].p_paddr := VA;
- phdr[data].p_filesz := SizeOf.data + pad;
- phdr[data].p_memsz := SizeOf.data + pad;
- phdr[data].p_flags := PF_R + PF_W;
- phdr[data].p_align := 1000H;
- INC(offset, phdr[data].p_filesz);
- VA := BaseAdr + offset + 3000H;
- phdr[bss].p_type := 1;
- phdr[bss].p_offset := offset;
- phdr[bss].p_vaddr := VA;
- phdr[bss].p_paddr := VA;
- phdr[bss].p_filesz := 0;
- phdr[bss].p_memsz := SizeOf.bss + 16;
- phdr[bss].p_flags := PF_R + PF_W;
- phdr[bss].p_align := 1000H;
- Address.Code := ehdr.e_entry;
- Address.Data := phdr[data].p_vaddr + pad;
- Address.Bss := WR.align(phdr[bss].p_vaddr, 16);
- Address.Import := 0;
- PE32.fixup(program, Address, amd64);
- item := symtab.first;
- WHILE item # NIL DO
- IF item(Elf32_Sym).value # 0 THEN
- INC(item(Elf32_Sym).value, ehdr.e_entry)
- END;
- item := item.next
- END;
- IF so THEN
- item := LISTS.getidx(dynamic, 10); item(Elf32_Dyn).d_val := ehdr.e_entry;
- item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry
- END;
- WR.Create(FileName);
- FOR i := 0 TO EI_NIDENT - 1 DO
- WR.WriteByte(ehdr.e_ident[i])
- END;
- Write16(ehdr.e_type);
- Write16(ehdr.e_machine);
- WR.Write32LE(ehdr.e_version);
- IF amd64 THEN
- WR.Write64LE(ehdr.e_entry);
- WR.Write64LE(ehdr.e_phoff);
- WR.Write64LE(ehdr.e_shoff)
- ELSE
- WR.Write32LE(ehdr.e_entry);
- WR.Write32LE(ehdr.e_phoff);
- WR.Write32LE(ehdr.e_shoff)
- END;
- WR.Write32LE(ehdr.e_flags);
- Write16(ehdr.e_ehsize);
- Write16(ehdr.e_phentsize);
- Write16(ehdr.e_phnum);
- Write16(ehdr.e_shentsize);
- Write16(ehdr.e_shnum);
- Write16(ehdr.e_shstrndx);
- IF amd64 THEN
- WritePH64(phdr[interp]);
- WritePH64(phdr[dyn]);
- WritePH64(phdr[header]);
- WritePH64(phdr[text]);
- WritePH64(phdr[data]);
- WritePH64(phdr[bss])
- ELSE
- WritePH(phdr[interp]);
- WritePH(phdr[dyn]);
- WritePH(phdr[header]);
- WritePH(phdr[text]);
- WritePH(phdr[data]);
- WritePH(phdr[bss])
- END;
- FOR i := 0 TO lenInterpreter - 1 DO
- WR.WriteByte(ORD(Interpreter[i]))
- END;
- IF amd64 THEN
- item := dynamic.first;
- WHILE item # NIL DO
- WR.Write64LE(item(Elf32_Dyn).d_tag);
- WR.Write64LE(item(Elf32_Dyn).d_val);
- item := item.next
- END;
- item := symtab.first;
- WHILE item # NIL DO
- WR.Write32LE(item(Elf32_Sym).name);
- WR.WriteByte(ORD(item(Elf32_Sym).info));
- WR.WriteByte(ORD(item(Elf32_Sym).other));
- Write16(item(Elf32_Sym).shndx);
- WR.Write64LE(item(Elf32_Sym).value);
- WR.Write64LE(item(Elf32_Sym).size);
- item := item.next
- END;
- WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16);
- WR.Write32LE(1);
- WR.Write32LE(1);
- WR.Write64LE(0);
- WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8);
- WR.Write32LE(1);
- WR.Write32LE(2);
- WR.Write64LE(0)
- ELSE
- item := dynamic.first;
- WHILE item # NIL DO
- WR.Write32LE(item(Elf32_Dyn).d_tag);
- WR.Write32LE(item(Elf32_Dyn).d_val);
- item := item.next
- END;
- item := symtab.first;
- WHILE item # NIL DO
- WR.Write32LE(item(Elf32_Sym).name);
- WR.Write32LE(item(Elf32_Sym).value);
- WR.Write32LE(item(Elf32_Sym).size);
- WR.WriteByte(ORD(item(Elf32_Sym).info));
- WR.WriteByte(ORD(item(Elf32_Sym).other));
- Write16(item(Elf32_Sym).shndx);
- item := item.next
- END;
- WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8);
- WR.Write32LE(00000101H);
- WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4);
- WR.Write32LE(00000201H)
- END;
- WR.Write32LE(symCount);
- WR.Write32LE(symCount);
- FOR i := 0 TO symCount - 1 DO
- WR.Write32LE(CHL.GetInt(bucket, i))
- END;
- FOR i := 0 TO symCount - 1 DO
- WR.Write32LE(CHL.GetInt(chain, i))
- END;
- CHL.WriteToFile(strtab);
- IF amd64 THEN
- WR.Write64LE(0);
- WR.Write64LE(0)
- ELSE
- WR.Write32LE(0);
- WR.Write32LE(0)
- END;
- CHL.WriteToFile(program.code);
- WHILE pad > 0 DO
- WR.WriteByte(0);
- DEC(pad)
- END;
- CHL.WriteToFile(program.data);
- WR.Close;
- UTILS.chmod(FileName)
- END write;
- END ELF.
|