From: Marek Olšák <marek.ol...@amd.com>

UE4Editor has this issue.

This commit prevents hangs (release build) or assertion failures (debug
build).

Cc: 17.2 <mesa-sta...@lists.freedesktop.org>
---
 src/amd/common/ac_binary.c                          | 12 ++++++++++--
 src/amd/common/ac_binary.h                          |  2 +-
 src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c |  5 ++++-
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/amd/common/ac_binary.c b/src/amd/common/ac_binary.c
index 618b5cf..1bf52c7 100644
--- a/src/amd/common/ac_binary.c
+++ b/src/amd/common/ac_binary.c
@@ -102,59 +102,66 @@ static void parse_relocs(Elf *elf, Elf_Data *relocs, 
Elf_Data *symbols,
                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;
                strncpy(reloc->name, symbol_name, sizeof(reloc->name)-1);
                reloc->name[sizeof(reloc->name)-1] = 0;
        }
 }
 
-void ac_elf_read(const char *elf_data, unsigned elf_size,
+bool ac_elf_read(const char *elf_data, unsigned elf_size,
                 struct ac_shader_binary *binary)
 {
        char *elf_buffer;
        Elf *elf;
        Elf_Scn *section = NULL;
        Elf_Data *symbols = NULL, *relocs = NULL;
        size_t section_str_index;
        unsigned symbol_sh_link = 0;
+       bool success = true;
 
        /* One of the libelf implementations
         * (http://www.mr511.de/software/english.htm) requires calling
         * elf_version() before elf_memory().
         */
        elf_version(EV_CURRENT);
        elf_buffer = MALLOC(elf_size);
        memcpy(elf_buffer, elf_data, elf_size);
 
        elf = elf_memory(elf_buffer, elf_size);
 
        elf_getshdrstrndx(elf, &section_str_index);
 
        while ((section = elf_nextscn(elf, section))) {
                const char *name;
                Elf_Data *section_data = NULL;
                GElf_Shdr section_header;
                if (gelf_getshdr(section, &section_header) != &section_header) {
                        fprintf(stderr, "Failed to read ELF section header\n");
-                       return;
+                       success = false;
+                       break;
                }
                name = elf_strptr(elf, section_str_index, 
section_header.sh_name);
                if (!strcmp(name, ".text")) {
                        section_data = elf_getdata(section, section_data);
                        binary->code_size = section_data->d_size;
                        binary->code = MALLOC(binary->code_size * 
sizeof(unsigned char));
                        memcpy(binary->code, section_data->d_buf, 
binary->code_size);
                } else if (!strcmp(name, ".AMDGPU.config")) {
                        section_data = elf_getdata(section, section_data);
                        binary->config_size = section_data->d_size;
+                       if (!binary->config_size) {
+                               fprintf(stderr, ".AMDGPU.config is empty!\n");
+                               success = false;
+                               break;
+                       }
                        binary->config = MALLOC(binary->config_size * 
sizeof(unsigned char));
                        memcpy(binary->config, section_data->d_buf, 
binary->config_size);
                } else if (!strcmp(name, ".AMDGPU.disasm")) {
                        /* Always read disassembly if it's available. */
                        section_data = elf_getdata(section, section_data);
                        binary->disasm_string = strndup(section_data->d_buf,
                                                        section_data->d_size);
                } else if (!strncmp(name, ".rodata", 7)) {
                        section_data = elf_getdata(section, section_data);
                        binary->rodata_size = section_data->d_size;
@@ -179,20 +186,21 @@ void ac_elf_read(const char *elf_data, unsigned elf_size,
        FREE(elf_buffer);
 
        /* Cache the config size per symbol */
        if (binary->global_symbol_count) {
                binary->config_size_per_symbol =
                        binary->config_size / binary->global_symbol_count;
        } else {
                binary->global_symbol_count = 1;
                binary->config_size_per_symbol = binary->config_size;
        }
+       return success;
 }
 
 const unsigned char *ac_shader_binary_config_start(
        const struct ac_shader_binary *binary,
        uint64_t symbol_offset)
 {
        unsigned i;
        for (i = 0; i < binary->global_symbol_count; ++i) {
                if (binary->global_symbol_offsets[i] == symbol_offset) {
                        unsigned offset = i * binary->config_size_per_symbol;
diff --git a/src/amd/common/ac_binary.h b/src/amd/common/ac_binary.h
index a784a72..45f554e 100644
--- a/src/amd/common/ac_binary.h
+++ b/src/amd/common/ac_binary.h
@@ -76,21 +76,21 @@ struct ac_shader_config {
        unsigned spi_ps_input_ena;
        unsigned spi_ps_input_addr;
        unsigned float_mode;
        unsigned scratch_bytes_per_wave;
 };
 
 /*
  * Parse the elf binary stored in \p elf_data and create a
  * ac_shader_binary object.
  */
-void ac_elf_read(const char *elf_data, unsigned elf_size,
+bool ac_elf_read(const char *elf_data, unsigned elf_size,
                 struct ac_shader_binary *binary);
 
 /**
  * @returns A pointer to the start of the configuration information for
  * the function starting at \p symbol_offset of the binary.
  */
 const unsigned char *ac_shader_binary_config_start(
        const struct ac_shader_binary *binary,
        uint64_t symbol_offset);
 
diff --git a/src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c 
b/src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c
index df37267..7a59c90 100644
--- a/src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c
+++ b/src/gallium/drivers/radeonsi/si_shader_tgsi_setup.c
@@ -141,21 +141,24 @@ unsigned si_llvm_compile(LLVMModuleRef M, struct 
ac_shader_binary *binary,
                                   "LLVM emit error: %s", err);
                FREE(err);
                diag.retval = 1;
                goto out;
        }
 
        /* Extract Shader Code*/
        buffer_size = LLVMGetBufferSize(out_buffer);
        buffer_data = LLVMGetBufferStart(out_buffer);
 
-       ac_elf_read(buffer_data, buffer_size, binary);
+       if (!ac_elf_read(buffer_data, buffer_size, binary)) {
+               fprintf(stderr, "radeonsi: cannot read an ELF shader binary\n");
+               diag.retval = 1;
+       }
 
        /* Clean up */
        LLVMDisposeMemoryBuffer(out_buffer);
 
 out:
        if (diag.retval != 0)
                pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed");
        return diag.retval;
 }
 
-- 
2.7.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to