diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-05-20 10:02:13 -0400 |
---|---|---|
committer | GHC GitLab CI <ghc-ci@gitlab-haskell.org> | 2022-05-23 16:23:43 -0400 |
commit | 13b939e2ef4247887593e97e3eb4f2b4c7b05ef1 (patch) | |
tree | fdd6b5b81e28f641ee999702fa8a84321d853d98 | |
parent | 022ae00f7737328762bfb088dc7c7a52f66c4977 (diff) | |
download | haskell-13b939e2ef4247887593e97e3eb4f2b4c7b05ef1.tar.gz |
linker: Add support for gdb's JIT interface
(cherry picked from commit 3b909208273c75fb3fe6b05b75c4fe9bf635ed68)
-rw-r--r-- | rts/linker/BufferBuilder.c | 76 | ||||
-rw-r--r-- | rts/linker/JitObject.c | 43 |
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; +} |