mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-21 01:38:23 +02:00
nouveau/cubin: use libelf 64 bit instead of gelf
gelf was causing problems on android. We only need 64 bit so gelf should not be need Reviewed-by: Mel Henning <mhenning@darkrefraction.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40686>
This commit is contained in:
parent
21245929fc
commit
87004ffcae
1 changed files with 56 additions and 29 deletions
|
|
@ -9,13 +9,26 @@
|
|||
#include "util/log.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#include <gelf.h>
|
||||
#include <libelf.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* these symbols are not defined in the libelf lib used for android in CI */
|
||||
#ifndef ELF64_ST_VISIBILITY
|
||||
#define ELF64_ST_VISIBILITY(o) ((o)&0x3)
|
||||
#endif
|
||||
#ifndef STB_GLOBAL
|
||||
#define STB_GLOBAL 1
|
||||
#endif
|
||||
#ifndef STT_FUNC
|
||||
#define STT_FUNC 2
|
||||
#endif
|
||||
#ifndef STV_DEFAULT
|
||||
#define STV_DEFAULT 0
|
||||
#endif
|
||||
|
||||
static bool
|
||||
nv_cubin_error(const char *what)
|
||||
{
|
||||
|
|
@ -30,12 +43,12 @@ nv_cubin_module_get_section(struct nv_cubin_module *module,
|
|||
{
|
||||
Elf_Scn *section = NULL;
|
||||
while ((section = elf_nextscn(module->elf, section)) != NULL) {
|
||||
GElf_Shdr header;
|
||||
if (gelf_getshdr(section, &header) != &header)
|
||||
Elf64_Shdr *header = elf64_getshdr(section);
|
||||
if (!header)
|
||||
continue;
|
||||
|
||||
const char *section_name =
|
||||
elf_strptr(module->elf, module->shstrndx, header.sh_name);
|
||||
elf_strptr(module->elf, module->shstrndx, header->sh_name);
|
||||
if (!section_name || !*section_name)
|
||||
continue;
|
||||
|
||||
|
|
@ -194,14 +207,14 @@ static bool
|
|||
nv_cubin_function_init(struct nv_cubin_module *module,
|
||||
struct nv_cubin_function *function,
|
||||
uint32_t symbol_index, const char *symbol_name,
|
||||
GElf_Sym symbol)
|
||||
Elf64_Sym *symbol)
|
||||
{
|
||||
memset(function, 0, sizeof(*function));
|
||||
|
||||
if (symbol.st_size == 0)
|
||||
if (symbol->st_size == 0)
|
||||
return nv_cubin_error("Function with no size!");
|
||||
|
||||
size_t code_section_index = symbol.st_shndx;
|
||||
size_t code_section_index = symbol->st_shndx;
|
||||
if (code_section_index == SHN_UNDEF)
|
||||
return nv_cubin_error("Function with no code section!");
|
||||
|
||||
|
|
@ -209,16 +222,17 @@ nv_cubin_function_init(struct nv_cubin_module *module,
|
|||
if (!code_section)
|
||||
return nv_cubin_error("Function with invalid code section!");
|
||||
|
||||
GElf_Shdr code_section_header;
|
||||
if (gelf_getshdr(code_section, &code_section_header) != &code_section_header)
|
||||
Elf64_Shdr *code_section_header = elf64_getshdr(code_section);
|
||||
|
||||
if (!code_section_header)
|
||||
return nv_cubin_error("Couldn't get code section header");
|
||||
|
||||
Elf_Data *code_section_data = elf_getdata(code_section, NULL);
|
||||
if (!code_section_data)
|
||||
return nv_cubin_error("Couldn't get code section data");
|
||||
|
||||
size_t offset_in_section = symbol.st_value - code_section_header.sh_addr;
|
||||
if (offset_in_section + symbol.st_size > code_section_data->d_size)
|
||||
size_t offset_in_section = symbol->st_value - code_section_header->sh_addr;
|
||||
if (offset_in_section + symbol->st_size > code_section_data->d_size)
|
||||
return nv_cubin_error("Function extends beyond section bounds");
|
||||
|
||||
function->symbol_index = symbol_index;
|
||||
|
|
@ -233,7 +247,7 @@ nv_cubin_function_init(struct nv_cubin_module *module,
|
|||
|
||||
if (module->abi < NV_ELF_OSABI_41) {
|
||||
/* old version has SHF_BARRIERS in .sectionheader */
|
||||
const uint8_t shf_barriers = (code_section_header.sh_flags >> 20) & 0xf;
|
||||
const uint8_t shf_barriers = (code_section_header->sh_flags >> 20) & 0xf;
|
||||
function->num_control_barriers = shf_barriers;
|
||||
}
|
||||
|
||||
|
|
@ -252,19 +266,32 @@ nv_cubin_function_fini(struct nv_cubin_function *function)
|
|||
free(function->param_infos);
|
||||
}
|
||||
|
||||
static Elf64_Sym *
|
||||
nv_cubin_get_symbol(Elf_Data *data, uint32_t index)
|
||||
{
|
||||
Elf64_Sym *symbol = NULL;
|
||||
|
||||
if (index * sizeof(Elf64_Sym) < data->d_size) {
|
||||
Elf64_Sym *symbols = (Elf64_Sym *)data->d_buf;
|
||||
symbol = &symbols[index];
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static bool
|
||||
nv_cubin_module_parse_functions(struct nv_cubin_module *module)
|
||||
{
|
||||
/* Iterate over the symbol table and extract the data about each function. */
|
||||
Elf_Scn *symtab_section = NULL;
|
||||
GElf_Shdr symtab_section_header;
|
||||
Elf64_Shdr *symtab_section_header;
|
||||
while ((symtab_section = elf_nextscn(module->elf, symtab_section)) != NULL) {
|
||||
if (gelf_getshdr(symtab_section, &symtab_section_header) !=
|
||||
&symtab_section_header)
|
||||
symtab_section_header = elf64_getshdr(symtab_section);
|
||||
if (!symtab_section_header)
|
||||
return nv_cubin_error("Couldn't get section header");
|
||||
|
||||
/* We only care about symbol tables. */
|
||||
if (symtab_section_header.sh_type != SHT_SYMTAB)
|
||||
if (symtab_section_header->sh_type != SHT_SYMTAB)
|
||||
continue;
|
||||
|
||||
Elf_Data *symtab_data = elf_getdata(symtab_section, NULL);
|
||||
|
|
@ -272,21 +299,21 @@ nv_cubin_module_parse_functions(struct nv_cubin_module *module)
|
|||
return nv_cubin_error("Couldn't get .symtab section data");
|
||||
|
||||
uint32_t num_symbols =
|
||||
symtab_section_header.sh_size / symtab_section_header.sh_entsize;
|
||||
symtab_section_header->sh_size / symtab_section_header->sh_entsize;
|
||||
for (uint32_t i = 0; i < num_symbols; i++) {
|
||||
GElf_Sym symbol;
|
||||
if (gelf_getsym(symtab_data, i, &symbol) != &symbol)
|
||||
Elf64_Sym *symbol = nv_cubin_get_symbol(symtab_data, i);
|
||||
if (!symbol)
|
||||
return nv_cubin_error("Couldn't get symbol");
|
||||
|
||||
char *symbol_name = elf_strptr(
|
||||
module->elf, symtab_section_header.sh_link, symbol.st_name);
|
||||
module->elf, symtab_section_header->sh_link, symbol->st_name);
|
||||
/* We don't care about any unnamed functions. */
|
||||
if (!symbol_name || symbol_name[0] == '\0')
|
||||
continue;
|
||||
|
||||
if (GELF_ST_TYPE(symbol.st_info) != STT_FUNC ||
|
||||
GELF_ST_BIND(symbol.st_info) != STB_GLOBAL ||
|
||||
GELF_ST_VISIBILITY(symbol.st_other) != STV_DEFAULT)
|
||||
if (ELF64_ST_TYPE(symbol->st_info) != STT_FUNC ||
|
||||
ELF64_ST_BIND(symbol->st_info) != STB_GLOBAL ||
|
||||
ELF64_ST_VISIBILITY(symbol->st_other) != STV_DEFAULT)
|
||||
continue;
|
||||
|
||||
uint32_t function_idx = module->function_count++;
|
||||
|
|
@ -322,20 +349,20 @@ nv_cubin_module_init(struct nv_cubin_module *module, const void *data,
|
|||
if (elf_getshdrstrndx(module->elf, &module->shstrndx) != 0)
|
||||
return nv_cubin_error("Couldn't get section header string table index");
|
||||
|
||||
GElf_Ehdr ehdr;
|
||||
if (gelf_getehdr(module->elf, &ehdr) != &ehdr)
|
||||
Elf64_Ehdr *ehdr = elf64_getehdr(module->elf);
|
||||
if (!ehdr)
|
||||
return nv_cubin_error("Failed to get elf header");
|
||||
|
||||
if (ehdr.e_machine != 190 /* EM_CUDA */)
|
||||
if (ehdr->e_machine != 190 /* EM_CUDA */)
|
||||
return nv_cubin_error("ELF is not targeting Cuda");
|
||||
|
||||
module->abi = ehdr.e_ident[EI_OSABI];
|
||||
module->abi = ehdr->e_ident[EI_OSABI];
|
||||
|
||||
/* new version encodes e_flags differently... */
|
||||
if (module->abi >= NV_ELF_OSABI_41)
|
||||
module->sm = (ehdr.e_flags >> 8) & 0xFF;
|
||||
module->sm = (ehdr->e_flags >> 8) & 0xFF;
|
||||
else
|
||||
module->sm = (ehdr.e_flags >> 16) & 0xFF;
|
||||
module->sm = (ehdr->e_flags >> 16) & 0xFF;
|
||||
|
||||
if (!nv_cubin_module_parse_functions(module))
|
||||
return nv_cubin_error("Couldn't parse functions");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue