From 968a89b1417d24e3247c96950b434de1971b0d4e Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 28 Aug 2008 21:19:31 +0100 Subject: [PATCH] Relocating COM32 module --- com32/gdbstub/Makefile | 48 +++++++++++++++++++++++ com32/gdbstub/main.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 com32/gdbstub/Makefile create mode 100644 com32/gdbstub/main.c diff --git a/com32/gdbstub/Makefile b/com32/gdbstub/Makefile new file mode 100644 index 0000000..d9e55c8 --- /dev/null +++ b/com32/gdbstub/Makefile @@ -0,0 +1,48 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## GDB remote debugging +## + +topdir = ../.. +include ../MCONFIG + +CFLAGS += -fPIE + +LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC) +LNXLIBS = ../libutil/libutil_lnx.a + +MODULES = gdbstub.c32 +TESTFILES = + +OBJS = main.o + +all: $(MODULES) $(TESTFILES) + +gdbstub.elf : $(OBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lss *.c32 *.lnx *.com + +spotless: clean + rm -f *~ \#* + +install: all + mkdir -m 755 -p $(INSTALLROOT)$(AUXDIR) + install -m 644 $(MODULES) $(INSTALLROOT)$(AUXDIR) + +-include .*.d diff --git a/com32/gdbstub/main.c b/com32/gdbstub/main.c new file mode 100644 index 0000000..11c4e08 --- /dev/null +++ b/com32/gdbstub/main.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include + +#define COM32_LOAD_ADDR ((void*)0x101000) +#define STACK_RED_ZONE 0x1000 + +static inline void error(const char *msg) +{ + fputs(msg, stderr); +} + +static void shift_cmdline(struct com32_sys_args *com32) +{ + char *p; + + /* Skip leading whitespace */ + for (p = com32->cs_cmdline; *p != '\0' && *p == ' '; p++) + ; + + /* Skip first word */ + for (; *p != '\0' && *p != ' '; p++) + ; + + /* Skip whitespace after first word */ + for (; *p != '\0' && *p == ' '; p++) + ; + + com32->cs_cmdline = p; +} + +static __noreturn reloc_entry(void *ptr, size_t len, uintptr_t entry_esp, uintptr_t module_esp) +{ + size_t stack_frame_size = sizeof(struct com32_sys_args) + 4; + struct com32_sys_args *com32; + + /* Copy module to load address */ + memcpy(COM32_LOAD_ADDR, ptr, len); + + /* Copy stack frame onto module stack */ + module_esp = (module_esp - stack_frame_size) & ~15; + memcpy((void*)module_esp, (void*)entry_esp, stack_frame_size); + + /* Fix up command line */ + com32 = (struct com32_sys_args*)((char*)module_esp + 4); + shift_cmdline(com32); + + /* Invoke module with stack set up */ + asm volatile ( + "movl %0, %%esp\n\t" + "jmp *%%ecx" + : : "r"(module_esp), "c"(COM32_LOAD_ADDR) + ); + for(;;); /* shut the compiler up */ +} + +static inline __noreturn reloc(void *ptr, size_t len) +{ + extern uintptr_t __entry_esp; + extern char _start[], _end[]; + size_t total_size = _end - _start; + __noreturn (*success_fn)(void*, size_t, uintptr_t, uintptr_t); + uint32_t esp; + char *dest; + + /* Calculate relocation address, preserve current stack */ + asm volatile ("movl %%esp, %0\n\t" : "=m"(esp)); + dest = (char*)((esp - STACK_RED_ZONE - total_size) & ~3); + + /* Calculate entry point in relocated code */ + success_fn = (void*)(dest + ((char*)reloc_entry - _start)); + + /* Copy all sections to relocation address */ + printf("Relocating %d bytes from %p to %p\n", total_size, _start, dest); + memcpy(dest, _start, total_size); + + success_fn(ptr, len, __entry_esp, (uintptr_t)dest); +} + +int main(int argc, char *argv[]) +{ + void *data; + size_t data_len; + + openconsole(&dev_null_r, &dev_stdcon_w); + + if (argc < 2) { + error("Usage: gdbstub.c32 com32_file arguments...\n"); + return 1; + } + + if (loadfile(argv[1], &data, &data_len)) { + error("Unable to load file\n"); + return 1; + } + + /* No more lib calls after this point */ + reloc(data, data_len); +} -- 2.7.4