[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 6/7] mkimage: support images which require full relocation at mki
From: |
Ian Campbell |
Subject: |
[PATCH 6/7] mkimage: support images which require full relocation at mkimage time. |
Date: |
Sun, 29 Dec 2013 18:47:35 +0000 |
To do so support the specification of a "target_address" (which must be 0 for
image types which do not have this flag) and a new image flag to signal the
need for absolute relocation. If this flag is present then image->link_addr is
the default target.
Account for the target address when relocating.
Fabricate correct addresses for absolute symbols relating to the bss
("__bss_start" and "_end").
This functionality is not yet used by any image type and is connected only to
grub-mkimage ("-T option) and not yet to grub-install.
Signed-off-by: Ian Campbell <address@hidden>
---
include/grub/util/install.h | 2 +-
util/grub-install-common.c | 4 +--
util/grub-mkimage.c | 7 +++++
util/grub-mkimagexx.c | 74 +++++++++++++++++++++++++++++++--------------
util/mkimage.c | 24 ++++++++++++---
5 files changed, 81 insertions(+), 30 deletions(-)
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index bc987aa..b7ecf27 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -167,7 +167,7 @@ struct grub_install_image_target_desc;
void
grub_install_generate_image (const char *dir, const char *prefix,
- FILE *out,
+ FILE *out, grub_uint64_t target_address,
const char *outname, char *mods[],
char *memdisk_path, char **pubkey_paths,
size_t npubkeys,
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index ae26875..82a44f2 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -495,8 +495,8 @@ grub_install_make_image_wrap_file (const char *dir, const
char *prefix,
if (!tgt)
grub_util_error (_("unknown target format %s\n"), mkimage_target);
- grub_install_generate_image (dir, prefix, fp, outname,
- modules.entries, memdisk_path,
+ grub_install_generate_image (dir, prefix, fp, 0,
+ outname, modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt,
note, compression);
while (dc--)
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index a2bd4c1..267beaa 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -65,6 +65,7 @@ static struct argp_option options[] = {
/* TRANSLATORS: platform here isn't identifier. It can be translated. */
N_("use images and modules under DIR [default=%s/<platform>]"), 0},
{"prefix", 'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0},
+ {"target-address", 'T', N_("ADDR"), 0, N_("set kernel target address
[default=%d]"), 0},
{"memdisk", 'm', N_("FILE"), 0,
/* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated.
"embed" is a verb (command description). "*/
@@ -126,6 +127,7 @@ struct arguments
int note;
const struct grub_install_image_target_desc *image_target;
grub_compression_t comp;
+ grub_uint64_t target_address;
};
static error_t
@@ -217,6 +219,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
arguments->prefix = xstrdup (arg);
break;
+ case 'T':
+ arguments->target_address = strtoull (arg, NULL, 0);
+ break;
+
case 'v':
verbosity++;
break;
@@ -289,6 +295,7 @@ main (int argc, char *argv[])
grub_install_generate_image (arguments.dir,
arguments.prefix ? : DEFAULT_DIRECTORY, fp,
+ arguments.target_address,
arguments.output, arguments.modules,
arguments.memdisk, arguments.pubkeys,
arguments.npubkeys, arguments.config,
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index b4216ff..186d259 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -378,6 +378,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Shdr *symtab_section, Elf_Addr
*section_addresses,
Elf_Half section_entsize, Elf_Half num_sections,
void *jumpers, Elf_Addr jumpers_addr,
+ Elf_Addr bss_addr, size_t bss_size,
const struct grub_install_image_target_desc
*image_target)
{
Elf_Word symtab_size, sym_size, num_syms;
@@ -416,10 +417,14 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr
*sections,
}
else if (cur_index == STN_UNDEF)
{
- if (sym->st_name)
+ if (strcmp (name, "__bss_start") == 0 && bss_addr)
+ sym->st_value = bss_addr;
+ else if (strcmp (name, "_end") == 0 && bss_addr)
+ sym->st_value = bss_addr + bss_size;
+ else if (sym->st_name)
grub_util_error ("undefined symbol %s", name);
- else
- continue;
+
+ continue;
}
else if (cur_index >= num_sections)
grub_util_error ("section %d does not exist", cur_index);
@@ -584,7 +589,7 @@ static void
SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
Elf_Addr *section_addresses,
Elf_Half section_entsize, Elf_Half num_sections,
- const char *strtab,
+ const char *strtab, grub_uint64_t target_address,
char *pe_target, Elf_Addr tramp_off,
Elf_Addr got_off,
const struct grub_install_image_target_desc
*image_target)
@@ -867,6 +872,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr
*sections,
{
case R_ARM_ABS32:
{
+ sym_addr += target_address;
grub_util_info ("
ABS32:\ttarget=0x%08lx\toffset=(0x%08x)",
(unsigned long) ((char *) target
- (char *) e),
@@ -928,7 +934,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr
*sections,
grub_uint32_t tr_addr;
grub_int32_t new_offset;
tr_addr = (char *) tr - (char *) pe_target
- - target_section_addr;
+ - (target_address - target_section_addr);
new_offset = sym_addr - tr_addr - 12;
/* There is no immediate version of bx, only
register one... */
@@ -1337,6 +1343,7 @@ static Elf_Addr *
SUFFIX (locate_sections) (const char *kernel_path,
Elf_Shdr *sections, Elf_Half section_entsize,
Elf_Half num_sections, const char *strtab,
+ grub_uint64_t target_address,
size_t *exec_size, size_t *kernel_sz,
size_t *all_align,
const struct grub_install_image_target_desc
*image_target)
@@ -1351,7 +1358,7 @@ SUFFIX (locate_sections) (const char *kernel_path,
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
- current_address = 0;
+ current_address = target_address;
for (i = 0, s = sections;
i < num_sections;
@@ -1391,6 +1398,15 @@ SUFFIX (locate_sections) (const char *kernel_path,
grub_util_error ("%s", msg);
}
}
+ else if (!grub_image_needs_abs_reloc(image_target))
+ {
+ if (grub_host_to_target_addr (s->sh_addr))
+ grub_util_error (_("`%s' is miscompiled: its start address is
0x%llx"
+ " but this platform uses late relocation"),
+ kernel_path,
+ (unsigned long long) grub_host_to_target_addr
(s->sh_addr));
+ }
+
section_addresses[i] = current_address;
current_address += grub_host_to_target_addr (s->sh_size);
}
@@ -1398,7 +1414,7 @@ SUFFIX (locate_sections) (const char *kernel_path,
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
image_target->section_align)
- image_target->vaddr_offset;
- *exec_size = current_address;
+ *exec_size = current_address - target_address;
/* .data */
for (i = 0, s = sections;
@@ -1426,14 +1442,15 @@ SUFFIX (locate_sections) (const char *kernel_path,
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
image_target->section_align) -
image_target->vaddr_offset;
- *kernel_sz = current_address;
+ *kernel_sz = current_address - target_address;
return section_addresses;
}
static char *
SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
size_t *kernel_sz, size_t *bss_size,
- size_t total_module_size, grub_uint64_t *start,
+ size_t total_module_size, grub_uint64_t target_address,
+ grub_uint64_t *start,
void **reloc_section, size_t *reloc_size,
size_t *align,
const struct grub_install_image_target_desc *image_target)
@@ -1444,6 +1461,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
Elf_Shdr *sections;
Elf_Addr *section_addresses;
Elf_Addr *section_vaddresses;
+ Elf_Addr bss_addr = 0;
int i;
Elf_Shdr *s;
Elf_Half num_sections;
@@ -1455,6 +1473,9 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
Elf_Shdr *symtab_section = 0;
grub_size_t got = 0;
+ if (target_address && !grub_image_needs_abs_reloc(image_target))
+ grub_util_error("cannot perform absolute relocation for this image type");
+
*start = 0;
kernel_size = grub_util_get_image_size (kernel_path);
@@ -1481,7 +1502,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
section_addresses = SUFFIX (locate_sections) (kernel_path,
sections, section_entsize,
- num_sections, strtab,
+ num_sections, strtab,
target_address,
exec_size, kernel_sz, align,
image_target);
@@ -1530,9 +1551,9 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
for (i = 0; i < num_sections; i++)
section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
- if (!grub_image_needs_reloc(image_target))
+ if (!grub_image_needs_reloc(image_target) ||
grub_image_needs_abs_reloc(image_target))
{
- Elf_Addr current_address = *kernel_sz;
+ Elf_Addr current_address = target_address + *kernel_sz;
for (i = 0, s = sections;
i < num_sections;
@@ -1558,11 +1579,16 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
section_vaddresses[i] = current_address
+ image_target->vaddr_offset;
current_address += grub_host_to_target_addr (s->sh_size);
+
+ if (!bss_addr)
+ bss_addr = section_vaddresses[i];
}
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
image_target->section_align)
- image_target->vaddr_offset;
- *bss_size = current_address - *kernel_sz;
+ *bss_size = current_address - *kernel_sz - target_address;
+ grub_util_info ("locating bss at 0x%x-0x%x (0x%x bytes)",
+ (int)bss_addr, (int)(bss_addr + *bss_size),
(int)*bss_size);
}
else
*bss_size = 0;
@@ -1603,6 +1629,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
(char *) out_img + ia64jmp_off,
ia64jmp_off
+ image_target->vaddr_offset,
+ bss_addr, *bss_size,
image_target);
if (*start == INVALID_START_ADDR)
grub_util_error ("start symbol is not defined");
@@ -1612,17 +1639,18 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
/* Resolve addresses in the virtual address space. */
SUFFIX (relocate_addresses) (e, sections, section_addresses,
section_entsize,
- num_sections, strtab,
+ num_sections, strtab, target_address,
out_img, tramp_off, ia64_got_off,
image_target);
- *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
- section_vaddresses, sections,
- section_entsize, num_sections,
- strtab, ia64jmp_off
- + image_target->vaddr_offset,
- 2 * ia64jmpnum + (got / 8),
- image_target);
+ if (!grub_image_needs_abs_reloc(image_target))
+ *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
+ section_vaddresses,
sections,
+ section_entsize,
num_sections,
+ strtab, ia64jmp_off
+ +
image_target->vaddr_offset,
+ 2 * ia64jmpnum + (got / 8),
+ image_target);
}
for (i = 0, s = sections;
@@ -1632,10 +1660,10 @@ SUFFIX (load_image) (const char *kernel_path, size_t
*exec_size,
|| SUFFIX (is_text_section) (s, image_target))
{
if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
- memset (out_img + section_addresses[i], 0,
+ memset (out_img + section_addresses[i] - target_address, 0,
grub_host_to_target_addr (s->sh_size));
else
- memcpy (out_img + section_addresses[i],
+ memcpy (out_img + section_addresses[i] - target_address,
kernel_img + grub_host_to_target_addr (s->sh_offset),
grub_host_to_target_addr (s->sh_size));
}
diff --git a/util/mkimage.c b/util/mkimage.c
index 645e296..7b29acf 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -74,6 +74,7 @@ struct grub_install_image_target_desc
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_DECOMPRESSORS = 2,
PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
+ PLATFORM_FLAGS_ABS_RELOC = 8,
} flags;
unsigned total_module_size;
unsigned decompressor_compressed_size;
@@ -922,11 +923,16 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr
sym_addr)
return GRUB_ERR_NONE;
}
+static int grub_image_needs_abs_reloc(const struct
grub_install_image_target_desc *target)
+{
+ return target->flags & PLATFORM_FLAGS_ABS_RELOC;
+}
+
static int grub_image_needs_reloc(const struct grub_install_image_target_desc
*target)
{
if (target->id == IMAGE_EFI)
return 1;
- return 0;
+ return grub_image_needs_abs_reloc(target);
}
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -987,7 +993,8 @@ grub_install_get_image_targets_string (void)
void
grub_install_generate_image (const char *dir, const char *prefix,
- FILE *out, const char *outname, char *mods[],
+ FILE *out, grub_uint64_t target_address,
+ const char *outname, char *mods[],
char *memdisk_path, char **pubkey_paths,
size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc
*image_target,
@@ -1024,6 +1031,13 @@ grub_install_generate_image (const char *dir, const char
*prefix,
else
total_module_size = sizeof (struct grub_module_info32);
+ if (!target_address && grub_image_needs_abs_reloc(image_target))
+ {
+ grub_util_info ("Using default target address 0x%llx",
+ (unsigned long long)image_target->link_addr);
+ target_address = image_target->link_addr;
+ }
+
{
size_t i;
for (i = 0; i < npubkeys; i++)
@@ -1069,11 +1083,13 @@ grub_install_generate_image (const char *dir, const
char *prefix,
if (image_target->voidp_sizeof == 4)
kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size,
&bss_size,
- total_module_size, &start_address, &rel_section,
+ total_module_size, target_address,
+ &start_address, &rel_section,
&reloc_size, &align, image_target);
else
kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size,
&bss_size,
- total_module_size, &start_address, &rel_section,
+ total_module_size, target_address,
+ &start_address, &rel_section,
&reloc_size, &align, image_target);
if (image_target->id == IMAGE_XEN && align < 4096)
align = 4096;
--
1.8.4.rc3
- [PATCH 0/7] arm-uboot: support for different RAM bases, Ian Campbell, 2013/12/29
- [PATCH 2/7] mkimage: Replace hardcoded 0x400 in R_ARM_ABS32 relocation, Ian Campbell, 2013/12/29
- [PATCH 1/7] mkimage: Refactor IMAGE_EFI checks into a function grub_image_needs_reloc., Ian Campbell, 2013/12/29
- [PATCH 3/7] mkimage: account for space for trampolines earlier, Ian Campbell, 2013/12/29
- [PATCH 4/7] mkimage: make R_ARM_ABS32 debug output more consistent, Ian Campbell, 2013/12/29
- [PATCH 5/7] mkimage: allow linking at address 0, Ian Campbell, 2013/12/29
- [PATCH 6/7] mkimage: support images which require full relocation at mkimage time.,
Ian Campbell <=
- [PATCH 7/7] arm-uboot: support relocation at installation time, Ian Campbell, 2013/12/29
- Re: [PATCH 0/7] arm-uboot: support for different RAM bases, Ian Campbell, 2013/12/29
- Re: [PATCH 0/7] arm-uboot: support for different RAM bases, Leif Lindholm, 2013/12/29
- Re: [PATCH 0/7] arm-uboot: support for different RAM bases, Vladimir 'φ-coder/phcoder' Serbinenko, 2013/12/29