v2: - Use strdup for copying reloc names. - Free reloc memory. --- src/gallium/drivers/radeon/r600_pipe_common.h | 8 ++++ src/gallium/drivers/radeon/radeon_elf_util.c | 53 +++++++++++++++++++++++++-- src/gallium/drivers/radeon/radeon_elf_util.h | 7 ++++ 3 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index 60b8fae..6224668 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -89,6 +89,11 @@ struct r600_common_context; +struct radeon_shader_reloc { + char *name; + uint64_t offset; +}; + struct radeon_shader_binary { /** Shader code */ unsigned char *code; @@ -113,6 +118,9 @@ struct radeon_shader_binary { uint64_t *global_symbol_offsets; unsigned global_symbol_count; + struct radeon_shader_reloc *relocs; + unsigned reloc_count; + /** Set to 1 if the disassembly for this binary has been dumped to * stderr. */ int disassembled; diff --git a/src/gallium/drivers/radeon/radeon_elf_util.c b/src/gallium/drivers/radeon/radeon_elf_util.c index 8cda57a..9e8c53f 100644 --- a/src/gallium/drivers/radeon/radeon_elf_util.c +++ b/src/gallium/drivers/radeon/radeon_elf_util.c @@ -53,7 +53,8 @@ static void parse_symbol_table(Elf_Data *symbol_table_data, while (gelf_getsym(symbol_table_data, i++, &symbol)) { unsigned i; - if (GELF_ST_BIND(symbol.st_info) != STB_GLOBAL) { + if (GELF_ST_BIND(symbol.st_info) != STB_GLOBAL || + symbol.st_shndx == 0 /* Undefined symbol */) { continue; } @@ -75,6 +76,32 @@ static void parse_symbol_table(Elf_Data *symbol_table_data, } } +static void parse_relocs(Elf *elf, Elf_Data *relocs, Elf_Data *symbols, + unsigned symbol_sh_link, + struct radeon_shader_binary *binary) +{ + unsigned i; + + if (!relocs || !symbols || !binary->reloc_count) { + return; + } + binary->relocs = CALLOC(binary->reloc_count, + sizeof(struct radeon_shader_reloc)); + for (i = 0; i < binary->reloc_count; i++) { + GElf_Sym symbol; + GElf_Rel rel; + char *symbol_name; + struct radeon_shader_reloc *reloc = &binary->relocs[i]; + + gelf_getrel(relocs, i, &rel); + gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &symbol); + symbol_name = elf_strptr(elf, symbol_sh_link, symbol.st_name); + + reloc->offset = rel.r_offset; + reloc->name = strdup(symbol_name); + } +} + void radeon_elf_read(const char *elf_data, unsigned elf_size, struct radeon_shader_binary *binary, unsigned debug) @@ -82,7 +109,9 @@ void radeon_elf_read(const char *elf_data, unsigned elf_size, char *elf_buffer; Elf *elf; Elf_Scn *section = NULL; + Elf_Data *symbols = NULL, *relocs = NULL; size_t section_str_index; + unsigned symbol_sh_link; /* One of the libelf implementations * (http://www.mr511.de/software/english.htm) requires calling @@ -128,11 +157,18 @@ void radeon_elf_read(const char *elf_data, unsigned elf_size, binary->rodata = MALLOC(binary->rodata_size * sizeof(unsigned char)); memcpy(binary->rodata, section_data->d_buf, binary->rodata_size); } else if (!strncmp(name, ".symtab", 7)) { - section_data = elf_getdata(section, section_data); - parse_symbol_table(section_data, §ion_header, binary); + symbols = elf_getdata(section, section_data); + symbol_sh_link = section_header.sh_link; + parse_symbol_table(symbols, §ion_header, binary); + } else if (!strcmp(name, ".rel.text")) { + relocs = elf_getdata(section, section_data); + binary->reloc_count = section_header.sh_size / + section_header.sh_entsize; } } + parse_relocs(elf, relocs, symbols, symbol_sh_link, binary); + if (elf){ elf_end(elf); } @@ -162,8 +198,19 @@ const unsigned char *radeon_shader_binary_config_start( return binary->config; } +void radeon_shader_binary_free_relocs(struct radeon_shader_reloc *relocs, + unsigned reloc_count) +{ + unsigned i; + for (i = 0; i < reloc_count; i++) { + FREE(relocs[i].name); + } + FREE(relocs); +} + void radeon_shader_binary_free_members(struct radeon_shader_binary *binary) { FREE(binary->code); FREE(binary->config); FREE(binary->rodata); + radeon_shader_binary_free_relocs(binary->relocs, binary->reloc_count); } diff --git a/src/gallium/drivers/radeon/radeon_elf_util.h b/src/gallium/drivers/radeon/radeon_elf_util.h index ccac563..cff07f2 100644 --- a/src/gallium/drivers/radeon/radeon_elf_util.h +++ b/src/gallium/drivers/radeon/radeon_elf_util.h @@ -30,6 +30,7 @@ #include <stdint.h> struct radeon_shader_binary; +struct radeon_shader_reloc; /* * Parse the elf binary stored in \p elf_data and create a @@ -51,4 +52,10 @@ const unsigned char *radeon_shader_binary_config_start( * not free \p binary. */ void radeon_shader_binary_free_members(struct radeon_shader_binary *binary); + +/** + * Free \p relocs and all member data. + */ +void radeon_shader_binary_free_relocs(struct radeon_shader_reloc *relocs, + unsigned reloc_count); #endif /* RADEON_ELF_UTIL_H */ -- 1.8.5.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev