int dump_shdr( elf_t * elf ) { Elf32_Shdr * shdr; size_t count, i; if( !elf ) error_ret("null arg",-1); if(!(shdr = get_shdr(elf))) error_ret("can't get shdr",-1); count = elf->shdr_count; printf("addr offset type flags size\n"); for( i = 0 ; i < count ; i++ ) { printf("0x%08x ",shdr[i].sh_addr); printf("0x%08x ",shdr[i].sh_offset); printf("0x%08x ",shdr[i].sh_type); printf("0x%08x ",shdr[i].sh_flags); printf("0x%08x ",shdr[i].sh_size); putchar('\n'); } return(0); }
uint32_t get_size(char* name) { Elf64_Shdr* hdr = get_shdr(name); if(hdr) { return hdr->sh_size; } else { return 0; } }
/** * Return section headers of the symbol table and the associated string table. * There must be exactly one symbol table and its name must be ".symtab" and * its associated string table must have name ".strtab". */ static int get_symtab(const char *elf, size_t elfsz, Elf32_Shdr **shsymtab, Elf32_Shdr **shsymstr) { Elf32_Ehdr *eh = (Elf32_Ehdr*)elf; Elf32_Shdr *shshstr = NULL; const char *secname; unsigned i; *shsymtab = *shsymstr = NULL; for(i = 0; i < eh->e_shnum; i++) { Elf32_Shdr *sh = get_shdr(elf, elfsz, i); if(!sh) return -1; if(i == eh->e_shstrndx) { shshstr = sh; } else if(sh->sh_type == SHT_SYMTAB) { if(*shsymtab) /* Don't allow multiple symtabs. */ return -1; *shsymtab = sh; } } if(!*shsymtab || !shshstr) return -1; secname = get_string(elf, elfsz, shshstr, (*shsymtab)->sh_name); if((*shsymtab)->sh_link >= eh->e_shnum || !secname || !Sequal(secname, ".symtab")) return -1; *shsymstr = get_shdr(elf, elfsz, (*shsymtab)->sh_link); if(!*shsymstr) return -1; secname = get_string(elf, elfsz, shshstr, (*shsymstr)->sh_name); if(((*shsymstr)->sh_type != SHT_STRTAB) || !secname || !Sequal(secname, ".strtab")) return -1; return 0; }
/** * Get contents of elf section * * @param[in] shndx The index in section header of the section to get * * @return Section contents in a malloced memory block */ void * Elf32_info::load_elf_section(int shndx) const { const Elf32_Shdr * shdr = reinterpret_cast<const Elf32_Shdr *>(get_shdr(shndx)); const size_t size = shdr->sh_size; const unsigned long offset = shdr->sh_offset; uint8_t * section = new uint8_t[size]; if( pread(m_fd, section, size, offset) != (int) size) { LOG_ERROR("Failed to read section table"); delete [] section; exit(0); } return section; }
int main(int argc, char* argv[]) { if(argc < 3) { printf("Usage: pnkc [kernel elf] [kernel smap] [kernel pnkc]\n"); return 0; } int fd = open(argv[1], O_RDONLY); if(fd < 0) { printf("Cannot open file: %s\n", argv[1]); return 1; } struct stat state; if(stat(argv[1], &state) != 0) { printf("Cannot get state of file: %s\n", argv[1]); return 2; } Elf64_Ehdr* ehdr = mmap(NULL, state.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if(ehdr == (void*)-1) { printf("Cannot open file: %s\n", argv[1]); return 1; } if(ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 || ehdr->e_ident[2] != ELFMAG2 || ehdr->e_ident[3] != ELFMAG3) { printf("Illegal file format: %s\n", argv[1]); return 3; } Elf64_Shdr* shdr = (Elf64_Shdr*)((uint8_t*)ehdr + ehdr->e_shoff); char* strs = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset; Elf64_Shdr* get_shdr(char* name) { for(int i = 0; i < ehdr->e_shnum; i++) { if(strcmp(name, strs + shdr[i].sh_name) == 0) return &shdr[i]; } return NULL; } uint32_t get_offset(char* name, uint64_t base) { Elf64_Shdr* hdr = get_shdr(name); if(hdr) { return hdr->sh_addr - base; } else { return 0; } }
int main(int argc, char* argv[]) { if(argc < 3) { printf("Usage: smap [kernel elf] [system map]\n"); return 0; } int fd = open(argv[1], O_RDONLY); if(fd < 0) { printf("Cannot open file: %s\n", argv[1]); return 1; } struct stat state; if(stat(argv[1], &state) != 0) { printf("Cannot get state of file: %s\n", argv[1]); return 2; } Elf64_Ehdr* ehdr = mmap(NULL, state.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if(ehdr == (void*)-1) { printf("Cannot open file: %s\n", argv[1]); return 1; } if(ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 || ehdr->e_ident[2] != ELFMAG2 || ehdr->e_ident[3] != ELFMAG3) { printf("Illegal file format: %s\n", argv[1]); return 3; } Elf64_Shdr* shdr = (Elf64_Shdr*)((uint8_t*)ehdr + ehdr->e_shoff); char* strs = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset; Elf64_Shdr* get_shdr(char* name) { for(int i = 0; i < ehdr->e_shnum; i++) { if(strcmp(name, strs + shdr[i].sh_name) == 0) return &shdr[i]; } return NULL; } Elf64_Shdr* strtab = get_shdr(".strtab"); char* str = (char*)ehdr + strtab->sh_offset; char* name(int offset) { return str + offset; } int count = 0; int text_size = 0; Elf64_Shdr* symtab = get_shdr(".symtab"); Elf64_Sym* sym = (void*)ehdr + symtab->sh_offset; int size = symtab->sh_size / sizeof(Elf64_Sym); for(int i = 0; i < size; i++) { if(ELF64_ST_BIND(sym[i].st_info) != STB_GLOBAL) continue; int type = ELF64_ST_TYPE(sym[i].st_info); switch(type) { case STT_NOTYPE: case STT_OBJECT: case STT_FUNC: break; default: printf("Unknown symbol type: %d for %s\n", type, name(sym[i].st_name)); return 4; } count++; text_size += strlen(name(sym[i].st_name)) + 1; } // Make data structure int total = sizeof(Symbol) * (count + 1) + text_size; Symbol* symbols = malloc(total); char* text = (void*)symbols + total - text_size; int j = 0; for(int i = 0; i < size; i++) { if(ELF64_ST_BIND(sym[i].st_info) != STB_GLOBAL) continue; int type = ELF64_ST_TYPE(sym[i].st_info); switch(type) { case STT_NOTYPE: type = SYMBOL_TYPE_NONE; break; case STT_OBJECT: type = SYMBOL_TYPE_DATA; break; case STT_FUNC: type = SYMBOL_TYPE_FUNC; break; default: ;// Not possible } symbols[j].name = (void*)((void*)text - (void*)symbols); symbols[j].type = type; symbols[j].address = (void*)(uint64_t)sym[i].st_value; j++; char* symname = name(sym[i].st_name); int len = strlen(symname) + 1; memcpy(text, symname, len); text += len; } close(fd); // Write int fd2 = open(argv[2], O_RDWR | O_CREAT, 0644); if(fd2 < 0) { printf("Cannot open file: %s\n", argv[2]); return 1; } // Write symbols int len = write(fd2, symbols, total); if(len != total) { printf("Cannot write fully: %d < %d\n", len, total); return 5; } close(fd2); return 0; }
/** * Get the section address value for the section sprcified by the * index * * @param[in] shndx The index in section header of the section to get * * @return the address */ unsigned Elf32_info::get_section_address(int shndx) const { const Elf32_Shdr * shdr = reinterpret_cast<const Elf32_Shdr *>(get_shdr(shndx)); return shdr->sh_addr; }
/** * Get the section link value for the section specified by the * index * * @param[in] idx The index in section header of the section to get * * @return the value of section link field */ unsigned Elf32_info::get_section_link(int idx) const { const Elf32_Shdr * shdr = reinterpret_cast<const Elf32_Shdr *>(get_shdr(idx)); return shdr->sh_link; }
/** * Get the section name value for the section specified by the * index * * @param[in] idx The index in section header of the section to get * * @return the section name */ char * Elf32_info::get_section_name(int idx) const { const Elf32_Shdr * shdr = reinterpret_cast<const Elf32_Shdr *>(get_shdr(idx)); const int name_idx = shdr->sh_name; return &m_shstrtab[name_idx]; }
unsigned Elf32_info::get_section_size(int symtab_idx) const { const Elf32_Shdr * shdr = reinterpret_cast<const Elf32_Shdr *>(get_shdr(symtab_idx)); return shdr->sh_size; }