Index: head/stand/common/load_elf.c =================================================================== --- head/stand/common/load_elf.c +++ head/stand/common/load_elf.c @@ -87,6 +87,112 @@ u_int64_t __elfN(relocation_offset) = 0; +extern void elf_wrong_field_size(void); +#define CONVERT_FIELD(b, f, e) \ + switch (sizeof((b)->f)) { \ + case 2: \ + (b)->f = e ## 16toh((b)->f); \ + break; \ + case 4: \ + (b)->f = e ## 32toh((b)->f); \ + break; \ + case 8: \ + (b)->f = e ## 64toh((b)->f); \ + break; \ + default: \ + /* Force a link time error. */ \ + elf_wrong_field_size(); \ + break; \ + } + +#define CONVERT_SWITCH(h, d, f) \ + switch ((h)->e_ident[EI_DATA]) { \ + case ELFDATA2MSB: \ + f(d, be); \ + break; \ + case ELFDATA2LSB: \ + f(d, le); \ + break; \ + default: \ + return (EINVAL); \ + } + + +static int elf_header_convert(Elf_Ehdr *ehdr) +{ + /* + * Fixup ELF header endianness. + * + * The Xhdr structure was loaded using block read call to optimize file + * accesses. It might happen, that the endianness of the system memory + * is different that endianness of the ELF header. Swap fields here to + * guarantee that Xhdr always contain valid data regardless of + * architecture. + */ +#define HEADER_FIELDS(b, e) \ + CONVERT_FIELD(b, e_type, e); \ + CONVERT_FIELD(b, e_machine, e); \ + CONVERT_FIELD(b, e_version, e); \ + CONVERT_FIELD(b, e_entry, e); \ + CONVERT_FIELD(b, e_phoff, e); \ + CONVERT_FIELD(b, e_shoff, e); \ + CONVERT_FIELD(b, e_flags, e); \ + CONVERT_FIELD(b, e_ehsize, e); \ + CONVERT_FIELD(b, e_phentsize, e); \ + CONVERT_FIELD(b, e_phnum, e); \ + CONVERT_FIELD(b, e_shentsize, e); \ + CONVERT_FIELD(b, e_shnum, e); \ + CONVERT_FIELD(b, e_shstrndx, e) + + CONVERT_SWITCH(ehdr, ehdr, HEADER_FIELDS); + +#undef HEADER_FIELDS + + return (0); +} + +static int elf_program_header_convert(const Elf_Ehdr *ehdr, Elf_Phdr *phdr) +{ +#define PROGRAM_HEADER_FIELDS(b, e) \ + CONVERT_FIELD(b, p_type, e); \ + CONVERT_FIELD(b, p_flags, e); \ + CONVERT_FIELD(b, p_offset, e); \ + CONVERT_FIELD(b, p_vaddr, e); \ + CONVERT_FIELD(b, p_paddr, e); \ + CONVERT_FIELD(b, p_filesz, e); \ + CONVERT_FIELD(b, p_memsz, e); \ + CONVERT_FIELD(b, p_align, e) + + CONVERT_SWITCH(ehdr, phdr, PROGRAM_HEADER_FIELDS); + +#undef PROGRAM_HEADER_FIELDS + + return (0); +} + +static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr) +{ +#define SECTION_HEADER_FIELDS(b, e) \ + CONVERT_FIELD(b, sh_name, e); \ + CONVERT_FIELD(b, sh_type, e); \ + CONVERT_FIELD(b, sh_link, e); \ + CONVERT_FIELD(b, sh_info, e); \ + CONVERT_FIELD(b, sh_flags, e); \ + CONVERT_FIELD(b, sh_addr, e); \ + CONVERT_FIELD(b, sh_offset, e); \ + CONVERT_FIELD(b, sh_size, e); \ + CONVERT_FIELD(b, sh_addralign, e); \ + CONVERT_FIELD(b, sh_entsize, e) + + CONVERT_SWITCH(ehdr, shdr, SECTION_HEADER_FIELDS); + +#undef SECTION_HEADER_FIELDS + + return (0); +} +#undef CONVERT_SWITCH +#undef CONVERT_FIELD + static int __elfN(load_elf_header)(char *filename, elf_file_t ef) { @@ -127,63 +233,10 @@ goto error; } -#ifdef __powerpc__ - /* - * XXX: should be in a separate helper. - * - * Fixup ELF endianness. - * - * The Xhdr structure was loaded using block read call to - * optimize file accesses. It might happen, that the endianness - * of the system memory is different that endianness of - * the ELF header. - * Swap fields here to guarantee that Xhdr always contain - * valid data regardless of architecture. - */ - if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { - ehdr->e_type = be16toh(ehdr->e_type); - ehdr->e_machine = be16toh(ehdr->e_machine); - ehdr->e_version = be32toh(ehdr->e_version); - if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { - ehdr->e_entry = be64toh(ehdr->e_entry); - ehdr->e_phoff = be64toh(ehdr->e_phoff); - ehdr->e_shoff = be64toh(ehdr->e_shoff); - } else { - ehdr->e_entry = be32toh(ehdr->e_entry); - ehdr->e_phoff = be32toh(ehdr->e_phoff); - ehdr->e_shoff = be32toh(ehdr->e_shoff); - } - ehdr->e_flags = be32toh(ehdr->e_flags); - ehdr->e_ehsize = be16toh(ehdr->e_ehsize); - ehdr->e_phentsize = be16toh(ehdr->e_phentsize); - ehdr->e_phnum = be16toh(ehdr->e_phnum); - ehdr->e_shentsize = be16toh(ehdr->e_shentsize); - ehdr->e_shnum = be16toh(ehdr->e_shnum); - ehdr->e_shstrndx = be16toh(ehdr->e_shstrndx); + err = elf_header_convert(ehdr); + if (err) + goto error; - } else { - ehdr->e_type = le16toh(ehdr->e_type); - ehdr->e_machine = le16toh(ehdr->e_machine); - ehdr->e_version = le32toh(ehdr->e_version); - if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { - ehdr->e_entry = le64toh(ehdr->e_entry); - ehdr->e_phoff = le64toh(ehdr->e_phoff); - ehdr->e_shoff = le64toh(ehdr->e_shoff); - } else { - ehdr->e_entry = le32toh(ehdr->e_entry); - ehdr->e_phoff = le32toh(ehdr->e_phoff); - ehdr->e_shoff = le32toh(ehdr->e_shoff); - } - ehdr->e_flags = le32toh(ehdr->e_flags); - ehdr->e_ehsize = le16toh(ehdr->e_ehsize); - ehdr->e_phentsize = le16toh(ehdr->e_phentsize); - ehdr->e_phnum = le16toh(ehdr->e_phnum); - ehdr->e_shentsize = le16toh(ehdr->e_shentsize); - ehdr->e_shnum = le16toh(ehdr->e_shnum); - ehdr->e_shstrndx = le16toh(ehdr->e_shstrndx); - } -#endif - if (ehdr->e_version != EV_CURRENT || ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ err = EFTYPE; goto error; @@ -453,57 +506,8 @@ phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { -#ifdef __powerpc__ - /* - * XXX: should be in a seprate helper. - * - * Fixup ELF endianness. - * - * The Xhdr structure was loaded using block read call to - * optimize file accesses. It might happen, that the endianness - * of the system memory is different that endianness of - * the ELF header. - * Swap fields here to guarantee that Xhdr always contain - * valid data regardless of architecture. - */ - if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { - phdr[i].p_type = be32toh(phdr[i].p_type); - phdr[i].p_flags = be32toh(phdr[i].p_flags); - if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { - phdr[i].p_offset = be64toh(phdr[i].p_offset); - phdr[i].p_vaddr = be64toh(phdr[i].p_vaddr); - phdr[i].p_paddr = be64toh(phdr[i].p_paddr); - phdr[i].p_filesz = be64toh(phdr[i].p_filesz); - phdr[i].p_memsz = be64toh(phdr[i].p_memsz); - phdr[i].p_align = be64toh(phdr[i].p_align); - } else { - phdr[i].p_offset = be32toh(phdr[i].p_offset); - phdr[i].p_vaddr = be32toh(phdr[i].p_vaddr); - phdr[i].p_paddr = be32toh(phdr[i].p_paddr); - phdr[i].p_filesz = be32toh(phdr[i].p_filesz); - phdr[i].p_memsz = be32toh(phdr[i].p_memsz); - phdr[i].p_align = be32toh(phdr[i].p_align); - } - } else { - phdr[i].p_type = le32toh(phdr[i].p_type); - phdr[i].p_flags = le32toh(phdr[i].p_flags); - if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { - phdr[i].p_offset = le64toh(phdr[i].p_offset); - phdr[i].p_vaddr = le64toh(phdr[i].p_vaddr); - phdr[i].p_paddr = le64toh(phdr[i].p_paddr); - phdr[i].p_filesz = le64toh(phdr[i].p_filesz); - phdr[i].p_memsz = le64toh(phdr[i].p_memsz); - phdr[i].p_align = le64toh(phdr[i].p_align); - } else { - phdr[i].p_offset = le32toh(phdr[i].p_offset); - phdr[i].p_vaddr = le32toh(phdr[i].p_vaddr); - phdr[i].p_paddr = le32toh(phdr[i].p_paddr); - phdr[i].p_filesz = le32toh(phdr[i].p_filesz); - phdr[i].p_memsz = le32toh(phdr[i].p_memsz); - phdr[i].p_align = le32toh(phdr[i].p_align); - } - } -#endif + if (elf_program_header_convert(ehdr, phdr)) + continue; /* We want to load PT_LOAD segments only.. */ if (phdr[i].p_type != PT_LOAD) @@ -580,63 +584,8 @@ goto nosyms; } -#ifdef __powerpc__ - /* - * XXX: should be in a seprate helper. - * - * Fixup ELF endianness. - * - * The Xhdr structure was loaded using block read call to - * optimize file accesses. It might happen, that the endianness - * of the system memory is different that endianness of - * the ELF header. - * Swap fields here to guarantee that Xhdr always contain - * valid data regardless of architecture. - */ - for (i = 0; i < ehdr->e_shnum; i++) { - if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { - shdr[i].sh_name = be32toh(shdr[i].sh_name); - shdr[i].sh_type = be32toh(shdr[i].sh_type); - shdr[i].sh_link = be32toh(shdr[i].sh_link); - shdr[i].sh_info = be32toh(shdr[i].sh_info); - if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { - shdr[i].sh_flags = be64toh(shdr[i].sh_flags); - shdr[i].sh_addr = be64toh(shdr[i].sh_addr); - shdr[i].sh_offset = be64toh(shdr[i].sh_offset); - shdr[i].sh_size = be64toh(shdr[i].sh_size); - shdr[i].sh_addralign = be64toh(shdr[i].sh_addralign); - shdr[i].sh_entsize = be64toh(shdr[i].sh_entsize); - } else { - shdr[i].sh_flags = be32toh(shdr[i].sh_flags); - shdr[i].sh_addr = be32toh(shdr[i].sh_addr); - shdr[i].sh_offset = be32toh(shdr[i].sh_offset); - shdr[i].sh_size = be32toh(shdr[i].sh_size); - shdr[i].sh_addralign = be32toh(shdr[i].sh_addralign); - shdr[i].sh_entsize = be32toh(shdr[i].sh_entsize); - } - } else { - shdr[i].sh_name = le32toh(shdr[i].sh_name); - shdr[i].sh_type = le32toh(shdr[i].sh_type); - shdr[i].sh_link = le32toh(shdr[i].sh_link); - shdr[i].sh_info = le32toh(shdr[i].sh_info); - if (ehdr->e_ident[EI_CLASS] == ELFCLASS64) { - shdr[i].sh_flags = le64toh(shdr[i].sh_flags); - shdr[i].sh_addr = le64toh(shdr[i].sh_addr); - shdr[i].sh_offset = le64toh(shdr[i].sh_offset); - shdr[i].sh_size = le64toh(shdr[i].sh_size); - shdr[i].sh_addralign = le64toh(shdr[i].sh_addralign); - shdr[i].sh_entsize = le64toh(shdr[i].sh_entsize); - } else { - shdr[i].sh_flags = le32toh(shdr[i].sh_flags); - shdr[i].sh_addr = le32toh(shdr[i].sh_addr); - shdr[i].sh_offset = le32toh(shdr[i].sh_offset); - shdr[i].sh_size = le32toh(shdr[i].sh_size); - shdr[i].sh_addralign = le32toh(shdr[i].sh_addralign); - shdr[i].sh_entsize = le32toh(shdr[i].sh_entsize); - } - } - } -#endif + for (i = 0; i < ehdr->e_shnum; i++) + elf_section_header_convert(ehdr, &shdr[i]); file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr);