• 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