radeon: Teach radeon_elf_read() how to parse reloc information v3

v2:
  - Use strdup for copying reloc names.
  - Free reloc memory.

v3:
  - Add free_relocs parameter to radeon_shader_binary_free_members()
This commit is contained in:
Tom Stellard 2014-12-09 20:03:50 -05:00
parent 5667aa58c4
commit dfdaf3eb7e
5 changed files with 78 additions and 7 deletions

View file

@ -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;

View file

@ -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, &section_header, binary);
symbols = elf_getdata(section, section_data);
symbol_sh_link = section_header.sh_link;
parse_symbol_table(symbols, &section_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,25 @@ const unsigned char *radeon_shader_binary_config_start(
return binary->config;
}
void radeon_shader_binary_free_members(struct radeon_shader_binary *binary) {
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,
unsigned free_relocs)
{
FREE(binary->code);
FREE(binary->config);
FREE(binary->rodata);
if (free_relocs) {
radeon_shader_binary_free_relocs(binary->relocs,
binary->reloc_count);
}
}

View file

@ -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
@ -49,6 +50,15 @@ const unsigned char *radeon_shader_binary_config_start(
/**
* Free all memory allocated for members of \p binary. This function does
* not free \p binary.
*
* @param free_relocs If false, reolc information will not be freed.
*/
void radeon_shader_binary_free_members(struct radeon_shader_binary *binary);
void radeon_shader_binary_free_members(struct radeon_shader_binary *binary,
unsigned free_relocs);
/**
* 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 */

View file

@ -439,7 +439,7 @@ static void si_delete_compute_state(struct pipe_context *ctx, void* state){
pipe_resource_reference(
(struct pipe_resource **)&program->input_buffer, NULL);
radeon_shader_binary_free_members(&program->binary);
radeon_shader_binary_free_members(&program->binary, true);
FREE(program);
}

View file

@ -2621,7 +2621,7 @@ int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader,
return r;
}
r = si_shader_binary_read(sscreen, shader, &binary);
radeon_shader_binary_free_members(&binary);
radeon_shader_binary_free_members(&binary, true);
return r;
}