1/* 2 * Copyright (c) 1999-2004 University of New South Wales 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <strops.h> 8#include <binaries/elf/elf.h> 9 10int 11elf64_checkFile(void *elfFile) 12{ 13 struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile; 14 if (fileHdr->e_ident[EI_MAG0] != ELFMAG0 15 || fileHdr->e_ident[EI_MAG1] != ELFMAG1 16 || fileHdr->e_ident[EI_MAG2] != ELFMAG2 17 || fileHdr->e_ident[EI_MAG3] != ELFMAG3) { 18 return -1; /* not an elf file */ 19 } 20 if (fileHdr->e_ident[EI_CLASS] != ELFCLASS64) { 21 return -2; /* not 64-bit file */ 22 } 23#if 0 24 if (fileHdr->e_ident[EI_DATA] != ELFDATA2LSB) { 25 return -3; /* not big-endian file */ 26 } 27 if (fileHdr->e_ident[EI_VERSION] != 1) { 28 return -4; /* wrong version of elf */ 29 } 30 if (fileHdr->e_machine != 8) { 31 return -5; /* wrong architecture (not MIPS) */ 32 } 33 if (fileHdr->e_type != 2) { 34 return -6; /* not an executable program */ 35 } 36 if (fileHdr->e_phentsize != sizeof(struct Elf64_Phdr)) { 37 return -7; 38 } /* unexpected size of program segment 39 * header */ 40 if (fileHdr->e_phnum == 0) { 41 return -8; /* no program segments */ 42 } 43 if ((fileHdr->e_flags & 0x7e) != 0) { 44 return -9; 45 } /* wrong flags (did you forgot to compile 46 * with -mno-abicalls?) */ 47#endif 48 return 0; /* elf file looks OK */ 49} 50 51struct Elf64_Phdr * 52elf64_getProgramSegmentTable(void *elfFile) 53/* 54 * Returns a pointer to the program segment table, which is an array of 55 * ELF64_Phdr_t structs. The size of the array can be found by calling 56 * getNumProgramSegments. 57 */ 58{ 59 struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile; 60 return (struct Elf64_Phdr *) ((size_t)fileHdr->e_phoff + (size_t) elfFile); 61} 62 63unsigned 64elf64_getNumSections(void *elfFile) 65/* 66 * Returns the number of program segments in this elf file. 67 */ 68{ 69 struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile; 70 return fileHdr->e_shnum; 71} 72 73char * 74elf64_getStringTable(void *elfFile, int string_segment) 75{ 76 struct Elf64_Shdr *sections = elf64_getSectionTable(elfFile); 77 return (char *) elfFile + sections[string_segment].sh_offset; 78} 79 80char * 81elf64_getSegmentStringTable(void *elfFile) 82{ 83 struct Elf64_Header *fileHdr = (struct Elf64_Header *) elfFile; 84 if (fileHdr->e_shstrndx == 0) { 85 return NULL; 86 } else { 87 return elf64_getStringTable(elfFile, fileHdr->e_shstrndx); 88 } 89} 90 91char * 92elf64_getSectionName(void *elfFile, int i) 93{ 94 struct Elf64_Shdr *sections = elf64_getSectionTable(elfFile); 95 char *str_table = elf64_getSegmentStringTable(elfFile); 96 if (str_table == NULL) { 97 return "<corrupted>"; 98 } else { 99 return str_table + sections[i].sh_name; 100 } 101} 102 103uint64_t 104elf64_getSectionSize(void *elfFile, int i) 105{ 106 struct Elf64_Shdr *sections = elf64_getSectionTable(elfFile); 107 return sections[i].sh_size; 108} 109 110uint64_t 111elf64_getSectionAddr(struct Elf64_Header *elfFile, int i) 112{ 113 struct Elf64_Shdr *sections = elf64_getSectionTable(elfFile); 114 return sections[i].sh_addr; 115} 116 117void * 118elf64_getSection(void *elfFile, int i) 119{ 120 struct Elf64_Shdr *sections = elf64_getSectionTable(elfFile); 121 return (char *)elfFile + sections[i].sh_offset; 122} 123 124void * 125elf64_getSectionNamed(void *elfFile, char *str) 126{ 127 int numSections = elf64_getNumSections(elfFile); 128 int i; 129 for (i = 0; i < numSections; i++) { 130 if (strcmp(str, elf64_getSectionName(elfFile, i)) == 0) { 131 return elf64_getSection(elfFile, i); 132 } 133 } 134 return NULL; 135} 136 137uint16_t 138elf64_getNumProgramHeaders(struct Elf64_Header *elfFile) 139{ 140 return elfFile->e_phnum; 141} 142 143int 144elf64_getSegmentType (void *elfFile, int segment) 145{ 146 return elf64_getProgramSegmentTable(elfFile)[segment].p_type; 147} 148 149void 150elf64_getSegmentInfo(void *elfFile, int segment, uint64_t *p_vaddr, 151 uint64_t *p_paddr, uint64_t *p_filesz, uint64_t *p_offset, 152 uint64_t *p_memsz) 153{ 154 struct Elf64_Phdr *segments; 155 156 segments = elf64_getProgramSegmentTable(elfFile); 157 *p_vaddr = segments[segment].p_vaddr; 158 *p_paddr = segments[segment].p_paddr; 159 *p_filesz = segments[segment].p_filesz; 160 *p_offset = segments[segment].p_offset; 161 *p_memsz = segments[segment].p_memsz; 162} 163 164uint64_t 165elf64_getEntryPoint (struct Elf64_Header *elfFile) 166{ 167 return elf64_read64(&elfFile->e_entry); 168} 169 170/* 171 * Debugging functions 172 */ 173 174#if 0 175/* 176 * prints out some details of one elf file 177 */ 178void 179elf64_showDetails(void *elfFile, int size, char *name) 180{ 181 struct Elf64_Phdr *segments; 182 unsigned numSegments; 183 struct Elf64_Shdr *sections; 184 unsigned numSections; 185 int i, 186 r; 187 char *str_table; 188 189 printf("Found an elf64 file called \"%s\" located " 190 "at address 0x%lx\n", name, elfFile); 191 192 if ((r = elf64_checkFile(elfFile)) != 0) { 193 char *magic = elfFile; 194 printf("Invalid elf file (%d)\n", r); 195 printf("Magic is: %02.2hhx %02.2hhx %02.2hhx %02.2hhx\n", 196 magic[0], magic[1], magic[2], magic[3]); 197 return; 198 } 199 200 str_table = elf64_getSegmentStringTable(elfFile); 201 202 printf("Got str_table... %p\n", str_table); 203 204 /* 205 * get a pointer to the table of program segments 206 */ 207 segments = elf64_getProgramSegmentTable(elfFile); 208 numSegments = elf64_getNumProgramSegments(elfFile); 209 210 sections = elf64_getSectionTable(elfFile); 211 numSections = elf64_getNumSections(elfFile); 212 213 if ((void *) sections > (void *) elfFile + size || 214 (((uintptr_t) sections & 0xf) != 0)) { 215 printf("Corrupted elfFile..\n"); 216 return; 217 } 218 printf("Sections: %p\n", sections); 219 /* 220 * print out info about each section 221 */ 222 223 /* 224 * print out info about each program segment 225 */ 226 printf("Program Headers:\n"); 227 printf(" Type Offset VirtAddr PhysAddr " 228 "FileSiz MemSiz Flg Align\n"); 229 for (i = 0; i < numSegments; i++) { 230 231 if (segments[i].p_type != 1) { 232 printf("segment %d is not loadable, " 233 "skipping\n", i); 234 } else { 235 printf(" LOAD 0x%06lx 0x%08lx 0x%08lx" 236 " 0x%05lx 0x%05lx %c%c%c 0x%04lx\n", 237 segments[i].p_offset, segments[i].p_vaddr, 238 segments[i].p_vaddr, 239 segments[i].p_filesz, segments[i].p_memsz, 240 segments[i].p_flags & PF_R ? 'R' : ' ', 241 segments[i].p_flags & PF_W ? 'W' : ' ', 242 segments[i].p_flags & PF_X ? 'E' : ' ', 243 segments[i].p_align); 244 } 245 } 246 247 printf("Section Headers:\n"); 248 printf(" [Nr] Name Type Addr Off\n"); 249 for (i = 0; i < numSections; i++) { 250 if (elf_checkSection(elfFile, i) == 0) { 251 printf("%-17.17s %-15.15s %08x %06x\n", elf64_getSectionName(elfFile, i), " " /* sections[i].sh_type 252 */ , 253 sections[i].sh_addr, sections[i].sh_offset); 254 } 255 } 256} 257#endif 258