From: Christian Franke <Christian.Franke@t-online.de>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [PATCH] Kernel fixes for Cygwin
Date: Sun, 20 Jul 2008 22:51:52 +0200 [thread overview]
Message-ID: <4883A568.10709@t-online.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 983 bytes --]
This adds Cygwin support to kernel sources. It handles the issues
introduced by PE->ELF conversion and adds support for HAVE_ASM_USCORE.
Christian
2007-07-20 Christian Franke <franke@computer.org>
* include/grub/dl.h: Remove .previous, gas supports this only
for ELF format.
* include/grub/symbol.h [__CYGWIN__] (#define FUNCTION/VARIABLE):
Remove .type, gas supports this only for ELF format.
* kern/dl.c (grub_dl_resolve_symbols): Add check for grub_mod_init
and grub_mod_fini for symbols without a type. Handle HAVE_ASM_USCORE
case for these symbols.
(grub_dl_resolve_dependencies): Add check for trailing nullbytes
in symbol table. This fixes an infinite loop if table is zero filled.
* kern/i386/dl.c [__CYGWIN__] (fix_pc_rel_relocation): New function
to fix bad PC relative relocation produced by objcopy.
[__CYGWIN__] (grub_arch_dl_relocate_symbols): Add fix of PC relative relocation.
(grub_arch_dl_relocate_symbols): Abort on unknown relocation type.
[-- Attachment #2: grub2-Cygwin-kern.patch --]
[-- Type: text/x-diff, Size: 5836 bytes --]
diff --git a/include/grub/dl.h b/include/grub/dl.h
index b630c6f..3029f95 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -40,11 +40,12 @@ grub_##name##_fini (void) { grub_mod_fini (); } \
static void \
grub_mod_fini (void)
+/* Note: .previous not supported for non-ELF targets. */
#define GRUB_MOD_NAME(name) \
-__asm__ (".section .modname,\"S\"\n.string \"" #name "\"\n.previous")
+__asm__ (".section .modname\n.string \"" #name "\"\n")
#define GRUB_MOD_DEP(name) \
-__asm__ (".section .moddeps,\"S\"\n.string \"" #name "\"\n.previous")
+__asm__ (".section .moddeps\n.string \"" #name "\"\n")
struct grub_dl_segment
{
diff --git a/include/grub/symbol.h b/include/grub/symbol.h
index aa0ea5a..72209d1 100644
--- a/include/grub/symbol.h
+++ b/include/grub/symbol.h
@@ -28,8 +28,14 @@
# define EXT_C(sym) sym
#endif
+#ifndef __CYGWIN__
#define FUNCTION(x) .globl EXT_C(x) ; .type EXT_C(x), "function" ; EXT_C(x):
#define VARIABLE(x) .globl EXT_C(x) ; .type EXT_C(x), "object" ; EXT_C(x):
+#else
+/* .type not supported for non-ELF targets. XXX: Check this in configure? */
+#define FUNCTION(x) .globl EXT_C(x) ; EXT_C(x):
+#define VARIABLE(x) .globl EXT_C(x) ; EXT_C(x):
+#endif
/* Mark an exported symbol. */
#ifndef GRUB_SYMBOL_GENERATOR
diff --git a/kern/dl.c b/kern/dl.c
index c0d9f1d..7950c0d 100644
--- a/kern/dl.c
+++ b/kern/dl.c
@@ -53,6 +53,12 @@ typedef Elf64_Sym Elf_Sym;
#endif
+#ifdef HAVE_ASM_USCORE
+# define SYM_USCORE "_"
+#else
+# define SYM_USCORE ""
+#endif
+
\f
struct grub_dl_list
@@ -347,17 +353,31 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
unsigned char type = ELF_ST_TYPE (sym->st_info);
unsigned char bind = ELF_ST_BIND (sym->st_info);
const char *name = str + sym->st_name;
-
+ int check_mod_func = 0;
+
switch (type)
{
case STT_NOTYPE:
- /* Resolve a global symbol. */
- if (sym->st_name != 0 && sym->st_shndx == 0)
+ if (sym->st_name != 0)
{
- sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name);
- if (! sym->st_value)
- return grub_error (GRUB_ERR_BAD_MODULE,
- "the symbol `%s' not found", name);
+ if (sym->st_shndx == 0)
+ {
+ /* Resolve a global symbol. */
+ sym->st_value = (Elf_Addr) grub_dl_resolve_symbol (name);
+ if (! sym->st_value)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "the symbol `%s' not found", name);
+ }
+ else
+ { /* Static functions and global variables have no type
+ if initial format was not ELF. */
+ sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
+ sym->st_shndx);
+ if (bind == STB_LOCAL)
+ check_mod_func = 1;
+ else if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
+ return grub_errno;
+ }
}
else
sym->st_value = 0;
@@ -374,14 +394,10 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
case STT_FUNC:
sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod,
sym->st_shndx);
- if (bind != STB_LOCAL)
- if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
- return grub_errno;
-
- if (grub_strcmp (name, "grub_mod_init") == 0)
- mod->init = (void (*) (grub_dl_t)) sym->st_value;
- else if (grub_strcmp (name, "grub_mod_fini") == 0)
- mod->fini = (void (*) (void)) sym->st_value;
+ if (bind == STB_LOCAL)
+ check_mod_func = 1;
+ else if (grub_dl_register_symbol (name, (void *) sym->st_value, mod))
+ return grub_errno;
break;
case STT_SECTION:
@@ -397,6 +413,13 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
return grub_error (GRUB_ERR_BAD_MODULE,
"unknown symbol type `%d'", (int) type);
}
+ if (check_mod_func)
+ {
+ if (grub_strcmp (name, SYM_USCORE "grub_mod_init") == 0)
+ mod->init = (void (*) (grub_dl_t)) sym->st_value;
+ else if (grub_strcmp (name, SYM_USCORE "grub_mod_fini") == 0)
+ mod->fini = (void (*) (void)) sym->st_value;
+ }
}
return GRUB_ERR_NONE;
@@ -454,7 +477,7 @@ grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e)
const char *name = (char *) e + s->sh_offset;
const char *max = name + s->sh_size;
- while (name < max)
+ while (name < max && *name) /* Segment may contain trailing 0. */
{
grub_dl_t m;
grub_dl_dep_t dep;
diff --git a/kern/i386/dl.c b/kern/i386/dl.c
index e9e43e5..94d1510 100644
--- a/kern/i386/dl.c
+++ b/kern/i386/dl.c
@@ -37,6 +37,28 @@ grub_arch_dl_check_header (void *ehdr)
return GRUB_ERR_NONE;
}
+#ifdef __CYGWIN__
+/* Fix PC relative relocation. Objcopy does not adjust
+the addent when converting from pe-i386 to elf32-i386. */
+static int
+fix_pc_rel_relocation (Elf32_Word *addr)
+{
+ /* To be safe, check instruction first. */
+ const unsigned char * pc = (const unsigned char *)addr - 1;
+ if (!(*pc == 0xe8/*call*/ || *pc == 0xe9/*jmp*/))
+ return grub_error (GRUB_ERR_BAD_MODULE, "unknown pc-relative instruction %02x", *pc);
+ /* Check and adjust offset. */
+ if (*addr != (Elf32_Word)-4)
+ {
+ if (*addr != 0)
+ return grub_error (GRUB_ERR_BAD_MODULE, "invalid pc-relative relocation base %lx",
+ (long)(*addr));
+ *addr = (Elf32_Word)-4;
+ }
+ return GRUB_ERR_NONE;
+}
+#endif
+
/* Relocate symbols. */
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
@@ -99,9 +121,17 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
break;
case R_386_PC32:
+#ifdef __CYGWIN__
+ if (fix_pc_rel_relocation (addr))
+ return grub_errno;
+#endif
*addr += (sym->st_value - (Elf32_Word) seg->addr
- rel->r_offset);
break;
+
+ default:
+ return grub_error (GRUB_ERR_BAD_MODULE, "unknown relocation type %x.",
+ ELF32_R_TYPE (rel->r_info));
}
}
}
next reply other threads:[~2008-07-20 20:52 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-20 20:51 Christian Franke [this message]
2008-07-21 7:02 ` [PATCH] Kernel fixes for Cygwin Bean
2008-07-21 7:25 ` Bean
2008-07-21 10:33 ` Christian Franke
2008-07-21 10:56 ` Bean
2008-07-22 16:58 ` Christian Franke
2008-07-21 11:02 ` Javier Martín
2008-07-21 11:16 ` Christian Franke
2008-07-21 15:51 ` Pavel Roskin
2008-07-21 16:50 ` Javier Martín
2008-07-21 17:03 ` Pavel Roskin
2008-07-21 17:23 ` Javier Martín
2008-07-21 19:59 ` Pavel Roskin
2008-07-21 10:21 ` Christian Franke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4883A568.10709@t-online.de \
--to=christian.franke@t-online.de \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.