📄 grub-mkimage.c
字号:
sym_addr = get_symbol_address (e, symtab_section, ELF32_R_SYM (info)); switch (ELF32_R_TYPE (info)) { case R_386_NONE: break; case R_386_32: /* This is absolute. */ *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target) + sym_addr); grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x", *target, offset); break; case R_386_PC32: /* This is relative. */ *target = grub_cpu_to_le32 (grub_le_to_cpu32 (*target) + sym_addr - target_section_addr - offset); grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x", *target, offset); break; default: grub_util_error ("unknown relocation type %d", ELF32_R_TYPE (info)); break; } } }}voidwrite_padding (FILE *out, size_t size){ size_t i; for (i = 0; i < size; i++) if (fputc (0, out) == EOF) grub_util_error ("padding failed");}/* Add a PE32's fixup entry for a relocation. Return the resulting address after having written to the file OUT. */Elf32_Addradd_fixup_entry (struct grub_pe32_fixup_block **block, grub_uint16_t type, Elf32_Addr addr, int flush, Elf32_Addr current_address, FILE *out){ struct grub_pe32_fixup_block *b = *block; /* First, check if it is necessary to write out the current block. */ if (b) { if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr) { grub_uint32_t size; if (flush) { /* Add as much padding as necessary to align the address with a section boundary. */ Elf32_Addr next_address; unsigned padding_size; size_t index; next_address = current_address + b->block_size; padding_size = ((align_pe32_section (next_address) - next_address) >> 1); index = ((b->block_size - sizeof (*b)) >> 1); grub_util_info ("adding %d padding fixup entries", padding_size); while (padding_size--) { b->entries[index++] = 0; b->block_size += 2; } } else if (b->block_size & (8 - 1)) { /* If not aligned with a 32-bit boundary, add a padding entry. */ size_t index; grub_util_info ("adding a padding fixup entry"); index = ((b->block_size - sizeof (*b)) >> 1); b->entries[index] = 0; b->block_size += 2; } /* Flush it. */ grub_util_info ("writing %d bytes of a fixup block starting at 0x%x", b->block_size, b->page_rva); size = b->block_size; current_address += size; b->page_rva = grub_cpu_to_le32 (b->page_rva); b->block_size = grub_cpu_to_le32 (b->block_size); if (fwrite (b, size, 1, out) != 1) grub_util_error ("write failed"); free (b); *block = b = 0; } } if (! flush) { grub_uint16_t entry; size_t index; /* If not allocated yet, allocate a block with enough entries. */ if (! b) { *block = b = xmalloc (sizeof (*b) + 2 * 0x1000); /* The spec does not mention the requirement of a Page RVA. Here, align the address with a 4K boundary for safety. */ b->page_rva = (addr & ~(0x1000 - 1)); b->block_size = sizeof (*b); } /* Sanity check. */ if (b->block_size >= sizeof (*b) + 2 * 0x1000) grub_util_error ("too many fixup entries"); /* Add a new entry. */ index = ((b->block_size - sizeof (*b)) >> 1); entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva); b->entries[index] = grub_cpu_to_le16 (entry); b->block_size += 2; } return current_address;}/* Write out zeros to make space for the header. */static Elf32_Addrmake_header_space (FILE *out){ Elf32_Addr addr; addr = get_starting_section_address (); write_padding (out, addr); return addr;}/* Write text sections. */static Elf32_Addrwrite_text_sections (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize, Elf32_Half num_sections, const char *strtab){ Elf32_Half i; Elf32_Shdr *s; Elf32_Addr addr; for (i = 0, s = sections; i < num_sections; i++, s = (Elf32_Shdr *) ((char *) s + section_entsize)) if (is_text_section (s)) { Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign); Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset); Elf32_Word size = grub_le_to_cpu32 (s->sh_size); const char *name = strtab + grub_le_to_cpu32 (s->sh_name); if (align) { addr = align_address (current_address, align); if (current_address != addr) { grub_util_info ("padding %d bytes for the ELF section alignment", addr - current_address); write_padding (out, addr - current_address); current_address = addr; } } grub_util_info ("writing the text section %s at 0x%x", name, current_address); if (fwrite ((char *) e + offset, size, 1, out) != 1) grub_util_error ("write failed"); current_address += size; } addr = align_pe32_section (current_address); if (addr != current_address) { grub_util_info ("padding %d bytes for the PE32 section alignment", addr - current_address); write_padding (out, addr - current_address); } return addr;}/* Write data sections. */static Elf32_Addrwrite_data_sections (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e, Elf32_Shdr *sections, Elf32_Half section_entsize, Elf32_Half num_sections, const char *strtab){ Elf32_Half i; Elf32_Shdr *s; Elf32_Addr addr; for (i = 0, s = sections; i < num_sections; i++, s = (Elf32_Shdr *) ((char *) s + section_entsize)) if (is_data_section (s)) { Elf32_Word align = grub_le_to_cpu32 (s->sh_addralign); Elf32_Off offset = grub_le_to_cpu32 (s->sh_offset); Elf32_Word size = grub_le_to_cpu32 (s->sh_size); const char *name = strtab + grub_le_to_cpu32 (s->sh_name); if (align) { addr = align_address (current_address, align); if (current_address != addr) { grub_util_info ("padding %d bytes for the ELF section alignment", addr - current_address); write_padding (out, addr - current_address); current_address = addr; } } grub_util_info ("writing the data section %s at 0x%x", name, current_address); if (s->sh_type == grub_cpu_to_le32 (SHT_NOBITS)) write_padding (out, size); else if (fwrite ((char *) e + offset, size, 1, out) != 1) grub_util_error ("write failed"); current_address += size; } addr = align_pe32_section (current_address); if (addr != current_address) { grub_util_info ("padding %d bytes for the PE32 section alignment", addr - current_address); write_padding (out, addr - current_address); } return addr;}/* Write modules. */static Elf32_Addrmake_mods_section (FILE *out, Elf32_Addr current_address, const char *dir, char *mods[]){ struct grub_util_path_list *path_list; grub_size_t total_module_size; struct grub_util_path_list *p; struct grub_module_info modinfo; Elf32_Addr addr; path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); total_module_size = sizeof (struct grub_module_info); for (p = path_list; p; p = p->next) { total_module_size += (grub_util_get_image_size (p->name) + sizeof (struct grub_module_header)); } grub_util_info ("the total module size is 0x%x", total_module_size); modinfo.magic = grub_cpu_to_le32 (GRUB_MODULE_MAGIC); modinfo.offset = grub_cpu_to_le32 (sizeof (modinfo)); modinfo.size = grub_cpu_to_le32 (total_module_size); if (fwrite (&modinfo, sizeof (modinfo), 1, out) != 1) grub_util_error ("write failed"); for (p = path_list; p; p = p->next) { struct grub_module_header header; size_t mod_size; char *mod_image; grub_util_info ("adding module %s", p->name); mod_size = grub_util_get_image_size (p->name); header.offset = grub_cpu_to_le32 (sizeof (header)); header.size = grub_cpu_to_le32 (mod_size + sizeof (header)); mod_image = grub_util_read_image (p->name); if (fwrite (&header, sizeof (header), 1, out) != 1 || fwrite (mod_image, mod_size, 1, out) != 1) grub_util_error ("write failed"); free (mod_image); } for (p = path_list; p; ) { struct grub_util_path_list *q; q = p->next; free (p); p = q; } current_address += total_module_size; addr = align_pe32_section (current_address); if (addr != current_address) { grub_util_info ("padding %d bytes for the PE32 section alignment", addr - current_address); write_padding (out, addr - current_address); } return addr;}/* Make a .reloc section. */static Elf32_Addrmake_reloc_section (FILE *out, Elf32_Addr current_address, Elf32_Ehdr *e, Elf32_Addr *section_addresses, Elf32_Shdr *sections, Elf32_Half section_entsize, Elf32_Half num_sections, const char *strtab){ Elf32_Half i; Elf32_Shdr *s;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -