elf symbols

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-14 19:14:24 +01:00
parent 4a04699258
commit 865a0f8aa7
3 changed files with 95 additions and 1 deletions

View file

@ -43,6 +43,9 @@ grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]);
grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[]);
void grub_multiboot_set_bootdev (void);
void
grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
unsigned shndx, void *data);
#endif /* ! GRUB_MULTIBOOT_HEADER */

View file

@ -129,6 +129,67 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
if (i == ehdr->e_phnum)
return grub_error (GRUB_ERR_BAD_OS, "entry point isn't in a segment");
if (ehdr->e_shnum)
{
grub_uint8_t *shdr, *shdrptr;
shdr = grub_malloc (ehdr->e_shnum * ehdr->e_shentsize);
if (!shdr)
return grub_errno;
if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1)
return grub_error (GRUB_ERR_BAD_OS,
"invalid offset to section headers");
if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize)
!= (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
return grub_error (GRUB_ERR_BAD_OS,
"couldn't read sections headers from file");
for (shdrptr = shdr, i = 0; i < ehdr->e_shnum;
shdrptr += ehdr->e_shentsize, i++)
{
Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
void *src;
grub_addr_t target;
grub_err_t err;
/* This section is a loaded section,
so we don't care. */
if (sh->sh_addr != 0)
continue;
/* This section is empty, so we don't care. */
if (sh->sh_size == 0)
continue;
err
= grub_relocator_alloc_chunk_align (grub_multiboot_relocator,
&src, &target, 0,
(0xffffffff - sh->sh_size) + 1,
sh->sh_size,
sh->sh_addralign,
GRUB_RELOCATOR_PREFERENCE_NONE);
if (err)
{
grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
return err;
}
if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1)
return grub_error (GRUB_ERR_BAD_OS,
"invalid offset in section header");
if (grub_file_read (file, src, sh->sh_size)
!= (grub_ssize_t) sh->sh_size)
return grub_error (GRUB_ERR_BAD_OS,
"couldn't read segment from file");
sh->sh_addr = target;
}
grub_multiboot_add_elfsyms (ehdr->e_shnum, ehdr->e_shentsize,
ehdr->e_shstrndx, shdr);
}
#undef phdr
return grub_errno;

View file

@ -46,6 +46,9 @@ static unsigned modcnt;
static char *cmdline = NULL;
static grub_uint32_t bootdev;
static int bootdev_set;
static grub_size_t elf_sec_num, elf_sec_entsize;
static unsigned elf_sec_shstrndx;
static void *elf_sections;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
@ -73,7 +76,8 @@ grub_multiboot_get_mbi_size (void)
{
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ();
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+ elf_sec_entsize * elf_sec_num;
}
/* Fill previously allocated Multiboot mmap. */
@ -192,9 +196,30 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
}
if (elf_sec_num)
{
mbi->u.elf_sec.addr = ptrdest;
grub_memcpy (ptrorig, elf_sections, elf_sec_entsize * elf_sec_num);
mbi->u.elf_sec.num = elf_sec_num;
mbi->u.elf_sec.size = elf_sec_entsize;
mbi->u.elf_sec.shndx = elf_sec_shstrndx;
mbi->flags |= MULTIBOOT_INFO_ELF_SHDR;
}
return GRUB_ERR_NONE;
}
void
grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
unsigned shndx, void *data)
{
elf_sec_num = num;
elf_sec_shstrndx = shndx;
elf_sec_entsize = entsize;
elf_sections = data;
}
void
grub_multiboot_free_mbi (void)
{
@ -215,6 +240,11 @@ grub_multiboot_free_mbi (void)
}
modules = NULL;
modules_last = NULL;
grub_free (elf_sections);
elf_sections = NULL;
elf_sec_entsize = 0;
elf_sec_num = 0;
}
grub_err_t