From: Ram Pai <linuxram@us.ibm.com>
To: grub-devel@gnu.org
Cc: tlfalcon@linux.vnet.ibm.com, tbberry@us.ibm.com,
anton@au1.ibm.com, linuxram@us.ibm.com, tonyb@au1.ibm.com,
Anton Blanchard <anton@samba.org>
Subject: [RFC PATCH 15/23] Add ppc64 relocations
Date: Wed, 26 Feb 2014 10:31:14 -0800 [thread overview]
Message-ID: <1393439482-20341-16-git-send-email-linuxram@us.ibm.com> (raw)
In-Reply-To: <1393439482-20341-1-git-send-email-linuxram@us.ibm.com>
From: Anton Blanchard <anton@samba.org>
Add ppc64 relocations
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
From: Anton Blanchard <anton@samba.org>
---
grub-core/kern/powerpc/dl.c | 179 +++++++++++++++++++++++++++++++++++++++++---
include/grub/elf.h | 3 +
2 files changed, 172 insertions(+), 10 deletions(-)
diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c
index 7677e5a..2a3b022 100644
--- a/grub-core/kern/powerpc/dl.c
+++ b/grub-core/kern/powerpc/dl.c
@@ -23,6 +23,20 @@
#include <grub/err.h>
#include <grub/i18n.h>
+#if defined( __powerpc64__ ) || defined( __powerpc64le__ )
+#define ELFCLASSXX ELFCLASS64
+#define ELFMACHINEXX EM_PPC64
+#else
+#define ELFCLASSXX ELFCLASS32
+#define ELFMACHINEXX EM_PPC32
+#endif
+
+#if defined( __powerpc64le__ )
+#define ELFDATA2XSB ELFDATA2LSB
+#else
+#define ELFDATA2XSB ELFDATA2MSB
+#endif
+
/* Check if EHDR is a valid ELF header. */
grub_err_t
grub_arch_dl_check_header (void *ehdr)
@@ -30,14 +44,77 @@ grub_arch_dl_check_header (void *ehdr)
Elf_Ehdr *e = ehdr;
/* Check the magic numbers. */
- if (e->e_ident[EI_CLASS] != ELFCLASS32
- || e->e_ident[EI_DATA] != ELFDATA2MSB
- || e->e_machine != EM_PPC)
+ if (e->e_ident[EI_CLASS] != ELFCLASSXX
+ || e->e_ident[EI_DATA] != ELFDATA2XSB
+ || e->e_machine != ELFMACHINEXX)
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
return GRUB_ERR_NONE;
}
+
+
+
+#if defined( __powerpc64le__ )
+struct trampoline
+{
+ grub_uint32_t std;
+ grub_uint32_t addis;
+ grub_uint32_t addi;
+ grub_uint32_t mtctr;
+ grub_uint32_t bctr;
+};
+
+static const struct trampoline trampoline_template =
+ {
+ 0xf8410018, /* std r2,24(r1) */
+ 0x3d800000, /* addis r12,0,0 */
+ 0x398c0000, /* addi r12,r12,0 */
+ 0x7d8903a6, /* mtctr r12 */
+ 0x4e800420, /* bctr */
+ };
+
+#define PPC_NOP 0x60000000
+#define RESTORE_TOC 0xe8410018 /* ld r2,24(r1) */
+
+#define STO_PPC64_LOCAL_BIT 5
+#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
+
+static inline unsigned int
+ppc64_decode_local_entry(unsigned int other)
+{
+ return ((1 << other) >> 2) << 2;
+}
+
+#define PPC64_LOCAL_ENTRY_OFFSET(other) \
+ ppc64_decode_local_entry (((other) & STO_PPC64_LOCAL_MASK) \
+ >> STO_PPC64_LOCAL_BIT)
+
+
+
+#elif defined( __powerpc64__ )
+
+#error "NOT SUPPORTED YET"
+
+static int grub_arch_dl_is_in_opd (grub_dl_t mod, void *ehdr, unsigned long addr)
+{
+ unsigned long start, end;
+ Elf_Shdr *s = grub_dl_find_section(ehdr, ".opd");
+
+ if (!s)
+ return 0;
+
+ start = (unsigned long)grub_dl_find_section_addr(mod, ehdr, ".opd");
+ end = start + s->sh_size;
+
+ if ((start <= addr) && (addr < end))
+ return 1;
+ else
+ return 0;
+}
+
+#else
+
/* For low-endian reverse lis and addr_high as well as ori and addr_low. */
struct trampoline
{
@@ -55,8 +132,20 @@ static const struct trampoline trampoline_template =
0x4e800420,
};
+#endif
+
#pragma GCC diagnostic ignored "-Wcast-align"
+static unsigned long grub_arch_dl_get_toc (grub_dl_t mod, void *ehdr)
+{
+ unsigned long i = (unsigned long)grub_dl_find_section_addr(mod, ehdr, ".toc");
+ if (!i)
+ return 0;
+
+ return i;
+}
+
+
grub_err_t
grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
grub_size_t *got)
@@ -89,12 +178,15 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
return GRUB_ERR_NONE;
}
+#define PPC_LO(v) ((v) & 0xffff)
+#define PPC_HI(v) (((v) >> 16) & 0xffff)
+#define PPC_HA(v) PPC_HI ((v) + 0x8000)
+
/* Relocate symbols. */
grub_err_t
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
Elf_Shdr *s, grub_dl_segment_t seg)
{
-#ifdef powerpc
Elf_Rela *rel, *max;
for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset),
@@ -104,7 +196,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
{
Elf_Word *addr;
Elf_Sym *sym;
- grub_uint32_t value;
+ Elf_Addr value;
if (seg->size < rel->r_offset)
return grub_error (GRUB_ERR_BAD_MODULE,
@@ -119,6 +211,76 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
value = sym->st_value + rel->r_addend;
switch (ELF_R_TYPE (rel->r_info))
{
+#ifdef __powerpc64le__
+ case GRUB_ELF_R_PPC_REL24:
+ {
+ struct trampoline *tptr = mod->trampptr;
+ Elf_Sword delta;
+ if (sym->st_shndx == SHN_UNDEF)
+ {
+ grub_memcpy (tptr, &trampoline_template, sizeof (*tptr));
+
+ tptr->addis |= PPC_HA(value);
+ tptr->addi |= PPC_LO(value);
+
+ mod->trampptr = tptr + 1;
+ delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr;
+
+ if (*(addr+1) != PPC_NOP)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "Missing NOP after PPC_REL24 got %x", *(addr+1));
+ *(addr+1) = RESTORE_TOC;
+ } else
+ delta = (grub_uint8_t *)value - (grub_uint8_t *) addr +
+ PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
+
+
+ if (delta << 6 >> 6 != delta)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "relocation overflow");
+
+ *(Elf_Word *) (addr) = (*addr & ~0x03fffffc) | (delta & 0x03fffffc);
+ }
+ break;
+
+ case GRUB_ELF_R_PPC64_ADDR64:
+ *(Elf_Xword *) addr = value;
+ break;
+
+ case GRUB_ELF_R_PPC64_TOC:
+ *(Elf_Xword *) addr = grub_arch_dl_get_toc(mod, ehdr);
+ break;
+
+ case GRUB_ELF_R_PPC64_TOC16_HA:
+ value -= grub_arch_dl_get_toc(mod, ehdr);
+ *(Elf_Half *) addr = PPC_HA(value);
+ break;
+
+ case GRUB_ELF_R_PPC64_TOC16_LO:
+ value -= grub_arch_dl_get_toc(mod, ehdr);
+ *(Elf_Half *) addr = PPC_LO(value);
+ break;
+
+ case GRUB_ELF_R_PPC64_TOC16_LO_DS:
+ value -= grub_arch_dl_get_toc(mod, ehdr);
+ if (value & 3)
+ return grub_error (GRUB_ERR_BAD_MODULE,
+ "bad TOC16_LO_DS relocation");
+
+ *(Elf_Half *) addr = ((*(Elf_Half *) addr) & ~0xfffc) | (value & 0xfffc);
+ break;
+
+ case GRUB_ELF_R_PPC64_REL16_HA:
+ value -= (unsigned long) addr;
+ *(Elf_Half *) addr = PPC_HA(value);
+ break;
+
+ case GRUB_ELF_R_PPC64_REL16_LO:
+ value -= (unsigned long) addr;
+ *(Elf_Half *) addr = PPC_LO(value);
+ break;
+#else
+
case GRUB_ELF_R_PPC_ADDR16_LO:
*(Elf_Half *) addr = value;
break;
@@ -156,6 +318,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
case GRUB_ELF_R_PPC_REL32:
*addr = value - (Elf_Word) addr;
break;
+#endif
+
default:
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("relocation 0x%x is not implemented yet"),
@@ -164,9 +328,4 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
}
return GRUB_ERR_NONE;
-#else
- return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- N_("relocation is not implemented yet for module=%llx ehdr=%llx Elf_Shdr=%llx seg=%llx"),
- mod, ehdr, s, seg);
-#endif
}
diff --git a/include/grub/elf.h b/include/grub/elf.h
index bee7583..224d164 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -1998,6 +1998,9 @@ typedef Elf32_Addr Elf32_Conflict;
#define GRUB_ELF_R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
#define GRUB_ELF_R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
+#define GRUB_ELF_R_PPC64_REL16_LO 250
+#define GRUB_ELF_R_PPC64_REL16_HA 252
+
/* This is a phony reloc to handle any old fashioned TOC16 references
that may still be in object files. */
#define GRUB_ELF_R_PPC_TOC16 255
--
1.8.5.3
next prev parent reply other threads:[~2014-02-26 18:32 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-26 18:30 [RFC PATCH 00/23] grub 64bit little-endian on power Ram Pai
2014-02-26 18:31 ` [RFC PATCH 01/23] Add a new architecture to the build process Ram Pai
2014-02-26 18:31 ` [RFC PATCH 02/23] Build LE grub as O1 Ram Pai
2014-02-26 18:31 ` [RFC PATCH 03/23] ignore .TOC. symbol Ram Pai
2014-04-01 16:52 ` Andrey Borzenkov
2014-02-26 18:31 ` [RFC PATCH 04/23] grub-install can now recognize and install a LE grub boot loader Ram Pai
2014-02-26 18:31 ` [RFC PATCH 05/23] set ABI version in e_flag of the PPC64LE ELF image Ram Pai
2014-02-26 18:31 ` [RFC PATCH 06/23] Add IEEE1275_ADDR helper Ram Pai
2014-04-01 17:11 ` Andrey Borzenkov
2014-02-26 18:31 ` [RFC PATCH 07/23] Fix some more warnings when casting Ram Pai
2014-02-26 18:31 ` [RFC PATCH 08/23] Add powerpc64 types Ram Pai
2014-04-01 17:15 ` Andrey Borzenkov
2014-04-02 17:02 ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 09/23] Fix warnings when building powerpc linux loader 64bit Ram Pai
2014-04-01 17:21 ` Andrey Borzenkov
2014-04-02 17:03 ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 10/23] GRUB_ELF_R_PPC_* processing is applicable only for 32 bit bootloader Ram Pai
2014-02-26 18:31 ` [RFC PATCH 11/23] Fix powerpc setjmp/longjmp 64bit issues Ram Pai
2014-04-01 17:27 ` Andrey Borzenkov
2014-04-02 17:06 ` Ram Pai
2014-04-02 17:19 ` Andrey Borzenkov
2014-04-02 17:48 ` Ram Pai
2014-04-02 17:56 ` Andrey Borzenkov
2014-04-02 18:55 ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 12/23] Add powerpc64 ieee1275 trampoline Ram Pai
2014-02-26 18:31 ` [RFC PATCH 13/23] Add 64bit support to powerpc startup code Ram Pai
2014-02-26 18:31 ` [RFC PATCH 14/23] Add grub_dl_find_section_addr Ram Pai
2014-02-26 18:31 ` Ram Pai [this message]
2014-02-26 18:31 ` [RFC PATCH 16/23] ppc64 doesn't need libgcc routines Ram Pai
2014-02-26 18:31 ` [RFC PATCH 17/23] Use FUNC_START/FUNC_END for powerpc function definitions Ram Pai
2014-02-26 18:31 ` [RFC PATCH 18/23] .TOC. symbol is special in ppc64le Ram Pai
2014-02-26 18:31 ` [RFC PATCH 19/23] align .toc section on 4byte boundary Ram Pai
2014-02-26 18:31 ` [RFC PATCH 20/23] fix parameter to firmware calls Ram Pai
2014-04-01 17:45 ` Andrey Borzenkov
2014-04-02 17:08 ` Ram Pai
2014-04-02 17:16 ` Andrey Borzenkov
2014-02-26 18:31 ` [RFC PATCH 21/23] powerpc64 is not necessarily BigEndian anymore! :) Ram Pai
2014-04-01 17:49 ` Andrey Borzenkov
2014-04-01 20:22 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-03 17:33 ` Ram Pai
2014-04-03 17:53 ` Andrey Borzenkov
2014-04-03 18:37 ` Ram Pai
2014-04-03 19:03 ` Andrey Borzenkov
2014-04-03 19:26 ` Ram Pai
2014-04-03 19:42 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-03 20:23 ` Ram Pai
2014-04-03 19:54 ` Andrey Borzenkov
2014-04-03 20:32 ` Ram Pai
2014-04-03 21:41 ` Vladimir 'phcoder' Serbinenko
2014-04-04 2:28 ` Andrey Borzenkov
2014-04-04 17:47 ` Ram Pai
2014-04-04 18:17 ` Andrey Borzenkov
2014-04-04 18:24 ` Dinar Valeev
2014-04-04 19:12 ` Andrey Borzenkov
2014-04-04 20:29 ` Dinar Valeev
2014-04-04 22:19 ` Ram Pai
[not found] ` <CAEaD8JN9SkqU9+BkU2MYub=aC3Wb143nMPgRWjVbFvgit90yBQ@mail.gmail.com>
2014-04-05 0:04 ` Fwd: " Vladimir 'phcoder' Serbinenko
2014-09-27 5:42 ` Andrei Borzenkov
2014-09-28 6:33 ` Andrei Borzenkov
2014-04-04 6:37 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-04 17:08 ` Andrey Borzenkov
2014-04-05 15:45 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-05 16:49 ` Andrey Borzenkov
2014-04-05 18:29 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-05 18:48 ` Andrey Borzenkov
2014-04-02 17:09 ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 22/23] fix segfaults if initrd Ram Pai
2014-02-26 18:31 ` [RFC PATCH 23/23] Optional: Power7 VSX instructions workaround Ram Pai
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=1393439482-20341-16-git-send-email-linuxram@us.ibm.com \
--to=linuxram@us.ibm.com \
--cc=anton@au1.ibm.com \
--cc=anton@samba.org \
--cc=grub-devel@gnu.org \
--cc=tbberry@us.ibm.com \
--cc=tlfalcon@linux.vnet.ibm.com \
--cc=tonyb@au1.ibm.com \
/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.