diff options
author | Stefan Hajnoczi <stefanha@gmail.com> | 2008-08-28 21:19:31 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@gmail.com> | 2008-08-28 21:19:31 +0100 |
commit | 968a89b1417d24e3247c96950b434de1971b0d4e (patch) | |
tree | 2149233184d2430c2e03a1bea47aa1f0bce09bff | |
parent | 2a6fef03f88e7aa56009f608dccd17e6f24dde97 (diff) | |
download | syslinux.git-968a89b1417d24e3247c96950b434de1971b0d4e.tar.gz syslinux.git-968a89b1417d24e3247c96950b434de1971b0d4e.tar.xz syslinux.git-968a89b1417d24e3247c96950b434de1971b0d4e.zip |
Relocating COM32 module
-rw-r--r-- | com32/gdbstub/Makefile | 48 | ||||
-rw-r--r-- | com32/gdbstub/main.c | 102 |
2 files changed, 150 insertions, 0 deletions
diff --git a/com32/gdbstub/Makefile b/com32/gdbstub/Makefile new file mode 100644 index 00000000..d9e55c8c --- /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 00000000..11c4e08b --- /dev/null +++ b/com32/gdbstub/main.c @@ -0,0 +1,102 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <console.h> +#include <com32.h> +#include <syslinux/loadfile.h> + +#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); +} |