Esempio n. 1
0
static void elf_file_read_program_headers(struct elf_file_t *elf_file)
{
	struct elf_buffer_t *buffer;
	struct elf_program_header_t *program_header;
	Elf32_Ehdr *elf_header;

	int count;
	int i;

	/* Create program header list */
	buffer = &elf_file->buffer;
	elf_header = elf_file->header;
	elf_file->program_header_list = list_create();
	if (!elf_header->e_phnum)
		return;

	/* Check program header size */
	if (elf_header->e_phentsize != sizeof(Elf32_Phdr))
		fatal("%s: program header size %d (should be %d)",
			elf_file->path, elf_header->e_phentsize, (int) sizeof(Elf32_Phdr));

	/* Read program headers */
	elf_buffer_seek(buffer, elf_header->e_phoff);
	for (i = 0; i < elf_header->e_phnum; i++)
	{
		/* Allocate program header */
		program_header = calloc(1, sizeof(struct elf_program_header_t));
		program_header->header = elf_buffer_tell(buffer);

		/* Advance buffer */
		count = elf_buffer_read(buffer, NULL, sizeof(Elf32_Phdr));
		if (count < sizeof(Elf32_Phdr))
			fatal("%s: unexpected end of file while reading program headers", elf_file->path);

		/* Add program header to list */
		list_add(elf_file->program_header_list, program_header);
	}

	/* Dump program headers */
	elf_debug("Program headers:\n");
	elf_debug("idx type       offset     vaddr      paddr      filesz    memsz     flags  align\n");
	for (i = 0; i < 80; i++)
		elf_debug("-");
	elf_debug("\n");
	for (i = 0; i < list_count(elf_file->program_header_list); i++) {
		program_header = list_get(elf_file->program_header_list, i);
		elf_debug("%-3d 0x%-8x 0x%-8x 0x%-8x 0x%-8x %-9u %-9u %-6u %u\n", i,
			program_header->header->p_type,
			program_header->header->p_offset,
			program_header->header->p_vaddr,
			program_header->header->p_paddr,
			program_header->header->p_filesz,
			program_header->header->p_memsz,
			program_header->header->p_flags,
			program_header->header->p_align);
	}
	elf_debug("\n");
}
Esempio n. 2
0
static void elf_file_read_section_headers(struct elf_file_t *elf_file)
{
	int i, count;

	struct elf_buffer_t *buffer;
	struct elf_section_t *section;
	Elf32_Ehdr *elf_header;

	/* Create section list */
	elf_file->section_list = list_create();

	/* Check section size and number */
	buffer = &elf_file->buffer;
	elf_header = elf_file->header;
	if (!elf_header->e_shnum || elf_header->e_shentsize != sizeof(Elf32_Shdr))
		fatal("%s: number of sections is 0 or section size is not %d",
			elf_file->path, (int) sizeof(Elf32_Shdr));

	/* Read section headers */
	elf_buffer_seek(buffer, elf_header->e_shoff);
	for (i = 0; i < elf_header->e_shnum; i++)
	{
		/* Allocate section */
		section = xcalloc(1, sizeof(struct elf_section_t));
		section->header = elf_buffer_tell(buffer);

		/* Advance buffer */
		count = elf_buffer_read(buffer, NULL, sizeof(Elf32_Shdr));
		if (count < sizeof(Elf32_Shdr))
			fatal("%s: unexpected end of file while reading section headers", elf_file->path);

		/* Get section contents, if section type is not SHT_NOBITS (8) */
		if (section->header->sh_type != 8)
		{
			section->buffer.ptr = buffer->ptr + section->header->sh_offset;
			section->buffer.size = section->header->sh_size;
			section->buffer.pos = 0;
			assert(section->buffer.ptr >= buffer->ptr);
			if (section->buffer.ptr + section->buffer.size > buffer->ptr + buffer->size)
				fatal("section %d out of the ELF boundaries (offs=0x%x, size=%u, ELF_size=%u)",
						i, section->header->sh_offset, section->header->sh_size, buffer->size);
		}

		/* Add section to list */
		list_add(elf_file->section_list, section);
	}

	/* Read string table, and update section names */
	assert(elf_header->e_shstrndx < elf_header->e_shnum);
	elf_file->string_table = list_get(elf_file->section_list, elf_header->e_shstrndx);
	assert(elf_file->string_table->header->sh_type == 3);
	for (i = 0; i < list_count(elf_file->section_list); i++) {
		section = list_get(elf_file->section_list, i);
		section->name = elf_file->string_table->buffer.ptr + section->header->sh_name;
	}
}
Esempio n. 3
0
/* Decode notes in the PT_NOTE segment of the given encoding dictionary entry */
static void si_bin_file_read_notes(struct si_bin_file_t *bin_file, struct si_bin_enc_dict_entry_t *enc_dict_entry)
{
    struct elf_buffer_t *buffer;

    /* Get buffer and set position */
    buffer = &enc_dict_entry->pt_note_buffer;
    elf_buffer_seek(buffer, 0);

    /* Decode notes */
    elf_debug("Reading notes in PT_NOTE segment (enc. dict. for machine=0x%x)\n",
              enc_dict_entry->header->d_machine);
    while (buffer->pos < buffer->size)
        si_bin_file_read_note_header(bin_file, enc_dict_entry);
    elf_debug("\n\n\n");
}
Esempio n. 4
0
/* Create internal ELF file object from an external ELF file object */
static struct elf_file_t *internal_elf_file_create(struct elf_file_t *external_elf_file)
{
	struct elf_section_t *external_section;
	void *section_buf;

