mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-11 12:20:15 +01:00
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()
This commit is contained in:
parent
5667aa58c4
commit
dfdaf3eb7e
5 changed files with 78 additions and 7 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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, §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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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_relocs(struct radeon_shader_reloc *relocs,
|
||||
unsigned reloc_count);
|
||||
#endif /* RADEON_ELF_UTIL_H */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue