[Mesa-dev] [PATCH 2/5] radeon: Teach radeon_elf_read() how to parse reloc information v2

Tom Stellard thomas.stellard at amd.com
Thu Jan 15 16:48:06 PST 2015


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, &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,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



More information about the mesa-dev mailing list