From 2bdcaf319b1d74ffbaccf08a58336f804761beab Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Thu, 9 Jul 2026 23:51:55 -0400 Subject: Refactor into monorepo --- elf/.envrc | 1 + elf/.gitignore | 7 + elf/Makefile | 55 ++++ elf/elf.pdf | Bin 0 -> 4584428 bytes elf/include/lcq/elf.h | 239 +++++++++++++++++ elf/include/lcq/elf/platform/amd64.h | 26 ++ elf/include/lcq/elf/platform/x86.h | 22 ++ elf/packages.nix | 14 + elf/src/elf.c | 490 +++++++++++++++++++++++++++++++++++ elf/src/main.c | 204 +++++++++++++++ 10 files changed, 1058 insertions(+) create mode 100644 elf/.envrc create mode 100644 elf/.gitignore create mode 100644 elf/Makefile create mode 100644 elf/elf.pdf create mode 100644 elf/include/lcq/elf.h create mode 100644 elf/include/lcq/elf/platform/amd64.h create mode 100644 elf/include/lcq/elf/platform/x86.h create mode 100644 elf/packages.nix create mode 100644 elf/src/elf.c create mode 100644 elf/src/main.c (limited to 'elf') diff --git a/elf/.envrc b/elf/.envrc new file mode 100644 index 0000000..c4b17d7 --- /dev/null +++ b/elf/.envrc @@ -0,0 +1 @@ +use_flake diff --git a/elf/.gitignore b/elf/.gitignore new file mode 100644 index 0000000..e65382e --- /dev/null +++ b/elf/.gitignore @@ -0,0 +1,7 @@ +./6502 +build_*/ +.direnv/ +TAGS +*.o +*.a +*.so \ No newline at end of file diff --git a/elf/Makefile b/elf/Makefile new file mode 100644 index 0000000..0d5db59 --- /dev/null +++ b/elf/Makefile @@ -0,0 +1,55 @@ +CC ?= gcc +AR ?= ar +override CPPFLAGS += -MMD -MP +override CFLAGS += -march=native --std=c89 -g -Ideps/ -Isrc/ -Iinclude/ -Wall -Wextra -Wpedantic -Wconversion -Wformat-security -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wnull-dereference -Wfloat-equal -Wundef -Wpointer-arith -Wbad-function-cast -Wlogical-op -Wmissing-braces -Wcast-align -Wstrict-overflow=5 -ftrapv +override += -g -static + +BUILD = build_$(CC) + +SRCS := src/elf.c +CHK_SOURCES ?= src/main.c $(SRCS) +OBJECTS := $(SRCS:src/%.c=$(BUILD)/%.o) +EXE := elf +LIB := libcolonq-elf.a + +prefix ?= /usr/local +exec_prefix ?= $(prefix) +bindir ?= $(exec_prefix)/bin +includedir ?= $(prefix)/include +libdir ?= $(exec_prefix)/lib + +.PHONY: all clean install check-syntax + +all: $(EXE) $(LIB) + +$(EXE): $(BUILD)/main.o $(LIB) + $(CC) -o $@ $^ $(LDFLAGS) + +$(LIB): $(OBJECTS) + ar rcs $@ $^ + +$(BUILD): + mkdir $(BUILD)/ + +$(BUILD)/%.o: src/%.c | $(BUILD) + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< + +clean: + -rm $(EXE) + -rm $(LIB) + -rm -r $(BUILD)/ + +TAGS: $(SRCS) + ctags --output-format=etags $^ + +install: $(EXE) $(LIB) + mkdir -p $(DESTDIR)$(bindir) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) + install $(EXE) $(DESTDIR)$(bindir)/$(EXE) + install $(LIB) $(DESTDIR)$(libdir)/$(LIB) + cp -r include/* $(DESTDIR)$(includedir) + +check-syntax: TAGS + gcc $(CFLAGS) -fsyntax-only $(CHK_SOURCES) + +-include $(BUILD)/main.d +-include $(OBJECTS:.o=.d) diff --git a/elf/elf.pdf b/elf/elf.pdf new file mode 100644 index 0000000..f193f57 Binary files /dev/null and b/elf/elf.pdf differ diff --git a/elf/include/lcq/elf.h b/elf/include/lcq/elf.h new file mode 100644 index 0000000..57a1d3f --- /dev/null +++ b/elf/include/lcq/elf.h @@ -0,0 +1,239 @@ +#ifndef LCOLONQ_ELF_H +#define LCOLONQ_ELF_H + +#include +#include +#include + +/* context */ +typedef enum elf_class { + ELF_CLASS_INVALID = 0, + ELF_CLASS_32 = 1, + ELF_CLASS_64 = 2 +} elf_class; +typedef enum elf_endianness { + ELF_ENDIANNESS_INVALID = 0, + ELF_ENDIANNESS_LITTLE = 1, + ELF_ENDIANNESS_BIG = 2 +} elf_endianness; +#define ELF_HEADER_IDENT_SIZE 16 +typedef struct elf_header_ident { + elf_class file_class; + elf_endianness endianness; + u8 version; + u8 abi; + u8 abi_version; +} elf_header_ident; +typedef struct elf_ctx { + u8 *buf; i64 len; + elf_header_ident ident; +} elf_ctx; +i64 elf_read_header_ident(elf_header_ident *i, u8 *buf, i64 len); +i64 elf_write_header_ident(elf_header_ident *i, u8 *buf, i64 len); +elf_ctx elf_load_from_path(char *p); +elf_ctx elf_ctx_new(u8 *buf, i64 len, elf_class cl, elf_endianness end); + +/* header */ +typedef enum elf_type { + ELF_TYPE_NONE = 0, + ELF_TYPE_REL = 1, + ELF_TYPE_EXEC = 2, + ELF_TYPE_DYN = 3, + ELF_TYPE_CORE = 4, + ELF_TYPE_LO_OS = 0xfe00, ELF_TYPE_HI_OS = 0xfeff, + ELF_TYPE_LO_PROC = 0xff00, ELF_TYPE_HI_PROC = 0xffff +} elf_type; +typedef enum elf_machine { + ELF_MACHINE_NONE = 0, + ELF_MACHINE_X86 = 3, + ELF_MACHINE_AMD64 = 62 +} elf_machine; +#define ELF32_HEADER_SIZE 52 +#define ELF64_HEADER_SIZE 64 +i64 elf_header_size(elf_ctx *ctx); +typedef struct elf_header { + elf_type type; + elf_machine machine; + u32 version; + u64 entry; + u64 program_header_offset; + u64 section_header_offset; + u32 flags; + u16 elf_header_size; + u16 program_header_entry_size; + u16 program_header_entries; + u16 section_header_entry_size; + u16 section_header_entries; + u16 section_name_table_index; +} elf_header; +i64 elf_read_header(elf_header *ret, elf_ctx *ctx); +i64 elf_write_header(elf_header *h, elf_ctx *ctx); +u64 elf_program_header_offset(elf_header *h, u64 idx); +u64 elf_section_header_offset(elf_header *h, u64 idx); + +/* section header */ +typedef enum elf_section_type { + ELF_SECTION_TYPE_NULL = 0, + ELF_SECTION_TYPE_PROGBITS = 1, + ELF_SECTION_TYPE_SYMTAB = 2, + ELF_SECTION_TYPE_STRTAB = 3, + ELF_SECTION_TYPE_RELA = 4, + ELF_SECTION_TYPE_HASH = 5, + ELF_SECTION_TYPE_DYNAMIC = 6, + ELF_SECTION_TYPE_NOTE = 7, + ELF_SECTION_TYPE_NOBITS = 8, + ELF_SECTION_TYPE_REL = 9, + ELF_SECTION_TYPE_SHLIB = 10, + ELF_SECTION_TYPE_DYNSYM = 11, + ELF_SECTION_TYPE_INIT_ARRAY = 14, + ELF_SECTION_TYPE_FINI_ARRAY = 15, + ELF_SECTION_TYPE_PREINIT_ARRAY = 16, + ELF_SECTION_TYPE_GROUP = 17, + ELF_SECTION_TYPE_SYMTAB_SHNDX = 18 +} elf_section_type; +/* enums are only guaranteed to represent signed int in c89 */ +#define ELF_SECTION_TYPE_LO_OS 0x60000000 +#define ELF_SECTION_TYPE_HI_OS 0x6fffffff +#define ELF_SECTION_TYPE_LO_PROC 0x70000000 +#define ELF_SECTION_TYPE_HI_PROC 0x7fffffff +#define ELF_SECTION_TYPE_LO_USER 0x80000000 +#define ELF_SECTION_TYPE_HI_USER 0x8fffffff +typedef enum elf_section_flag { + ELF_SECTION_FLAG_WRITE = 0x1, + ELF_SECTION_FLAG_ALLOC = 0x2, + ELF_SECTION_FLAG_EXECINSTR = 0x4, + ELF_SECTION_FLAG_MERGE = 0x10, + ELF_SECTION_FLAG_STRINGS = 0x20, + ELF_SECTION_FLAG_INFO_LINK = 0x40, + ELF_SECTION_FLAG_LINK_ORDER = 0x80, + ELF_SECTION_FLAG_OS_NONCOMFORMING = 0x100, + ELF_SECTION_FLAG_GROUP = 0x200, + ELF_SECTION_FLAG_TLS = 0x400, + ELF_SECTION_FLAG_COMPRESSED = 0x800 +} elf_section_flag; +#define ELF_SECTION_FLAG_MASKOS 0x0ff00000 +#define ELF_SECTION_FLAG_MASKPROC 0xf0000000 +#define ELF32_SECTION_HEADER_SIZE 40 +#define ELF64_SECTION_HEADER_SIZE 64 +i64 elf_section_header_size(elf_ctx *ctx); +typedef struct elf_section_header { + u32 name_index; + u32 /* elf_section_type */ type; + u64 /* elf_section_flag */ flags; + u64 addr; + u64 offset; + u64 size; + u32 link; + u32 info; + u64 addr_alignment; + u64 entry_size; +} elf_section_header; +i64 elf_read_section_header(elf_section_header *ret, elf_ctx *ctx, u64 off); +i64 elf_write_section_header(elf_section_header *sh, elf_ctx *ctx, u64 off); +char *elf_read_section_name(elf_ctx *ctx, elf_header *h, elf_section_header *sh); + +/* symbols */ +typedef enum elf_symbol_binding { + ELF_SYMBOL_BINDING_LOCAL = 0, + ELF_SYMBOL_BINDING_GLOBAL = 1, + ELF_SYMBOL_BINDING_WEAK = 2, + ELF_SYMBOL_BINDING_LO_OS = 10, + ELF_SYMBOL_BINDING_HI_OS = 12, + ELF_SYMBOL_BINDING_LO_PROC = 13, + ELF_SYMBOL_BINDING_HI_PROC = 15 +} elf_symbol_binding; +typedef enum elf_symbol_type { + ELF_SYMBOL_TYPE_NOTYPE = 0, + ELF_SYMBOL_TYPE_OBJECT = 1, + ELF_SYMBOL_TYPE_FUNC = 2, + ELF_SYMBOL_TYPE_SECTION = 3, + ELF_SYMBOL_TYPE_FILE = 4, + ELF_SYMBOL_TYPE_COMMON = 5, + ELF_SYMBOL_TYPE_TLS = 6, + ELF_SYMBOL_TYPE_LO_OS = 10, + ELF_SYMBOL_TYPE_HI_OS = 12, + ELF_SYMBOL_TYPE_LO_PROC = 13, + ELF_SYMBOL_TYPE_HI_PROC = 15 +} elf_symbol_type; +typedef enum elf_symbol_visibility { + ELF_SYMBOL_VISIBILITY_DEFAULT = 0, + ELF_SYMBOL_VISIBILITY_INTERNAL = 1, + ELF_SYMBOL_VISIBILITY_HIDDEN = 2, + ELF_SYMBOL_VISIBILITY_PROTECTED = 3 +} elf_symbol_visibility; +#define ELF32_SYMBOL_SIZE 16 +#define ELF64_SYMBOL_SIZE 24 +i64 elf_symbol_size(elf_ctx *ctx); +typedef struct elf_symbol { + u64 size; + u64 value; + u32 name_index; + elf_symbol_binding bind; elf_symbol_type type; /* info */ + elf_symbol_visibility visibility; /* other */ + u16 section_header_index; +} elf_symbol; +i64 elf_read_symbol(elf_symbol *ret, elf_ctx *ctx, u64 off); +i64 elf_write_symbol(elf_symbol *sym, elf_ctx *ctx, u64 off); +char *elf_read_symbol_name(elf_ctx *ctx, elf_header *h, elf_section_header *sh, elf_symbol *sym); + +/* relocations */ +#define ELF32_REL_SIZE 8 +#define ELF64_REL_SIZE 16 +i64 elf_rel_size(elf_ctx *ctx); +typedef struct elf_rel { + u64 offset; + u64 symtab_index, type; /* info */ +} elf_rel; +#define ELF32_RELA_SIZE 12 +#define ELF64_RELA_SIZE 24 +i64 elf_rela_size(elf_ctx *ctx); +typedef struct elf_rela { + u64 offset; + u64 symtab_index; u64 type; + i64 addend; +} elf_rela; +i64 elf_read_rel(elf_rel *ret, elf_ctx *ctx, u64 off); +i64 elf_read_rela(elf_rela *ret, elf_ctx *ctx, u64 off); + +typedef enum elf_program_header_type { + ELF_PROGRAM_HEADER_TYPE_NULL = 0, + ELF_PROGRAM_HEADER_TYPE_LOAD = 1, + ELF_PROGRAM_HEADER_TYPE_DYNAMIC = 2, + ELF_PROGRAM_HEADER_TYPE_INTERP = 3, + ELF_PROGRAM_HEADER_TYPE_NOTE = 4, + ELF_PROGRAM_HEADER_TYPE_SHLIB = 5, + ELF_PROGRAM_HEADER_TYPE_PHDR = 6, + ELF_PROGRAM_HEADER_TYPE_TLS = 7 +} elf_program_header_type; +#define ELF_PROGRAM_HEADER_TYPE_LOOS 0x60000000 +#define ELF_PROGRAM_HEADER_TYPE_HIOS 0x6fffffff +#define ELF_PROGRAM_HEADER_TYPE_LOPROC 0x70000000 +#define ELF_PROGRAM_HEADER_TYPE_HIPROC 0x7fffffff +typedef enum elf_program_header_flag { + ELF_PROGRAM_HEADER_FLAG_X = 0x1, + ELF_PROGRAM_HEADER_FLAG_W = 0x2, + ELF_PROGRAM_HEADER_FLAG_R = 0x4 +} elf_program_header_flag; +#define ELF_PROGRAM_HEADER_FLAG_MASKOS 0xff00000 +#define ELF_PROGRAM_HEADER_FLAG_MASKPROC 0xf0000000 +#define ELF32_PROGRAM_HEADER_SIZE 32 +#define ELF64_PROGRAM_HEADER_SIZE 56 +i64 elf_program_header_size(elf_ctx *ctx); +typedef struct elf_program_header { + u32 /* elf_program_header_type */ type; + u64 offset; + u64 virtual_addr; + u64 physical_addr; + u64 file_size; + u64 mem_size; + u32 /* elf_program_header_flag */ flags; + u64 align; +} elf_program_header; +i64 elf_read_program_header(elf_program_header *ret, elf_ctx *ctx, u64 off); +i64 elf_write_program_header(elf_program_header *ph, elf_ctx *ctx, u64 off); + +/* writing bytes */ +i64 elf_write_bytes(elf_ctx *ctx, u64 *off, u8 *buf, i64 len); +#define ELF_STRTAB_BYTES_OFF(str) (u8*)str,strlen(str)+1 + +#endif diff --git a/elf/include/lcq/elf/platform/amd64.h b/elf/include/lcq/elf/platform/amd64.h new file mode 100644 index 0000000..19b4ffb --- /dev/null +++ b/elf/include/lcq/elf/platform/amd64.h @@ -0,0 +1,26 @@ +#ifndef LCOLONQ_ELF_PLATFORM_AMD64_H +#define LCOLONQ_ELF_PLATFORM_AMD64_H +typedef enum elf_relocation_amd64 { + ELF_RELOCATION_AMD64_NONE = 0, + ELF_RELOCATION_AMD64_64 = 1, + ELF_RELOCATION_AMD64_PC32 = 2, + ELF_RELOCATION_AMD64_GOT32 = 3, + ELF_RELOCATION_AMD64_PLT32 = 4, + ELF_RELOCATION_AMD64_COPY = 5, + ELF_RELOCATION_AMD64_GLOB_DAT = 6, + ELF_RELOCATION_AMD64_JUMP_SLOT = 7, + ELF_RELOCATION_AMD64_RELATIVE = 8, + ELF_RELOCATION_AMD64_GOTPCREL = 9, + ELF_RELOCATION_AMD64_32 = 10, + ELF_RELOCATION_AMD64_32S = 11, + ELF_RELOCATION_AMD64_16 = 12, + ELF_RELOCATION_AMD64_PC16 = 13, + ELF_RELOCATION_AMD64_8 = 14, + ELF_RELOCATION_AMD64_PC8 = 15, + ELF_RELOCATION_AMD64_PC64 = 24, + ELF_RELOCATION_AMD64_GOTOFF64 = 25, + ELF_RELOCATION_AMD64_GOTPC32 = 26, + ELF_RELOCATION_AMD64_SIZE32 = 32, + ELF_RELOCATION_AMD64_SIZE64 = 33 +} elf_relocation_amd64; +#endif diff --git a/elf/include/lcq/elf/platform/x86.h b/elf/include/lcq/elf/platform/x86.h new file mode 100644 index 0000000..37b57a3 --- /dev/null +++ b/elf/include/lcq/elf/platform/x86.h @@ -0,0 +1,22 @@ +#ifndef LCOLONQ_ELF_PLATFORM_X86_H +#define LCOLONQ_ELF_PLATFORM_X86_H +typedef enum elf_relocation_x86 { + ELF_RELOCATION_X86_NONE = 0, + ELF_RELOCATION_X86_32 = 1, + ELF_RELOCATION_X86_PC32 = 2, + ELF_RELOCATION_X86_GOT32 = 3, + ELF_RELOCATION_X86_PLT32 = 4, + ELF_RELOCATION_X86_COPY = 5, + ELF_RELOCATION_X86_GLOB_DAT = 6, + ELF_RELOCATION_X86_JMP_SLOT = 7, + ELF_RELOCATION_X86_RELATIVE = 8, + ELF_RELOCATION_X86_GOTOFF = 9, + ELF_RELOCATION_X86_GOTPC = 10, + ELF_RELOCATION_X86_32PLT = 11, + ELF_RELOCATION_X86_16 = 20, + ELF_RELOCATION_X86_PC16 = 21, + ELF_RELOCATION_X86_8 = 22, + ELF_RELOCATION_X86_PC8 = 23, + ELF_RELOCATION_X86_SIZE32 = 38 +} elf_relocation_x86; +#endif diff --git a/elf/packages.nix b/elf/packages.nix new file mode 100644 index 0000000..bce9c82 --- /dev/null +++ b/elf/packages.nix @@ -0,0 +1,14 @@ +pkgs: lcq: { + native = pkgs.stdenv.mkDerivation { + pname = "libcolonq-elf"; + version = "git"; + src = ./.; + hardeningDisable = ["all"]; + buildInputs = [ + lcq.prelude.native + ]; + installPhase = '' + make prefix=$out install + ''; + }; +} diff --git a/elf/src/elf.c b/elf/src/elf.c new file mode 100644 index 0000000..ed0d145 --- /dev/null +++ b/elf/src/elf.c @@ -0,0 +1,490 @@ +#include + +#include +#include +#include +#include +#include + +i64 elf_read_header_ident(elf_header_ident *ret, u8 *buf, i64 len) { + if (len < ELF_HEADER_IDENT_SIZE) return -1; + if (buf[0] != 0x7f || buf[1] != 'E' || buf[2] != 'L' || buf[3] != 'F') return -1; + ret->file_class = buf[4]; + ret->endianness = buf[5]; + ret->version = buf[6]; + ret->abi = buf[7]; + ret->abi_version = buf[8]; + return 0; +} + +i64 elf_write_header_ident(elf_header_ident *i, u8 *buf, i64 len) { + if (len < ELF_HEADER_IDENT_SIZE) return -1; + buf[0] = 0x7f; buf[1] = 'E'; buf[2] = 'L'; buf[3] = 'F'; + buf[4] = i->file_class; + buf[5] = i->endianness; + buf[6] = i->version; + buf[7] = i->abi; + buf[8] = i->abi_version; + return 0; +} + +elf_ctx elf_load_from_path(char *p) { + FILE *f = NULL; + i64 len = 0; + u8 *buf = NULL; + elf_ctx ret; + ret.buf = NULL; ret.len = -1; + if (!p) return ret; + f = fopen(p, "r"); + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, 0, SEEK_SET); + buf = calloc((size_t) len, sizeof(u8)); + if ((size_t) len != fread(buf, sizeof(u8), (size_t) len, f) + || elf_read_header_ident(&ret.ident, buf, len) < 0) { + free(buf); + } else { + ret.buf = buf; ret.len = len; + } + fclose(f); + return ret; +} + +elf_ctx elf_ctx_new(u8 *buf, i64 len, elf_class cl, elf_endianness end) { + elf_ctx ret; + ret.buf = buf; ret.len = len; + ret.ident.file_class = cl; + ret.ident.endianness = end; + ret.ident.version = 1; + ret.ident.abi = 0; + ret.ident.abi_version = 0; + elf_write_header_ident(&ret.ident, ret.buf, ret.len); + return ret; +} + +static u8 read_u8(elf_ctx *ctx, u64 *off) { + assert(off != NULL); + assert((i64) *off < ctx->len); + return ctx->buf[(*off)++]; +} +static void write_u8(elf_ctx *ctx, u64 *off, u8 x) { + assert(off != NULL); + assert((i64) *off < ctx->len); + ctx->buf[(*off)++] = x; +} +static u16 read_u16(elf_ctx *ctx, u64 *off) { + u16 b0, b1; + assert(off != NULL); + assert((i64) *off < ctx->len); + assert(ctx->ident.endianness == ELF_ENDIANNESS_LITTLE + || ctx->ident.endianness == ELF_ENDIANNESS_BIG); + b0 = ctx->buf[(*off)++]; b1 = ctx->buf[(*off)++]; + if (ctx->ident.endianness == ELF_ENDIANNESS_LITTLE) { + return b0 | b1 << 8; + } else { + return b0 << 8 | b1; + } +} +static void write_u16(elf_ctx *ctx, u64 *off, u16 x) { + u16 b0, b1; + assert(off != NULL); + assert((i64) *off < ctx->len); + assert(ctx->ident.endianness == ELF_ENDIANNESS_LITTLE + || ctx->ident.endianness == ELF_ENDIANNESS_BIG); + b0 = x; b1 = x >> 8; + if (ctx->ident.endianness == ELF_ENDIANNESS_LITTLE) { + ctx->buf[(*off)++] = (u8) b0; ctx->buf[(*off)++] = (u8) b1; + } else { + ctx->buf[(*off)++] = (u8) b1; ctx->buf[(*off)++] = (u8) b0; + } +} +static u32 read_u32(elf_ctx *ctx, u64 *off) { + u32 b0, b1, b2, b3; + assert(off != NULL); + assert((i64) *off < ctx->len); + assert(ctx->ident.endianness == ELF_ENDIANNESS_LITTLE + || ctx->ident.endianness == ELF_ENDIANNESS_BIG); + b0 = ctx->buf[(*off)++]; b1 = ctx->buf[(*off)++]; + b2 = ctx->buf[(*off)++]; b3 = ctx->buf[(*off)++]; + if (ctx->ident.endianness == ELF_ENDIANNESS_LITTLE) { + return b0 | b1 << 8 | b2 << 16 | b3 << 24; + } else { + return b0 << 24 | b1 << 16 | b2 << 8 | b3; + } +} +static void write_u32(elf_ctx *ctx, u64 *off, u32 x) { + u32 b0, b1, b2, b3; + assert(off != NULL); + assert((i64) *off < ctx->len); + assert(ctx->ident.endianness == ELF_ENDIANNESS_LITTLE + || ctx->ident.endianness == ELF_ENDIANNESS_BIG); + b0 = x; b1 = x >> 8; b2 = x >> 16; b3 = x >> 24; + if (ctx->ident.endianness == ELF_ENDIANNESS_LITTLE) { + ctx->buf[(*off)++] = (u8) b0; ctx->buf[(*off)++] = (u8) b1; + ctx->buf[(*off)++] = (u8) b2; ctx->buf[(*off)++] = (u8) b3; + } else { + ctx->buf[(*off)++] = (u8) b3; ctx->buf[(*off)++] = (u8) b2; + ctx->buf[(*off)++] = (u8) b1; ctx->buf[(*off)++] = (u8) b0; + } +} +static u64 read_u64(elf_ctx *ctx, u64 *off) { + u64 b0, b1, b2, b3, b4, b5, b6, b7; + assert(off != NULL); + assert((i64) *off < ctx->len); + assert(ctx->ident.endianness == ELF_ENDIANNESS_LITTLE + || ctx->ident.endianness == ELF_ENDIANNESS_BIG); + b0 = ctx->buf[(*off)++]; b1 = ctx->buf[(*off)++]; + b2 = ctx->buf[(*off)++]; b3 = ctx->buf[(*off)++]; + b4 = ctx->buf[(*off)++]; b5 = ctx->buf[(*off)++]; + b6 = ctx->buf[(*off)++]; b7 = ctx->buf[(*off)++]; + if (ctx->ident.endianness == ELF_ENDIANNESS_LITTLE) { + return b0 | b1 << 8 | b2 << 16 | b3 << 24 + | b4 << 32 | b5 << 40 | b6 << 48 | b7 << 56; + } else { + return b0 << 56 | b1 << 48 | b2 << 40 | b3 << 32 + | b4 << 24 | b5 << 16 | b6 << 8 | b7; + } +} +static void write_u64(elf_ctx *ctx, u64 *off, u64 x) { + u64 b0, b1, b2, b3, b4, b5, b6, b7; + assert(off != NULL); + assert((i64) *off < ctx->len); + assert(ctx->ident.endianness == ELF_ENDIANNESS_LITTLE + || ctx->ident.endianness == ELF_ENDIANNESS_BIG); + b0 = x; b1 = x >> 8; b2 = x >> 16; b3 = x >> 24; + b4 = x >> 32; b5 = x >> 40; b6 = x >> 48; b7 = x >> 56; + if (ctx->ident.endianness == ELF_ENDIANNESS_LITTLE) { + ctx->buf[(*off)++] = (u8) b0; ctx->buf[(*off)++] = (u8) b1; + ctx->buf[(*off)++] = (u8) b2; ctx->buf[(*off)++] = (u8) b3; + ctx->buf[(*off)++] = (u8) b4; ctx->buf[(*off)++] = (u8) b5; + ctx->buf[(*off)++] = (u8) b6; ctx->buf[(*off)++] = (u8) b7; + } else { + ctx->buf[(*off)++] = (u8) b7; ctx->buf[(*off)++] = (u8) b6; + ctx->buf[(*off)++] = (u8) b5; ctx->buf[(*off)++] = (u8) b4; + ctx->buf[(*off)++] = (u8) b3; ctx->buf[(*off)++] = (u8) b2; + ctx->buf[(*off)++] = (u8) b1; ctx->buf[(*off)++] = (u8) b0; + } +} +static u64 read_file_class_word(elf_ctx *ctx, u64 *off) { + assert(ctx); + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (ctx->ident.file_class == ELF_CLASS_32) { + return (u64) read_u32(ctx, off); + } else { + return (u64) read_u64(ctx, off); + } +} +static void write_file_class_word(elf_ctx *ctx, u64 *off, u64 x) { + assert(ctx); + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (ctx->ident.file_class == ELF_CLASS_32) { + write_u32(ctx, off, (u32) x); + } else { + write_u64(ctx, off, x); + } +} +static i64 read_file_class_signed_word(elf_ctx *ctx, u64 *off) { + assert(ctx); + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (ctx->ident.file_class == ELF_CLASS_32) { + return (i64) (i32) read_u32(ctx, off); + } else { + return (i64) read_u64(ctx, off); + } +} +static void write_file_class_signed_word(elf_ctx *ctx, u64 *off, i64 x) { + assert(ctx); + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (ctx->ident.file_class == ELF_CLASS_32) { + assert(x < UINT32_MAX); + write_u32(ctx, off, (u32) (u64) x); + } else { + write_u64(ctx, off, (u64) x); + } +} + +i64 elf_header_size(elf_ctx *ctx) { + return ctx->ident.file_class == ELF_CLASS_32 + ? ELF32_HEADER_SIZE : ELF64_HEADER_SIZE; +} +i64 elf_read_header(elf_header *ret, elf_ctx *ctx) { + u64 off = ELF_HEADER_IDENT_SIZE; + i64 sz = elf_header_size(ctx); + if (!ret || !ctx || ctx->len < sz) return -1; + ret->type = read_u16(ctx, &off); + ret->machine = read_u16(ctx, &off); + ret->version = read_u32(ctx, &off); + ret->entry = read_file_class_word(ctx, &off); + ret->program_header_offset = read_file_class_word(ctx, &off); + ret->section_header_offset = read_file_class_word(ctx, &off); + ret->flags = read_u32(ctx, &off); + ret->elf_header_size = read_u16(ctx, &off); + ret->program_header_entry_size = read_u16(ctx, &off); + ret->program_header_entries = read_u16(ctx, &off); + ret->section_header_entry_size = read_u16(ctx, &off); + ret->section_header_entries = read_u16(ctx, &off); + ret->section_name_table_index = read_u16(ctx, &off); + return 0; +} +i64 elf_write_header(elf_header *h, elf_ctx *ctx) { + u64 off = ELF_HEADER_IDENT_SIZE; + i64 sz = elf_header_size(ctx); + if (!h || !ctx || ctx->len < sz) return -1; + write_u16(ctx, &off, h->type); + write_u16(ctx, &off, h->machine); + write_u32(ctx, &off, h->version); + printf("entry off: %lu\n", off); + write_file_class_word(ctx, &off, h->entry); + write_file_class_word(ctx, &off, h->program_header_offset); + write_file_class_word(ctx, &off, h->section_header_offset); + write_u32(ctx, &off, h->flags); + write_u16(ctx, &off, h->elf_header_size); + write_u16(ctx, &off, h->program_header_entry_size); + write_u16(ctx, &off, h->program_header_entries); + write_u16(ctx, &off, h->section_header_entry_size); + write_u16(ctx, &off, h->section_header_entries); + write_u16(ctx, &off, h->section_name_table_index); + return 0; +} + +/* given the index of a program/section header, return its file offset */ +u64 elf_program_header_offset(elf_header *h, u64 idx) { + return h->program_header_offset + idx * h->program_header_entry_size; +} +u64 elf_section_header_offset(elf_header *h, u64 idx) { + return h->section_header_offset + idx * h->section_header_entry_size; +} + +i64 elf_section_header_size(elf_ctx *ctx) { + return ctx->ident.file_class == ELF_CLASS_32 + ? ELF32_SECTION_HEADER_SIZE : ELF64_SECTION_HEADER_SIZE; +} +i64 elf_read_section_header(elf_section_header *ret, elf_ctx *ctx, u64 off) { + i64 sz = elf_section_header_size(ctx); + if (!ret || !ctx || ctx->len < (i64) off + sz) return -1; + ret->name_index = read_u32(ctx, &off); + ret->type = read_u32(ctx, &off); + ret->flags = read_file_class_word(ctx, &off); + ret->addr = read_file_class_word(ctx, &off); + ret->offset = read_file_class_word(ctx, &off); + ret->size = read_file_class_word(ctx, &off); + ret->link = read_u32(ctx, &off); + ret->info = read_u32(ctx, &off); + ret->addr_alignment = read_file_class_word(ctx, &off); + ret->entry_size = read_file_class_word(ctx, &off); + return 0; +} +i64 elf_write_section_header(elf_section_header *sh, elf_ctx *ctx, u64 off) { + i64 sz = elf_section_header_size(ctx); + if (!sh || !ctx || ctx->len < (i64) off + sz) return -1; + printf("section off: %lu\n", off); + write_u32(ctx, &off, sh->name_index); + write_u32(ctx, &off, sh->type); + write_file_class_word(ctx, &off, sh->flags); + write_file_class_word(ctx, &off, sh->addr); + write_file_class_word(ctx, &off, sh->offset); + write_file_class_word(ctx, &off, sh->size); + write_u32(ctx, &off, sh->link); + write_u32(ctx, &off, sh->info); + write_file_class_word(ctx, &off, sh->addr_alignment); + write_file_class_word(ctx, &off, sh->entry_size); + return 0; +} + +char *elf_read_section_name(elf_ctx *ctx, elf_header *h, elf_section_header *sh) { + elf_section_header name_section; + if (!ctx || !h || !sh) return NULL; + if (h->section_name_table_index >= h->section_header_entries) return NULL; + if (elf_read_section_header(&name_section, ctx, + elf_section_header_offset(h, h->section_name_table_index)) < 0) + return NULL; + return (char *) &ctx->buf[name_section.offset + sh->name_index]; +} + +i64 elf_symbol_size(elf_ctx *ctx) { + return ctx->ident.file_class == ELF_CLASS_32 + ? ELF32_SYMBOL_SIZE : ELF64_SYMBOL_SIZE; +} +i64 elf_read_symbol(elf_symbol *ret, elf_ctx *ctx, u64 off) { + i64 sz = elf_symbol_size(ctx); + u8 info = 0, other = 0; + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (!ret || !ctx || ctx->len < (i64) off + sz) return -1; + if (ctx->ident.file_class == ELF_CLASS_32) { + ret->name_index = read_u32(ctx, &off); + ret->value = read_u32(ctx, &off); + ret->size = read_u32(ctx, &off); + info = read_u8(ctx, &off); + ret->bind = info >> 4; + ret->type = info & 0xf; + other = read_u8(ctx, &off); + ret->visibility = other & 0x3; + ret->section_header_index = read_u16(ctx, &off); + } else { + ret->name_index = read_u32(ctx, &off); + info = read_u8(ctx, &off); + ret->bind = info >> 4; + ret->type = info & 0xf; + other = read_u8(ctx, &off); + ret->visibility = other & 0x3; + ret->section_header_index = read_u16(ctx, &off); + ret->value = read_u64(ctx, &off); + ret->size = read_u64(ctx, &off); + } + return 0; +} +i64 elf_write_symbol(elf_symbol *sym, elf_ctx *ctx, u64 off) { + i64 sz = elf_symbol_size(ctx); + u8 info, other; + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (!sym || !ctx || ctx->len < (i64) off + sz) return -1; + if (ctx->ident.file_class == ELF_CLASS_32) { + write_u32(ctx, &off, sym->name_index); + write_u32(ctx, &off, (u32) sym->value); + write_u32(ctx, &off, (u32) sym->size); + info = (u8) sym->bind << 4 | sym->type; + write_u8(ctx, &off, info); + other = sym->visibility; + write_u8(ctx, &off, other); + write_u16(ctx, &off, sym->section_header_index); + } else { + write_u32(ctx, &off, sym->name_index); + info = (u8) sym->bind << 4 | sym->type; + write_u8(ctx, &off, info); + other = sym->visibility; + write_u8(ctx, &off, other); + write_u16(ctx, &off, sym->section_header_index); + write_u64(ctx, &off, sym->value); + write_u64(ctx, &off, sym->size); + } + return 0; +} + +static void parse_relocation_info( + u64 *symtab_index, u64 *type, elf_ctx *ctx, u64 info +) { + assert(symtab_index != NULL && type != NULL); + assert(ctx->ident.file_class == ELF_CLASS_32 + || ctx->ident.file_class == ELF_CLASS_64); + if (ctx->ident.file_class == ELF_CLASS_32) { + info &= 0xffffffff; + *symtab_index = info >> 8; + *type = (u8) info; + } else { + *symtab_index = info > 32; + *type = info & 0xffffffff; + } +} +char *elf_read_symbol_name( + elf_ctx *ctx, elf_header *h, elf_section_header *sh, elf_symbol *sym +) { + elf_section_header name_section; + if (!ctx || !sh || !sh) return NULL; + if (!(sh->type == ELF_SECTION_TYPE_SYMTAB + || sh->type == ELF_SECTION_TYPE_DYNSYM)) + return NULL; + if (sh->link >= h->section_header_entries) return NULL; + if (elf_read_section_header(&name_section, ctx, + elf_section_header_offset(h, sh->link)) < 0) + return NULL; + return (char *) &ctx->buf[name_section.offset + sym->name_index]; +} + +i64 elf_rel_size(elf_ctx *ctx) { + return ctx->ident.file_class == ELF_CLASS_32 + ? ELF32_REL_SIZE : ELF64_REL_SIZE; +} +i64 elf_read_rel(elf_rel *ret, elf_ctx *ctx, u64 off) { + i64 sz = elf_rel_size(ctx); + u64 info; + if (!ret || !ctx || ctx->len < (i64) off + sz) return -1; + ret->offset = read_file_class_word(ctx, &off); + info = read_file_class_word(ctx, &off); + parse_relocation_info(&ret->symtab_index, &ret->type, ctx, info); + return 0; +} + +i64 elf_rela_size(elf_ctx *ctx) { + return ctx->ident.file_class == ELF_CLASS_32 + ? ELF32_RELA_SIZE : ELF64_RELA_SIZE; +} +i64 elf_read_rela(elf_rela *ret, elf_ctx *ctx, u64 off) { + i64 sz = elf_rela_size(ctx); + u64 info; + if (!ret || !ctx || ctx->len < (i64) off + sz) return -1; + ret->offset = read_file_class_word(ctx, &off); + info = read_file_class_word(ctx, &off); + parse_relocation_info(&ret->symtab_index, &ret->type, ctx, info); + ret->addend = read_file_class_signed_word(ctx, &off); + return 0; +} + +i64 elf_program_header_size(elf_ctx *ctx) { + return ctx->ident.file_class == ELF_CLASS_32 + ? ELF32_PROGRAM_HEADER_SIZE : ELF64_PROGRAM_HEADER_SIZE; +} +i64 elf_read_program_header(elf_program_header *ret, elf_ctx *ctx, u64 off) { + i64 sz = elf_program_header_size(ctx); + if (!ret || !ctx || ctx->len < (i64) off + sz) return -1; + if (ctx->ident.file_class == ELF_CLASS_32) { + ret->type = read_u32(ctx, &off); + ret->offset = read_file_class_word(ctx, &off); + ret->virtual_addr = read_file_class_word(ctx, &off); + ret->physical_addr = read_file_class_word(ctx, &off); + ret->file_size = read_u32(ctx, &off); + ret->mem_size = read_u32(ctx, &off); + ret->flags = read_u32(ctx, &off); + ret->align = read_u32(ctx, &off); + } else { + ret->type = read_u32(ctx, &off); + ret->flags = read_u32(ctx, &off); + ret->offset = read_file_class_word(ctx, &off); + ret->virtual_addr = read_file_class_word(ctx, &off); + ret->physical_addr = read_file_class_word(ctx, &off); + ret->file_size = read_u64(ctx, &off); + ret->mem_size = read_u64(ctx, &off); + ret->align = read_u64(ctx, &off); + } + return 0; +} +i64 elf_write_program_header(elf_program_header *ph, elf_ctx *ctx, u64 off) { + i64 sz = elf_program_header_size(ctx); + if (!ph || !ctx || ctx->len < (i64) off + sz) return -1; + if (ctx->ident.file_class == ELF_CLASS_32) { + write_u32(ctx, &off, ph->type); + write_file_class_word(ctx, &off, ph->offset); + write_file_class_word(ctx, &off, ph->virtual_addr); + write_file_class_word(ctx, &off, ph->physical_addr); + write_u32(ctx, &off, (u32) ph->file_size); + write_u32(ctx, &off, (u32) ph->mem_size); + write_u32(ctx, &off, ph->flags); + write_u32(ctx, &off, (u32) ph->align); + } else { + write_u32(ctx, &off, ph->type); + write_u32(ctx, &off, ph->flags); + write_file_class_word(ctx, &off, ph->offset); + write_file_class_word(ctx, &off, ph->virtual_addr); + write_file_class_word(ctx, &off, ph->physical_addr); + write_u64(ctx, &off, ph->file_size); + write_u64(ctx, &off, ph->mem_size); + write_u64(ctx, &off, ph->align); + } + return 0; +} + +i64 elf_write_bytes(elf_ctx *ctx, u64 *off, u8 *buf, i64 len) { + i64 i = 0; + if (!ctx || !buf || ctx->len < (i64) *off + len) return -1; + for (; i < len; ++i) { + printf("byte off: %ld\n", (i64) *off + i); + ctx->buf[(i64) *off + i] = buf[i]; + } + *off += (u64) len; + return 0; +} diff --git a/elf/src/main.c b/elf/src/main.c new file mode 100644 index 0000000..8a79586 --- /dev/null +++ b/elf/src/main.c @@ -0,0 +1,204 @@ +#include +#include +#include + +#include + +u8 TEST_PROG[] = { + 0x48, 0xc7, 0xc0, 0x3c, 0x00, 0x00, 0x00, /* mov $0x3c,%rax */ + 0x48, 0xc7, 0xc7, 0x2a, 0x00, 0x00, 0x00, /* mov $0x2a,%rdi */ + 0x0f, 0x05 /* syscall */ +}; + +int main(int argc, char **argv) { + elf_ctx e = {0}; + elf_header h = {0}; + elf_section_header sh = {0}; + elf_program_header ph = {0}; + i64 i = 0; + + if (argc < 3) { fprintf(stderr, "usage: %s MODE ELF-PATH\n", argv[0]); return 1; } + if (strcmp(argv[1], "read") == 0) { + e = elf_load_from_path(argv[2]); + elf_read_header(&h, &e); + printf("%d %d %d %d %d\n", e.ident.file_class, e.ident.endianness, e.ident.version, e.ident.abi, e.ident.abi_version); + printf("type=%u, machine=%u\n", h.type, h.machine); + printf("version=%u, entry=0x%lx\n", h.version, h.entry); + printf("ph=%lu, sh=%lu\n", h.program_header_offset, h.section_header_offset); + printf("flags=%u, eh=%u\n", h.flags, h.elf_header_size); + printf("ph_ent_size=%u, ph_ents=%u\n", h.program_header_entry_size, h.program_header_entries); + printf("sh_ent_size=%u, sh_ents=%u\n", h.section_header_entry_size, h.section_header_entries); + printf("nametable=%u\n", h.section_name_table_index); + + for (i = 0; i < h.section_header_entries; ++i) { + char *name = NULL; + elf_read_section_header(&sh, &e, elf_section_header_offset(&h, (u64) i)); + name = elf_read_section_name(&e, &h, &sh); + printf("section %ld (%s) type: %u\n", i, name, sh.type); + } + for (i = 0; i < h.section_header_entries; ++i) { + elf_read_section_header(&sh, &e, elf_section_header_offset(&h, (u64) i)); + if (sh.type == ELF_SECTION_TYPE_SYMTAB) { + u64 symoff = 0; + for (symoff = 0; symoff < sh.size; symoff += sh.entry_size) { + elf_symbol s = {0}; + elf_read_symbol(&s, &e, sh.offset + symoff); + printf("symbol offset %ld (%s) type: %u\n", + symoff, + elf_read_symbol_name(&e, &h, &sh, &s), + s.type + ); + } + } + } + } else { + elf_symbol s = {0}; + i64 len = 1024 * 16; + u8 *buf = calloc((size_t) len, sizeof(u8)); + FILE *f = NULL; + u64 sh_off = 0, + shstrtab_off = 0, + shstrtab_name_off = 0, + shstrtab_len = 0, + strtab_off = 0, + strtab_name_off = 0, + strtab_len = 0, + symtab_off = 0, + symtab_name_off = 0, + symtab_len = 0, + text_off = 0, + text_name_off = 0, + text_len = 0, + program_header_off = 0, + off = 0, + symbols = 0, + sections = 0; + e = elf_ctx_new(buf, len, ELF_CLASS_64, ELF_ENDIANNESS_LITTLE); + off = ELF64_HEADER_SIZE; + + /* make space for program header */ + program_header_off = off; + off += ELF64_PROGRAM_HEADER_SIZE; + + /* write shstrtab */ + shstrtab_off = off; + e.buf[off++] = 0; + shstrtab_name_off = off - shstrtab_off; elf_write_bytes(&e, &off, ELF_STRTAB_BYTES_OFF(".shstrtab")); + strtab_name_off = off - shstrtab_off; elf_write_bytes(&e, &off, ELF_STRTAB_BYTES_OFF(".strtab")); + symtab_name_off = off - shstrtab_off; elf_write_bytes(&e, &off, ELF_STRTAB_BYTES_OFF(".symtab")); + text_name_off = off - shstrtab_off; elf_write_bytes(&e, &off, ELF_STRTAB_BYTES_OFF(".text")); + e.buf[off++] = 0; + shstrtab_len = off - shstrtab_off; + + /* write strtab */ + strtab_off = off; + e.buf[off++] = 0; + elf_write_bytes(&e, &off, ELF_STRTAB_BYTES_OFF("_start")); + e.buf[off++] = 0; + strtab_len = off - strtab_off; + + /* write symtab */ + symtab_off = off; + printf("symtab_off: %lu\n", symtab_off); + /* null symbol */ + symbols += 1; + s.size = 0; + s.value = 0; + s.name_index = 0; + s.bind = ELF_SYMBOL_BINDING_LOCAL; + s.type = ELF_SYMBOL_TYPE_NOTYPE; + s.visibility = ELF_SYMBOL_VISIBILITY_DEFAULT; + s.section_header_index = 0; + elf_write_symbol(&s, &e, off); + off += ELF64_SYMBOL_SIZE; + + /* _start */ + symbols += 1; + s.size = 0; + s.value = 0x401000; + s.name_index = 1; + s.bind = ELF_SYMBOL_BINDING_GLOBAL; + s.type = ELF_SYMBOL_TYPE_NOTYPE; + s.visibility = ELF_SYMBOL_VISIBILITY_DEFAULT; + s.section_header_index = 4; + elf_write_symbol(&s, &e, off); + off += ELF64_SYMBOL_SIZE; + symtab_len = off - symtab_off; + + /* write text */ + /* text_off = off; */ + text_off = 0x1000; + text_len = text_off; + elf_write_bytes(&e, &text_len, TEST_PROG, sizeof(TEST_PROG)); + /* text_len = off - text_off; */ + text_len -= text_off; + + /* write section headers */ + sh_off = off; + + /* null section */ + sections += 1; + sh.name_index = 0; sh.type = ELF_SECTION_TYPE_NULL; + sh.flags = 0; sh.addr = 0; sh.offset = 0; sh.size = 0; + sh.link = 0; sh.info = 0; sh.addr_alignment = 0; sh.entry_size = 0; + elf_write_section_header(&sh, &e, off); off += ELF64_SECTION_HEADER_SIZE; + + /* .shstrtab */ + sections += 1; + sh.name_index = (u32) shstrtab_name_off; sh.type = ELF_SECTION_TYPE_STRTAB; + sh.flags = 0; sh.addr = 0; sh.offset = shstrtab_off; sh.size = shstrtab_len; + sh.link = 0; sh.info = 0; sh.addr_alignment = 0; sh.entry_size = 0; + elf_write_section_header(&sh, &e, off); off += ELF64_SECTION_HEADER_SIZE; + + /* .strtab */ + sections += 1; + sh.name_index = (u32) strtab_name_off; sh.type = ELF_SECTION_TYPE_STRTAB; + sh.flags = 0; sh.addr = 0; sh.offset = strtab_off; sh.size = strtab_len; + sh.link = 0; sh.info = 0; sh.addr_alignment = 0; sh.entry_size = 0; + elf_write_section_header(&sh, &e, off); off += ELF64_SECTION_HEADER_SIZE; + + /* .symtab */ + sections += 1; + sh.name_index = (u32) symtab_name_off; sh.type = ELF_SECTION_TYPE_SYMTAB; + sh.flags = 0; sh.addr = 0; sh.offset = symtab_off; sh.size = symtab_len; + sh.link = 2; sh.info = 1; sh.addr_alignment = 0; sh.entry_size = ELF64_SYMBOL_SIZE; + elf_write_section_header(&sh, &e, off); off += ELF64_SECTION_HEADER_SIZE; + + /* .text */ + sections += 1; + sh.name_index = (u32) text_name_off; sh.type = ELF_SECTION_TYPE_PROGBITS; + sh.flags = ELF_SECTION_FLAG_ALLOC | ELF_SECTION_FLAG_EXECINSTR; + sh.addr = 0x401000; sh.offset = text_off; sh.size = text_len; + sh.link = 0; sh.info = 0; sh.addr_alignment = 0; sh.entry_size = 0; + elf_write_section_header(&sh, &e, off); off += ELF64_SECTION_HEADER_SIZE; + + /* write program header */ + ph.type = ELF_PROGRAM_HEADER_TYPE_LOAD; + ph.offset = text_off; + ph.virtual_addr = 0x401000; + ph.physical_addr = 0; + ph.file_size = (u32) text_len; + ph.mem_size = (u32) text_len; + ph.flags = ELF_PROGRAM_HEADER_FLAG_R | ELF_PROGRAM_HEADER_FLAG_X; + ph.align = 0; + elf_write_program_header(&ph, &e, program_header_off); + + /* write header at the start */ + h.type = ELF_TYPE_EXEC; + h.machine = ELF_MACHINE_AMD64; + h.version = 1; + h.entry = 0x401000; + h.program_header_offset = program_header_off; + h.program_header_entry_size = ELF64_PROGRAM_HEADER_SIZE; + h.program_header_entries = 1; + h.section_header_offset = sh_off; + h.section_header_entry_size = ELF64_SECTION_HEADER_SIZE; + h.section_header_entries = (u16) sections; + h.section_name_table_index = 1; + elf_write_header(&h, &e); + f = fopen(argv[2], "w+"); + fwrite(buf, sizeof(u8), (size_t) len, f); + fclose(f); + } + return 0; +} -- cgit v1.3.1