grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 6/7] mkimage: support images which require full relocation at


From: Leif Lindholm
Subject: Re: [PATCH 6/7] mkimage: support images which require full relocation at mkimage time.
Date: Sun, 29 Dec 2013 22:53:00 +0000
User-agent: Mutt/1.5.21 (2010-09-15)

On Sun, Dec 29, 2013 at 06:47:35PM +0000, Ian Campbell wrote:
> 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},

For this to actually print a default value, you need to also update
the help_filter function. Also, you probably want a %p here.
---
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -65,7 +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},
+  {"target-address", 'T', N_("ADDR"), 0, N_("set kernel target address 
[default=%p]"), 0},
   {"memdisk",  'm', N_("FILE"), 0,
    /* TRANSLATORS: "memdisk" here isn't an identifier, it can be translated.
     "embed" is a verb (command description).  "*/
@@ -104,6 +104,8 @@ help_filter (int key, const char *text, void *input 
__attribute__ ((unused)))
        free (formats);
        return ret;
       }
+    case 'T':
+       return xasprintf (text, GRUB_KERNEL_ARM_UBOOT_DEFAULT_LINK_ADDR);
     default:
       return (char *) text;
     }

---
(Of course, you probably want to abstract away the ARM_UBOOT bit...)

>    {"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);

The above is only indentation changes?

>      }
>  
>    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
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]