[Mesa-dev] [PATCH] ac: fail shader compilation if libelf is replaced by an incompatible version
Samuel Pitoiset
samuel.pitoiset at gmail.com
Thu Aug 10 09:59:59 UTC 2017
Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
On 08/09/2017 10:34 PM, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> UE4Editor has this issue.
>
> This commit prevents hangs (release build) or assertion failures (debug
> build).
>
> Cc: 17.2 <mesa-stable at 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, §ion_str_index);
>
> while ((section = elf_nextscn(elf, section))) {
> const char *name;
> Elf_Data *section_data = NULL;
> GElf_Shdr section_header;
> if (gelf_getshdr(section, §ion_header) != §ion_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;
> }
>
>
More information about the mesa-dev
mailing list