[Mesa-dev] [PATCH 1/4] radeon: Teach radeon_elf_read() how to parse reloc information

Tom Stellard thomas.stellard at amd.com
Wed Jan 7 13:03:42 PST 2015


---
 src/gallium/drivers/radeon/r600_pipe_common.h |  8 +++++
 src/gallium/drivers/radeon/radeon_elf_util.c  | 44 +++++++++++++++++++++++++--
 2 files changed, 49 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 ec39a89..85d0375 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,34 @@ 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;
+		unsigned offset;
+		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 = MALLOC(strlen(symbol_name) + 1);
+		strcpy(reloc->name, symbol_name);
+	}
+}
+
 void radeon_elf_read(const char *elf_data, unsigned elf_size,
 					struct radeon_shader_binary *binary,
 					unsigned debug)
@@ -82,7 +111,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 +159,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);
 	}
-- 
1.8.5.5



More information about the mesa-dev mailing list