Subversion Repositories Kolibri OS

Rev

Rev 6613 | Rev 7693 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2019, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE ELF;
  9.  
  10. IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS;
  11.  
  12.  
  13. CONST
  14.  
  15.     EI_NIDENT = 16;
  16.     ET_EXEC = 2;
  17.     ET_DYN = 3;
  18.  
  19.     EM_386 = 3;
  20.     EM_8664 = 3EH;
  21.  
  22.     ELFCLASS32 = 1;
  23.     ELFCLASS64 = 2;
  24.  
  25.     ELFDATA2LSB = 1;
  26.     ELFDATA2MSB = 2;
  27.  
  28.     PF_X = 1;
  29.     PF_W = 2;
  30.     PF_R = 4;
  31.  
  32.  
  33. TYPE
  34.  
  35.     Elf32_Ehdr = RECORD
  36.  
  37.         e_ident: ARRAY EI_NIDENT OF BYTE;
  38.  
  39.         e_type,
  40.         e_machine: WCHAR;
  41.  
  42.         e_version,
  43.         e_entry,
  44.         e_phoff,
  45.         e_shoff,
  46.         e_flags: INTEGER;
  47.  
  48.         e_ehsize,
  49.         e_phentsize,
  50.         e_phnum,
  51.         e_shentsize,
  52.         e_shnum,
  53.         e_shstrndx: WCHAR
  54.  
  55.     END;
  56.  
  57.  
  58.     Elf32_Phdr = RECORD
  59.  
  60.         p_type,
  61.         p_offset,
  62.         p_vaddr,
  63.         p_paddr,
  64.         p_filesz,
  65.         p_memsz,
  66.         p_flags,
  67.         p_align: INTEGER
  68.  
  69.     END;
  70.  
  71.     FILE = WR.FILE;
  72.  
  73.  
  74. PROCEDURE align (n, _align: INTEGER): INTEGER;
  75. BEGIN
  76.     IF n MOD _align # 0 THEN
  77.         n := n + _align - (n MOD _align)
  78.     END
  79.  
  80.     RETURN n
  81. END align;
  82.  
  83.  
  84. PROCEDURE Write16 (file: FILE; w: WCHAR);
  85. BEGIN
  86.     WR.Write16LE(file, ORD(w))
  87. END Write16;
  88.  
  89.  
  90. PROCEDURE WritePH (file: FILE; ph: Elf32_Phdr);
  91. BEGIN
  92.     WR.Write32LE(file, ph.p_type);
  93.     WR.Write32LE(file, ph.p_offset);
  94.     WR.Write32LE(file, ph.p_vaddr);
  95.     WR.Write32LE(file, ph.p_paddr);
  96.     WR.Write32LE(file, ph.p_filesz);
  97.     WR.Write32LE(file, ph.p_memsz);
  98.     WR.Write32LE(file, ph.p_flags);
  99.     WR.Write32LE(file, ph.p_align)
  100. END WritePH;
  101.  
  102.  
  103. PROCEDURE WritePH64 (file: FILE; ph: Elf32_Phdr);
  104. BEGIN
  105.     WR.Write32LE(file, ph.p_type);
  106.     WR.Write32LE(file, ph.p_flags);
  107.     WR.Write64LE(file, ph.p_offset);
  108.     WR.Write64LE(file, ph.p_vaddr);
  109.     WR.Write64LE(file, ph.p_paddr);
  110.     WR.Write64LE(file, ph.p_filesz);
  111.     WR.Write64LE(file, ph.p_memsz);
  112.     WR.Write64LE(file, ph.p_align)
  113. END WritePH64;
  114.  
  115.  
  116. PROCEDURE fixup (program: BIN.PROGRAM; text, data, bss: INTEGER; amd64: BOOLEAN);
  117. VAR
  118.     reloc: BIN.RELOC;
  119.     L, delta: INTEGER;
  120.  
  121. BEGIN
  122.     reloc := program.rel_list.first(BIN.RELOC);
  123.     WHILE reloc # NIL DO
  124.  
  125.         L := BIN.get32le(program.code, reloc.offset);
  126.         delta := 3 - reloc.offset - text - 7 * ORD(amd64);
  127.  
  128.         CASE reloc.opcode OF
  129.         |BIN.PICDATA: BIN.put32le(program.code, reloc.offset, L + data + delta)
  130.         |BIN.PICCODE: BIN.put32le(program.code, reloc.offset, BIN.GetLabel(program, L) + text + delta)
  131.         |BIN.PICBSS:  BIN.put32le(program.code, reloc.offset, L + bss + delta)
  132.         END;
  133.  
  134.         reloc := reloc.next(BIN.RELOC)
  135.     END;
  136. END fixup;
  137.  
  138.  
  139. PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; amd64: BOOLEAN);
  140. CONST
  141.     interp  =  0;
  142.     dyn     =  1;
  143.     header  =  2;
  144.     text    =  3;
  145.     data    =  4;
  146.     bss     =  5;
  147.  
  148. VAR
  149.     ehdr: Elf32_Ehdr;
  150.     phdr: ARRAY 16 OF Elf32_Phdr;
  151.  
  152.     i, LoadAdr, offset, pad, VA: INTEGER;
  153.  
  154.     SizeOf: RECORD header, code, data, bss: INTEGER END;
  155.  
  156.     File: FILE;
  157.  
  158.     str: ARRAY 40 OF CHAR; lstr: INTEGER;
  159.     Dyn: ARRAY 350 OF BYTE;
  160.  
  161. BEGIN
  162.     IF amd64 THEN
  163.         str := "/lib64/ld-linux-x86-64.so.2"
  164.     ELSE
  165.         str := "/lib/ld-linux.so.2"
  166.     END;
  167.     lstr := LENGTH(str);
  168.  
  169.     IF amd64 THEN
  170.         LoadAdr := 400000H
  171.     ELSE
  172.         LoadAdr := 08048000H
  173.     END;
  174.  
  175.     SizeOf.code := CHL.Length(program.code);
  176.     SizeOf.data := CHL.Length(program.data);
  177.     SizeOf.bss  := program.bss;
  178.  
  179.     ehdr.e_ident[0] := 7FH;
  180.     ehdr.e_ident[1] := ORD("E");
  181.     ehdr.e_ident[2] := ORD("L");
  182.     ehdr.e_ident[3] := ORD("F");
  183.     IF amd64 THEN
  184.         ehdr.e_ident[4] := ELFCLASS64
  185.     ELSE
  186.         ehdr.e_ident[4] := ELFCLASS32
  187.     END;
  188.     ehdr.e_ident[5] := ELFDATA2LSB;
  189.     ehdr.e_ident[6] := 1;
  190.     ehdr.e_ident[7] := 3;
  191.     FOR i := 8 TO EI_NIDENT - 1 DO
  192.         ehdr.e_ident[i] := 0
  193.     END;
  194.  
  195.     ehdr.e_type := WCHR(ET_EXEC);
  196.     ehdr.e_version := 1;
  197.     ehdr.e_shoff := 0;
  198.     ehdr.e_flags := 0;
  199.     ehdr.e_shnum := WCHR(0);
  200.     ehdr.e_shstrndx := WCHR(0);
  201.     ehdr.e_phnum := WCHR(6);
  202.  
  203.     IF amd64 THEN
  204.         ehdr.e_machine := WCHR(EM_8664);
  205.         ehdr.e_phoff := 40H;
  206.         ehdr.e_ehsize := WCHR(40H);
  207.         ehdr.e_phentsize := WCHR(38H);
  208.         ehdr.e_shentsize := WCHR(40H)
  209.     ELSE
  210.         ehdr.e_machine := WCHR(EM_386);
  211.         ehdr.e_phoff := 34H;
  212.         ehdr.e_ehsize := WCHR(34H);
  213.         ehdr.e_phentsize := WCHR(20H);
  214.         ehdr.e_shentsize := WCHR(28H)
  215.     END;
  216.  
  217.     SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum);
  218.  
  219.     phdr[interp].p_type := 3;
  220.     phdr[interp].p_offset := SizeOf.header;
  221.     phdr[interp].p_vaddr := LoadAdr + phdr[interp].p_offset;
  222.     phdr[interp].p_paddr := LoadAdr + phdr[interp].p_offset;
  223.     phdr[interp].p_filesz := lstr + 1;
  224.     phdr[interp].p_memsz := lstr + 1;
  225.     phdr[interp].p_flags := PF_R;
  226.     phdr[interp].p_align := 1;
  227.  
  228.     phdr[dyn].p_type := 2;
  229.     phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz;
  230.     phdr[dyn].p_vaddr := LoadAdr + phdr[dyn].p_offset;
  231.     phdr[dyn].p_paddr := LoadAdr + phdr[dyn].p_offset;
  232.     IF amd64 THEN
  233.         phdr[dyn].p_filesz := 0A0H;
  234.         phdr[dyn].p_memsz  := 0A0H
  235.     ELSE
  236.         phdr[dyn].p_filesz := 50H;
  237.         phdr[dyn].p_memsz  := 50H
  238.     END;
  239.     phdr[dyn].p_flags := PF_R;
  240.     phdr[dyn].p_align := 1;
  241.  
  242.     offset := 0;
  243.  
  244.     phdr[header].p_type := 1;
  245.     phdr[header].p_offset := offset;
  246.     phdr[header].p_vaddr := LoadAdr;
  247.     phdr[header].p_paddr := LoadAdr;
  248.     IF amd64 THEN
  249.         phdr[header].p_filesz := 305H;
  250.         phdr[header].p_memsz  := 305H
  251.     ELSE
  252.         phdr[header].p_filesz := 1D0H;
  253.         phdr[header].p_memsz  := 1D0H
  254.     END;
  255.     phdr[header].p_flags := PF_R + PF_W;
  256.     phdr[header].p_align := 1000H;
  257.    
  258.     offset := offset + phdr[header].p_filesz;
  259.     VA := LoadAdr + offset + 1000H;          
  260.  
  261.     phdr[text].p_type := 1;
  262.     phdr[text].p_offset := offset;
  263.     phdr[text].p_vaddr := VA;
  264.     phdr[text].p_paddr := VA;
  265.     phdr[text].p_filesz := SizeOf.code;
  266.     phdr[text].p_memsz := SizeOf.code;
  267.     phdr[text].p_flags := PF_X + PF_R;
  268.     phdr[text].p_align := 1000H;
  269.  
  270.     ehdr.e_entry := phdr[text].p_vaddr;
  271.    
  272.     offset := offset + phdr[text].p_filesz;
  273.     VA := LoadAdr + offset + 2000H;
  274.     pad := (16 - VA MOD 16) MOD 16;
  275.  
  276.     phdr[data].p_type := 1;
  277.     phdr[data].p_offset := offset;
  278.     phdr[data].p_vaddr := VA;
  279.     phdr[data].p_paddr := VA;
  280.     phdr[data].p_filesz := SizeOf.data + pad;
  281.     phdr[data].p_memsz := SizeOf.data + pad;
  282.     phdr[data].p_flags := PF_R + PF_W;
  283.     phdr[data].p_align := 1000H;
  284.                    
  285.     offset := offset + phdr[data].p_filesz;
  286.     VA := LoadAdr + offset + 3000H;
  287.  
  288.     phdr[bss].p_type := 1;
  289.     phdr[bss].p_offset := offset;
  290.     phdr[bss].p_vaddr := VA;
  291.     phdr[bss].p_paddr := VA;
  292.     phdr[bss].p_filesz := 0;
  293.     phdr[bss].p_memsz := SizeOf.bss + 16;
  294.     phdr[bss].p_flags := PF_R + PF_W;
  295.     phdr[bss].p_align := 1000H;
  296.  
  297.     fixup(program, phdr[text].p_vaddr, phdr[data].p_vaddr + pad, align(phdr[bss].p_vaddr, 16), amd64);
  298.  
  299.     File := WR.Create(FileName);
  300.  
  301.     FOR i := 0 TO EI_NIDENT - 1 DO
  302.         WR.WriteByte(File, ehdr.e_ident[i])
  303.     END;
  304.  
  305.     Write16(File, ehdr.e_type);
  306.     Write16(File, ehdr.e_machine);
  307.  
  308.     WR.Write32LE(File, ehdr.e_version);
  309.     IF amd64 THEN
  310.         WR.Write64LE(File, ehdr.e_entry);
  311.         WR.Write64LE(File, ehdr.e_phoff);
  312.         WR.Write64LE(File, ehdr.e_shoff)
  313.     ELSE
  314.         WR.Write32LE(File, ehdr.e_entry);
  315.         WR.Write32LE(File, ehdr.e_phoff);
  316.         WR.Write32LE(File, ehdr.e_shoff)
  317.     END;
  318.     WR.Write32LE(File, ehdr.e_flags);
  319.  
  320.     Write16(File, ehdr.e_ehsize);
  321.     Write16(File, ehdr.e_phentsize);
  322.     Write16(File, ehdr.e_phnum);
  323.     Write16(File, ehdr.e_shentsize);
  324.     Write16(File, ehdr.e_shnum);
  325.     Write16(File, ehdr.e_shstrndx);
  326.  
  327.     IF amd64 THEN
  328.         WritePH64(File, phdr[interp]);
  329.         WritePH64(File, phdr[dyn]);
  330.         WritePH64(File, phdr[header]);
  331.         WritePH64(File, phdr[text]);
  332.         WritePH64(File, phdr[data]);
  333.         WritePH64(File, phdr[bss])
  334.     ELSE
  335.         WritePH(File, phdr[interp]);
  336.         WritePH(File, phdr[dyn]);
  337.         WritePH(File, phdr[header]);
  338.         WritePH(File, phdr[text]);
  339.         WritePH(File, phdr[data]);
  340.         WritePH(File, phdr[bss])
  341.     END;
  342.  
  343.     FOR i := 0 TO lstr DO
  344.         WR.WriteByte(File, ORD(str[i]))
  345.     END;
  346.  
  347.     i := 0;
  348.     IF amd64 THEN
  349.         BIN.InitArray(Dyn, i, "01000000000000000E000000000000000500000000000000DC02400000000000");
  350.         BIN.InitArray(Dyn, i, "0A00000000000000190000000000000006000000000000004C02400000000000");
  351.         BIN.InitArray(Dyn, i, "0B00000000000000180000000000000007000000000000009402400000000000");
  352.         BIN.InitArray(Dyn, i, "0800000000000000300000000000000009000000000000001800000000000000");
  353.         BIN.InitArray(Dyn, i, "0400000000000000C40240000000000000000000000000000000000000000000");
  354.         BIN.InitArray(Dyn, i, "0000000000000000000000000000000000000000000000000100000012000000");
  355.         BIN.InitArray(Dyn, i, "0000000000000000000000000000000008000000120000000000000000000000");
  356.         BIN.InitArray(Dyn, i, "0000000000000000F50240000000000001000000010000000000000000000000");
  357.         BIN.InitArray(Dyn, i, "FD02400000000000010000000200000000000000000000000100000003000000");
  358.         BIN.InitArray(Dyn, i, "0000000001000000020000000000000000646C6F70656E00646C73796D006C69");
  359.         BIN.InitArray(Dyn, i, "62646C2E736F2E320000000000000000000000000000000000")
  360.     ELSE
  361.         BIN.InitArray(Dyn, i, "010000000E00000005000000AF8104080A000000190000000600000057810408");
  362.         BIN.InitArray(Dyn, i, "0B00000010000000110000008781040812000000100000001300000008000000");
  363.         BIN.InitArray(Dyn, i, "0400000097810408000000000000000000000000000000000000000000000000");
  364.         BIN.InitArray(Dyn, i, "0100000000000000000000001200000008000000000000000000000012000000");
  365.         BIN.InitArray(Dyn, i, "C881040801010000CC8104080102000001000000030000000000000001000000");
  366.         BIN.InitArray(Dyn, i, "020000000000000000646C6F70656E00646C73796D006C6962646C2E736F2E32");
  367.         BIN.InitArray(Dyn, i, "000000000000000000")
  368.     END;
  369.  
  370.     WR.Write(File, Dyn, i);
  371.  
  372.     CHL.WriteToFile(File, program.code);
  373.     WHILE pad > 0 DO
  374.         WR.WriteByte(File, 0);
  375.         DEC(pad)
  376.     END;
  377.     CHL.WriteToFile(File, program.data);
  378.     WR.Close(File)
  379. END write;
  380.  
  381.  
  382. END ELF.