diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-05-20 16:50:19 -0400 |
---|---|---|
committer | GHC GitLab CI <ghc-ci@gitlab-haskell.org> | 2022-05-23 16:24:07 -0400 |
commit | 1ca1efdc8758458a28414f6d00c679b8f9a6bd0a (patch) | |
tree | 4920de7dbbe621634157ef1fa7af8b8e1ad2ecfc | |
parent | 13b939e2ef4247887593e97e3eb4f2b4c7b05ef1 (diff) | |
download | haskell-1ca1efdc8758458a28414f6d00c679b8f9a6bd0a.tar.gz |
jit object
(cherry picked from commit 9af5422203769f2f939d4a61e7de54b402863bc5)
-rw-r--r-- | rts/Linker.c | 2 | ||||
-rw-r--r-- | rts/linker/BufferBuilder.c | 23 | ||||
-rw-r--r-- | rts/linker/BufferBuilder.h | 37 | ||||
-rw-r--r-- | rts/linker/JitObject.c | 97 | ||||
-rw-r--r-- | rts/linker/JitObject.h | 5 | ||||
-rw-r--r-- | rts/linker/JitObjectCoff.c | 47 | ||||
-rw-r--r-- | rts/linker/JitObjectElf.c | 105 | ||||
-rw-r--r-- | rts/rts.cabal.in | 9 |
8 files changed, 267 insertions, 58 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index e0a3a07dc2..b0ffa46688 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1630,6 +1630,8 @@ int ocTryLoad (ObjectCode* oc) { # endif if (!r) { return r; } + register_jit_object(oc); + IF_DEBUG(linker, ocDebugBelch(oc, "protecting mappings\n")); #if defined(NEED_SYMBOL_EXTRAS) ocProtectExtras(oc); diff --git a/rts/linker/BufferBuilder.c b/rts/linker/BufferBuilder.c index 2c4f84836e..9f6ff04277 100644 --- a/rts/linker/BufferBuilder.c +++ b/rts/linker/BufferBuilder.c @@ -1,15 +1,12 @@ #include "Rts.h" - -struct BufferBuilder { - uint8_t *buffer; // start of buffer - uint8_t *head; // next unfilled byte - uint8_t *end // end of buffer -}; +#include "RtsUtils.h" +#include "BufferBuilder.h" +#include <string.h> struct BufferBuilder buffer_builder_new(size_t initial_sz) { uint8_t *buffer = stgMallocBytes(initial_sz, "new_buffer_builder"); - return struct BufferBuilder { + return (struct BufferBuilder) { .buffer = buffer, .head = buffer, .end = buffer + initial_sz, @@ -62,15 +59,3 @@ void buffer_builder_append(struct BufferBuilder *bb, struct BufferBuilder *src) buffer_builder_push(bb, bb->buffer, sz); } -#define DEFINE_BUILDER(ty) \ - void buffer_builder_#ty(struct BufferBuilder *bb, ty#_t x) \ - { return (ty#_t *) buffer_builder_push(bb, &x, sizeof(x)); } -DEFINE_BUILDER(uint8) -DEFINE_BUILDER(uint16) -DEFINE_BUILDER(uint32) -DEFINE_BUILDER(uint64) -DEFINE_BUILDER(int8) -DEFINE_BUILDER(int16) -DEFINE_BUILDER(int32) -DEFINE_BUILDER(int64) -#undef DEFINE_BUILDER diff --git a/rts/linker/BufferBuilder.h b/rts/linker/BufferBuilder.h new file mode 100644 index 0000000000..facccb8335 --- /dev/null +++ b/rts/linker/BufferBuilder.h @@ -0,0 +1,37 @@ +#pragma once + +#include <stddef.h> +#include <stdint.h> + +struct BufferBuilder { + uint8_t *buffer; // start of buffer + uint8_t *head; // next unfilled byte + uint8_t *end; // end of buffer +}; + +struct BufferBuilder buffer_builder_new(size_t initial_sz); +void buffer_builder_free(struct BufferBuilder *bb); +size_t buffer_builder_filled_size(struct BufferBuilder *bb); +size_t buffer_builder_reserved_size(struct BufferBuilder *bb); +void buffer_builder_realloc(struct BufferBuilder *bb, size_t new_sz); +uint8_t *buffer_builder_push(struct BufferBuilder *bb, uint8_t *x, size_t sz); +void buffer_builder_append(struct BufferBuilder *bb, struct BufferBuilder *src); + +#define buffer_builder_push_struct(bb, x) \ + (typeof(x)*) buffer_builder_push(bb, (uint8_t *) &x, sizeof(x)) + +#define DEFINE_BUILDER(ty) \ + static inline ty ## _t* buffer_builder_ ## ty(struct BufferBuilder *bb, ty ## _t x) \ + { return (ty ## _t *) buffer_builder_push(bb, (uint8_t *) &x, sizeof(x)); } + +DEFINE_BUILDER(uint8); +DEFINE_BUILDER(uint16); +DEFINE_BUILDER(uint32); +DEFINE_BUILDER(uint64); +DEFINE_BUILDER(int8); +DEFINE_BUILDER(int16); +DEFINE_BUILDER(int32); +DEFINE_BUILDER(int64); + +#undef DEFINE_BUILDER + diff --git a/rts/linker/JitObject.c b/rts/linker/JitObject.c index bd8b432f9e..48652283b7 100644 --- a/rts/linker/JitObject.c +++ b/rts/linker/JitObject.c @@ -1,43 +1,62 @@ #include "BufferBuilder.h" +#include "JitObject.h" +#include "LinkerInternals.h" +#include "RtsUtils.h" -void *build_jit_object_coff(ObjectCode *oc) +/* + * GDB JIT interface + */ + +typedef enum +{ + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN +} jit_actions_t; + +struct jit_code_entry { - struct BufferBuilder bb = buffer_builder_new(4096); - - // COFF header - buffer_builder_uint16(bb, IMAGE_FILE_MACHINE_AMD64); - buffer_builder_uint16(bb, 1); // NumberOfSections - buffer_builder_uint32(bb, 0); // TimeDateStamp - uint32_t *ptr_to_symbol_table = buffer_builder_uint32(bb, 0); // PointerToSymbolTable - buffer_builder_uint32(bb, n_syms); // NumberOfSymbols - buffer_builder_uint16(bb, 0); // SizeOfOptionalHeader - buffer_builder_uint16(bb, 0); // Characteristics - - // Sections - buffer_builder_push(bb, ".text\0\0\0", 8); // Name - buffer_builder_uint32(bb, sect_sz); // VirtualSize - buffer_builder_uint32(bb, sect_base); // VirtualAddress - buffer_builder_uint32(bb, 0); // SizeOfRawData - buffer_builder_uint32(bb, 0); // PointerToRawData - buffer_builder_uint32(bb, 0); // PointerToRelocations - buffer_builder_uint32(bb, 0); // PointerToLinenumbers - buffer_builder_uint16(bb, 0); // NumberOfRelocations - buffer_builder_uint16(bb, 0); // NumberOfLinenumbers - buffer_builder_uint32(bb, 0); // Characteristics - - struct BufferBuilder strings = buffer_builder_new(4096); - for (int i=0; i < oc->n_symbols; i++) { - Symbol_t *sym = oc->symbols[i]; - size_t offset = buffer_builder_filled_size(strings); - buffer_builder_push(strings, sym->name); - buffer_builder_uint32(bb, 0); - buffer_builder_uint32(bb, offset); // RawName index - buffer_builder_uint32(bb, value); // Value - buffer_builder_uint16(bb, 1); // SectionNumber - buffer_builder_uint8(bb, 0x20); // StorageClass - buffer_builder_uint8(bb, 0); // NumberOfAuxSymbols - } - - buffer_builder_append(bb, strings); - return bb->start; + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; +}; + +struct jit_descriptor +{ + uint32_t version; + /* This type should be jit_actions_t, but we use uint32_t + to be explicit about the bitwidth. */ + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; +}; + +/* GDB puts a breakpoint in this function. */ +void __jit_debug_register_code(void); +void __attribute__((noinline)) __jit_debug_register_code() { }; + +/* Make sure to specify the version statically, because the + debugger may check the version before we can set it. */ +struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; + +/* + * Registering a JIT object + */ + +void register_jit_object(ObjectCode *oc) +{ + struct BufferBuilder buf = build_jit_object(oc); + + struct jit_code_entry *code_entry = stgMallocBytes(sizeof(struct jit_code_entry), "register_jit_object"); + code_entry->next_entry = __jit_debug_descriptor.first_entry; + code_entry->prev_entry = NULL; + code_entry->symfile_addr = (const char *) buf.buffer; + code_entry->symfile_size = buffer_builder_filled_size(&buf); + + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + __jit_debug_descriptor.first_entry = code_entry; + __jit_debug_descriptor.relevant_entry = code_entry; + __jit_debug_register_code(); } + diff --git a/rts/linker/JitObject.h b/rts/linker/JitObject.h new file mode 100644 index 0000000000..1f21ee28c8 --- /dev/null +++ b/rts/linker/JitObject.h @@ -0,0 +1,5 @@ +#include "LinkerInternals.h" +#include "BufferBuilder.h" + +void register_jit_object(ObjectCode *oc); +struct BufferBuilder build_jit_object(ObjectCode *oc); diff --git a/rts/linker/JitObjectCoff.c b/rts/linker/JitObjectCoff.c new file mode 100644 index 0000000000..77ce9fecc9 --- /dev/null +++ b/rts/linker/JitObjectCoff.c @@ -0,0 +1,47 @@ +#include "BufferBuilder.h" +#include "JitObject.h" +#include "LinkerInternals.h" +#include "RtsUtils.h" + +struct BufferBuilder build_jit_object(ObjectCode *oc) +{ + struct BufferBuilder bb = buffer_builder_new(4096); + + // COFF header + buffer_builder_uint16(&bb, IMAGE_FILE_MACHINE_AMD64); + buffer_builder_uint16(&bb, 1); // NumberOfSections + buffer_builder_uint32(&bb, 0); // TimeDateStamp + uint32_t *ptr_to_symbol_table = buffer_builder_uint32(&bb, 0); // PointerToSymbolTable + buffer_builder_uint32(&bb, n_syms); // NumberOfSymbols + buffer_builder_uint16(&bb, 0); // SizeOfOptionalHeader + buffer_builder_uint16(&bb, 0); // Characteristics + + // Sections + buffer_builder_push(&bb, ".text\0\0\0", 8); // Name + buffer_builder_uint32(&bb, sect_sz); // VirtualSize + buffer_builder_uint32(&bb, sect_base); // VirtualAddress + buffer_builder_uint32(&bb, 0); // SizeOfRawData + buffer_builder_uint32(&bb, 0); // PointerToRawData + buffer_builder_uint32(&bb, 0); // PointerToRelocations + buffer_builder_uint32(&bb, 0); // PointerToLinenumbers + buffer_builder_uint16(&bb, 0); // NumberOfRelocations + buffer_builder_uint16(&bb, 0); // NumberOfLinenumbers + buffer_builder_uint32(&bb, 0); // Characteristics + + struct BufferBuilder strings = buffer_builder_new(4096); + for (int i=0; i < oc->n_symbols; i++) { + Symbol_t *sym = &oc->symbols[i]; + size_t offset = buffer_builder_filled_size(&strings); + buffer_builder_push(&strings, sym->name, strlen(sym->name)); + buffer_builder_uint32(&bb, 0); + buffer_builder_uint32(&bb, offset); // RawName index + buffer_builder_uint32(&bb, value); // Value + buffer_builder_uint16(&bb, 1); // SectionNumber + buffer_builder_uint8(&bb, 0x20); // StorageClass + buffer_builder_uint8(&bb, 0); // NumberOfAuxSymbols + } + + buffer_builder_append(&bb, strings); + return bb; +} + diff --git a/rts/linker/JitObjectElf.c b/rts/linker/JitObjectElf.c new file mode 100644 index 0000000000..41653ad45e --- /dev/null +++ b/rts/linker/JitObjectElf.c @@ -0,0 +1,105 @@ +#include "BufferBuilder.h" +#include "elf_compat.h" +#include "linker/Elf.h" +#include "JitObject.h" +#include "LinkerInternals.h" +#include "RtsUtils.h" + +#include <string.h> + +#define TEXT_SECTION_IDX 1 + +struct BufferBuilder build_jit_object(ObjectCode *oc) +{ + struct BufferBuilder bb = buffer_builder_new(4096); + + // ELF header + Elf64_Ehdr ehdr = { + .e_ident = { + ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, + ELFCLASS64, + ELFDATA2LSB, + EV_CURRENT, + }, + .e_type = ET_REL, + .e_machine = EM_386, + .e_version = EV_CURRENT, + .e_entry = 0, + .e_phoff = 0, + .e_shoff = 0, // will be filled in later + .e_flags = 0, + .e_ehsize = sizeof(Elf64_Ehdr), + .e_phentsize = sizeof(Elf64_Phdr), + .e_phnum = 0, + .e_shentsize = sizeof(Elf64_Shdr), + .e_shnum = 2, + .e_shstrndx = 0, + }; + + Elf64_Ehdr *ehdr_ptr = buffer_builder_push_struct(&bb, ehdr); + + // String table + struct BufferBuilder strings = buffer_builder_new(4096); + buffer_builder_uint8(&strings, 0); + + // Section table + struct BufferBuilder shtab = buffer_builder_new(4096); + Elf64_Shdr shtab_zero_ent = { + .sh_name = 0, + .sh_type = SHT_NULL, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = 0, + .sh_size = 0, + .sh_link = SHN_UNDEF, + .sh_info = 0, + .sh_addralign = 0, + .sh_entsize = 0, + }; + buffer_builder_push_struct(&shtab, shtab_zero_ent); + + Elf64_Shdr shtab_text_ent = { + .sh_name = 1, + .sh_type = SHT_NULL, + .sh_flags = SHF_ALLOC | SHF_EXECINSTR, + .sh_addr = 0, + .sh_offset = 0, // will be filled in later + .sh_size = 0, + .sh_link = SHN_UNDEF, + .sh_info = 0, + .sh_addralign = 0, + .sh_entsize = 0, + }; + buffer_builder_push_struct(&shtab, shtab_zero_ent); + + // Symbol table + struct BufferBuilder symtab = buffer_builder_new(4096); + Elf64_Sym symtab_zero_ent = { + .st_name = 0, + .st_value = 0, + .st_size = 0, + .st_info = 0, + .st_other = 0, + .st_shndx = SHN_UNDEF, + }; + buffer_builder_push_struct(&symtab, symtab_zero_ent); + + for (int i=0; i < oc->n_symbols; i++) { + Symbol_t *sym = &oc->symbols[i]; + size_t sym_name_offset = buffer_builder_filled_size(&strings); + buffer_builder_push(&strings, sym->name, strlen(sym->name)+1); + + Elf64_Sym symtab_ent = { + .st_name = sym_name_offset, + .st_value = hi, + .st_size = 0, + .st_info = 0, + .st_other = 0, + .st_shndx = TEXT_SECTION_IDX, + }; + buffer_builder_push_struct(&symtab, symtab_ent); + } + + return bb; +} + diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in index cc449ee522..e2f0bf11fa 100644 --- a/rts/rts.cabal.in +++ b/rts/rts.cabal.in @@ -470,6 +470,13 @@ library if arch(ppc) || arch(ppc64) || arch(s390x) || arch(riscv64) asm-sources: StgCRunAsm.S + -- gdb JIT object logic + if os(mingw32) + c-sources: linker/JitObjectCoff.c + else + if os(linux) || os(freebsd) + c-sources: linker/JitObjectElf.c + c-sources: Adjustor.c adjustor/AdjustorPool.c ExecPage.c @@ -548,8 +555,10 @@ library hooks/OnExit.c hooks/OutOfHeap.c hooks/StackOverflow.c + linker/BufferBuilder.c linker/CacheFlush.c linker/Elf.c + linker/JitObject.c linker/LoadArchive.c linker/M32Alloc.c linker/MMap.c |