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

Tom Stellard tstellar at kemper.freedesktop.org
Tue Jan 20 16:59:00 UTC 2015


Module: Mesa
Branch: master
Commit: dfdaf3eb7edac939f5d1a32db2968944852b28fa
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=dfdaf3eb7edac939f5d1a32db2968944852b28fa

Author: Tom Stellard <thomas.stellard at amd.com>
Date:   Tue Dec  9 20:03:50 2014 -0500

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()

---

 src/gallium/drivers/radeon/r600_pipe_common.h |    8 ++++
 src/gallium/drivers/radeon/radeon_elf_util.c  |   61 +++++++++++++++++++++++--
 src/gallium/drivers/radeon/radeon_elf_util.h  |   12 ++++-
 src/gallium/drivers/radeonsi/si_compute.c     |    2 +-
 src/gallium/drivers/radeonsi/si_shader.c      |    2 +-
 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 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..fd0632b 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 ccac563..ab83f98 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 f911e1f..20fec84 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 a891bc6..81cb2ef 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;
 }
 




More information about the mesa-commit mailing list