Beispiel #1
0
static void si_bin_file_read_enc_dict(struct si_bin_file_t *bin_file)
{
    struct elf_file_t *elf_file;
    struct elf_buffer_t *buffer;
    Elf32_Ehdr *elf_header;

    struct elf_program_header_t *program_header;

    struct si_bin_enc_dict_entry_t *enc_dict_entry;
    struct si_bin_enc_dict_entry_header_t *enc_dict_entry_header;
    int enc_dict_entry_count;

    int i;

    /* ELF header */
    elf_file = bin_file->elf_file;
    elf_header = elf_file->header;
    buffer = &elf_file->buffer;
    elf_debug("**\n** Parsing AMD Binary (Internal ELF file)\n** %s\n**\n\n", elf_file->path);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_CLASS], ELFCLASS32);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_DATA], ELFDATA2LSB);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_OSABI], 0x64);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_ABIVERSION], 1);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_type, ET_EXEC);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_machine, 0x7d);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_entry, 0);

    /* Look for encoding dictionary (program header with type 'PT_LOPROC+2') */
    program_header = NULL;
    for (i = 0; i < list_count(elf_file->program_header_list); i++)
    {
        program_header = list_get(elf_file->program_header_list, i);
        if (program_header->header->p_type == PT_LOPROC + 2)
            break;
    }
    if (i == list_count(elf_file->program_header_list) || !program_header)
        fatal("%s: no encoding dictionary", elf_file->path);
    elf_debug("Encoding dictionary found in program header %d\n", i);

    /* Parse encoding dictionary */
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_vaddr, 0);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_paddr, 0);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_memsz, 0);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_flags, 0);
    SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_align, 0);
    assert(program_header->header->p_filesz % sizeof(struct si_bin_enc_dict_entry_header_t) == 0);
    enc_dict_entry_count = program_header->header->p_filesz / sizeof(struct si_bin_enc_dict_entry_header_t);
    elf_debug("  -> %d entries\n\n", enc_dict_entry_count);

    /* Read encoding dictionary entries */
    bin_file->enc_dict = list_create();
    elf_buffer_seek(buffer, program_header->header->p_offset);
    for (i = 0; i < enc_dict_entry_count; i++) {

        /* Create entry */
        enc_dict_entry = calloc(1, sizeof(struct si_bin_enc_dict_entry_t));
        enc_dict_entry->header = elf_buffer_tell(buffer);
        elf_buffer_read(buffer, NULL, sizeof(struct si_bin_enc_dict_entry_header_t));
        list_add(bin_file->enc_dict, enc_dict_entry);

        /* Store encoding dictionary entry for Evergreen (code 9) */
        if (enc_dict_entry->header->d_machine == 9)
        {
            bin_file->enc_dict_entry_southern_islands = enc_dict_entry;
        }
        else if (enc_dict_entry->header->d_machine == 26)
        {
            /* Southern Islands has code 26 */
            bin_file->enc_dict_entry_southern_islands = enc_dict_entry;
        }
    }

    /* Debug */
    elf_debug("idx %-15s %-10s %-10s %-10s %-10s\n", "d_machine", "d_type",
              "d_offset", "d_size", "d_flags");
    for (i = 0; i < 80; i++)
        elf_debug("-");
    elf_debug("\n");
    for (i = 0; i < list_count(bin_file->enc_dict); i++)
    {
        char machine_str[MAX_STRING_SIZE];

        enc_dict_entry = list_get(bin_file->enc_dict, i);
        enc_dict_entry_header = enc_dict_entry->header;
        snprintf(machine_str, sizeof(machine_str), "%d (%s)",
                 enc_dict_entry_header->d_machine, map_value(&enc_dict_machine_map,
                         enc_dict_entry_header->d_machine - 1));
        elf_debug("%3d %-15s 0x%-8x 0x%-8x %-10d 0x%-8x\n",
                  i, machine_str,
                  enc_dict_entry_header->d_type,
                  enc_dict_entry_header->d_offset,
                  enc_dict_entry_header->d_size,
                  enc_dict_entry_header->d_flags);
    }
    elf_debug("\n\n");
}
Beispiel #2
0
static void si_bin_file_read_enc_dict(struct si_bin_file_t *bin_file) {
  struct elf_file_t *elf_file;
  struct elf_buffer_t *buffer;
  Elf32_Ehdr *elf_header;

  struct elf_program_header_t *program_header;

  struct si_bin_enc_dict_entry_t *enc_dict_entry;
  struct si_bin_enc_dict_entry_header_t *enc_dict_entry_header;
  int enc_dict_entry_count;

  int i;

  /* ELF header */
  elf_file = bin_file->elf_file;
  elf_header = elf_file->header;
  buffer = &elf_file->buffer;
  elf_debug("**\n** Parsing AMD Binary (Internal ELF file)\n** %s\n**\n\n",
            elf_file->path);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_CLASS], ELFCLASS32);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_DATA], ELFDATA2LSB);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_OSABI], 0x64);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_ident[EI_ABIVERSION], 1);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_type, ET_EXEC);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_machine, 0x7d);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(elf_header->e_entry, 0);

  /* Look for encoding dictionary (program header with type 'PT_LOPROC+2') */
  program_header = NULL;
  for (i = 0; i < list_count(elf_file->program_header_list); i++) {
    program_header = list_get(elf_file->program_header_list, i);
    if (program_header->header->p_type == PT_LOPROC + 2) break;
  }
  if (i == list_count(elf_file->program_header_list) || !program_header)
    fatal("%s: no encoding dictionary", elf_file->path);
  elf_debug("Encoding dictionary found in program header %d\n", i);

  /* Parse encoding dictionary */
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_vaddr, 0);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_paddr, 0);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_memsz, 0);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_flags, 0);
  SI_BIN_FILE_NOT_SUPPORTED_NEQ(program_header->header->p_align, 0);
  assert(program_header->header->p_filesz %
             sizeof(struct si_bin_enc_dict_entry_header_t) ==
         0);
  enc_dict_entry_count = program_header->header->p_filesz /
                         sizeof(struct si_bin_enc_dict_entry_header_t);
  elf_debug("  -> %d entries\n\n", enc_dict_entry_count);

  /* Read encoding dictionary entries */
  bin_file->enc_dict = list_create();
  elf_buffer_seek(buffer, program_header->header->p_offset);
  for (i = 0; i < enc_dict_entry_count; i++) {
    /* Create entry */
    enc_dict_entry = xcalloc(1, sizeof(struct si_bin_enc_dict_entry_t));
    enc_dict_entry->header = elf_buffer_tell(buffer);
    elf_buffer_read(buffer, NULL,
                    sizeof(struct si_bin_enc_dict_entry_header_t));
    list_add(bin_file->enc_dict, enc_dict_entry);

    /* Store encoding dictionary entry for Southern Islands.
     * Apparently the valid code changes by driver version */
    if (enc_dict_entry->header->d_machine == 9) {
      /* Driver XXX */
      elf_debug("machine = %d (tahiti or pitcairn)\n",
                enc_dict_entry->header->d_machine);
      bin_file->enc_dict_entry_southern_islands = enc_dict_entry;
    } else if (enc_dict_entry->header->d_machine == 25) {
      /* This entry is always present but doesn't seem
       * useful information.  We should probably figure
       * out what is stored here. */
      elf_debug("machine = 25 (skip this entry)\n");
    } else if (enc_dict_entry->header->d_machine == 26) {
      /* Driver XXX */
      elf_debug("machine = %d (tahiti or pitcairn)\n",
                enc_dict_entry->header->d_machine);
      bin_file->enc_dict_entry_southern_islands = enc_dict_entry;
    } else if (enc_dict_entry->header->d_machine == 27) {
      /* Driver 12.4 */
      elf_debug("machine = %d (tahiti or pitcairn)\n",
                enc_dict_entry->header->d_machine);
      bin_file->enc_dict_entry_southern_islands = enc_dict_entry;
    } else if (enc_dict_entry->header->d_machine == 28) {
      elf_debug("machine = %d (capeverde)\n",
                enc_dict_entry->header->d_machine);
      bin_file->enc_dict_entry_southern_islands = enc_dict_entry;
    } else {
      fatal("%s: unknown machine number (%d)\n", __FUNCTION__,
            enc_dict_entry->header->d_machine);
    }
  }

  /* Debug */
  elf_debug("idx %-15s %-10s %-10s %-10s %-10s\n", "d_machine", "d_type",
            "d_offset", "d_size", "d_flags");
  for (i = 0; i < 80; i++) elf_debug("-");
  elf_debug("\n");
  for (i = 0; i < list_count(bin_file->enc_dict); i++) {
    char machine_str[MAX_STRING_SIZE];

    enc_dict_entry = list_get(bin_file->enc_dict, i);
    enc_dict_entry_header = enc_dict_entry->header;
    snprintf(machine_str, sizeof(machine_str), "%d (%s)",
             enc_dict_entry_header->d_machine,
             str_map_value(&enc_dict_machine_map,
                           enc_dict_entry_header->d_machine - 1));
    elf_debug("%3d %-15s 0x%-8x 0x%-8x %-10d 0x%-8x\n", i, machine_str,
              enc_dict_entry_header->d_type, enc_dict_entry_header->d_offset,
              enc_dict_entry_header->d_size, enc_dict_entry_header->d_flags);
  }
  elf_debug("\n\n");
}