summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-05-20 10:02:13 -0400
committerGHC GitLab CI <ghc-ci@gitlab-haskell.org>2022-05-23 16:23:43 -0400
commit13b939e2ef4247887593e97e3eb4f2b4c7b05ef1 (patch)
treefdd6b5b81e28f641ee999702fa8a84321d853d98
parent022ae00f7737328762bfb088dc7c7a52f66c4977 (diff)
downloadhaskell-13b939e2ef4247887593e97e3eb4f2b4c7b05ef1.tar.gz
linker: Add support for gdb's JIT interface
(cherry picked from commit 3b909208273c75fb3fe6b05b75c4fe9bf635ed68)
-rw-r--r--rts/linker/BufferBuilder.c76
-rw-r--r--rts/linker/JitObject.c43
2 files changed, 119 insertions, 0 deletions
diff --git a/rts/linker/BufferBuilder.c b/rts/linker/BufferBuilder.c
new file mode 100644
index 0000000000..2c4f84836e
--- /dev/null
+++ b/rts/linker/BufferBuilder.c
@@ -0,0 +1,76 @@
+#include "Rts.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)
+{
+ uint8_t *buffer = stgMallocBytes(initial_sz, "new_buffer_builder");
+ return struct BufferBuilder {
+ .buffer = buffer,
+ .head = buffer,
+ .end = buffer + initial_sz,
+ };
+}
+
+void buffer_builder_free(struct BufferBuilder *bb)
+{
+ stgFree(bb->buffer);
+ bb->buffer = NULL;
+ bb->head = NULL;
+ bb->end = NULL;
+}
+
+size_t buffer_builder_filled_size(struct BufferBuilder *bb)
+{
+ return bb->head - bb->buffer;
+}
+
+size_t buffer_builder_reserved_size(struct BufferBuilder *bb)
+{
+ return bb->end - bb->buffer;
+}
+
+void buffer_builder_realloc(struct BufferBuilder *bb, size_t new_sz)
+{
+ size_t filled_sz = buffer_builder_filled_size(bb);
+ ASSERT(filled_sz <= new_sz);
+ uint8_t *buffer = stgReallocBytes(bb->buffer, new_sz, "new_buffer_builder");
+ bb->buffer = buffer;
+ bb->head = buffer + filled_sz;
+ bb->end = buffer + new_sz;
+}
+
+uint8_t *buffer_builder_push(struct BufferBuilder *bb, uint8_t *x, size_t sz)
+{
+ if (bb->head + sz > bb->end) {
+ buffer_builder_realloc(bb, 2*buffer_builder_reserved_size(bb));
+ }
+
+ memcpy(bb->head, x, sz);
+ uint8_t *ret = bb->head;
+ bb->head += sz;
+ return ret;
+}
+
+void buffer_builder_append(struct BufferBuilder *bb, struct BufferBuilder *src)
+{
+ size_t sz = buffer_builder_filled_size(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/JitObject.c b/rts/linker/JitObject.c
new file mode 100644
index 0000000000..bd8b432f9e
--- /dev/null
+++ b/rts/linker/JitObject.c
@@ -0,0 +1,43 @@
+#include "BufferBuilder.h"
+
+void *build_jit_object_coff(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);
+ 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;
+}