	struct elf_file_t *internal_elf_file;
	int internal_elf_offset;
	void *internal_elf_base;
	int internal_elf_size;

	int i;
	/* Create internal shader object */
	for (i = 0; i < list_count(external_elf_file->section_list); i++)
	{
		/* Get section */
		external_section = list_get(external_elf_file->section_list, i);

		/* Internal ELF in the section with name 'binary' */
		if (!strcmp(external_section->name,"binary"))
		{

			elf_buffer_seek(&external_elf_file->buffer, external_section->header->sh_offset);
			section_buf = calloc(1, external_section->header->sh_size);
			memcpy(section_buf, external_elf_file->buffer.ptr + external_elf_file->buffer.pos, external_section->header->sh_size);

			internal_elf_offset = (int)(search_elf_magic(section_buf) - section_buf);
			internal_elf_base = section_buf + internal_elf_offset;
			internal_elf_size = external_section->header->sh_size - internal_elf_offset;

			internal_elf_file = elf_file_create_from_buffer(internal_elf_base, internal_elf_size, external_section->name);

			free(section_buf);
			break;
		}
	}

	return internal_elf_file;
}
Esempio n. 5
0
static void elf_file_read_program_headers(struct elf_file_t *elf_file)
{
	struct elf_buffer_t *buffer;
	struct elf_program_header_t *program_header;
	Elf32_Ehdr *elf_header;

	int count;
	int i;

	/* Create program header list */
	buffer = &elf_file->buffer;
	elf_header = elf_file->header;
	elf_file->program_header_list = list_create();
	if (!elf_header->e_phnum)
		return;

	/* Check program header size */
	if (elf_header->e_phentsize != sizeof(Elf32_Phdr))
		fatal("%s: program header size %d (should be %d)",
			elf_file->path, elf_header->e_phentsize, (int) sizeof(Elf32_Phdr));

	/* Read program headers */
	elf_buffer_seek(buffer, elf_header->e_phoff);
	for (i = 0; i < elf_header->e_phnum; i++)
	{
		/* Allocate program header */
		program_header = xcalloc(1, sizeof(struct elf_program_header_t));
		program_header->header = elf_buffer_tell(buffer);

		/* Advance buffer */
		count = elf_buffer_read(buffer, NULL, sizeof(Elf32_Phdr));
		if (count < sizeof(Elf32_Phdr))
			fatal("%s: unexpected end of file while reading program headers", elf_file->path);

		/* Add program header to list */
		list_add(elf_file->program_header_list, program_header);
	}
}
Esempio n. 6
0
/* Set 'isa_buffer' element for a shader object, the shader object must have the 'shader_kind' element set first */
static int amd_opengl_shader_set_isa_buffer(struct amd_opengl_shader_t *amd_opengl_shader)
{
	struct elf_section_t *internal_section;
	int isa_offset;

	int i;

	if (!&amd_opengl_shader->isa_buffer)
		fatal("%s: shader error", __FUNCTION__);	

		/* Initialize ISA buffer */
		if (amd_opengl_shader->internal_elf_file)
		{
			for (i = 0; i < list_count(amd_opengl_shader->internal_elf_file->section_list); i++)
			{
				internal_section = list_get(amd_opengl_shader->internal_elf_file->section_list, i);

				/* ISAs in '.text' section */
				if (!strcmp(internal_section->name,".text"))
				{					
					isa_offset = get_isa_offset(amd_opengl_shader);
					elf_buffer_seek(&amd_opengl_shader->internal_elf_file->buffer, internal_section->header->sh_offset);
					
					amd_opengl_shader->isa_buffer.ptr  = amd_opengl_shader->internal_elf_file->buffer.ptr + amd_opengl_shader->internal_elf_file->buffer.pos + isa_offset;
					amd_opengl_shader->isa_buffer.size = amd_opengl_shader->internal_elf_file->buffer.size - isa_offset;
					amd_opengl_shader->isa_buffer.pos  = 0;
					return 1;
				}
			}

		}
		else
			fatal("No internal ELF for this shader!");

		return 0;
}
Esempio n. 7
0
static void evg_opencl_kernel_load_metadata(struct evg_opencl_kernel_t *kernel)
{
	char line[MAX_STRING_SIZE];
	char *line_ptrs[MAX_STRING_SIZE];
	int token_count;
	struct evg_opencl_kernel_arg_t *arg;
	struct elf_buffer_t *buffer;

	/* Open as text file */
	buffer = &kernel->metadata_buffer;
	elf_buffer_seek(buffer, 0);
	evg_opencl_debug("Kernel Metadata:\n"); 
	for (;;)
	{
		/* Read line from buffer */
		elf_buffer_read_line(buffer, line, MAX_STRING_SIZE);
		if (!line[0])
			break;
		evg_opencl_debug("\t%s\n", line);

		/* Split line */
		line_ptrs[0] = strtok(line, ":;\n");
		for (token_count = 1; (line_ptrs[token_count] = strtok(NULL, ":\n")); token_count++);

		/* Ignored entries */
		if (!line_ptrs[0] ||
			!strcmp(line_ptrs[0], "ARGSTART") ||
			!strcmp(line_ptrs[0], "version") ||
			!strcmp(line_ptrs[0], "device") ||
			!strcmp(line_ptrs[0], "uniqueid") ||
			!strcmp(line_ptrs[0], "uavid") ||
			!strcmp(line_ptrs[0], "ARGEND"))
			continue;

		/* Image */
		if (!strcmp(line_ptrs[0], "image"))
		{
			/* Create input image argument */
			arg = evg_opencl_kernel_arg_create(line_ptrs[1]);
			arg->kind = EVG_OPENCL_KERNEL_ARG_KIND_IMAGE;
			if (!strcmp(line_ptrs[2], "2D"))
			{
				/* Ignore dimensions for now */
			}
			else if (!strcmp(line_ptrs[2], "3D"))
			{
				/* Ignore dimensions for now */
			}
			else
			{
				fatal("%s: Invalid number of dimensions for OpenCL Image (%s)\n%s",
					__FUNCTION__, line_ptrs[2], evg_err_opencl_param_note);
			}
			
			if (!strcmp(line_ptrs[3], "RO"))
			{
				arg->access_type = EVG_OPENCL_KERNEL_ARG_READ_ONLY;
			}
			else if (!strcmp(line_ptrs[3], "WO"))
			{
				arg->access_type = EVG_OPENCL_KERNEL_ARG_WRITE_ONLY;
			}
			else
			{
				fatal("%s: Invalid memory access type for OpenCL Image (%s)\n%s",
					__FUNCTION__, line_ptrs[3], evg_err_opencl_param_note);
			}
			arg->uav = atoi(line_ptrs[4]);
			arg->mem_scope = EVG_OPENCL_MEM_SCOPE_GLOBAL;

			list_add(kernel->arg_list, arg);

			continue;

		} 

		/* Memory */
		if (!strcmp(line_ptrs[0], "memory"))
		{
			if (!strcmp(line_ptrs[1], "hwprivate"))
			{
				EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(2, "0");
			}
			else if (!strcmp(line_ptrs[1], "hwregion"))
			{
				EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3);
				EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(2, "0");
			}
			else if (!strcmp(line_ptrs[1], "hwlocal"))
			{
				EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3);
				kernel->func_mem_local = atoi(line_ptrs[2]);
			}
			else if (!strcmp(line_ptrs[1], "datareqd"))
			{
				EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(2); 
			}
			else
				EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED(1);

			continue;
		}

		/* Entry 'value'. Format: value:<ArgName>:<DataType>:<Size>:<ConstNum>:<ConstOffset> */
		if (!strcmp(line_ptrs[0], "value"))
		{
			EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(6);
			EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(3, "1");
			EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(4, "1");
			arg = evg_opencl_kernel_arg_create(line_ptrs[1]);
			arg->kind = EVG_OPENCL_KERNEL_ARG_KIND_VALUE;
			list_add(kernel->arg_list, arg);

			continue;
		}

		/* Entry 'pointer'. Format: pointer:<name>:<type>:?:?:<addr>:?:?:<elem_size> */
		if (!strcmp(line_ptrs[0], "pointer"))
		{
			/* APP SDK 2.5 supplies 9 tokens, 2.6 supplies 10 tokens */
			/* Metadata version 3:1:104 (as specified in entry 'version') uses 12 items. */
			if (token_count != 9 && token_count != 10 && token_count != 12)
			{
				EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(10);
			}
			EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(3, "1");
			EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(4, "1");

			/* We don't know what the two last entries are, so make sure that they are
			 * set to 0. If they're not 0, it probably means something important. */
			if (token_count == 12)
			{
				EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(10, "0");
				EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(11, "0");
			}

			arg = evg_opencl_kernel_arg_create(line_ptrs[1]);
			arg->kind = EVG_OPENCL_KERNEL_ARG_KIND_POINTER;

			list_add(kernel->arg_list, arg);
			if (!strcmp(line_ptrs[6], "uav"))
			{
				arg->mem_scope = EVG_OPENCL_MEM_SCOPE_GLOBAL;
				arg->uav = atoi(line_ptrs[7]);
			}
			else if (!strcmp(line_ptrs[6], "hl"))
			{
				arg->mem_scope = EVG_OPENCL_MEM_SCOPE_LOCAL;
				arg->uav = atoi(line_ptrs[7]);
			}
			else if (!strcmp(line_ptrs[6], "hc"))
			{
				arg->mem_scope = EVG_OPENCL_MEM_SCOPE_CONSTANT;
				arg->uav = atoi(line_ptrs[7]);
			}
			else
				EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED(6);

			continue;
		}

		/* Entry 'function'. Format: function:?:<uniqueid> */
		if (!strcmp(line_ptrs[0], "function"))
		{
			EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3);
			EVG_OPENCL_KERNEL_METADATA_NOT_SUPPORTED_NEQ(1, "1");
			kernel->func_uniqueid = atoi(line_ptrs[2]);
			continue;
		}

		/* Entry 'sampler'. Format: sampler:name:ID:location:value.
		 * 'location' is 1 for kernel defined samplers, 0 for kernel argument.
		 * 'value' is bitfield value of sampler (0 if a kernel argument) */
		if (!strcmp(line_ptrs[0], "sampler"))
		{
			/* As far as I can tell, the actual sampler data is stored 
			 * as a value, so adding it to the argument list is not required */
			continue;
		}

		/* Entry 'reflection'. Format: reflection:<arg_id>:<type>
		 * Observed first in version 3:1:104 of metadata.
		 * This entry specifies the type of the argument, as specified in the OpenCL
		 * kernel function header. It is currently ignored, since this information
		 * is extracted from the argument descriptions in 'value' and 'pointer' entries.
		 */
		if (!strcmp(line_ptrs[0], "reflection"))
		{
			EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3);
			continue;
		}

		/* Entry 'privateid'. Format: privateid:<id>
		 * Observed first in version 3:1:104 of metadata. Not sure what this entry is for.
		 */
		if (!strcmp(line_ptrs[0], "privateid"))
		{
			EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(2);
			continue;
		}

		/* Entry 'constarg'. Format: constarg:<arg_id>:<arg_name>
		 * Observed first in version 3:1:104 of metadata. It shows up when an argument
		 * is declared as '__global const'. Entry ignored here. */
		if (!strcmp(line_ptrs[0], "constarg"))
		{
			EVG_OPENCL_KERNEL_METADATA_TOKEN_COUNT(3);
			continue;
		}

		/* Warn about uninterpreted entries */
		warning("kernel '%s': unknown meta data entry '%s'",
			kernel->name, line_ptrs[0]);
	}
}
Esempio n. 8
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");
}
Esempio n. 9
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");
}
Esempio n. 10
0
struct cuda_function_t *cuda_function_create(struct cuda_module_t *module,
	char *func_name)
{
	struct cuda_function_t *function;

	struct elf_file_t *cubin;
	struct elf_section_t *sec;
	struct elf_section_t *func_text_sec;
	struct elf_section_t *func_info_sec;
	char func_text_sec_name[MAX_STRING_SIZE];
	char func_info_sec_name[MAX_STRING_SIZE];
	unsigned char inst_bin_byte;
	char arg_name[MAX_STRING_SIZE];
	int i;

	/* Allocate */
	function = xcalloc(1, sizeof(struct cuda_function_t));

	/* Initialization */
	function->id = list_count(function_list);
	function->name = xstrdup(func_name);
	function->module_id = module->id;

	/* Get cubin */
	cubin = module->elf_file;

	/* Get .text.kernel_name section */
	snprintf(func_text_sec_name, sizeof func_text_sec_name, ".text.%s",
			func_name);
	for (i = 0; i < list_count(cubin->section_list); ++i)
	{
		sec = list_get(cubin->section_list, i);
		if (!strncmp(sec->name, func_text_sec_name, strlen(func_text_sec_name)))
		{
			func_text_sec = list_get(cubin->section_list, i);
			break;
		}
	}
	assert(i < list_count(cubin->section_list));

	/* Get instruction binary */
	function->inst_bin_size = func_text_sec->header->sh_size;
	function->inst_bin = xcalloc(1, function->inst_bin_size);
	for (i = 0; i < function->inst_bin_size; ++i)
	{
		elf_buffer_seek(&(cubin->buffer), func_text_sec->header->sh_offset + i);
		elf_buffer_read(&(cubin->buffer), &inst_bin_byte, 1);
		if (i % 8 == 0 || i % 8 == 1 || i % 8 == 2 || i % 8 == 3)
		{
			function->inst_bin[i / 8] |= (unsigned long long int)(inst_bin_byte)
					<< (i * 8 + 32);
		}
		else
		{
			function->inst_bin[i / 8] |= (unsigned long long int)(inst_bin_byte)
					<< (i * 8 - 32);
		}
	}

	/* Get GPR usage */
	function->num_gpr = func_text_sec->header->sh_info >> 24;

	/* Get .nv.info.kernel_name section */
	snprintf(func_info_sec_name, MAX_STRING_SIZE, ".nv.info.%s",
			function->name);
	for (i = 0; i < list_count(cubin->section_list); ++i)
	{
		sec = list_get(cubin->section_list, i);
		if (!strncmp(sec->name, func_info_sec_name, strlen(func_info_sec_name)))
		{
			func_info_sec = list_get(cubin->section_list, i);
			break;
		}
	}
	assert(i < list_count(cubin->section_list));

	/* Get the number of arguments */
	function->arg_count = ((unsigned char *)func_info_sec->buffer.ptr)[10] / 4;

	/* Create arguments */
	function->arg_array = xcalloc(function->arg_count, 
			sizeof(struct cuda_function_arg_t *));
	for (i = 0; i < function->arg_count; ++i)
	{
		snprintf(arg_name, MAX_STRING_SIZE, "arg_%d", i);
		function->arg_array[i] = cuda_function_arg_create(arg_name);
	}

	/* Add function to function list */
	list_add(function_list, function);

	return function;
}