static void resolve_relocations(sym_strtab **list) { Elf_Scn *scn; Elf64_Shdr *shdr; scn = NULL; while ((scn = elf_nextscn(e, scn))) { if ((shdr = elf64_getshdr(scn)) == NULL) exit_error("gelf_getshdr() fail"); if (shdr->sh_type == SHT_DYNSYM) { Elf_Data *data; data = elf_getdata(scn, NULL); dynsym_tab = (Elf64_Sym*)data->d_buf; } if (shdr->sh_type == SHT_STRTAB && shdr->sh_flags == SHF_ALLOC) { Elf_Data *data; data = elf_getdata(scn, NULL); dynsym_strtab = (char*)data->d_buf; } } if (!dynsym_tab) return; scn = NULL; while ((scn = elf_nextscn(e, scn))) { if ((shdr = elf64_getshdr(scn)) == NULL) exit_error("gelf_getshdr() fail"); if (shdr->sh_type == SHT_RELA) reloc_treatment(scn, shdr, list); } }
int ElfWriter::newSection(LIBDWARF_CALLBACK_NAME_TYPE name, uint64_t size, uint32_t type, uint64_t flags, uint64_t addr/* = 0*/) { Elf_Scn *scn = elf_newscn(m_elf); if (!scn) { logError("Unable to create new section"); return -1; } Elf64_Shdr *sectionHdr = elf64_getshdr(scn); if (!sectionHdr) { logError("Unable to create section header"); return -1; } int nameOffset = addSectionString(name); sectionHdr->sh_name = nameOffset; sectionHdr->sh_type = type; sectionHdr->sh_flags = flags; sectionHdr->sh_size = size; sectionHdr->sh_addr = addr; sectionHdr->sh_offset = 0; sectionHdr->sh_link = 0; sectionHdr->sh_info = 0; sectionHdr->sh_addralign = 1; sectionHdr->sh_entsize = 0; return elf_ndxscn(scn); }
static struct code_template* function_template_load64(Elf* e, Elf64_Sym* func64) { Elf_Scn* scn = elf_getscn(e, func64->st_shndx); assert(scn); Elf64_Shdr* shdr64 = elf64_getshdr(scn); assert(shdr64); return ct_load(e, scn, func64->st_value, func64->st_size, shdr64->sh_addralign); }
Elf_Scn* getSection(Elf *elf,const char *name) { Elf64_Ehdr *ehdr = elf64_getehdr(elf); if(!ehdr) return NULL; Elf_Data *data = elf_getdata(elf_getscn(elf,ehdr->e_shstrndx),NULL); if(!data) return NULL; for(Elf_Scn *scn = NULL;(scn = elf_nextscn(elf,scn));) { Elf64_Shdr *shdr = elf64_getshdr(scn); if(shdr && !strcmp(name,(const char*)data->d_buf + shdr->sh_name)) return scn; } return NULL; }
static void load_symtab(sym_strtab **list, Elf_Scn *sym_scn) { Elf_Data *data; size_t nb_symbols; sym_shdr = elf64_getshdr(sym_scn); data = elf_getdata(sym_scn, NULL); symtab = (Elf64_Sym*)data->d_buf; nb_symbols = sym_shdr->sh_size / sym_shdr->sh_entsize; for (size_t i = 0; i < nb_symbols; ++i) if (ELF64_ST_TYPE(symtab[i].st_info) == STT_FUNC || ELF64_ST_TYPE(symtab[i].st_info) == STT_NOTYPE) add_symbol(list, symtab[i].st_value, elf_strptr(e, sym_shdr->sh_link, symtab[i].st_name)); }
static Elf_Scn *get_sym_shdr(void) { Elf_Scn *scn; Elf64_Shdr *shdr; scn = NULL; while ((scn = elf_nextscn(e, scn))) { if ((shdr = elf64_getshdr(scn)) == NULL) exit_error("gelf_getshdr() fail"); if (shdr->sh_type == SHT_SYMTAB) break; } if (!scn) exit_error("symtab not found omg"); return scn; }
int write_shdr(elf_data_t *elf, Elf_Scn *scn, GElf_Shdr *shdr, size_t sidx, char **err) { off_t off; size_t n, shdr_size; void *shdr_buf; if(!gelf_update_shdr(scn, shdr)) { (*err) = "failed to update section header"; return -1; } if(elf->bits == 32) { shdr_buf = elf32_getshdr(scn); shdr_size = sizeof(Elf32_Shdr); } else { shdr_buf = elf64_getshdr(scn); shdr_size = sizeof(Elf64_Shdr); } if(!shdr_buf) { (*err) = "failed to get section header"; return -1; } off = lseek(elf->fd, elf->ehdr.e_shoff + sidx*elf->ehdr.e_shentsize, SEEK_SET); if(off < 0) { (*err) = "lseek failed"; return -1; } n = write(elf->fd, shdr_buf, shdr_size); if(n != shdr_size) { (*err) = "write failed"; return -1; } return 0; }
int xlate_named_init_elf(Elf * elf, const char *section_name, xlate_table_con * ret_tab_ptr) { int retstatus = XLATE_TB_STATUS_NO_ERROR; xlate_table_con newtab = 0; Elf_Scn *scn = 0; int is64bit = 0; char *ident; size_t identsize; Elf_Scn *xlscn = 0; Elf64_Shdr *shdr64 = 0; Elf32_Shdr *shdr32 = 0; Elf32_Ehdr *ehdr32 = 0; Elf64_Ehdr *ehdr64 = 0; Elf_Data *xlatedata = 0; int stringindex = 0; char * sec_name; if(elf_kind(elf) != ELF_K_ELF) { return XLATE_TB_STATUS_NOT_ELF; } ident = elf_getident(elf,&identsize); if(ident == 0 || identsize < EI_NIDENT) { return XLATE_TB_STATUS_ELF_IDENT_BAD; } if(ident[EI_CLASS] == ELFCLASS64) { is64bit = 1; } if(is64bit) { ehdr64 = elf64_getehdr(elf); if(ehdr64 == 0 ) { return XLATE_TB_STATUS_ELF_EHDR_BAD; } stringindex = ehdr64->e_shstrndx; } else { ehdr32 = elf32_getehdr(elf); if(ehdr32 == 0 ) { return XLATE_TB_STATUS_ELF_EHDR_BAD; } stringindex = ehdr32->e_shstrndx; } for(scn = elf_nextscn(elf,scn); scn != 0 && xlscn == 0 ; scn = elf_nextscn(elf,scn)) { if(is64bit) { shdr64 = elf64_getshdr(scn); if(shdr64 == 0) { return XLATE_TB_STATUS_ELF_SHDR_BAD; } sec_name = elf_strptr(elf,stringindex,shdr64->sh_name); if(sec_name == 0) { return XLATE_TB_STATUS_ELF_STRPTR_BAD; } if(shdr64->sh_type != SHT_MIPS_XLATE && shdr64->sh_type != SHT_MIPS_XLATE_DEBUG && shdr64->sh_type != SHT_MIPS_XLATE_OLD ) { continue; } if(!streq(section_name,sec_name)) { continue; } xlscn = scn; break; } else { shdr32 = elf32_getshdr(scn); if(shdr32 == 0) { return XLATE_TB_STATUS_ELF_SHDR_BAD; } sec_name = elf_strptr(elf,stringindex,shdr32->sh_name); if(sec_name == 0) { return XLATE_TB_STATUS_ELF_STRPTR_BAD; } if(shdr32->sh_type != SHT_MIPS_XLATE && shdr32->sh_type != SHT_MIPS_XLATE_DEBUG && shdr32->sh_type != SHT_MIPS_XLATE_OLD ) { continue; } if(!streq(section_name,sec_name)) { continue; } xlscn = scn; break; } } if(xlscn == 0) { return XLATE_TB_STATUS_NO_XLATE; } xlatedata = elf_getdata(xlscn,NULL); if(xlatedata == NULL || xlatedata->d_size == 0) { return XLATE_TB_STATUS_NO_XLATE_DATA; } newtab = (xlate_table_con)malloc(sizeof(struct xlate_table_con_s)); if(newtab == NULL) { return XLATE_TB_STATUS_ALLOC_FAIL; } bzero(newtab,sizeof(struct xlate_table_con_s)); newtab->xc_elf = elf; newtab->xc_section_data = xlatedata->d_buf; newtab->xc_data_size = xlatedata->d_size; if(newtab->xc_data_size != xlatedata->d_size) { /* we have a gigantic section and are compiled only 32 bit. ** we simply cannot handle and I don't think the ** mmap would have worked anyway so we cannot really ** get here. */ free(newtab); return XLATE_TB_STATUS_SECTION_TOO_BIG; } retstatus = _xlate_fill_in_table_data(newtab,is64bit); if(retstatus != XLATE_TB_STATUS_NO_ERROR) { free(newtab); return retstatus; } newtab->xc_valid_table = VALID_TABLE_MAGIC; *ret_tab_ptr = newtab; return retstatus; }
static void print_relocinfo_64 (Dwarf_Debug dbg, Elf *elf) { #ifdef HAVE_ELF64_GETEHDR Elf_Scn *scn = NULL; Elf_Data *data; Elf64_Ehdr *ehdr64; Elf64_Shdr *shdr64; char *scn_name; int i; if ((ehdr64 = elf64_getehdr(elf)) == NULL) { print_error(dbg, "DW_ELF_GETEHDR_ERROR",DW_DLV_OK, err); } while ((scn = elf_nextscn(elf, scn)) != NULL) { if ((shdr64 = elf64_getshdr(scn)) == NULL) { print_error(dbg, "DW_ELF_GETSHDR_ERROR",DW_DLV_OK, err); } if ((scn_name = elf_strptr(elf,ehdr64->e_shstrndx, shdr64->sh_name)) == NULL) { print_error(dbg, "DW_ELF_STRPTR_ERROR",DW_DLV_OK, err); } if (shdr64->sh_type == SHT_SYMTAB) { size_t sym_size = 0; size_t count = 0; if ((sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size)) == NULL) { print_error(dbg, "no symbol table data",DW_DLV_OK, err); } count = sym_size / sizeof (Elf64_Sym); sym_64 ++; if ((sym_data_64 = read_64_syms(sym_64, count, elf, shdr64->sh_link)) == NULL) { print_error(dbg, "problem reading symbol table data",DW_DLV_OK, err); } } else if (strncmp(scn_name, ".rel.debug_", 11)) continue; else if (strcmp(scn_name, ".rel.debug_info") == 0) { SECT_DATA_SET(DW_SECTION_REL_DEBUG_INFO) } else if (strcmp(scn_name, ".rel.debug_line") == 0) { SECT_DATA_SET(DW_SECTION_REL_DEBUG_LINE) } else if (strcmp(scn_name, ".rel.debug_pubname") == 0) { SECT_DATA_SET(DW_SECTION_REL_DEBUG_PUBNAME) } else if (strcmp(scn_name, ".rel.debug_aranges") == 0) { SECT_DATA_SET(DW_SECTION_REL_DEBUG_ARANGES) } else if (strcmp(scn_name, ".rel.debug_abbrev") == 0) { SECT_DATA_SET(DW_SECTION_REL_DEBUG_ABBREV) } else if (strcmp(scn_name, ".rel.debug_frame") == 0) { SECT_DATA_SET(DW_SECTION_REL_DEBUG_FRAME) } } /* while */ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i ++) { if (sect_data[i].buf != NULL && sect_data[i].size > 0) { print_reloc_information_64(i, sect_data[i].buf, sect_data[i].size); } } #endif }
/* Given an Elf ptr, set up dbg with pointers to all the Dwarf data sections. Return NULL on error. This function is also responsible for determining whether the given object contains Dwarf information or not. The test currently used is that it contains either a .debug_info or a .debug_frame section. If not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to return DW_DLV_NO_ENTRY. Earlier, we had thought of using only the presence/absence of .debug_info to test, but we added .debug_frame since there could be stripped objects that have only a .debug_frame section for exception processing. DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR */ static int _dwarf_setup(Dwarf_Debug dbg, dwarf_elf_handle elf, Dwarf_Error * error) { #ifdef __SGI_FAST_LIBELF Elf64_Ehdr ehdr; Elf64_Shdr shdr; enum elf_sgi_error_type sres; unsigned char const* ehdr_ident; #else Elf32_Ehdr *ehdr32; #ifdef HAVE_ELF64_GETEHDR Elf64_Ehdr *ehdr64; #endif Elf32_Shdr *shdr32; #ifdef HAVE_ELF64_GETSHDR Elf64_Shdr *shdr64; #endif Elf_Scn *scn; char *ehdr_ident; #endif /* !defined(__SGI_FAST_LIBELF) */ Dwarf_Half machine; char *scn_name; int is_64bit; int foundDwarf; Dwarf_Unsigned section_size; Dwarf_Unsigned section_count; Dwarf_Half section_index; foundDwarf = FALSE; dbg->de_elf = elf; dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad; #ifdef __SGI_FAST_LIBELF sres = elf_sgi_ehdr(elf, &ehdr); if (sres != ELF_SGI_ERROR_OK) { DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres), DW_DLV_ERROR); } ehdr_ident = ehdr.e_ident; section_count = ehdr.e_shnum; machine = ehdr.e_machine; #else if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETIDENT_ERROR, DW_DLV_ERROR); } #endif is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64); dbg->de_same_endian = 1; dbg->de_copy_word = memcpy; #ifdef WORDS_BIGENDIAN dbg->de_big_endian_object = 1; if (ehdr_ident[EI_DATA] == ELFDATA2LSB) { dbg->de_same_endian = 0; dbg->de_big_endian_object = 0; dbg->de_copy_word = _dwarf_memcpy_swap_bytes; } #else /* little endian */ dbg->de_big_endian_object = 0; if (ehdr_ident[EI_DATA] == ELFDATA2MSB) { dbg->de_same_endian = 0; dbg->de_big_endian_object = 1; dbg->de_copy_word = _dwarf_memcpy_swap_bytes; } #endif /* !WORDS_BIGENDIAN */ /* The following de_length_size is Not Too Significant. Only used one calculation, and an appoximate one at that. */ dbg->de_length_size = is_64bit ? 8 : 4; dbg->de_pointer_size = is_64bit ? 8 : 4; #ifdef __SGI_FAST_LIBELF /* We've already loaded the ELF header, so there's nothing to do here */ #else #ifdef HAVE_ELF64_GETEHDR if (is_64bit) { ehdr64 = elf64_getehdr(elf); if (ehdr64 == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR, DW_DLV_ERROR); } section_count = ehdr64->e_shnum; machine = ehdr64->e_machine; } else #endif { ehdr32 = elf32_getehdr(elf); if (ehdr32 == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR, DW_DLV_ERROR); } section_count = ehdr32->e_shnum; machine = ehdr32->e_machine; } #endif /* !defined(__SGI_FAST_LIBELF) */ if (is_64bit && machine != EM_MIPS) { /* MIPS/IRIX makes pointer size and length size 8 for -64. Other platforms make length 4 always. */ /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus tools, and the dwarfv2.1 64bit extension setting. */ dbg->de_length_size = 4; } /* We start at index 1 to skip the initial empty section. */ for (section_index = 1; section_index < section_count; ++section_index) { #ifdef __SGI_FAST_LIBELF sres = elf_sgi_shdr(elf, section_index, &shdr); if (sres != ELF_SGI_ERROR_OK) { DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres), DW_DLV_ERROR); } section_size = shdr.sh_size; sres = elf_sgi_string(elf, ehdr.e_shstrndx, shdr.sh_name, (char const** )&scn_name); if (sres != ELF_SGI_ERROR_OK) { DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres), DW_DLV_ERROR); } #else /* !defined(__SGI_FAST_LIBELF) */ scn = elf_getscn(elf, section_index); if (scn == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_MDE, DW_DLV_ERROR); } #ifdef HAVE_ELF64_GETSHDR if (is_64bit) { shdr64 = elf64_getshdr(scn); if (shdr64 == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR, DW_DLV_ERROR); } section_size = shdr64->sh_size; if ((scn_name = elf_strptr(elf, ehdr64->e_shstrndx, shdr64->sh_name)) == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR, DW_DLV_ERROR); } } else #endif /* HAVE_ELF64_GETSHDR */ { if ((shdr32 = elf32_getshdr(scn)) == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR, 0); } section_size = shdr32->sh_size; if ((scn_name = elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name)) == NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR, DW_DLV_ERROR); } } #endif /* !defined(__SGI_FAST_LIBELF) */ if (strncmp(scn_name, ".debug_", 7) && strcmp(scn_name, ".eh_frame") ) continue; else if (strcmp(scn_name, ".debug_info") == 0) { if (dbg->de_debug_info != NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* Know no reason to allow empty debug_info section */ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_NULL, DW_DLV_ERROR); } foundDwarf = TRUE; dbg->de_debug_info_index = section_index; dbg->de_debug_info_size = section_size; } else if (strcmp(scn_name, ".debug_abbrev") == 0) { if (dbg->de_debug_abbrev != NULL) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* Know no reason to allow empty debug_abbrev section */ DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_NULL, DW_DLV_ERROR); } dbg->de_debug_abbrev_index = section_index; dbg->de_debug_abbrev_size = section_size; } else if (strcmp(scn_name, ".debug_aranges") == 0) { if (dbg->de_debug_aranges_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ARANGES_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_aranges_index = section_index; dbg->de_debug_aranges_size = section_size; } else if (strcmp(scn_name, ".debug_line") == 0) { if (dbg->de_debug_line_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_LINE_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_line_index = section_index; dbg->de_debug_line_size = section_size; } else if (strcmp(scn_name, ".debug_frame") == 0) { if (dbg->de_debug_frame_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_FRAME_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_frame_index = section_index; dbg->de_debug_frame_size = section_size; foundDwarf = TRUE; } else if (strcmp(scn_name, ".eh_frame") == 0) { /* gnu egcs-1.1.2 data */ if (dbg->de_debug_frame_eh_gnu_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_FRAME_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_frame_eh_gnu_index = section_index; dbg->de_debug_frame_size_eh_gnu = section_size; foundDwarf = TRUE; } else if (strcmp(scn_name, ".debug_loc") == 0) { if (dbg->de_debug_loc_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_LOC_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_loc_index = section_index; dbg->de_debug_loc_size = section_size; } else if (strcmp(scn_name, ".debug_pubnames") == 0) { if (dbg->de_debug_pubnames_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_PUBNAMES_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_pubnames_index = section_index; dbg->de_debug_pubnames_size = section_size; } else if (strcmp(scn_name, ".debug_str") == 0) { if (dbg->de_debug_str_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_STR_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_str_index = section_index; dbg->de_debug_str_size = section_size; } else if (strcmp(scn_name, ".debug_funcnames") == 0) { if (dbg->de_debug_funcnames_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_FUNCNAMES_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_funcnames_index = section_index; dbg->de_debug_funcnames_size = section_size; } else if (strcmp(scn_name, ".debug_typenames") == 0) { if (dbg->de_debug_typenames_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_TYPENAMES_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_typenames_index = section_index; dbg->de_debug_typenames_size = section_size; } else if (strcmp(scn_name, ".debug_varnames") == 0) { if (dbg->de_debug_varnames_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_VARNAMES_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_varnames_index = section_index; dbg->de_debug_varnames_size = section_size; } else if (strcmp(scn_name, ".debug_weaknames") == 0) { if (dbg->de_debug_weaknames_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_WEAKNAMES_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_weaknames_index = section_index; dbg->de_debug_weaknames_size = section_size; } else if (strcmp(scn_name, ".debug_macinfo") == 0) { if (dbg->de_debug_macinfo_index != 0) { DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_MACINFO_DUPLICATE, DW_DLV_ERROR); } if (section_size == 0) { /* a zero size section is just empty. Ok, no error */ continue; } dbg->de_debug_macinfo_index = section_index; dbg->de_debug_macinfo_size = section_size; } } if (foundDwarf) { return DW_DLV_OK; } return (DW_DLV_NO_ENTRY); }
int xlate_init_elf(Elf * elf, int open_debug_table, xlate_table_con * ret_tab_ptr) { int res; Elf32_Word wanttype; Elf_Scn *scn = 0; int is64bit = 0; char *ident; size_t identsize; Elf64_Shdr *shdr64 = 0; Elf32_Shdr *shdr32 = 0; Elf32_Ehdr *ehdr32 = 0; Elf64_Ehdr *ehdr64 = 0; int stringindex = 0; char * sec_name; if(elf_kind(elf) != ELF_K_ELF) { return XLATE_TB_STATUS_NOT_ELF; } ident = elf_getident(elf,&identsize); if(open_debug_table == XLATE_OPEN_STD_TABLE) { /* we take the first SHT_MIPS_XLATE*/ wanttype = SHT_MIPS_XLATE; } else if(open_debug_table == XLATE_OPEN_DEBUG_TABLE) { /* we take the first SHT_MIPS_XLATE_DEBUG */ wanttype = SHT_MIPS_XLATE_DEBUG; } else { return XLATE_TB_STATUS_NO_XLATE; } res = XLATE_TB_STATUS_NO_XLATE; if(ident == 0 || identsize < EI_NIDENT) { return XLATE_TB_STATUS_ELF_IDENT_BAD; } if(ident[EI_CLASS] == ELFCLASS64) { is64bit = 1; } if(is64bit) { ehdr64 = elf64_getehdr(elf); if(ehdr64 == 0 ) { return XLATE_TB_STATUS_ELF_EHDR_BAD; } stringindex = ehdr64->e_shstrndx; } else { ehdr32 = elf32_getehdr(elf); if(ehdr32 == 0 ) { return XLATE_TB_STATUS_ELF_EHDR_BAD; } stringindex = ehdr32->e_shstrndx; } for(scn = elf_nextscn(elf,scn); scn != 0 ; scn = elf_nextscn(elf,scn)) { if(is64bit) { shdr64 = elf64_getshdr(scn); if(shdr64 == 0) { return XLATE_TB_STATUS_ELF_SHDR_BAD; } sec_name = elf_strptr(elf,stringindex,shdr64->sh_name); if(sec_name == 0) { return XLATE_TB_STATUS_ELF_STRPTR_BAD; } if(shdr64->sh_type != wanttype) { continue; } res = xlate_named_init_elf(elf, sec_name,ret_tab_ptr); return res; } else { shdr32 = elf32_getshdr(scn); if(shdr32 == 0) { return XLATE_TB_STATUS_ELF_SHDR_BAD; } sec_name = elf_strptr(elf,stringindex,shdr32->sh_name); if(sec_name == 0) { return XLATE_TB_STATUS_ELF_STRPTR_BAD; } if(shdr32->sh_type != wanttype) { continue; } res = xlate_named_init_elf(elf, sec_name,ret_tab_ptr); return res; } } return res; }
int elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags) { if (scn == NULL) return -1; if ((flags & ~ELF_CHF_FORCE) != 0) { __libelf_seterrno (ELF_E_INVALID_OPERAND); return -1; } bool force = (flags & ELF_CHF_FORCE) != 0; Elf *elf = scn->elf; GElf_Ehdr ehdr; if (gelf_getehdr (elf, &ehdr) == NULL) return -1; int elfclass = elf->class; int elfdata = ehdr.e_ident[EI_DATA]; Elf64_Xword sh_flags; Elf64_Word sh_type; Elf64_Xword sh_addralign; if (elfclass == ELFCLASS32) { Elf32_Shdr *shdr = elf32_getshdr (scn); if (shdr == NULL) return -1; sh_flags = shdr->sh_flags; sh_type = shdr->sh_type; sh_addralign = shdr->sh_addralign; } else { Elf64_Shdr *shdr = elf64_getshdr (scn); if (shdr == NULL) return -1; sh_flags = shdr->sh_flags; sh_type = shdr->sh_type; sh_addralign = shdr->sh_addralign; } if ((sh_flags & SHF_ALLOC) != 0) { __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS); return -1; } if (sh_type == SHT_NULL || sh_type == SHT_NOBITS) { __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE); return -1; } /* For GNU compression we cannot really know whether the section is already compressed or not. Just try and see what happens... */ // int compressed = (sh_flags & SHF_COMPRESSED); if (inflate == 1) { size_t hsize = 4 + 8; /* GNU "ZLIB" + 8 byte size. */ size_t orig_size, new_size, orig_addralign; void *out_buf = __libelf_compress (scn, hsize, elfdata, &orig_size, &orig_addralign, &new_size, force); /* Compression would make section larger, don't change anything. */ if (out_buf == (void *) -1) return 0; /* Compression failed, return error. */ if (out_buf == NULL) return -1; uint64_t be64_size = htobe64 (orig_size); memmove (out_buf, "ZLIB", 4); memmove (out_buf + 4, &be64_size, sizeof (be64_size)); /* We don't know anything about sh_entsize, sh_addralign and sh_flags won't have a SHF_COMPRESSED hint in the GNU format. Just adjust the sh_size. */ if (elfclass == ELFCLASS32) { Elf32_Shdr *shdr = elf32_getshdr (scn); shdr->sh_size = new_size; } else { Elf64_Shdr *shdr = elf64_getshdr (scn); shdr->sh_size = new_size; } __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE); /* The section is now compressed, we could keep the uncompressed data around, but since that might have been multiple Elf_Data buffers let the user uncompress it explicitly again if they want it to simplify bookkeeping. */ scn->zdata_base = NULL; return 1; } else if (inflate == 0) { /* In theory the user could have constucted a compressed section by hand. But we always just take the rawdata directly and decompress that. */ Elf_Data *data = elf_rawdata (scn, NULL); if (data == NULL) return -1; size_t hsize = 4 + 8; /* GNU "ZLIB" + 8 byte size. */ if (data->d_size < hsize || memcmp (data->d_buf, "ZLIB", 4) != 0) { __libelf_seterrno (ELF_E_NOT_COMPRESSED); return -1; } /* There is a 12-byte header of "ZLIB" followed by an 8-byte big-endian size. There is only one type and Alignment isn't preserved separately. */ uint64_t gsize; memcpy (&gsize, data->d_buf + 4, sizeof gsize); gsize = be64toh (gsize); /* One more sanity check, size should be bigger than original data size plus some overhead (4 chars ZLIB + 8 bytes size + 6 bytes zlib stream overhead + 5 bytes overhead max for one 16K block) and should fit into a size_t. */ if (gsize + 4 + 8 + 6 + 5 < data->d_size || gsize > SIZE_MAX) { __libelf_seterrno (ELF_E_NOT_COMPRESSED); return -1; } size_t size = gsize; size_t size_in = data->d_size - hsize; void *buf_in = data->d_buf + hsize; void *buf_out = __libelf_decompress (buf_in, size_in, size); if (buf_out == NULL) return -1; /* We don't know anything about sh_entsize, sh_addralign and sh_flags won't have a SHF_COMPRESSED hint in the GNU format. Just adjust the sh_size. */ if (elfclass == ELFCLASS32) { Elf32_Shdr *shdr = elf32_getshdr (scn); shdr->sh_size = size; } else { Elf64_Shdr *shdr = elf64_getshdr (scn); shdr->sh_size = size; } __libelf_reset_rawdata (scn, buf_out, size, sh_addralign, __libelf_data_type (elf, sh_type)); scn->zdata_base = buf_out; return 1; } else { __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE); return -1; } }
/* dwarf_elf_object_access_get_section() If writing a function vaguely like this for a non-elf object, be sure that when section-index is passed in as zero that you set the fields in *ret_scn to reflect an empty section with an empty string as the section name. Adjust your section indexes of your non-elf-reading-code for all the necessary functions in Dwarf_Obj_Access_Methods_s accordingly. */ static int dwarf_elf_object_access_get_section_info( void* obj_in, Dwarf_Half section_index, Dwarf_Obj_Access_Section* ret_scn, int* error) { dwarf_elf_object_access_internals_t*obj = (dwarf_elf_object_access_internals_t*)obj_in; Elf32_Shdr *shdr32 = 0; #ifdef HAVE_ELF64_GETSHDR Elf64_Shdr *shdr64 = 0; #endif Elf_Scn *scn = 0; scn = elf_getscn(obj->elf, section_index); if (scn == NULL) { *error = DW_DLE_MDE; return DW_DLV_ERROR; } if (obj->is_64bit) { #ifdef HAVE_ELF64_GETSHDR shdr64 = elf64_getshdr(scn); if (shdr64 == NULL) { *error = DW_DLE_ELF_GETSHDR_ERROR; return DW_DLV_ERROR; } /* Get also section 'sh_type' and sh_info' fields, so the caller can use it for additional tasks that require that info. */ ret_scn->type = shdr64->sh_type; ret_scn->size = shdr64->sh_size; ret_scn->addr = shdr64->sh_addr; ret_scn->link = shdr64->sh_link; ret_scn->info = shdr64->sh_info; ret_scn->entrysize = shdr64->sh_entsize; ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx, shdr64->sh_name); if (ret_scn->name == NULL) { *error = DW_DLE_ELF_STRPTR_ERROR; return DW_DLV_ERROR; } return DW_DLV_OK; #else *error = DW_DLE_MISSING_ELF64_SUPPORT; return DW_DLV_ERROR; #endif /* HAVE_ELF64_GETSHDR */ } if ((shdr32 = elf32_getshdr(scn)) == NULL) { *error = DW_DLE_ELF_GETSHDR_ERROR; return DW_DLV_ERROR; } /* Get also the section type, so the caller can use it for additional tasks that require to know the section type. */ ret_scn->type = shdr32->sh_type; ret_scn->size = shdr32->sh_size; ret_scn->addr = shdr32->sh_addr; ret_scn->link = shdr32->sh_link; ret_scn->info = shdr32->sh_info; ret_scn->entrysize = shdr32->sh_entsize; ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx, shdr32->sh_name); if (ret_scn->name == NULL) { *error = DW_DLE_ELF_STRPTR_ERROR; return DW_DLV_ERROR; } return DW_DLV_OK; }
static uint32_t* ExtractIsaBinaryFromElfBinary(uint64_t isaOffset, const void* pBinary, size_t binarySize) { if (nullptr == pBinary || 0 == binarySize) { return nullptr; } // get isa binary from .hsatext section with a relative byte offset (isaOffset) // Determine the ELF type: bool isELF = false; bool isELF32 = false; bool isELF64 = false; // The ELF executable header is 16 bytes: if (16 < binarySize) { // Check for the ELF header start: const unsigned char* pBinaryAsUBytes = (const unsigned char*)pBinary; isELF = ((0x7f == pBinaryAsUBytes[0]) && ('E' == pBinaryAsUBytes[1]) && ('L' == pBinaryAsUBytes[2]) && ('F' == pBinaryAsUBytes[3])); isELF32 = isELF && (0x01 == pBinaryAsUBytes[4]); isELF64 = isELF && (0x02 == pBinaryAsUBytes[4]); } // Validate: if (!isELF) { return nullptr; } if (!isELF32 && !isELF64) { assert(!"Unsupported ELF sub-format!"); return nullptr; } // Set the version of elf: elf_version(EV_CURRENT); // Initialize the binary as ELF from memory: Elf* pContainerElf = elf_memory((char*)pBinary, binarySize); if (nullptr == pContainerElf) { return nullptr; } // First get the .hsatext section: static const std::string isaSectionName = ".hsatext"; // Get the shared strings section: size_t sectionHeaderStringSectionIndex = 0; int rcShrstr = elf_getshdrstrndx(pContainerElf, §ionHeaderStringSectionIndex); if ((0 != rcShrstr) || (0 == sectionHeaderStringSectionIndex)) { return nullptr; } // Iterate the sections to find the isa section Elf_Scn* pCurrentSection = elf_nextscn(pContainerElf, nullptr); while (nullptr != pCurrentSection) { size_t strOffset = 0; if (isELF32) { // Get the section header: Elf32_Shdr* pCurrentSectionHeader = elf32_getshdr(pCurrentSection); if (nullptr != pCurrentSectionHeader) { // Get the name and link: strOffset = pCurrentSectionHeader->sh_name; } } else if (isELF64) { // Get the section header: Elf64_Shdr* pCurrentSectionHeader = elf64_getshdr(pCurrentSection); if (nullptr != pCurrentSectionHeader) { // Get the name and link: strOffset = pCurrentSectionHeader->sh_name; } } // Get the current section's name: char* pCurrentSectionName = elf_strptr(pContainerElf, sectionHeaderStringSectionIndex, strOffset); if (nullptr != pCurrentSectionName) { if (isaSectionName == pCurrentSectionName) { // Get the section's data: Elf_Data* pSectionData = elf_getdata(pCurrentSection, nullptr); if (nullptr != pSectionData) { // Found the section, no need to continue: // the isa binary is prefixed with an amd_kernel_code_t structure uint64_t buffer = reinterpret_cast<uint64_t>(pSectionData->d_buf) + isaOffset + sizeof(amd_kernel_code_t); return reinterpret_cast<uint32_t*>(buffer); } } } // Get the next section: pCurrentSection = elf_nextscn(pContainerElf, pCurrentSection); } return nullptr; }
int main(int argc,char *argv[]) { if(argc<2) { printf("Usage: %s [elf path]\n",argv[0]); return 0; } int fd = open(argv[1],OFLAGS); if(fd<0) { fprintf(stderr,"Unable to open elf file: %s\n",argv[1]); return 1; } elf_version(EV_CURRENT); Elf *elf = elf_begin(fd,ELF_C_READ,NULL); if(!elf) { fprintf(stderr,"libelf could not read elf file: %s\n",elf_errmsg(elf_errno())); return 1; } Elf_Scn *prx = getSection(elf,".sys_proc_prx_param"); if(!prx || memcmp(elf_getdata(prx,NULL)->d_buf,prx_magic,sizeof(prx_magic))) { fprintf(stderr,"elf does not have a prx parameter section.\n"); return 1; } Elf_Scn *stubsection = getSection(elf,".lib.stub"); Elf_Data *stubdata = elf_getdata(stubsection,NULL); Elf64_Shdr *stubshdr = elf64_getshdr(stubsection); Stub *stubbase = (Stub*)stubdata->d_buf; size_t stubcount = stubdata->d_size/sizeof(Stub); Elf_Scn *fnidsection = getSection(elf,".rodata.sceFNID"); Elf64_Shdr *fnidshdr = elf64_getshdr(fnidsection); for(Stub *stub = stubbase;stub<stubbase + stubcount;stub++) { uint32_t fnid = BE32(stub->fnid); uint32_t end = fnidshdr->sh_addr + fnidshdr->sh_size; for(Stub *substub = stubbase;substub<(stubbase + stubcount);substub++) { if(stub==substub) continue; uint32_t newfnid = BE32(substub->fnid); if(newfnid>=fnid && newfnid<end) end = newfnid; } uint16_t fnidcount = (end - fnid)/4; if(BE16(stub->imports)!=fnidcount) { lseek(fd,stubshdr->sh_offset + (stub - stubbase)*sizeof(Stub)+offsetof(Stub,imports),SEEK_SET); fnidcount = BE16(fnidcount); if(write(fd,&fnidcount,sizeof(fnidcount))!=sizeof(fnidcount)) { printf("Error occurred during write in %s:%d\n",__FILE__,__LINE__); } } } Elf_Scn *opdsection = getSection(elf,".opd"); Elf_Data *opddata = elf_getdata(opdsection,NULL); Elf64_Shdr *opdshdr = elf64_getshdr(opdsection); Opd64 *opdbase = (Opd64*)opddata->d_buf; size_t opdcount = opddata->d_size/sizeof(Opd64); for(Opd64 *opd = opdbase;opd<(opdbase + opdcount);opd++) { opd->data = BE64(((BE64(opd->func)<<32ULL) | (BE64(opd->rtoc)&0xffffffffULL))); lseek(fd,opdshdr->sh_offset + (opd - opdbase)*sizeof(Opd64),SEEK_SET); if(write(fd,opd,sizeof(Opd64))!=sizeof(Opd64)) { printf("Error occurred during write in %s:%d\n",__FILE__,__LINE__); } } elf_end(elf); close(fd); return 0; }