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"); }
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; } }
/* 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"); }
/* 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; }
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); } }
/* 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; }
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]); } }
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"); }
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"); }
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; }