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

Re: [PATCH v2] x86/efi: Use generic PE/COFF structures



Hello everyone,

Any comments on v2 patch?
Just checking if you missed this email or didn't have time for review.

BR,
Milan

On Tue, Aug 27, 2024 at 3:43 PM Milan Djokic <milandjokic1995@xxxxxxxxx> wrote:
>
> From: Nikola Jelic <nikola.jelic@xxxxxxxxx>
>
> Adapted x86 efi parser and mkreloc utility to use generic PE header
> (efi/pe.h), instead of locally defined structures for each component.
>
> Signed-off-by: Nikola Jelic <nikola.jelic@xxxxxxxxx>
> Signed-off-by: Milan Djokic <milan.djokic@xxxxxxxxx>
> ---
> Changes in V2:
>   - Using pe header constants instead of hardcoded values (magic,
>     machine)
> ---
>  xen/arch/x86/efi/mkreloc.c | 134 +++++++++++--------------------------
>  xen/common/efi/pe.c        |  96 ++++++--------------------
>  2 files changed, 61 insertions(+), 169 deletions(-)
>
> diff --git a/xen/arch/x86/efi/mkreloc.c b/xen/arch/x86/efi/mkreloc.c
> index 083740ab8a..89c525d81e 100644
> --- a/xen/arch/x86/efi/mkreloc.c
> +++ b/xen/arch/x86/efi/mkreloc.c
> @@ -9,45 +9,7 @@
>  #include <sys/mman.h>
>  #include <unistd.h>
>
> -struct mz_hdr {
> -    uint16_t signature;
> -#define MZ_SIGNATURE 0x5a4d
> -    uint16_t last_page_size;
> -    uint16_t page_count;
> -    uint16_t relocation_count;
> -    uint16_t header_paras;
> -    uint16_t min_paras;
> -    uint16_t max_paras;
> -    uint16_t entry_ss;
> -    uint16_t entry_sp;
> -    uint16_t checksum;
> -    uint16_t entry_ip;
> -    uint16_t entry_cs;
> -    uint16_t relocations;
> -    uint16_t overlay;
> -    uint8_t reserved[32];
> -    uint32_t extended_header_base;
> -};
> -
> -struct pe_hdr {
> -    uint32_t signature;
> -#define PE_SIGNATURE 0x00004550
> -    uint16_t cpu;
> -    uint16_t section_count;
> -    int32_t timestamp;
> -    uint32_t symbols_file_offset;
> -    uint32_t symbol_count;
> -    uint16_t opt_hdr_size;
> -    uint16_t flags;
> -    struct {
> -        uint16_t magic;
> -#define PE_MAGIC_EXE32     0x010b
> -#define PE_MAGIC_EXE32PLUS 0x020b
> -        uint8_t linker_major, linker_minor;
> -        uint32_t code_size, data_size, bss_size;
> -        uint32_t entry_rva, code_rva, data_rva;
> -    } opt_hdr;
> -};
> +#include "../../../include/efi/pe.h"
>
>  #define PE_PAGE_SIZE 0x1000
>
> @@ -55,22 +17,6 @@ struct pe_hdr {
>  #define PE_BASE_RELOC_HIGHLOW  3
>  #define PE_BASE_RELOC_DIR64   10
>
> -struct coff_section {
> -    char name[8];
> -    uint32_t size;
> -    uint32_t rva;
> -    uint32_t file_size;
> -    uint32_t file_offset;
> -    uint32_t relocation_file_offset;
> -    uint32_t line_number_file_offset;
> -    uint16_t relocation_count;
> -    uint16_t line_number_count;
> -    uint32_t flags;
> -#define COFF_SECTION_BSS         0x00000080U
> -#define COFF_SECTION_DISCARDABLE 0x02000000U
> -#define COFF_SECTION_WRITEABLE   0x80000000U
> -};
> -
>  static void usage(const char *cmd, int rc)
>  {
>      fprintf(rc ? stderr : stdout,
> @@ -80,7 +26,7 @@ static void usage(const char *cmd, int rc)
>  }
>
>  static unsigned int load(const char *name, int *handle,
> -                         struct coff_section **sections,
> +                         struct section_header **sections,
>                           uint_fast64_t *image_base,
>                           uint32_t *image_size,
>                           unsigned int *width)
> @@ -88,6 +34,7 @@ static unsigned int load(const char *name, int *handle,
>      int in = open(name, O_RDONLY);
>      struct mz_hdr mz_hdr;
>      struct pe_hdr pe_hdr;
> +    struct pe32_opt_hdr pe32_opt_hdr;
>      uint32_t base;
>
>      if ( in < 0 ||
> @@ -96,16 +43,17 @@ static unsigned int load(const char *name, int *handle,
>          perror(name);
>          exit(2);
>      }
> -    if ( mz_hdr.signature != MZ_SIGNATURE ||
> -         mz_hdr.relocations < sizeof(mz_hdr) ||
> -         !mz_hdr.extended_header_base )
> +    if ( mz_hdr.magic != MZ_MAGIC ||
> +         mz_hdr.reloc_table_offset < sizeof(mz_hdr) ||
> +         !mz_hdr.peaddr )
>      {
>          fprintf(stderr, "%s: Wrong DOS file format\n", name);
>          exit(2);
>      }
>
> -    if ( lseek(in, mz_hdr.extended_header_base, SEEK_SET) < 0 ||
> +    if ( lseek(in, mz_hdr.peaddr, SEEK_SET) < 0 ||
>           read(in, &pe_hdr, sizeof(pe_hdr)) != sizeof(pe_hdr) ||
> +         read(in, &pe32_opt_hdr, sizeof(pe32_opt_hdr)) != 
> sizeof(pe32_opt_hdr) ||
>           read(in, &base, sizeof(base)) != sizeof(base) ||
>           /*
>            * Luckily the image size field lives at the
> @@ -117,35 +65,33 @@ static unsigned int load(const char *name, int *handle,
>          perror(name);
>          exit(3);
>      }
> -    switch ( (pe_hdr.signature == PE_SIGNATURE &&
> -              pe_hdr.opt_hdr_size > sizeof(pe_hdr.opt_hdr)) *
> -             pe_hdr.opt_hdr.magic )
> +    switch ( (pe_hdr.magic == PE_MAGIC &&
> +              pe_hdr.opt_hdr_size > sizeof(pe32_opt_hdr)) *
> +              pe32_opt_hdr.magic )
>      {
> -    case PE_MAGIC_EXE32:
> +    case PE_OPT_MAGIC_PE32:
>          *width = 32;
>          *image_base = base;
>          break;
> -    case PE_MAGIC_EXE32PLUS:
> +    case PE_OPT_MAGIC_PE32PLUS:
>          *width = 64;
> -        *image_base = ((uint64_t)base << 32) | pe_hdr.opt_hdr.data_rva;
> +        *image_base = ((uint64_t)base << 32) | pe32_opt_hdr.data_base;
>          break;
>      default:
>          fprintf(stderr, "%s: Wrong PE file format\n", name);
>          exit(3);
>      }
>
> -    *sections = malloc(pe_hdr.section_count * sizeof(**sections));
> +    *sections = malloc(pe_hdr.sections * sizeof(**sections));
>      if ( !*sections )
>      {
>          perror(NULL);
>          exit(4);
>      }
> -    if ( lseek(in,
> -               mz_hdr.extended_header_base + offsetof(struct pe_hdr, 
> opt_hdr) +
> -                  pe_hdr.opt_hdr_size,
> +    if ( lseek(in, mz_hdr.peaddr + sizeof(pe_hdr) + pe_hdr.opt_hdr_size,
>                 SEEK_SET) < 0 ||
> -         read(in, *sections, pe_hdr.section_count * sizeof(**sections)) !=
> -             pe_hdr.section_count * sizeof(**sections) )
> +         read(in, *sections, pe_hdr.sections * sizeof(**sections)) !=
> +             pe_hdr.sections * sizeof(**sections) )
>      {
>          perror(name);
>          exit(4);
> @@ -153,12 +99,12 @@ static unsigned int load(const char *name, int *handle,
>
>      *handle = in;
>
> -    return pe_hdr.section_count;
> +    return pe_hdr.sections;
>  }
>
>  static long page_size;
>
> -static const void *map_section(const struct coff_section *sec, int in,
> +static const void *map_section(const struct section_header *sec, int in,
>                                 const char *name)
>  {
>      const char *ptr;
> @@ -166,10 +112,10 @@ static const void *map_section(const struct 
> coff_section *sec, int in,
>
>      if ( !page_size )
>          page_size = sysconf(_SC_PAGESIZE);
> -    offs = sec->file_offset & (page_size - 1);
> +    offs = sec->data_addr & (page_size - 1);
>
> -    ptr = mmap(0, offs + sec->file_size, PROT_READ, MAP_PRIVATE, in,
> -               sec->file_offset - offs);
> +    ptr = mmap(0, offs + sec->raw_data_size, PROT_READ, MAP_PRIVATE, in,
> +               sec->data_addr - offs);
>      if ( ptr == MAP_FAILED )
>      {
>          perror(name);
> @@ -179,15 +125,15 @@ static const void *map_section(const struct 
> coff_section *sec, int in,
>      return ptr + offs;
>  }
>
> -static void unmap_section(const void *ptr, const struct coff_section *sec)
> +static void unmap_section(const void *ptr, const struct section_header *sec)
>  {
> -    unsigned long offs = sec->file_offset & (page_size - 1);
> +    unsigned long offs = sec->data_addr & (page_size - 1);
>
> -    munmap((char *)ptr - offs, offs + sec->file_size);
> +    munmap((char *)ptr - offs, offs + sec->raw_data_size);
>  }
>
>  static void diff_sections(const unsigned char *ptr1, const unsigned char 
> *ptr2,
> -                          const struct coff_section *sec,
> +                          const struct section_header *sec,
>                            int_fast64_t diff, unsigned int width,
>                            uint_fast64_t base, uint_fast64_t end)
>  {
> @@ -208,7 +154,7 @@ static void diff_sections(const unsigned char *ptr1, 
> const unsigned char *ptr2,
>      while ( !(diff & (((int_fast64_t)1 << ((disp + 1) * CHAR_BIT)) - 1)) )
>          ++disp;
>
> -    for ( i = 0; i < sec->file_size; ++i )
> +    for ( i = 0; i < sec->raw_data_size; ++i )
>      {
>          uint_fast32_t rva;
>          union {
> @@ -222,7 +168,7 @@ static void diff_sections(const unsigned char *ptr1, 
> const unsigned char *ptr2,
>          if ( ptr1[i] == ptr2[i] )
>              continue;
>
> -        if ( i < disp || i + width - disp > sec->file_size )
> +        if ( i < disp || i + width - disp > sec->raw_data_size )
>          {
>              fprintf(stderr,
>                      "Bogus difference at %.8s:%08" PRIxFAST32 "\n",
> @@ -250,11 +196,11 @@ static void diff_sections(const unsigned char *ptr1, 
> const unsigned char *ptr2,
>              reloc_size += reloc_size & 2;
>              if ( reloc_size )
>                  printf("\t.equ rva_%08" PRIxFAST32 "_relocs,"
> -                             " %#08" PRIxFAST32 "\n",
> +                       " %#08" PRIxFAST32 "\n",
>                         cur_rva, reloc_size);
>              printf("\t.balign 4\n"
>                     "\t.long %#08" PRIxFAST32 ","
> -                          " rva_%08" PRIxFAST32 "_relocs\n",
> +                   " rva_%08" PRIxFAST32 "_relocs\n",
>                     rva, rva);
>              cur_rva = rva;
>              reloc_size = 8;
> @@ -267,7 +213,7 @@ static void diff_sections(const unsigned char *ptr1, 
> const unsigned char *ptr2,
>              exit(3);
>          }
>
> -        if ( !(sec->flags & COFF_SECTION_WRITEABLE) )
> +        if ( !(sec->flags & IMAGE_SCN_MEM_WRITE) )
>              fprintf(stderr,
>                      "Warning: relocation to r/o section %.8s:%08" PRIxFAST32 
> "\n",
>                      sec->name, i - disp);
> @@ -285,7 +231,7 @@ int main(int argc, char *argv[])
>      unsigned int i, nsec, width1, width2;
>      uint_fast64_t base1, base2;
>      uint32_t size1, size2;
> -    struct coff_section *sec1, *sec2;
> +    struct section_header *sec1, *sec2;
>
>      if ( argc == 1 ||
>           !strcmp(argv[1], "-?") ||
> @@ -328,16 +274,16 @@ int main(int argc, char *argv[])
>
>          if ( memcmp(sec1[i].name, sec2[i].name, sizeof(sec1[i].name)) ||
>               sec1[i].rva != sec2[i].rva ||
> -             sec1[i].size != sec2[i].size ||
> -             sec1[i].file_size != sec2[i].file_size ||
> +             sec1[i].virtual_size != sec2[i].virtual_size ||
> +             sec1[i].raw_data_size != sec2[i].raw_data_size ||
>               sec1[i].flags != sec2[i].flags )
>          {
>              fprintf(stderr, "Mismatched section %u parameters\n", i);
>              return 5;
>          }
>
> -        if ( !sec1[i].size ||
> -             (sec1[i].flags & (COFF_SECTION_DISCARDABLE|COFF_SECTION_BSS)) )
> +        if ( !sec1[i].virtual_size ||
> +             (sec1[i].flags & (IMAGE_SCN_MEM_DISCARDABLE | 
> IMAGE_SCN_CNT_UNINITIALIZED_DATA)) )
>              continue;
>
>          /*
> @@ -354,10 +300,10 @@ int main(int argc, char *argv[])
>              return 3;
>          }
>
> -        if ( sec1[i].file_size > sec1[i].size )
> +        if ( sec1[i].raw_data_size > sec1[i].virtual_size )
>          {
> -            sec1[i].file_size = sec1[i].size;
> -            sec2[i].file_size = sec2[i].size;
> +            sec1[i].raw_data_size = sec1[i].virtual_size;
> +            sec2[i].raw_data_size = sec2[i].virtual_size;
>          }
>          ptr1 = map_section(sec1 + i, in1, argv[1]);
>          ptr2 = map_section(sec2 + i, in2, argv[2]);
> diff --git a/xen/common/efi/pe.c b/xen/common/efi/pe.c
> index ef8a2543e0..560f35188d 100644
> --- a/xen/common/efi/pe.c
> +++ b/xen/common/efi/pe.c
> @@ -20,78 +20,28 @@
>   * Lesser General Public License for more details.
>   */
>
> -
>  #include "efi.h"
> +#include "efi/pe.h"
>
> -struct DosFileHeader {
> -    UINT8   Magic[2];
> -    UINT16  LastSize;
> -    UINT16  nBlocks;
> -    UINT16  nReloc;
> -    UINT16  HdrSize;
> -    UINT16  MinAlloc;
> -    UINT16  MaxAlloc;
> -    UINT16  ss;
> -    UINT16  sp;
> -    UINT16  Checksum;
> -    UINT16  ip;
> -    UINT16  cs;
> -    UINT16  RelocPos;
> -    UINT16  nOverlay;
> -    UINT16  reserved[4];
> -    UINT16  OEMId;
> -    UINT16  OEMInfo;
> -    UINT16  reserved2[10];
> -    UINT32  ExeHeader;
> -};
> -
> -#if defined(__arm__) || defined (__aarch64__)
> -#define PE_HEADER_MACHINE 0xaa64
> +#if defined(__arm__) || defined(__aarch64__)
> +#define PE_HEADER_MACHINE IMAGE_FILE_MACHINE_ARM64
>  #elif defined(__x86_64__)
> -#define PE_HEADER_MACHINE 0x8664
> +#define PE_HEADER_MACHINE IMAGE_FILE_MACHINE_AMD64
>  #else
>  #error "Unknown architecture"
>  #endif
>
> -struct PeFileHeader {
> -    UINT16  Machine;
> -    UINT16  NumberOfSections;
> -    UINT32  TimeDateStamp;
> -    UINT32  PointerToSymbolTable;
> -    UINT32  NumberOfSymbols;
> -    UINT16  SizeOfOptionalHeader;
> -    UINT16  Characteristics;
> -};
> -
> -struct PeHeader {
> -    UINT8   Magic[4];
> -    struct PeFileHeader FileHeader;
> -};
> -
> -struct PeSectionHeader {
> -    CHAR8   Name[8];
> -    UINT32  VirtualSize;
> -    UINT32  VirtualAddress;
> -    UINT32  SizeOfRawData;
> -    UINT32  PointerToRawData;
> -    UINT32  PointerToRelocations;
> -    UINT32  PointerToLinenumbers;
> -    UINT16  NumberOfRelocations;
> -    UINT16  NumberOfLinenumbers;
> -    UINT32  Characteristics;
> -};
> -
> -static bool __init pe_name_compare(const struct PeSectionHeader *sect,
> +static bool __init pe_name_compare(const struct section_header *sect,
>                                     const CHAR16 *name)
>  {
>      size_t i;
>
> -    if ( sect->Name[0] != '.' )
> +    if ( sect->name[0] != '.' )
>          return false;
>
> -    for ( i = 1; i < sizeof(sect->Name); i++ )
> +    for ( i = 1; i < sizeof(sect->name); i++ )
>      {
> -        const char c = sect->Name[i];
> +        const char c = sect->name[i];
>
>          if ( c != name[i - 1] )
>              return false;
> @@ -105,33 +55,29 @@ static bool __init pe_name_compare(const struct 
> PeSectionHeader *sect,
>  const void *__init pe_find_section(const void *image, const UINTN image_size,
>                                     const CHAR16 *section_name, UINTN 
> *size_out)
>  {
> -    const struct DosFileHeader *dos = image;
> -    const struct PeHeader *pe;
> -    const struct PeSectionHeader *sect;
> +    const struct mz_hdr *mz = image;
> +    const struct pe_hdr *pe;
> +    const struct section_header *sect;
>      UINTN offset, i;
>
> -    if ( image_size < sizeof(*dos) ||
> -         dos->Magic[0] != 'M' ||
> -         dos->Magic[1] != 'Z' )
> +    if ( image_size < sizeof(*mz) ||
> +         mz->magic != MZ_MAGIC )
>          return NULL;
>
> -    offset = dos->ExeHeader;
> +    offset = mz->peaddr;
>      pe = image + offset;
>
>      offset += sizeof(*pe);
>      if ( image_size < offset ||
> -         pe->Magic[0] != 'P' ||
> -         pe->Magic[1] != 'E' ||
> -         pe->Magic[2] != '\0' ||
> -         pe->Magic[3] != '\0' )
> +         pe->magic != PE_MAGIC )
>          return NULL;
>
> -    if ( pe->FileHeader.Machine != PE_HEADER_MACHINE )
> +    if ( pe->machine != PE_HEADER_MACHINE )
>          return NULL;
>
> -    offset += pe->FileHeader.SizeOfOptionalHeader;
> +    offset += pe->opt_hdr_size;
>
> -    for ( i = 0; i < pe->FileHeader.NumberOfSections; i++ )
> +    for ( i = 0; i < pe->sections; i++ )
>      {
>          sect = image + offset;
>          if ( image_size < offset + sizeof(*sect) )
> @@ -143,13 +89,13 @@ const void *__init pe_find_section(const void *image, 
> const UINTN image_size,
>              continue;
>          }
>
> -        if ( image_size < sect->VirtualSize + sect->VirtualAddress )
> +        if ( image_size < sect->virtual_size + sect->rva )
>              blexit(L"PE invalid section size + address");
>
>          if ( size_out )
> -            *size_out = sect->VirtualSize;
> +            *size_out = sect->virtual_size;
>
> -        return image + sect->VirtualAddress;
> +        return image + sect->rva;
>      }
>
>      return NULL;
> --
> 2.25.1
>



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.