[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, §ion_header, binary);
+ symbols = elf_getdata(section, section_data);
+ symbol_sh_link = section_header.sh_link;
+ parse_symbol_table(symbols, §ion_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