summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format239
-rw-r--r--Makefile10
-rw-r--r--instructions.h76
-rw-r--r--main.c8
-rw-r--r--registers.h76
-rw-r--r--tiny.s11
-rw-r--r--write_elf.c141
7 files changed, 561 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..451482f
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,239 @@
+---
+Language: Cpp
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignArrayOfStructures: Right
+AlignConsecutiveAssignments:
+ Enabled: true
+ AcrossEmptyLines: true
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveBitFields:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveDeclarations:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveMacros:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: true
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveShortCaseStatements:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCaseColons: false
+AlignEscapedNewlines: Right
+AlignOperands: Align
+AlignTrailingComments:
+ Kind: Always
+ OverEmptyLines: 0
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowBreakBeforeNoexceptSpecifier: Never
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortCompoundRequirementOnASingleLine: true
+AllowShortEnumsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLambdasOnASingleLine: All
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterReturnType: AllDefinitions
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: MultiLine
+AttributeMacros:
+ - __capability
+BinPackArguments: true
+BinPackParameters: true
+BitFieldColonSpacing: Both
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterExternBlock: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakAdjacentStringLiterals: true
+BreakAfterAttributes: Leave
+BreakAfterJavaFieldAnnotations: false
+BreakArrays: true
+BreakBeforeBinaryOperators: None
+BreakBeforeConceptDeclarations: Always
+BreakBeforeBraces: Attach
+BreakBeforeInlineASMColon: OnlyMultiline
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeColon
+BreakInheritanceList: BeforeColon
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 2
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IfMacros:
+ - KJ_IF_MAYBE
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseBlocks: false
+IndentCaseLabels: false
+IndentExternBlock: AfterExternBlock
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentRequiresClause: true
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+InsertBraces: false
+InsertNewlineAtEOF: false
+InsertTrailingCommas: None
+IntegerLiteralSeparator:
+ Binary: 0
+ BinaryMinDigits: 0
+ Decimal: 0
+ DecimalMinDigits: 0
+ Hex: 0
+ HexMinDigits: 0
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+KeepEmptyLinesAtEOF: false
+LambdaBodyIndentation: Signature
+LineEnding: DeriveLF
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+PackConstructorInitializers: BinPack
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakScopeResolution: 500
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyIndentedWhitespace: 0
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Left
+PPIndentWidth: -1
+QualifierAlignment: Leave
+ReferenceAlignment: Pointer
+ReflowComments: true
+RemoveBracesLLVM: false
+RemoveParentheses: Leave
+RemoveSemicolon: false
+RequiresClausePosition: OwnLine
+RequiresExpressionIndentation: OuterScope
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SkipMacroDefinitionBody: false
+SortIncludes: CaseSensitive
+SortJavaStaticImport: Before
+SortUsingDeclarations: LexicographicNumeric
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: true
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeJsonColon: false
+SpaceBeforeParens: ControlStatements
+SpaceBeforeParensOptions:
+ AfterControlStatements: true
+ AfterForeachMacros: true
+ AfterFunctionDefinitionName: false
+ AfterFunctionDeclarationName: false
+ AfterIfMacros: true
+ AfterOverloadedOperator: false
+ AfterPlacementOperator: true
+ AfterRequiresInClause: false
+ AfterRequiresInExpression: false
+ BeforeNonEmptyParentheses: false
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
+SpaceInEmptyBlock: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: Never
+SpacesInContainerLiterals: true
+SpacesInLineCommentPrefix:
+ Minimum: 1
+ Maximum: -1
+SpacesInParens: Never
+SpacesInParensOptions:
+ InCStyleCasts: false
+ InConditionalStatements: false
+ InEmptyParentheses: false
+ Other: false
+SpacesInSquareBrackets: false
+Standard: Latest
+StatementAttributeLikeMacros:
+ - Q_EMIT
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TabWidth: 8
+UseTab: Never
+WhitespaceSensitiveMacros:
+ - BOOST_PP_STRINGIZE
+ - CF_SWIFT_NAME
+ - NS_SWIFT_NAME
+ - PP_STRINGIZE
+ - STRINGIZE
+...
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..9f3c9a5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+.PHONY: fmt
+
+write-elf: main.c write_elf.c registers.h instructions.h
+ gcc -static-pie main.c -o write-elf
+
+tiny: tiny.s
+ nasm -f elf64 tiny.s
+
+fmt: main.c write_elf.c registers.h instructions.h
+ clang-format -i $^
diff --git a/instructions.h b/instructions.h
new file mode 100644
index 0000000..9727137
--- /dev/null
+++ b/instructions.h
@@ -0,0 +1,76 @@
+#ifndef INSTRUCTIONS_H
+#define INSTRUCTIONS_H
+
+// Prefixes
+// Prefix groups are mutually exclusive
+
+// Prefix group 1
+#define PREFIX_LOCK 0xf0
+#define PREFIX_REPNE 0xf2
+#define PREFIX_REPNZ PREFIX_REPNE
+#define PREFIX_REP 0xf3
+#define PREFIX_REPE PREFIX_REP
+#define PREFIX_REPZ PREFIX_REP
+
+// Prefix group 2
+#define PREFIX_OVERRIDE_SEGMENT_CS 0x2e
+#define PREFIX_OVERRIDE_SEGMENT_SS 0x36
+#define PREFIX_OVERRIDE_SEGMENT_DS 0x3e
+#define PREFIX_OVERRIDE_SEGMENT_ES 0x26
+#define PREFIX_OVERRIDE_SEGMENT_FS 0x64
+#define PREFIX_OVERRIDE_SEGMENT_GS 0x65
+#define PREFIX_BRANCH_NOT_TAKEN PREFIX_OVERRIDE_SEGMENT_CS
+#define PREFIX_BRANCH_TAKEN PREFIX_OVERRIDE_SEGMENT_DS
+
+// Prefix group 3
+#define PREFIX_OVERRIDE_OPSIZE 0x66
+
+// Prefix group 4
+#define PREFIX_OVERRIDE_ADDRESSSIZE 0x67
+
+// Instructions
+// Move double-word immediate
+#define MOVBI(reg, imm) (0xb0 + reg), (imm & 0xff)
+#define MOVWI(reg, imm) \
+ (0xb8 + reg), (imm & 0xff), ((imm >> 8) & 0xff), ((imm >> 16) & 0xff)
+#define MOVDI(reg, imm) \
+ (0xb8 + reg), (imm & 0xff), ((imm >> 8) & 0xff), ((imm >> 16) & 0xff), \
+ ((imm >> 24) & 0xff)
+// TODO replace 0x48 with encoding,
+// | 0 1 0 0 | W R X B |
+//
+// 0 1 0 0 -- fixed pattern
+// W -- Set to use 64-bit operands,
+// R -- extension to MODRM.reg field, registers
+// X -- extension to SIB.index field, 64-bit addressing
+// B -- extension to MODRM.rm or SIB.base field, 64-bit addressing
+#define MOVABS(reg, imm) 0x48, MOVD(reg, imm)
+#define MOVQ(reg, imm) 0x48, 89 c8
+
+#define ADD
+#define CALL
+#define CMP
+#define DEC
+#define DIV
+#define HLT
+#define IDIV
+#define IMUL
+#define INC
+#define INT
+#define INTO
+#define IRET
+#define JNZ
+#define JMP
+#define LEA
+#define POP
+#define PUSH
+#define RET
+#define RETN
+#define SUB
+#define XOR
+
+#define SYSCALL 0x0f, 0x05
+
+#define REX(mode) (0b01000000 | mode)
+
+#endif
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..da8eb0f
--- /dev/null
+++ b/main.c
@@ -0,0 +1,8 @@
+#include "write_elf.c"
+
+int
+main(int argc, char* argv[]) {
+ char opcodes[] = {};
+ write_elf("test.out", some_opcodes_len, some_opcodes);
+ return 0;
+}
diff --git a/registers.h b/registers.h
new file mode 100644
index 0000000..1f3b040
--- /dev/null
+++ b/registers.h
@@ -0,0 +1,76 @@
+#ifndef REGISTERS_H
+#define REGISTERS_H
+
+// 8-bit global pointer
+#define REG_AL 0
+#define REG_CL 1
+#define REG_DL 2
+#define REG_BL 3
+#define REG_AH 4
+#define REG_CH 5
+#define REG_DH 6
+#define REG_BH 7
+#define REG_R8L 8
+#define REG_R9L 9
+#define REG_R10L 10
+#define REG_R11L 11
+#define REG_R12L 12
+#define REG_R13L 13
+#define REG_R14L 14
+#define REG_R15L 15
+
+// 16-bit global pointer
+#define REG_AX 0
+#define REG_CX 1
+#define REG_DX 2
+#define REG_BX 3
+#define REG_SP 4
+#define REG_BP 5
+#define REG_SI 6
+#define REG_DI 7
+#define REG_R8W 8
+#define REG_R9W 9
+#define REG_R10W 10
+#define REG_R11W 11
+#define REG_R12W 12
+#define REG_R13W 13
+#define REG_R14W 14
+#define REG_R15W 15
+
+// 32-bit global pointer
+#define REG_EAX 0
+#define REG_ECX 1
+#define REG_EDX 2
+#define REG_EBX 3
+#define REG_ESP 4
+#define REG_EBP 5
+#define REG_ESI 6
+#define REG_EDI 7
+#define REG_R8D 8
+#define REG_R9D 9
+#define REG_R10D 10
+#define REG_R11D 11
+#define REG_R12D 12
+#define REG_R13D 13
+#define REG_R14D 14
+#define REG_R15D 15
+
+// 64-bit global pointer
+#define REG_RAX 0
+#define REG_RCX 1
+#define REG_RDX 2
+#define REG_RBX 3
+#define REG_RSP 4
+#define REG_RBP 5
+#define REG_RSI 6
+#define REG_RDI 7
+#define REG_R8 8
+#define REG_R9 9
+#define REG_R10 10
+#define REG_R11 11
+#define REG_R12 12
+#define REG_R13 13
+#define REG_R14 14
+#define REG_R15 15
+
+#endif
diff --git a/tiny.s b/tiny.s
new file mode 100644
index 0000000..1d3a901
--- /dev/null
+++ b/tiny.s
@@ -0,0 +1,11 @@
+BITS 64
+section .text
+ global _start
+
+_start:
+ ; 60 = syscall exit
+ mov eax, ecx
+
+ ; rdi is exit code
+ mov rdi, 0x41
+ syscall
diff --git a/write_elf.c b/write_elf.c
new file mode 100644
index 0000000..62b6cd3
--- /dev/null
+++ b/write_elf.c
@@ -0,0 +1,141 @@
+#include "instructions.h"
+#include "registers.h"
+#include <elf.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+unsigned char some_opcodes[] = {MOVDI(REG_EAX, 0x3c),
+ // 0xb8, 0x3c, 0x00, 0x00, 0x00,
+ MOVDI(REG_EDI, 0x41),
+ // 0xbf, 0x41, 0x00, 0x00, 0x00,
+ SYSCALL};
+unsigned int some_opcodes_len = sizeof(some_opcodes) / sizeof(some_opcodes[0]);
+
+int
+write_elf(char* restrict file, size_t opcodes_len, char* restrict opcodes) {
+ int error = 0;
+
+ Elf64_Phdr header_program[] = {
+ //{
+ // .p_type = PT_LOAD,
+ // .p_flags = PF_R,
+ // .p_offset = 0, /* Segment file offset */
+ // .p_vaddr = 0x400000, /* Segment virtual address */
+ // .p_paddr = 0x400000, /* Segment physical address */
+ // .p_filesz = 0xb0, /* Segment size in file */
+ // .p_memsz = 0xb0, /* Segment size in memory */
+ // .p_align = 0x1000, /* Segment alignment */
+ //},
+ {
+ .p_type = PT_LOAD,
+ .p_flags = PF_X | PF_R,
+ .p_offset =
+ sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr), /* Segment file offset */
+ .p_vaddr = 0x400000 + sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr), /* Segment virtual address */
+ .p_paddr = 0x400000 + sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr), /* Segment physical address */
+ .p_filesz = opcodes_len, /* Segment size in file */
+ .p_memsz = opcodes_len, /* Segment size in memory */
+ .p_align = 0x1, /* Segment alignment */
+ },
+ };
+
+ Elf64_Shdr header_section[] = {
+ {
+ // .init
+ // Index in section header string table
+ .sh_name = 0,
+ .sh_type = 0,
+ .sh_flags = 0,
+ .sh_addr = 0,
+ .sh_offset = 0,
+ .sh_size = 0,
+ .sh_link = 0,
+ .sh_info = 0,
+ .sh_addralign = 0,
+ .sh_entsize = 0,
+ },
+ {
+ // .init
+ // Index in section header string table
+ .sh_name = 0,
+ .sh_type = SHT_PROGBITS,
+ .sh_flags = SHF_ALLOC | SHF_EXECINSTR,
+ .sh_addr = 0x401000,
+ .sh_offset = 0x1000,
+ .sh_size = opcodes_len,
+ /* todo: deps on type */
+ .sh_link = 0,
+ /* todo: deps on type */
+ .sh_info = 0,
+ .sh_addralign = 4,
+ .sh_entsize = 0,
+ },
+ {
+ // .shstrtab Section Header String Table
+ // Index in section header string table
+ .sh_name = 1,
+ .sh_type = SHT_STRTAB,
+ .sh_flags = 0,
+ .sh_addr = 0x100,
+ .sh_offset = 0x2000,
+ .sh_size = opcodes_len,
+ /* todo: deps on type */
+ .sh_link = 0,
+ /* todo: deps on type */
+ .sh_info = 0,
+ .sh_addralign = 1,
+ .sh_entsize = 0,
+ },
+ };
+
+ unsigned char string_header_table[] = {0, '.', 'i', 'n', 'i', 't', 0};
+
+ Elf64_Ehdr header = {
+ // memset(&header, 0, sizeof(Elf64_Ehdr));
+ .e_ident = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS64, ELFDATA2LSB,
+ EV_CURRENT, ELFOSABI_SYSV},
+ .e_type = ET_EXEC,
+ .e_machine = EM_X86_64,
+ .e_version = EV_CURRENT,
+ .e_entry = 0x400000 + sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr), // point to VIRTUAL address of _start
+ .e_phoff = sizeof(Elf64_Ehdr) /* Program header table offset */,
+ .e_shoff = 0, // sizeof(Elf64_Ehdr) + sizeof(header_program) /* Section
+ // header table offset */,
+ .e_flags = 0,
+ .e_ehsize = sizeof(Elf64_Ehdr),
+ .e_phentsize = sizeof(Elf64_Phdr),
+ // If larger than PN_XNUM, then set to PN_XNUM and store real number in
+ // sh_info of first program header entry
+ .e_phnum = 1,
+ .e_shentsize = sizeof(header_section[0]),
+ // If larger than SHN_LORESERVE, then set to 0 and store real number in
+ // sh_size of first section header entry
+ .e_shnum = 0, // sizeof(header_section) / sizeof(header_section[0]),
+ // If larger than SHN_LORESERVE, then set to SHN_XINDEX and store real index
+ // in
+ // sh_link of first section header entry
+ .e_shstrndx = 0,
+ };
+
+ size_t bytes_written = 0;
+ FILE* fd = fopen(file, "w");
+
+ fwrite(&header, sizeof(Elf64_Ehdr), 1, fd);
+ fwrite(&header_program, sizeof(Elf64_Phdr),
+ sizeof(header_program) / sizeof(header_program[0]), fd);
+ // fseek(fd, 0x1000, SEEK_SET);
+
+ do {
+ bytes_written += fwrite(opcodes, sizeof(char), opcodes_len, fd);
+ } while (bytes_written != opcodes_len);
+ error = fclose(fd);
+ if (error) {
+ err(EXIT_FAILURE, "no way");
+ }
+ return 0;
+}