Provide __bss_start and _end symbols in grub-mkimage.
For this ensure that all bss sections are merged. We need this to correctly prelink non-PE relocatable images.
This commit is contained in:
parent
73a9c742fe
commit
df21fff504
2 changed files with 89 additions and 50 deletions
|
@ -33,6 +33,8 @@ struct grub_mkimage_layout
|
||||||
grub_size_t ia64_got_off;
|
grub_size_t ia64_got_off;
|
||||||
grub_size_t got_size;
|
grub_size_t got_size;
|
||||||
unsigned ia64jmpnum;
|
unsigned ia64jmpnum;
|
||||||
|
Elf_Addr bss_start;
|
||||||
|
Elf_Addr end;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Private header. Use only in mkimage-related sources. */
|
/* Private header. Use only in mkimage-related sources. */
|
||||||
|
|
|
@ -490,6 +490,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
|
||||||
Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
|
Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
|
||||||
Elf_Half section_entsize, Elf_Half num_sections,
|
Elf_Half section_entsize, Elf_Half num_sections,
|
||||||
void *jumpers, Elf_Addr jumpers_addr,
|
void *jumpers, Elf_Addr jumpers_addr,
|
||||||
|
Elf_Addr bss_start, Elf_Addr end,
|
||||||
const struct grub_install_image_target_desc *image_target)
|
const struct grub_install_image_target_desc *image_target)
|
||||||
{
|
{
|
||||||
Elf_Word symtab_size, sym_size, num_syms;
|
Elf_Word symtab_size, sym_size, num_syms;
|
||||||
|
@ -528,16 +529,22 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
|
||||||
}
|
}
|
||||||
else if (cur_index == STN_UNDEF)
|
else if (cur_index == STN_UNDEF)
|
||||||
{
|
{
|
||||||
if (sym->st_name)
|
if (sym->st_name && grub_strcmp (name, "__bss_start"))
|
||||||
|
sym->st_value = bss_start;
|
||||||
|
else if (sym->st_name && grub_strcmp (name, "__end"))
|
||||||
|
sym->st_value = end;
|
||||||
|
else if (sym->st_name)
|
||||||
grub_util_error ("undefined symbol %s", name);
|
grub_util_error ("undefined symbol %s", name);
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (cur_index >= num_sections)
|
else if (cur_index >= num_sections)
|
||||||
grub_util_error ("section %d does not exist", cur_index);
|
grub_util_error ("section %d does not exist", cur_index);
|
||||||
|
else
|
||||||
|
{
|
||||||
sym->st_value = (grub_target_to_host (sym->st_value)
|
sym->st_value = (grub_target_to_host (sym->st_value)
|
||||||
+ section_addresses[cur_index]);
|
+ section_addresses[cur_index]);
|
||||||
|
}
|
||||||
|
|
||||||
if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
|
if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
|
||||||
== STT_FUNC)
|
== STT_FUNC)
|
||||||
|
@ -1462,9 +1469,7 @@ SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_de
|
||||||
== (SHF_EXECINSTR | SHF_ALLOC));
|
== (SHF_EXECINSTR | SHF_ALLOC));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine if this section is a data section. This assumes that
|
/* Determine if this section is a data section. */
|
||||||
BSS is also a data section, since the converter initializes BSS
|
|
||||||
when producing PE32 to avoid a bug in EFI implementations. */
|
|
||||||
static int
|
static int
|
||||||
SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
|
SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
|
||||||
{
|
{
|
||||||
|
@ -1472,7 +1477,16 @@ SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_de
|
||||||
&& grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
|
&& grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
|
||||||
return 0;
|
return 0;
|
||||||
return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
|
return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
|
||||||
== SHF_ALLOC);
|
== SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
|
||||||
|
{
|
||||||
|
if (!is_relocatable (image_target))
|
||||||
|
return 0;
|
||||||
|
return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
|
||||||
|
== SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return if the ELF header is valid. */
|
/* Return if the ELF header is valid. */
|
||||||
|
@ -1492,6 +1506,32 @@ SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_i
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Elf_Addr
|
||||||
|
SUFFIX (put_section) (Elf_Shdr *s, int i,
|
||||||
|
Elf_Addr current_address,
|
||||||
|
Elf_Addr *section_addresses,
|
||||||
|
const char *strtab,
|
||||||
|
const struct grub_install_image_target_desc *image_target)
|
||||||
|
{
|
||||||
|
Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
|
||||||
|
const char *name = strtab + grub_host_to_target32 (s->sh_name);
|
||||||
|
|
||||||
|
if (align)
|
||||||
|
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
||||||
|
align)
|
||||||
|
- image_target->vaddr_offset;
|
||||||
|
|
||||||
|
grub_util_info ("locating the section %s at 0x%"
|
||||||
|
GRUB_HOST_PRIxLONG_LONG,
|
||||||
|
name, (unsigned long long) current_address);
|
||||||
|
if (!is_relocatable (image_target))
|
||||||
|
current_address = grub_host_to_target_addr (s->sh_addr)
|
||||||
|
- image_target->link_addr;
|
||||||
|
section_addresses[i] = current_address;
|
||||||
|
current_address += grub_host_to_target_addr (s->sh_size);
|
||||||
|
return current_address;
|
||||||
|
}
|
||||||
|
|
||||||
/* Locate section addresses by merging code sections and data sections
|
/* Locate section addresses by merging code sections and data sections
|
||||||
into .text and .data, respectively. Return the array of section
|
into .text and .data, respectively. Return the array of section
|
||||||
addresses. */
|
addresses. */
|
||||||
|
@ -1531,20 +1571,13 @@ SUFFIX (locate_sections) (const char *kernel_path,
|
||||||
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
||||||
if (SUFFIX (is_text_section) (s, image_target))
|
if (SUFFIX (is_text_section) (s, image_target))
|
||||||
{
|
{
|
||||||
Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
|
current_address = SUFFIX (put_section) (s, i,
|
||||||
const char *name = strtab + grub_host_to_target32 (s->sh_name);
|
current_address,
|
||||||
if (align)
|
section_addresses,
|
||||||
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
strtab,
|
||||||
align) - image_target->vaddr_offset;
|
image_target);
|
||||||
grub_util_info ("locating the section %s at 0x%"
|
if (!is_relocatable (image_target) &&
|
||||||
GRUB_HOST_PRIxLONG_LONG,
|
grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
|
||||||
name, (unsigned long long) current_address);
|
|
||||||
if (image_target->id != IMAGE_EFI)
|
|
||||||
{
|
|
||||||
current_address = grub_host_to_target_addr (s->sh_addr)
|
|
||||||
- image_target->link_addr;
|
|
||||||
if (grub_host_to_target_addr (s->sh_addr)
|
|
||||||
!= image_target->link_addr)
|
|
||||||
{
|
{
|
||||||
char *msg
|
char *msg
|
||||||
= grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
|
= grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
|
||||||
|
@ -1555,9 +1588,6 @@ SUFFIX (locate_sections) (const char *kernel_path,
|
||||||
grub_util_error ("%s", msg);
|
grub_util_error ("%s", msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
section_addresses[i] = current_address;
|
|
||||||
current_address += grub_host_to_target_addr (s->sh_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
||||||
image_target->section_align)
|
image_target->section_align)
|
||||||
|
@ -1569,27 +1599,31 @@ SUFFIX (locate_sections) (const char *kernel_path,
|
||||||
i < num_sections;
|
i < num_sections;
|
||||||
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
||||||
if (SUFFIX (is_data_section) (s, image_target))
|
if (SUFFIX (is_data_section) (s, image_target))
|
||||||
{
|
current_address = SUFFIX (put_section) (s, i,
|
||||||
Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
|
current_address,
|
||||||
const char *name = strtab + grub_host_to_target32 (s->sh_name);
|
section_addresses,
|
||||||
|
strtab,
|
||||||
if (align)
|
image_target);
|
||||||
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
|
||||||
align)
|
|
||||||
- image_target->vaddr_offset;
|
|
||||||
|
|
||||||
grub_util_info ("locating the section %s at 0x%"
|
|
||||||
GRUB_HOST_PRIxLONG_LONG,
|
|
||||||
name, (unsigned long long) current_address);
|
|
||||||
if (image_target->id != IMAGE_EFI)
|
|
||||||
current_address = grub_host_to_target_addr (s->sh_addr)
|
|
||||||
- image_target->link_addr;
|
|
||||||
section_addresses[i] = current_address;
|
|
||||||
current_address += grub_host_to_target_addr (s->sh_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
||||||
image_target->section_align) - image_target->vaddr_offset;
|
image_target->section_align) - image_target->vaddr_offset;
|
||||||
|
|
||||||
|
layout->bss_start = current_address;
|
||||||
|
|
||||||
|
/* .bss */
|
||||||
|
for (i = 0, s = sections;
|
||||||
|
i < num_sections;
|
||||||
|
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
||||||
|
if (SUFFIX (is_bss_section) (s, image_target))
|
||||||
|
current_address = SUFFIX (put_section) (s, i,
|
||||||
|
current_address,
|
||||||
|
section_addresses,
|
||||||
|
strtab,
|
||||||
|
image_target);
|
||||||
|
|
||||||
|
current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
|
||||||
|
image_target->section_align) - image_target->vaddr_offset;
|
||||||
|
layout->end = current_address;
|
||||||
layout->kernel_size = current_address;
|
layout->kernel_size = current_address;
|
||||||
return section_addresses;
|
return section_addresses;
|
||||||
}
|
}
|
||||||
|
@ -1789,8 +1823,11 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
|
||||||
i < num_sections;
|
i < num_sections;
|
||||||
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
|
||||||
if (SUFFIX (is_data_section) (s, image_target)
|
if (SUFFIX (is_data_section) (s, image_target)
|
||||||
|
|| SUFFIX (is_bss_section) (s, image_target)
|
||||||
|| SUFFIX (is_text_section) (s, image_target))
|
|| SUFFIX (is_text_section) (s, image_target))
|
||||||
{
|
{
|
||||||
|
/* Explicitly initialize BSS
|
||||||
|
when producing PE32 to avoid a bug in EFI implementations. */
|
||||||
if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
|
if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
|
||||||
memset (out_img + section_addresses[i], 0,
|
memset (out_img + section_addresses[i], 0,
|
||||||
grub_host_to_target_addr (s->sh_size));
|
grub_host_to_target_addr (s->sh_size));
|
||||||
|
|
Loading…
Reference in a new issue