ELF.ob07 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2019-2021, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE ELF;
  7. IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS, STRINGS;
  8. CONST
  9. EI_NIDENT = 16;
  10. ET_EXEC = 2;
  11. ET_DYN = 3;
  12. EM_386 = 3;
  13. EM_8664 = 3EH;
  14. ELFCLASS32 = 1;
  15. ELFCLASS64 = 2;
  16. ELFDATA2LSB = 1;
  17. ELFDATA2MSB = 2;
  18. PF_X = 1;
  19. PF_W = 2;
  20. PF_R = 4;
  21. TYPE
  22. Elf32_Ehdr = RECORD
  23. e_ident: ARRAY EI_NIDENT OF BYTE;
  24. e_type,
  25. e_machine: WCHAR;
  26. e_version,
  27. e_entry,
  28. e_phoff,
  29. e_shoff,
  30. e_flags: INTEGER;
  31. e_ehsize,
  32. e_phentsize,
  33. e_phnum,
  34. e_shentsize,
  35. e_shnum,
  36. e_shstrndx: WCHAR
  37. END;
  38. Elf32_Phdr = RECORD
  39. p_type,
  40. p_offset,
  41. p_vaddr,
  42. p_paddr,
  43. p_filesz,
  44. p_memsz,
  45. p_flags,
  46. p_align: INTEGER
  47. END;
  48. Elf32_Dyn = POINTER TO RECORD (LISTS.ITEM)
  49. d_tag, d_val: INTEGER
  50. END;
  51. Elf32_Sym = POINTER TO RECORD (LISTS.ITEM)
  52. name, value, size: INTEGER;
  53. info, other: CHAR;
  54. shndx: WCHAR
  55. END;
  56. VAR
  57. dynamic: LISTS.LIST;
  58. strtab: CHL.BYTELIST;
  59. symtab: LISTS.LIST;
  60. hashtab, bucket, chain: CHL.INTLIST;
  61. PROCEDURE Write16 (w: WCHAR);
  62. BEGIN
  63. WR.Write16LE(ORD(w))
  64. END Write16;
  65. PROCEDURE WritePH (ph: Elf32_Phdr);
  66. BEGIN
  67. WR.Write32LE(ph.p_type);
  68. WR.Write32LE(ph.p_offset);
  69. WR.Write32LE(ph.p_vaddr);
  70. WR.Write32LE(ph.p_paddr);
  71. WR.Write32LE(ph.p_filesz);
  72. WR.Write32LE(ph.p_memsz);
  73. WR.Write32LE(ph.p_flags);
  74. WR.Write32LE(ph.p_align)
  75. END WritePH;
  76. PROCEDURE WritePH64 (ph: Elf32_Phdr);
  77. BEGIN
  78. WR.Write32LE(ph.p_type);
  79. WR.Write32LE(ph.p_flags);
  80. WR.Write64LE(ph.p_offset);
  81. WR.Write64LE(ph.p_vaddr);
  82. WR.Write64LE(ph.p_paddr);
  83. WR.Write64LE(ph.p_filesz);
  84. WR.Write64LE(ph.p_memsz);
  85. WR.Write64LE(ph.p_align)
  86. END WritePH64;
  87. PROCEDURE NewDyn (tag, val: INTEGER);
  88. VAR
  89. dyn: Elf32_Dyn;
  90. BEGIN
  91. NEW(dyn);
  92. dyn.d_tag := tag;
  93. dyn.d_val := val;
  94. LISTS.push(dynamic, dyn)
  95. END NewDyn;
  96. PROCEDURE NewSym (name, value, size: INTEGER; info, other: CHAR; shndx: WCHAR);
  97. VAR
  98. sym: Elf32_Sym;
  99. BEGIN
  100. NEW(sym);
  101. sym.name := name;
  102. sym.value := value;
  103. sym.size := size;
  104. sym.info := info;
  105. sym.other := other;
  106. sym.shndx := shndx;
  107. LISTS.push(symtab, sym)
  108. END NewSym;
  109. PROCEDURE MakeHash (bucket, chain: CHL.INTLIST; symCount: INTEGER);
  110. VAR
  111. symi, hi, k: INTEGER;
  112. BEGIN
  113. FOR symi := 0 TO symCount - 1 DO
  114. CHL.SetInt(chain, symi, 0);
  115. hi := CHL.GetInt(hashtab, symi) MOD symCount;
  116. IF CHL.GetInt(bucket, hi) # 0 THEN
  117. k := symi;
  118. WHILE CHL.GetInt(chain, k) # 0 DO
  119. k := CHL.GetInt(chain, k)
  120. END;
  121. CHL.SetInt(chain, k, CHL.GetInt(bucket, hi))
  122. END;
  123. CHL.SetInt(bucket, hi, symi)
  124. END
  125. END MakeHash;
  126. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; fini: INTEGER; so, amd64: BOOLEAN);
  127. CONST
  128. interp = 0;
  129. dyn = 1;
  130. header = 2;
  131. text = 3;
  132. data = 4;
  133. bss = 5;
  134. linuxInterpreter64 = "/lib64/ld-linux-x86-64.so.2";
  135. linuxInterpreter32 = "/lib/ld-linux.so.2";
  136. exeBaseAddress32 = 8048000H;
  137. exeBaseAddress64 = 400000H;
  138. dllBaseAddress = 0;
  139. DT_NULL = 0;
  140. DT_NEEDED = 1;
  141. DT_HASH = 4;
  142. DT_STRTAB = 5;
  143. DT_SYMTAB = 6;
  144. DT_RELA = 7;
  145. DT_RELASZ = 8;
  146. DT_RELAENT = 9;
  147. DT_STRSZ = 10;
  148. DT_SYMENT = 11;
  149. DT_INIT = 12;
  150. DT_FINI = 13;
  151. DT_SONAME = 14;
  152. DT_REL = 17;
  153. DT_RELSZ = 18;
  154. DT_RELENT = 19;
  155. VAR
  156. ehdr: Elf32_Ehdr;
  157. phdr: ARRAY 16 OF Elf32_Phdr;
  158. i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER;
  159. SizeOf: RECORD header, code, data, bss: INTEGER END;
  160. Offset: RECORD symtab, reltab, hash, strtab: INTEGER END;
  161. Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER;
  162. item: LISTS.ITEM;
  163. Name: ARRAY 2048 OF CHAR;
  164. Address: PE32.VIRTUAL_ADDR;
  165. BEGIN
  166. dynamic := LISTS.create(NIL);
  167. symtab := LISTS.create(NIL);
  168. strtab := CHL.CreateByteList();
  169. IF amd64 THEN
  170. BaseAdr := exeBaseAddress64;
  171. Interpreter := linuxInterpreter64
  172. ELSE
  173. BaseAdr := exeBaseAddress32;
  174. Interpreter := linuxInterpreter32
  175. END;
  176. IF so THEN
  177. BaseAdr := dllBaseAddress
  178. END;
  179. lenInterpreter := LENGTH(Interpreter) + 1;
  180. SizeOf.code := CHL.Length(program.code);
  181. SizeOf.data := CHL.Length(program.data);
  182. SizeOf.bss := program.bss;
  183. ehdr.e_ident[0] := 7FH;
  184. ehdr.e_ident[1] := ORD("E");
  185. ehdr.e_ident[2] := ORD("L");
  186. ehdr.e_ident[3] := ORD("F");
  187. IF amd64 THEN
  188. ehdr.e_ident[4] := ELFCLASS64
  189. ELSE
  190. ehdr.e_ident[4] := ELFCLASS32
  191. END;
  192. ehdr.e_ident[5] := ELFDATA2LSB;
  193. ehdr.e_ident[6] := 1;
  194. ehdr.e_ident[7] := 3;
  195. FOR i := 8 TO EI_NIDENT - 1 DO
  196. ehdr.e_ident[i] := 0
  197. END;
  198. IF so THEN
  199. ehdr.e_type := WCHR(ET_DYN)
  200. ELSE
  201. ehdr.e_type := WCHR(ET_EXEC)
  202. END;
  203. ehdr.e_version := 1;
  204. ehdr.e_shoff := 0;
  205. ehdr.e_flags := 0;
  206. ehdr.e_shnum := WCHR(0);
  207. ehdr.e_shstrndx := WCHR(0);
  208. ehdr.e_phnum := WCHR(6);
  209. IF amd64 THEN
  210. ehdr.e_machine := WCHR(EM_8664);
  211. ehdr.e_phoff := 40H;
  212. ehdr.e_ehsize := WCHR(40H);
  213. ehdr.e_phentsize := WCHR(38H);
  214. ehdr.e_shentsize := WCHR(40H)
  215. ELSE
  216. ehdr.e_machine := WCHR(EM_386);
  217. ehdr.e_phoff := 34H;
  218. ehdr.e_ehsize := WCHR(34H);
  219. ehdr.e_phentsize := WCHR(20H);
  220. ehdr.e_shentsize := WCHR(28H)
  221. END;
  222. SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum);
  223. phdr[interp].p_type := 3;
  224. phdr[interp].p_offset := SizeOf.header;
  225. phdr[interp].p_vaddr := BaseAdr + phdr[interp].p_offset;
  226. phdr[interp].p_paddr := phdr[interp].p_vaddr;
  227. phdr[interp].p_filesz := lenInterpreter;
  228. phdr[interp].p_memsz := lenInterpreter;
  229. phdr[interp].p_flags := PF_R;
  230. phdr[interp].p_align := 1;
  231. phdr[dyn].p_type := 2;
  232. phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz;
  233. phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset;
  234. phdr[dyn].p_paddr := phdr[dyn].p_vaddr;
  235. hashtab := CHL.CreateIntList();
  236. CHL.PushInt(hashtab, STRINGS.HashStr(""));
  237. NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X);
  238. CHL.PushInt(hashtab, STRINGS.HashStr("dlopen"));
  239. NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X);
  240. CHL.PushInt(hashtab, STRINGS.HashStr("dlsym"));
  241. NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X);
  242. IF so THEN
  243. item := program.exp_list.first;
  244. WHILE item # NIL DO
  245. ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name));
  246. CHL.PushInt(hashtab, STRINGS.HashStr(Name));
  247. NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X);
  248. item := item.next
  249. END;
  250. ASSERT(CHL.GetStr(program.data, program.modname, Name))
  251. END;
  252. symCount := LISTS.count(symtab);
  253. bucket := CHL.CreateIntList();
  254. chain := CHL.CreateIntList();
  255. FOR i := 1 TO symCount DO
  256. CHL.PushInt(bucket, 0);
  257. CHL.PushInt(chain, 0)
  258. END;
  259. MakeHash(bucket, chain, symCount);
  260. NewDyn(DT_NEEDED, CHL.PushStr(strtab, "libdl.so.2"));
  261. NewDyn(DT_STRTAB, 0);
  262. NewDyn(DT_STRSZ, CHL.Length(strtab));
  263. NewDyn(DT_SYMTAB, 0);
  264. IF amd64 THEN
  265. NewDyn(DT_SYMENT, 24);
  266. NewDyn(DT_RELA, 0);
  267. NewDyn(DT_RELASZ, 48);
  268. NewDyn(DT_RELAENT, 24)
  269. ELSE
  270. NewDyn(DT_SYMENT, 16);
  271. NewDyn(DT_REL, 0);
  272. NewDyn(DT_RELSZ, 16);
  273. NewDyn(DT_RELENT, 8)
  274. END;
  275. NewDyn(DT_HASH, 0);
  276. IF so THEN
  277. NewDyn(DT_SONAME, CHL.PushStr(strtab, Name));
  278. NewDyn(DT_INIT, 0);
  279. NewDyn(DT_FINI, 0)
  280. END;
  281. NewDyn(DT_NULL, 0);
  282. Offset.symtab := LISTS.count(dynamic) * (8 + 8 * ORD(amd64));
  283. Offset.reltab := Offset.symtab + symCount * (16 + 8 * ORD(amd64));
  284. Offset.hash := Offset.reltab + (8 + 16 * ORD(amd64)) * 2;
  285. Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4;
  286. DynAdr := phdr[dyn].p_offset + BaseAdr;
  287. item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr;
  288. item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr;
  289. item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr;
  290. item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash + DynAdr;
  291. phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64);
  292. phdr[dyn].p_memsz := phdr[dyn].p_filesz;
  293. phdr[dyn].p_flags := PF_R;
  294. phdr[dyn].p_align := 1;
  295. offset := 0;
  296. phdr[header].p_type := 1;
  297. phdr[header].p_offset := offset;
  298. phdr[header].p_vaddr := BaseAdr;
  299. phdr[header].p_paddr := BaseAdr;
  300. phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz;
  301. phdr[header].p_memsz := phdr[header].p_filesz;
  302. phdr[header].p_flags := PF_R + PF_W;
  303. phdr[header].p_align := 1000H;
  304. INC(offset, phdr[header].p_filesz);
  305. VA := BaseAdr + offset + 1000H;
  306. phdr[text].p_type := 1;
  307. phdr[text].p_offset := offset;
  308. phdr[text].p_vaddr := VA;
  309. phdr[text].p_paddr := VA;
  310. phdr[text].p_filesz := SizeOf.code;
  311. phdr[text].p_memsz := SizeOf.code;
  312. phdr[text].p_flags := PF_X + PF_R;
  313. phdr[text].p_align := 1000H;
  314. ehdr.e_entry := phdr[text].p_vaddr;
  315. INC(offset, phdr[text].p_filesz);
  316. VA := BaseAdr + offset + 2000H;
  317. pad := (16 - VA MOD 16) MOD 16;
  318. phdr[data].p_type := 1;
  319. phdr[data].p_offset := offset;
  320. phdr[data].p_vaddr := VA;
  321. phdr[data].p_paddr := VA;
  322. phdr[data].p_filesz := SizeOf.data + pad;
  323. phdr[data].p_memsz := SizeOf.data + pad;
  324. phdr[data].p_flags := PF_R + PF_W;
  325. phdr[data].p_align := 1000H;
  326. INC(offset, phdr[data].p_filesz);
  327. VA := BaseAdr + offset + 3000H;
  328. phdr[bss].p_type := 1;
  329. phdr[bss].p_offset := offset;
  330. phdr[bss].p_vaddr := VA;
  331. phdr[bss].p_paddr := VA;
  332. phdr[bss].p_filesz := 0;
  333. phdr[bss].p_memsz := SizeOf.bss + 16;
  334. phdr[bss].p_flags := PF_R + PF_W;
  335. phdr[bss].p_align := 1000H;
  336. Address.Code := ehdr.e_entry;
  337. Address.Data := phdr[data].p_vaddr + pad;
  338. Address.Bss := WR.align(phdr[bss].p_vaddr, 16);
  339. Address.Import := 0;
  340. PE32.fixup(program, Address, amd64);
  341. item := symtab.first;
  342. WHILE item # NIL DO
  343. IF item(Elf32_Sym).value # 0 THEN
  344. INC(item(Elf32_Sym).value, ehdr.e_entry)
  345. END;
  346. item := item.next
  347. END;
  348. IF so THEN
  349. item := LISTS.getidx(dynamic, 10); item(Elf32_Dyn).d_val := ehdr.e_entry;
  350. item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry
  351. END;
  352. WR.Create(FileName);
  353. FOR i := 0 TO EI_NIDENT - 1 DO
  354. WR.WriteByte(ehdr.e_ident[i])
  355. END;
  356. Write16(ehdr.e_type);
  357. Write16(ehdr.e_machine);
  358. WR.Write32LE(ehdr.e_version);
  359. IF amd64 THEN
  360. WR.Write64LE(ehdr.e_entry);
  361. WR.Write64LE(ehdr.e_phoff);
  362. WR.Write64LE(ehdr.e_shoff)
  363. ELSE
  364. WR.Write32LE(ehdr.e_entry);
  365. WR.Write32LE(ehdr.e_phoff);
  366. WR.Write32LE(ehdr.e_shoff)
  367. END;
  368. WR.Write32LE(ehdr.e_flags);
  369. Write16(ehdr.e_ehsize);
  370. Write16(ehdr.e_phentsize);
  371. Write16(ehdr.e_phnum);
  372. Write16(ehdr.e_shentsize);
  373. Write16(ehdr.e_shnum);
  374. Write16(ehdr.e_shstrndx);
  375. IF amd64 THEN
  376. WritePH64(phdr[interp]);
  377. WritePH64(phdr[dyn]);
  378. WritePH64(phdr[header]);
  379. WritePH64(phdr[text]);
  380. WritePH64(phdr[data]);
  381. WritePH64(phdr[bss])
  382. ELSE
  383. WritePH(phdr[interp]);
  384. WritePH(phdr[dyn]);
  385. WritePH(phdr[header]);
  386. WritePH(phdr[text]);
  387. WritePH(phdr[data]);
  388. WritePH(phdr[bss])
  389. END;
  390. FOR i := 0 TO lenInterpreter - 1 DO
  391. WR.WriteByte(ORD(Interpreter[i]))
  392. END;
  393. IF amd64 THEN
  394. item := dynamic.first;
  395. WHILE item # NIL DO
  396. WR.Write64LE(item(Elf32_Dyn).d_tag);
  397. WR.Write64LE(item(Elf32_Dyn).d_val);
  398. item := item.next
  399. END;
  400. item := symtab.first;
  401. WHILE item # NIL DO
  402. WR.Write32LE(item(Elf32_Sym).name);
  403. WR.WriteByte(ORD(item(Elf32_Sym).info));
  404. WR.WriteByte(ORD(item(Elf32_Sym).other));
  405. Write16(item(Elf32_Sym).shndx);
  406. WR.Write64LE(item(Elf32_Sym).value);
  407. WR.Write64LE(item(Elf32_Sym).size);
  408. item := item.next
  409. END;
  410. WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16);
  411. WR.Write32LE(1);
  412. WR.Write32LE(1);
  413. WR.Write64LE(0);
  414. WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8);
  415. WR.Write32LE(1);
  416. WR.Write32LE(2);
  417. WR.Write64LE(0)
  418. ELSE
  419. item := dynamic.first;
  420. WHILE item # NIL DO
  421. WR.Write32LE(item(Elf32_Dyn).d_tag);
  422. WR.Write32LE(item(Elf32_Dyn).d_val);
  423. item := item.next
  424. END;
  425. item := symtab.first;
  426. WHILE item # NIL DO
  427. WR.Write32LE(item(Elf32_Sym).name);
  428. WR.Write32LE(item(Elf32_Sym).value);
  429. WR.Write32LE(item(Elf32_Sym).size);
  430. WR.WriteByte(ORD(item(Elf32_Sym).info));
  431. WR.WriteByte(ORD(item(Elf32_Sym).other));
  432. Write16(item(Elf32_Sym).shndx);
  433. item := item.next
  434. END;
  435. WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8);
  436. WR.Write32LE(00000101H);
  437. WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4);
  438. WR.Write32LE(00000201H)
  439. END;
  440. WR.Write32LE(symCount);
  441. WR.Write32LE(symCount);
  442. FOR i := 0 TO symCount - 1 DO
  443. WR.Write32LE(CHL.GetInt(bucket, i))
  444. END;
  445. FOR i := 0 TO symCount - 1 DO
  446. WR.Write32LE(CHL.GetInt(chain, i))
  447. END;
  448. CHL.WriteToFile(strtab);
  449. IF amd64 THEN
  450. WR.Write64LE(0);
  451. WR.Write64LE(0)
  452. ELSE
  453. WR.Write32LE(0);
  454. WR.Write32LE(0)
  455. END;
  456. CHL.WriteToFile(program.code);
  457. WHILE pad > 0 DO
  458. WR.WriteByte(0);
  459. DEC(pad)
  460. END;
  461. CHL.WriteToFile(program.data);
  462. WR.Close;
  463. UTILS.chmod(FileName)
  464. END write;
  465. END ELF.