diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:29:09 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:29:09 -0800 |
commit | 55a2c71f27d3e0b8344597c7f281e687cb7aeb1b (patch) | |
tree | ecd18b995aea8eeeb8b3823266280d41245bf0f7 /emulator/qtools/read_elf.cpp | |
parent | 82ea7a177797b844b252effea5c7c7c5d63ea4ac (diff) | |
download | sdk-55a2c71f27d3e0b8344597c7f281e687cb7aeb1b.zip sdk-55a2c71f27d3e0b8344597c7f281e687cb7aeb1b.tar.gz sdk-55a2c71f27d3e0b8344597c7f281e687cb7aeb1b.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'emulator/qtools/read_elf.cpp')
-rw-r--r-- | emulator/qtools/read_elf.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/emulator/qtools/read_elf.cpp b/emulator/qtools/read_elf.cpp new file mode 100644 index 0000000..1d1a74a --- /dev/null +++ b/emulator/qtools/read_elf.cpp @@ -0,0 +1,210 @@ +/************************************************************************* + Copyright (C) 2002,2003,2004,2005 Wei Qin + See file COPYING for more information. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +*************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include "read_elf.h" + +#define SwapHalf(a) (((a & 0x00ff) << 8) | ((a & 0xff00) >> 8)) +#define SwapWord(a) (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24)) +#define SwapAddr(a) SwapWord(a) +#define SwapOff(a) SwapWord(a) +#define SwapSection(a) SwapHalf(a) + +int LittleEndian() +{ + Elf32_Word a = 0x01020304; + return *(char *) &a == 0x04; +} + +void SwapElfHeader(Elf32_Ehdr *hdr) +{ + hdr->e_type = SwapHalf(hdr->e_type); + hdr->e_machine = SwapHalf(hdr->e_machine); + hdr->e_version = SwapWord(hdr->e_version); + hdr->e_entry = SwapAddr(hdr->e_entry); + hdr->e_phoff = SwapOff(hdr->e_phoff); + hdr->e_shoff = SwapOff(hdr->e_shoff); + hdr->e_flags = SwapWord(hdr->e_flags); + hdr->e_ehsize = SwapHalf(hdr->e_ehsize); + hdr->e_phentsize = SwapHalf(hdr->e_phentsize); + hdr->e_phnum = SwapHalf(hdr->e_phnum); + hdr->e_shentsize = SwapHalf(hdr->e_shentsize); + hdr->e_shnum = SwapHalf(hdr->e_shnum); + hdr->e_shstrndx = SwapHalf(hdr->e_shstrndx); +} + +void SwapSectionHeader(Elf32_Shdr *shdr) +{ + shdr->sh_name = SwapWord(shdr->sh_name); + shdr->sh_type = SwapWord(shdr->sh_type); + shdr->sh_flags = SwapWord(shdr->sh_flags); + shdr->sh_addr = SwapAddr(shdr->sh_addr); + shdr->sh_offset = SwapOff(shdr->sh_offset); + shdr->sh_size = SwapWord(shdr->sh_size); + shdr->sh_link = SwapWord(shdr->sh_link); + shdr->sh_info = SwapWord(shdr->sh_info); + shdr->sh_addralign = SwapWord(shdr->sh_addralign); + shdr->sh_entsize = SwapWord(shdr->sh_entsize); +} + +void SwapElfSymbol(Elf32_Sym *sym) +{ + sym->st_name = SwapWord(sym->st_name); + sym->st_value = SwapAddr(sym->st_value); + sym->st_size = SwapWord(sym->st_size); + sym->st_shndx = SwapSection(sym->st_shndx); +} + +void AdjustElfHeader(Elf32_Ehdr *hdr) +{ + switch(hdr->e_ident[EI_DATA]) + { + case ELFDATA2LSB: + if (!LittleEndian()) + SwapElfHeader(hdr); + break; + case ELFDATA2MSB: + if (LittleEndian()) + SwapElfHeader(hdr); + break; + } +} + +void AdjustSectionHeader(Elf32_Ehdr *hdr, Elf32_Shdr *shdr) +{ + switch(hdr->e_ident[EI_DATA]) + { + case ELFDATA2LSB: + if (!LittleEndian()) + SwapSectionHeader(shdr); + break; + case ELFDATA2MSB: + if (LittleEndian()) + SwapSectionHeader(shdr); + break; + } +} + +void AdjustElfSymbols(Elf32_Ehdr *hdr, Elf32_Sym *elf_symbols, int num_entries) +{ + if (hdr->e_ident[EI_DATA] == ELFDATA2LSB && LittleEndian()) + return; + if (hdr->e_ident[EI_DATA] == ELFDATA2MSB && !LittleEndian()) + return; + for (int ii = 0; ii < num_entries; ++ii) { + SwapElfSymbol(&elf_symbols[ii]); + } +} + +Elf32_Ehdr *ReadElfHeader(FILE *fobj) +{ + Elf32_Ehdr *hdr = new Elf32_Ehdr; + int rval = fread(hdr, sizeof(Elf32_Ehdr), 1, fobj); + if (rval != 1) { + delete hdr; + return NULL; + } + if (hdr->e_ident[EI_MAG0] != 0x7f || hdr->e_ident[EI_MAG1] != 'E' || + hdr->e_ident[EI_MAG2] != 'L' || hdr->e_ident[EI_MAG3] != 'F') { + delete hdr; + return NULL; + } + AdjustElfHeader(hdr); + return hdr; +} + +Elf32_Shdr *ReadSectionHeaders(Elf32_Ehdr *hdr, FILE *f) +{ + int i; + unsigned long sz = hdr->e_shnum * hdr->e_shentsize; + assert(sizeof(Elf32_Shdr) == hdr->e_shentsize); + Elf32_Shdr *shdr = new Elf32_Shdr[hdr->e_shnum]; + + if (fseek(f, hdr->e_shoff, SEEK_SET) != 0) + { + delete[] shdr; + return NULL; + } + if (fread(shdr, sz, 1, f) != 1) + { + delete[] shdr; + return NULL; + } + + for(i = 0; i < hdr->e_shnum; i++) + AdjustSectionHeader(hdr, shdr + i); + + return shdr; +} + + +char *ReadStringTable(Elf32_Ehdr *hdr, Elf32_Shdr *shdr_table, FILE *f) +{ + Elf32_Shdr *shdr = shdr_table + hdr->e_shstrndx; + char *string_table; + + string_table = new char[shdr->sh_size]; + fseek(f, shdr->sh_offset, SEEK_SET); + fread(string_table, shdr->sh_size, 1, f); + + return string_table; +} + +int ReadSection(Elf32_Shdr *shdr, void *buffer, FILE *f) +{ + if (fseek(f, shdr->sh_offset, SEEK_SET) != 0) + return -1; + if (fread(buffer, shdr->sh_size, 1, f) != 1) + return -1; + return 0; +} + +char *GetSymbolName(Elf32_Half index, char *string_table) +{ + return string_table + index; +} + +Elf32_Shdr *FindSymbolTableSection(Elf32_Ehdr *hdr, + Elf32_Shdr *shdr, + char *string_table) +{ + for(int ii = 0; ii < hdr->e_shnum; ii++) { + if (shdr[ii].sh_type == SHT_SYMTAB && + strcmp(GetSymbolName(shdr[ii].sh_name, string_table), + ".symtab") == 0) + { + return &shdr[ii]; + } + } + return NULL; +} + +Elf32_Shdr *FindSymbolStringTableSection(Elf32_Ehdr *hdr, + Elf32_Shdr *shdr, + char *string_table) +{ + for(int ii = 0; ii < hdr->e_shnum; ii++) { + if (shdr[ii].sh_type == SHT_STRTAB && + strcmp(GetSymbolName(shdr[ii].sh_name, string_table), + ".strtab") == 0) + { + return &shdr[ii]; + } + } + return NULL; +} |