1 /************************************************************************* 2 Copyright (C) 2002,2003,2004,2005 Wei Qin 3 See file COPYING for more information. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 *************************************************************************/ 15 16 #include <stdlib.h> 17 #include <string.h> 18 #include <errno.h> 19 #include <assert.h> 20 #include "read_elf.h" 21 22 #define SwapHalf(a) (((a & 0x00ff) << 8) | ((a & 0xff00) >> 8)) 23 #define SwapWord(a) (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24)) 24 #define SwapAddr(a) SwapWord(a) 25 #define SwapOff(a) SwapWord(a) 26 #define SwapSection(a) SwapHalf(a) 27 28 int LittleEndian() 29 { 30 Elf32_Word a = 0x01020304; 31 return *(char *) &a == 0x04; 32 } 33 34 void SwapElfHeader(Elf32_Ehdr *hdr) 35 { 36 hdr->e_type = SwapHalf(hdr->e_type); 37 hdr->e_machine = SwapHalf(hdr->e_machine); 38 hdr->e_version = SwapWord(hdr->e_version); 39 hdr->e_entry = SwapAddr(hdr->e_entry); 40 hdr->e_phoff = SwapOff(hdr->e_phoff); 41 hdr->e_shoff = SwapOff(hdr->e_shoff); 42 hdr->e_flags = SwapWord(hdr->e_flags); 43 hdr->e_ehsize = SwapHalf(hdr->e_ehsize); 44 hdr->e_phentsize = SwapHalf(hdr->e_phentsize); 45 hdr->e_phnum = SwapHalf(hdr->e_phnum); 46 hdr->e_shentsize = SwapHalf(hdr->e_shentsize); 47 hdr->e_shnum = SwapHalf(hdr->e_shnum); 48 hdr->e_shstrndx = SwapHalf(hdr->e_shstrndx); 49 } 50 51 void SwapSectionHeader(Elf32_Shdr *shdr) 52 { 53 shdr->sh_name = SwapWord(shdr->sh_name); 54 shdr->sh_type = SwapWord(shdr->sh_type); 55 shdr->sh_flags = SwapWord(shdr->sh_flags); 56 shdr->sh_addr = SwapAddr(shdr->sh_addr); 57 shdr->sh_offset = SwapOff(shdr->sh_offset); 58 shdr->sh_size = SwapWord(shdr->sh_size); 59 shdr->sh_link = SwapWord(shdr->sh_link); 60 shdr->sh_info = SwapWord(shdr->sh_info); 61 shdr->sh_addralign = SwapWord(shdr->sh_addralign); 62 shdr->sh_entsize = SwapWord(shdr->sh_entsize); 63 } 64 65 void SwapElfSymbol(Elf32_Sym *sym) 66 { 67 sym->st_name = SwapWord(sym->st_name); 68 sym->st_value = SwapAddr(sym->st_value); 69 sym->st_size = SwapWord(sym->st_size); 70 sym->st_shndx = SwapSection(sym->st_shndx); 71 } 72 73 void AdjustElfHeader(Elf32_Ehdr *hdr) 74 { 75 switch(hdr->e_ident[EI_DATA]) 76 { 77 case ELFDATA2LSB: 78 if (!LittleEndian()) 79 SwapElfHeader(hdr); 80 break; 81 case ELFDATA2MSB: 82 if (LittleEndian()) 83 SwapElfHeader(hdr); 84 break; 85 } 86 } 87 88 void AdjustSectionHeader(Elf32_Ehdr *hdr, Elf32_Shdr *shdr) 89 { 90 switch(hdr->e_ident[EI_DATA]) 91 { 92 case ELFDATA2LSB: 93 if (!LittleEndian()) 94 SwapSectionHeader(shdr); 95 break; 96 case ELFDATA2MSB: 97 if (LittleEndian()) 98 SwapSectionHeader(shdr); 99 break; 100 } 101 } 102 103 void AdjustElfSymbols(Elf32_Ehdr *hdr, Elf32_Sym *elf_symbols, int num_entries) 104 { 105 if (hdr->e_ident[EI_DATA] == ELFDATA2LSB && LittleEndian()) 106 return; 107 if (hdr->e_ident[EI_DATA] == ELFDATA2MSB && !LittleEndian()) 108 return; 109 for (int ii = 0; ii < num_entries; ++ii) { 110 SwapElfSymbol(&elf_symbols[ii]); 111 } 112 } 113 114 Elf32_Ehdr *ReadElfHeader(FILE *fobj) 115 { 116 Elf32_Ehdr *hdr = new Elf32_Ehdr; 117 int rval = fread(hdr, sizeof(Elf32_Ehdr), 1, fobj); 118 if (rval != 1) { 119 delete hdr; 120 return NULL; 121 } 122 if (hdr->e_ident[EI_MAG0] != 0x7f || hdr->e_ident[EI_MAG1] != 'E' || 123 hdr->e_ident[EI_MAG2] != 'L' || hdr->e_ident[EI_MAG3] != 'F') { 124 delete hdr; 125 return NULL; 126 } 127 AdjustElfHeader(hdr); 128 return hdr; 129 } 130 131 Elf32_Shdr *ReadSectionHeaders(Elf32_Ehdr *hdr, FILE *f) 132 { 133 int i; 134 unsigned long sz = hdr->e_shnum * hdr->e_shentsize; 135 assert(sizeof(Elf32_Shdr) == hdr->e_shentsize); 136 Elf32_Shdr *shdr = new Elf32_Shdr[hdr->e_shnum]; 137 138 if (fseek(f, hdr->e_shoff, SEEK_SET) != 0) 139 { 140 delete[] shdr; 141 return NULL; 142 } 143 if (fread(shdr, sz, 1, f) != 1) 144 { 145 delete[] shdr; 146 return NULL; 147 } 148 149 for(i = 0; i < hdr->e_shnum; i++) 150 AdjustSectionHeader(hdr, shdr + i); 151 152 return shdr; 153 } 154 155 156 char *ReadStringTable(Elf32_Ehdr *hdr, Elf32_Shdr *shdr_table, FILE *f) 157 { 158 Elf32_Shdr *shdr = shdr_table + hdr->e_shstrndx; 159 char *string_table; 160 161 string_table = new char[shdr->sh_size]; 162 fseek(f, shdr->sh_offset, SEEK_SET); 163 fread(string_table, shdr->sh_size, 1, f); 164 165 return string_table; 166 } 167 168 int ReadSection(Elf32_Shdr *shdr, void *buffer, FILE *f) 169 { 170 if (fseek(f, shdr->sh_offset, SEEK_SET) != 0) 171 return -1; 172 if (fread(buffer, shdr->sh_size, 1, f) != 1) 173 return -1; 174 return 0; 175 } 176 177 char *GetSymbolName(Elf32_Half index, char *string_table) 178 { 179 return string_table + index; 180 } 181 182 Elf32_Shdr *FindSymbolTableSection(Elf32_Ehdr *hdr, 183 Elf32_Shdr *shdr, 184 char *string_table) 185 { 186 for(int ii = 0; ii < hdr->e_shnum; ii++) { 187 if (shdr[ii].sh_type == SHT_SYMTAB && 188 strcmp(GetSymbolName(shdr[ii].sh_name, string_table), 189 ".symtab") == 0) 190 { 191 return &shdr[ii]; 192 } 193 } 194 return NULL; 195 } 196 197 Elf32_Shdr *FindSymbolStringTableSection(Elf32_Ehdr *hdr, 198 Elf32_Shdr *shdr, 199 char *string_table) 200 { 201 for(int ii = 0; ii < hdr->e_shnum; ii++) { 202 if (shdr[ii].sh_type == SHT_STRTAB && 203 strcmp(GetSymbolName(shdr[ii].sh_name, string_table), 204 ".strtab") == 0) 205 { 206 return &shdr[ii]; 207 } 208 } 209 return NULL; 210 } 211