• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LittleEndian()28 int LittleEndian()
29 {
30   Elf32_Word a = 0x01020304;
31   return *(char *) &a == 0x04;
32 }
33 
SwapElfHeader(Elf32_Ehdr * hdr)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 
SwapSectionHeader(Elf32_Shdr * shdr)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 
SwapElfSymbol(Elf32_Sym * sym)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 
AdjustElfHeader(Elf32_Ehdr * hdr)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 
AdjustSectionHeader(Elf32_Ehdr * hdr,Elf32_Shdr * shdr)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 
AdjustElfSymbols(Elf32_Ehdr * hdr,Elf32_Sym * elf_symbols,int num_entries)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 
ReadElfHeader(FILE * fobj)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 
ReadSectionHeaders(Elf32_Ehdr * hdr,FILE * f)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 
ReadStringTable(Elf32_Ehdr * hdr,Elf32_Shdr * shdr_table,FILE * f)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 
ReadSection(Elf32_Shdr * shdr,void * buffer,FILE * f)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 
GetSymbolName(Elf32_Half index,char * string_table)177 char *GetSymbolName(Elf32_Half index, char *string_table)
178 {
179   return string_table + index;
180 }
181 
FindSymbolTableSection(Elf32_Ehdr * hdr,Elf32_Shdr * shdr,char * string_table)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 
FindSymbolStringTableSection(Elf32_Ehdr * hdr,Elf32_Shdr * shdr,char * string_table)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