aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@gmail.com>2008-08-28 21:19:31 +0100
committerStefan Hajnoczi <stefanha@gmail.com>2008-08-28 21:19:31 +0100
commit968a89b1417d24e3247c96950b434de1971b0d4e (patch)
tree2149233184d2430c2e03a1bea47aa1f0bce09bff
parent2a6fef03f88e7aa56009f608dccd17e6f24dde97 (diff)
downloadsyslinux.git-968a89b1417d24e3247c96950b434de1971b0d4e.tar.gz
syslinux.git-968a89b1417d24e3247c96950b434de1971b0d4e.tar.xz
syslinux.git-968a89b1417d24e3247c96950b434de1971b0d4e.zip
Relocating COM32 module
-rw-r--r--com32/gdbstub/Makefile48
-rw-r--r--com32/gdbstub/main.c102
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);
+}