Skip to content

Commit

Permalink
[IO][External] ELF64 Parser (Headers)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eforen committed May 5, 2024
1 parent 1b78fb3 commit 516e36d
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 4 deletions.
23 changes: 19 additions & 4 deletions KANBAN.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
- [Done](#done)
- [Done 10/18/2021](#done-10182021)
- [Done 10/21/2021](#done-10212021)
- [Done 11/16/2021](#done-11162021)
- [Done 02/25/2023](#done-02252023)
- [Done 2023/03/08](#done-20230308)
- [Done 2023/05/20](#done-20230520)
- [Done 2023/05/21](#done-20230521)
- [Done 2023/05/26](#done-20230526)
- [Next Commit (Eforen)](#next-commit-eforen)
- [Done 2024/05/04](#done-20240504)
- [Next Commit (Eforen)](#next-commit-eforen-1)
- [Working On](#working-on)
- [Working on (Eforen)](#working-on-eforen)
- [Todos](#todos)
Expand All @@ -28,6 +31,9 @@
* [KUICK][TOKENIZER] Write Tests for every Token
* [KUICK][TOKENIZER] Implement all failing tests

## Done 11/16/2021
* [KUICK][TOKENIZER] Implement all failing tests

## Done 02/25/2023
* [KUICK][LEXER] Refactor switch the name of the parser and lexer because I had the definitions backwards
* [KUICK][PARSER] Change to using a parser that makes an intermediary AST (Abstract Syntax Tree)
Expand Down Expand Up @@ -91,8 +97,17 @@
* [KUICK][PARSER] Implement `LWU`
* [KUICK][PARSER] Implement `LD`

## Done 2024/05/04
### Next Commit (Eforen)
* [IO][External] ELF64 Parser (Headers)

# Working On
## Working on (Eforen)
* [IO][External] ELF64 Parser (Program Headers)
* [IO][External] ELF64 Parser (Sections)
* [IO][External] ELF64 Writer (Headers)
* [IO][External] ELF64 Writer (Program Headers)
* [IO][External] ELF64 Writer (Sections)
* [KIUCK][PARSER] Implement Pseudo Instructions
* [KIUCK][PARSER][TEST] Pseudo Instruction `beqz`
* [KIUCK][PARSER][TEST] Pseudo Instruction `bnez`
Expand All @@ -108,9 +123,10 @@
* [KUICK][ASSEMBLER] Write Tests for every Token

# Todos
* [KUICK][PARSER] Impliment `%hi(msg)`
* [KUICK][PARSER] Impliment `%lo(msg)`
* [KUICK][PARSER] Impliment `msg: .string "Hello World\n"`
## Todo
* [KUICK][PARSER] Implement `%hi(msg)`
* [KUICK][PARSER] Implement `%lo(msg)`
* [KUICK][PARSER] Implement `msg: .string "Hello World\n"`
* [KUICK][ASSEMBLER] Implement all failing tests
* Implement all RISC-V ASM directives in (RISC-V ASSEMBLY LANGUAGE Programmer Manual - Part 1)[https://shakti.org.in/docs/risc-v-asm-manual.pdf] (contact @ shakti[dot]iitm[@]gmail[dot]com)
* [KUICK][PARSER] Write Test for F Type Instruction `FADD.S`
Expand All @@ -120,6 +136,5 @@
* [KUICK][PARSER] Write Test for RV64I/E Instruction Set Instruction `LD`
* [KUICK][PARSER] Write Test for RV64I/E Instruction Set Instruction `SD`
* [Cite] Email SHAKTI Development Team requesting to include their PDF in this repository (RISC-V ASSEMBLY LANGUAGE Programmer Manual - Part 1)[https://shakti.org.in/docs/risc-v-asm-manual.pdf]
## Todo
## Planned for some time later
## Wishlist
1 change: 1 addition & 0 deletions src/Kore.Utility/Kore.Utility.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="elf.cs" />
<Compile Include="StringValue.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down
306 changes: 306 additions & 0 deletions src/Kore.Utility/elf.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
using System;
using System.IO;

namespace Kore.Utility.ELF {
public enum ELFClass : byte {
ELFCLASSNONE = 0,
ELFCLASS32 = 1,
ELFCLASS64 = 2
}

public enum ELFFormat : byte {
ELFDATANONE = 0,
ELFDATA2LSB = 1,
ELFDATA2MSB = 2
}

public enum ELFType : ushort {
ET_NONE = 0,
ET_REL = 1,
ET_EXEC = 2,
ET_DYN = 3,
ET_CORE = 4,
ET_LOPROC = 0xff00,
ET_HIPROC = 0xffff
}

/*
http://www.skyfree.org/linux/references/ELF_Format.pdf
https://interrupt.memfault.com/blog/elf-format-differences
*/

public struct Elf_Half {
public ushort Value;
public Elf_Half(ushort value) {
Value = value;
}
public Elf_Half(BinaryReader reader) {
Value = reader.ReadUInt16();
}
public static implicit operator Elf_Half(ushort value) {
return new Elf_Half(value);
}
public static implicit operator ushort(Elf_Half value) {
return value.Value;
}
}

public struct Elf_Word {
public uint Value;
public Elf_Word(uint value) {
Value = value;
}
public Elf_Word(BinaryReader reader) {
Value = reader.ReadUInt32();
}
public static implicit operator Elf_Word(uint value) {
return new Elf_Word(value);
}
public static implicit operator uint(Elf_Word value) {
return value.Value;
}
}

public struct Elf32_Addr {
public uint Value;
public Elf32_Addr(uint value) {
Value = value;
}
public Elf32_Addr(BinaryReader reader) {
Value = reader.ReadUInt32();
}
public static implicit operator Elf32_Addr(uint value) {
return new Elf32_Addr(value);
}
public static implicit operator uint(Elf32_Addr value) {
return value.Value;
}
}

public struct Elf64_Addr {
public ulong Value;
public Elf64_Addr(ulong value) {
Value = value;
}
public Elf64_Addr(BinaryReader reader) {
Value = reader.ReadUInt64();
}
public static implicit operator Elf64_Addr(ulong value) {
return new Elf64_Addr(value);
}
public static implicit operator ulong(Elf64_Addr value) {
return value.Value;
}
}

public struct Elf32_Off {
public uint Value;
public Elf32_Off(uint value) {
Value = value;
}
public Elf32_Off(BinaryReader reader) {
Value = reader.ReadUInt32();
}
public static implicit operator Elf32_Off(uint value) {
return new Elf32_Off(value);
}
public static implicit operator uint(Elf32_Off value) {
return value.Value;
}
}

public struct Elf64_Off {
public ulong Value;
public Elf64_Off(ulong value) {
Value = value;
}
public Elf64_Off(BinaryReader reader) {
Value = reader.ReadUInt64();
}
public static implicit operator Elf64_Off(ulong value) {
return new Elf64_Off(value);
}
public static implicit operator ulong(Elf64_Off value) {
return value.Value;
}
}

public struct Elf64_Xword {
public ulong Value;
public Elf64_Xword(ulong value) {
Value = value;
}
public Elf64_Xword(BinaryReader reader) {
Value = reader.ReadUInt64();
}
public static implicit operator Elf64_Xword(ulong value) {
return new Elf64_Xword(value);
}
public static implicit operator ulong(Elf64_Xword value) {
return value.Value;
}
}

public struct Elf64_Sxword {
public long Value;
public Elf64_Sxword(long value) {
Value = value;
}
public Elf64_Sxword(BinaryReader reader) {
Value = reader.ReadInt64();
}
public static implicit operator Elf64_Sxword(long value) {
return new Elf64_Sxword(value);
}
public static implicit operator long(Elf64_Sxword value) {
return value.Value;
}
}

/// <summary>
/// ELF Header
/// <seealso cref="https://upload.wikimedia.org/wikipedia/commons/e/e4/ELF_Executable_and_Linkable_Format_diagram_by_Ange_Albertini.png"/>
/// </summary>
public class ELF_FILE{
/// <summary>
/// 16 bytes 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
/// </summary>
public e_ident e_ident;
/// <summary>
/// 2 bytes 02 00 for ET_EXEC (Executable file) No other types are supported atm
/// </summary>
public ushort e_type;
/// <summary>
/// 2 bytes we only support RISC-V atm so must be 0xf3
/// </summary>
public ushort e_machine;
/// <summary>
/// 4 bytes 01 00 00 00 for version 1 should never change
/// </summary>
public uint e_version;
/// <summary>
/// 4 bytes entry point of the program in memory
/// </summary>
public ulong e_entry;
/// <summary>
/// 4 bytes offset of the program header table
/// </summary>
public ulong e_phoff;
/// <summary>
/// 4 bytes offset of the section header table
/// </summary>
public ulong e_shoff;
/// <summary>
/// 4 bytes flags usually 0
/// </summary>
public uint e_flags;
/// <summary>
/// 2 bytes size of this header
/// </summary>
public ushort e_ehsize;
/// <summary>
/// 2 bytes size of a program header table entry
/// </summary>
public ushort e_phentsize;
/// <summary>
/// 2 bytes number of entries in the program header table
/// </summary>
public ushort e_phnum;
/// <summary>
/// 2 bytes size of a single section header table entry
/// </summary>
public ushort e_shentsize;
/// <summary>
/// 2 bytes number of entries in the section header table
/// </summary>
public ushort e_shnum;
/// <summary>
/// 2 bytes section header table index of the entry associated with the section name string table
/// </summary>
public ushort e_shstrndx;
public static ELF_FILE FromBinaryReader(System.IO.BinaryReader reader) {
ELF_FILE file = new ELF_FILE();
file.e_ident = e_ident.FromBinaryReader(reader);
file.e_type = reader.ReadUInt16();
file.e_machine = reader.ReadUInt16();
file.e_version = reader.ReadUInt32();
file.e_entry = reader.ReadUInt64();
file.e_phoff = reader.ReadUInt64();
file.e_shoff = reader.ReadUInt64();
file.e_flags = reader.ReadUInt32();
file.e_ehsize = reader.ReadUInt16();
file.e_phentsize = reader.ReadUInt16();
file.e_phnum = reader.ReadUInt16();
file.e_shentsize = reader.ReadUInt16();
file.e_shnum = reader.ReadUInt16();
file.e_shstrndx = reader.ReadUInt16();
return file;
}
}

public class e_ident {
public byte EI_MAG0;
public byte EI_MAG1;
public byte EI_MAG2;
public byte EI_MAG3;
public byte EI_CLASS;
public byte EI_DATA;
public uint EI_VERSION;
public byte EI_OSABI;
public byte EI_ABIVERSION;
public byte[] EI_PAD = new byte[4];

public static e_ident FromBinaryReader(System.IO.BinaryReader reader) {
e_ident ident = new e_ident();
ident.EI_MAG0 = reader.ReadByte();
ident.EI_MAG1 = reader.ReadByte();
ident.EI_MAG2 = reader.ReadByte();
ident.EI_MAG3 = reader.ReadByte();
if (ident.EI_MAG0 != 0x7f || ident.EI_MAG1 != 0x45 || ident.EI_MAG2 != 0x4c || ident.EI_MAG3 != 0x46) {
throw new Exception("Not an ELF file");
}
ident.EI_CLASS = reader.ReadByte();
if (ident.EI_CLASS != (byte)ELFClass.ELFCLASS64) {
throw new Exception("Not a 64-bit ELF file");
}
ident.EI_DATA = reader.ReadByte();
if (ident.EI_DATA != 1) {
throw new Exception("Not a little-endian ELF file");
}
ident.EI_VERSION = reader.ReadUInt32();
if (ident.EI_VERSION != 1) {
throw new Exception("Not an ELF version 1 file");
}
ident.EI_OSABI = reader.ReadByte();
if(ident.EI_OSABI != 0) {
throw new Exception("Not an ELF version 0 OSABI file");
}
ident.EI_ABIVERSION = reader.ReadByte();
if(ident.EI_ABIVERSION != 0) {
throw new Exception("Not an ELF version 0 ABI file");
}
for(int i = 0; i < 4; i++) {
ident.EI_PAD[i] = reader.ReadByte();
}
return ident;
}

public static e_ident FromBytes(byte[] bytes) {
e_ident ident = new e_ident();
ident.EI_MAG0 = bytes[0];
ident.EI_MAG1 = bytes[1];
ident.EI_MAG2 = bytes[2];
ident.EI_MAG3 = bytes[3];
ident.EI_CLASS = bytes[4];
ident.EI_DATA = bytes[5];
ident.EI_VERSION = BitConverter.ToUInt32(bytes, 6);
ident.EI_OSABI = bytes[7];
ident.EI_ABIVERSION = bytes[8];
for(int i = 0; i < 4; i++) {
ident.EI_PAD[i] = bytes[9 + i];
}
return ident;
}
}

}

0 comments on commit 516e36d

Please sign in to comment.