summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Stellard <[email protected]>2014-12-09 20:03:50 -0500
committerTom Stellard <[email protected]>2015-01-20 09:55:43 -0500
commitdfdaf3eb7edac939f5d1a32db2968944852b28fa (patch)
tree513e8d60659b1c2309baefc5167d4fdc324e67b5 /src
parent5667aa58c49221a919526db08aab7da5bd2b3a5d (diff)
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()
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/radeon/r600_pipe_common.h8
-rw-r--r--src/gallium/drivers/radeon/radeon_elf_util.c61
-rw-r--r--src/gallium/drivers/radeon/radeon_elf_util.h12
-rw-r--r--src/gallium/drivers/radeonsi/si_compute.c2
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.c2
5 files changed, 78 insertions, 7 deletions
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index 60b8faeb29b..6224668ea6e 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 8cda57afff6..fd0632b7500 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, &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);
+ }
}
diff --git a/src/gallium/drivers/radeon/radeon_elf_util.h b/src/gallium/drivers/radeon/radeon_elf_util.h
index ccac5638310..ab83f98ea69 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
@@ -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,
+ unsigned free_relocs);
+
+/**
+ * Free \p relocs and all member data.
*/
-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);
#endif /* RADEON_ELF_UTIL_H */
diff --git a/src/gallium/drivers/radeonsi/si_compute.c b/src/gallium/drivers/radeonsi/si_compute.c
index f911e1f7620..20fec84ed77 100644
--- a/src/gallium/drivers/radeonsi/si_compute.c
+++ b/src/gallium/drivers/radeonsi/si_compute.c
@@ -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);
}
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index a891bc651d7..81cb2ef31bb 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -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;
}