[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, &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;
>   }
>   
> 


More information about the mesa-dev mailing list