URL
https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk
Subversion Repositories riscv_vhdl
Compare Revisions
- This comparison shows the changes necessary to convert path
/riscv_vhdl/trunk/debugger/src/libdbg64g/services/elfloader
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/srcproc.cpp
File deleted
/srcproc.h
File deleted
/elf_types.h
1,179 → 1,412
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief elf-file loader class declaration. |
*/ |
|
#ifndef __DEBUGGER_ELF_TYPES_H__ |
#define __DEBUGGER_ELF_TYPES_H__ |
|
#include <inttypes.h> |
|
namespace debugger { |
|
//#define EI_NIDENT 16 |
#define ARCH_64BITS |
|
#ifdef ARCH_64BITS |
typedef uint64_t Elf32_Addr; |
typedef uint64_t Elf32_Off; |
#else |
typedef unsigned int Elf32_Addr; |
typedef unsigned int Elf32_Off; |
#endif |
typedef unsigned short Elf32_Half; |
typedef signed int Elf32_Sword; |
typedef unsigned int Elf32_Word; |
|
static const char MAGIC_BYTES[] = {0x7f,'E','L','F',0}; |
|
enum E_EI { |
EI_MAG0, |
EI_MAG1, |
EI_MAG2, |
EI_MAG3, |
EI_CLASS, |
EI_DATA, |
EI_VERSION, |
EI_PAD, |
EI_NIDENT=16 |
}; |
static const uint8_t ELFCLASSNONE = 0; |
static const uint8_t ELFCLASS32 = 1; |
static const uint8_t ELFCLASS64 = 2; |
|
static const uint8_t ELFDATANONE = 0; |
static const uint8_t ELFDATA2LSB = 1; |
static const uint8_t ELFDATA2MSB = 2; |
|
static const uint8_t EV_NONE = 0; // Invalid version |
static const uint8_t EV_CURRENT = 1; // Current version |
//etype values: |
static const Elf32_Half ET_NONE = 0; // no file type |
static const Elf32_Half ET_REL = 1; // rellocatable file |
static const Elf32_Half ET_EXEC = 2; // executable file |
static const Elf32_Half ET_DYN = 3; // shared object file |
static const Elf32_Half ET_CORE = 4; // core file |
static const Elf32_Half ET_LOPROC = 0xff00; // Processor-specific |
static const Elf32_Half ET_HIPROC = 0xffff; // Processor-specific |
//emachine values: |
static const Elf32_Half EM_NONE = 0; // No machine |
static const Elf32_Half EM_M32 = 1; // AT&T WE 32100 |
static const Elf32_Half EM_SPARC = 2; // SPARC |
static const Elf32_Half EM_386 = 3; // Intel 386 |
static const Elf32_Half EM_68K = 4; // Motorola 68000 |
static const Elf32_Half EM_88K = 5; // Motorola 88000 |
static const Elf32_Half EM_860 = 7; // Intel 80860 |
static const Elf32_Half EM_MIPS = 8; // MIPS RS3000 |
|
typedef struct ElfHeaderType |
{ |
unsigned char e_ident[EI_NIDENT]; |
Elf32_Half e_type; // Shared/Executable/Rellocalable etc |
Elf32_Half e_machine; // SPARC, X86 etc |
Elf32_Word e_version; // |
uint64_t e_entry; // entry point |
uint64_t e_phoff; // Program header offset |
uint64_t e_shoff; // Section Header offset |
Elf32_Word e_flags; |
Elf32_Half e_ehsize; |
Elf32_Half e_phentsize; // size of one entry in the Program header. All entries are the same size |
Elf32_Half e_phnum; // number of entries in a Program header |
Elf32_Half e_shentsize; // entry size in the section header table. all entries are the same size |
Elf32_Half e_shnum; // number of section header entries |
Elf32_Half e_shstrndx; |
} ElfHeaderType; |
|
//sh_type: |
static const Elf32_Word SHT_NULL = 0; // section header is inactive |
static const Elf32_Word SHT_PROGBITS = 1; // section with CPU instructions |
static const Elf32_Word SHT_SYMTAB = 2; // section contains symbols table (also as SHT_DYNSIM) |
static const Elf32_Word SHT_STRTAB = 3; // section holds string table |
static const Elf32_Word SHT_RELA = 4; // section with relocation data |
static const Elf32_Word SHT_HASH = 5; // section with hash table. Must be for the dynamic lib |
static const Elf32_Word SHT_DYNAMIC = 6; // section holds information for dynamic linking. |
static const Elf32_Word SHT_NOTE = 7; |
static const Elf32_Word SHT_NOBITS = 8; // section with not initialized data |
static const Elf32_Word SHT_REL = 9; |
static const Elf32_Word SHT_SHLIB = 10; |
static const Elf32_Word SHT_DYNSYM = 11; // section contains debug symbol table |
static const Elf32_Word SHT_LOPROC = 0x70000000; |
static const Elf32_Word SHT_HIPROC = 0x7fffffff; |
static const Elf32_Word SHT_HIUSER = 0xffffffff; |
//sh_flags: |
static const Elf32_Word SHF_WRITE = 0x1; // section contains data that should be writable during process execution. |
static const Elf32_Word SHF_ALLOC = 0x2; // section occupies memory during process execution. |
static const Elf32_Word SHF_EXECINSTR = 0x4; // section contains executable machine instructions. |
static const Elf32_Word SHF_MASKPROC = 0xf0000000; // processor-specific sematic |
|
typedef struct SectionHeaderType |
{ |
Elf32_Word sh_name;//Index in a header section table (gives name of section) |
Elf32_Word sh_type; |
uint64_t sh_flags; |
uint64_t sh_addr; |
uint64_t sh_offset; |
uint64_t sh_size; |
Elf32_Word sh_link; |
Elf32_Word sh_info; |
uint64_t sh_addralign; |
uint64_t sh_entsize; |
} SectionHeaderType; |
|
|
#define ELF32_ST_BIND(i) ((i)>>4) |
#define ELF32_ST_TYPE(i) ((i)&0xf) |
#define ELF32_ST_INFO(b,t) (((b)<<4) + ((t)&0xf)) |
|
static const unsigned char STB_LOCAL = 0; |
static const unsigned char STB_GLOBAL = 1; |
static const unsigned char STB_WEAK = 2; |
static const unsigned char STB_LOPROC = 13; |
static const unsigned char STB_HIPROC = 15; |
|
static const unsigned char STT_NOTYPE = 0; |
static const unsigned char STT_OBJECT = 1; |
static const unsigned char STT_FUNC = 2; |
static const unsigned char STT_SECTION = 3; |
static const unsigned char STT_FILE = 4; |
static const unsigned char STT_LOPROC = 13; |
static const unsigned char STT_HIPROC = 15; |
|
typedef struct SymbolTableType |
{ |
Elf32_Word st_name; |
uint8_t st_info; |
uint8_t st_other; |
Elf32_Half st_shndx; |
uint64_t st_value; |
uint64_t st_size; |
} SymbolTableType; |
|
|
//p_type: |
static const Elf32_Word PT_NULL = 0; |
static const Elf32_Word PT_LOAD = 1; |
static const Elf32_Word PT_DYNAMIC = 2; |
static const Elf32_Word PT_INTERP = 3; |
static const Elf32_Word PT_NOTE = 4; |
static const Elf32_Word PT_SHLIB = 5; |
static const Elf32_Word PT_PHDR = 6; |
static const Elf32_Word PT_LOPROC = 0x70000000; |
static const Elf32_Word PT_HIPROC = 0x7fffffff; |
|
typedef struct ProgramHeaderType |
{ |
uint32_t p_type; |
uint32_t p_offset; |
uint64_t p_vaddr; |
uint64_t p_paddr; |
uint64_t p_filesz; |
uint64_t p_memsz; |
uint64_t p_flags; |
uint64_t p_align; |
} ProgramHeaderType; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_ELF_TYPES_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief elf-file loader class declaration. |
*/ |
|
#ifndef __DEBUGGER_ELF_TYPES_H__ |
#define __DEBUGGER_ELF_TYPES_H__ |
|
#include <inttypes.h> |
|
namespace debugger { |
|
//#define EI_NIDENT 16 |
#define ARCH_64BITS |
|
#ifdef ARCH_64BITS |
typedef uint64_t ElfAddr64; |
typedef uint64_t ElfOff64; |
#else |
typedef unsigned int Elf32_Addr; |
typedef unsigned int Elf32_Off; |
#endif |
typedef unsigned short ElfHalf; |
typedef signed int ElfSword; |
typedef unsigned int ElfWord; |
typedef uint64_t ElfDWord; |
|
typedef unsigned int ElfAddr32; |
typedef unsigned int ElfOff32; |
|
static const char MAGIC_BYTES[] = {0x7f,'E','L','F',0}; |
|
enum E_EI { |
EI_MAG0, |
EI_MAG1, |
EI_MAG2, |
EI_MAG3, |
EI_CLASS, |
EI_DATA, |
EI_VERSION, |
EI_PAD, |
EI_NIDENT=16 |
}; |
static const uint8_t ELFCLASSNONE = 0; |
static const uint8_t ELFCLASS32 = 1; |
static const uint8_t ELFCLASS64 = 2; |
|
static const uint8_t ELFDATANONE = 0; |
static const uint8_t ELFDATA2LSB = 1; |
static const uint8_t ELFDATA2MSB = 2; |
|
static const uint8_t EV_NONE = 0; // Invalid version |
static const uint8_t EV_CURRENT = 1; // Current version |
//etype values: |
static const ElfHalf ET_NONE = 0; // no file type |
static const ElfHalf ET_REL = 1; // rellocatable file |
static const ElfHalf ET_EXEC = 2; // executable file |
static const ElfHalf ET_DYN = 3; // shared object file |
static const ElfHalf ET_CORE = 4; // core file |
static const ElfHalf ET_LOPROC = 0xff00; // Processor-specific |
static const ElfHalf ET_HIPROC = 0xffff; // Processor-specific |
//emachine values: |
static const ElfHalf EM_NONE = 0; // No machine |
static const ElfHalf EM_M32 = 1; // AT&T WE 32100 |
static const ElfHalf EM_SPARC = 2; // SPARC |
static const ElfHalf EM_386 = 3; // Intel 386 |
static const ElfHalf EM_68K = 4; // Motorola 68000 |
static const ElfHalf EM_88K = 5; // Motorola 88000 |
static const ElfHalf EM_860 = 7; // Intel 80860 |
static const ElfHalf EM_MIPS = 8; // MIPS RS3000 |
|
struct Elf32_Ehdr { |
unsigned char e_ident[EI_NIDENT]; |
ElfHalf e_type; // Shared/Executable/Rellocalable etc |
ElfHalf e_machine; // SPARC, X86 etc |
ElfWord e_version; // |
ElfAddr32 e_entry; // entry point |
ElfOff32 e_phoff; // Program header offset |
ElfOff32 e_shoff; // Section Header offset |
ElfWord e_flags; |
ElfHalf e_ehsize; |
ElfHalf e_phentsize; // size of one entry in the Program header. All entries are the same size |
ElfHalf e_phnum; // number of entries in a Program header |
ElfHalf e_shentsize; // entry size in the section header table. all entries are the same size |
ElfHalf e_shnum; // number of section header entries |
ElfHalf e_shstrndx; |
}; |
|
struct Elf64_Ehdr { |
unsigned char e_ident[EI_NIDENT]; |
ElfHalf e_type; // Shared/Executable/Rellocalable etc |
ElfHalf e_machine; // SPARC, X86 etc |
ElfWord e_version; // |
ElfAddr64 e_entry; // entry point |
ElfOff64 e_phoff; // Program header offset |
ElfOff64 e_shoff; // Section Header offset |
ElfWord e_flags; |
ElfHalf e_ehsize; |
ElfHalf e_phentsize; // size of one entry in the Program header. All entries are the same size |
ElfHalf e_phnum; // number of entries in a Program header |
ElfHalf e_shentsize; // entry size in the section header table. all entries are the same size |
ElfHalf e_shnum; // number of section header entries |
ElfHalf e_shstrndx; |
}; |
|
|
static ElfHalf SwapBytes(ElfHalf v) { |
v = ((v>>8)&0xff) | ((v&0xFF)<<8); |
return v; |
} |
|
static ElfWord SwapBytes(ElfWord v) { |
v = ((v >> 24) & 0xff) | ((v >> 8) & 0xff00) |
| ((v << 8) & 0xff0000) | ((v & 0xFF) << 24); |
return v; |
} |
|
static ElfDWord SwapBytes(ElfDWord v) { |
v = ((v >> 56) & 0xffull) | ((v >> 48) & 0xff00ull) |
| ((v >> 40) & 0xff0000ull) | ((v >> 32) & 0xff000000ull) |
| ((v << 8) & 0xff000000ull) | ((v << 16) & 0xff0000000000ull) |
| ((v << 24) & 0xff0000000000ull) | ((v << 32) & 0xff00000000000000ull); |
return v; |
} |
|
class ElfHeaderType { |
public: |
ElfHeaderType(uint8_t *img) { |
pimg_ = img; |
isElf_ = true; |
for (int i = 0; i < 4; i++) { |
if (pimg_[i] != MAGIC_BYTES[i]) { |
isElf_ = false; |
} |
} |
is32b_ = pimg_[EI_CLASS] == ELFCLASS32; |
isMsb_ = pimg_[EI_DATA] == ELFDATA2MSB; |
if (is32b_) { |
Elf32_Ehdr *h = reinterpret_cast<Elf32_Ehdr *>(pimg_); |
if (isMsb_) { |
e_shoff_ = SwapBytes(h->e_shoff); |
e_shnum_ = SwapBytes(h->e_shnum); |
e_phoff_ = SwapBytes(h->e_phoff); |
} else { |
e_shoff_ = h->e_shoff; |
e_shnum_ = h->e_shnum; |
e_phoff_ = h->e_phoff; |
} |
} else { |
Elf64_Ehdr *h = reinterpret_cast<Elf64_Ehdr *>(pimg_); |
if (isMsb_) { |
e_shoff_ = SwapBytes(h->e_shoff); |
e_shnum_ = SwapBytes(h->e_shnum); |
e_phoff_ = SwapBytes(h->e_phoff); |
} else { |
e_shoff_ = h->e_shoff; |
e_shnum_ = h->e_shnum; |
e_phoff_ = h->e_phoff; |
} |
} |
} |
|
virtual bool isElf() { return isElf_; } |
virtual bool isElf32() { return is32b_; } |
virtual bool isElfMsb() { return isMsb_; } |
virtual uint64_t get_shoff() { return e_shoff_; } |
virtual ElfHalf get_shnum() { return e_shnum_; } |
virtual uint64_t get_phoff() { return e_phoff_; } |
protected: |
uint8_t *pimg_; |
bool isElf_; |
bool is32b_; |
bool isMsb_; |
uint64_t e_shoff_; |
ElfHalf e_shnum_; |
uint64_t e_phoff_; |
}; |
|
|
//sh_type: |
static const ElfWord SHT_NULL = 0; // section header is inactive |
static const ElfWord SHT_PROGBITS = 1; // section with CPU instructions |
static const ElfWord SHT_SYMTAB = 2; // section contains symbols table (also as SHT_DYNSIM) |
static const ElfWord SHT_STRTAB = 3; // section holds string table |
static const ElfWord SHT_RELA = 4; // section with relocation data |
static const ElfWord SHT_HASH = 5; // section with hash table. Must be for the dynamic lib |
static const ElfWord SHT_DYNAMIC = 6; // section holds information for dynamic linking. |
static const ElfWord SHT_NOTE = 7; |
static const ElfWord SHT_NOBITS = 8; // section with not initialized data |
static const ElfWord SHT_REL = 9; |
static const ElfWord SHT_SHLIB = 10; |
static const ElfWord SHT_DYNSYM = 11; // section contains debug symbol table |
static const ElfWord SHT_LOPROC = 0x70000000; |
static const ElfWord SHT_HIPROC = 0x7fffffff; |
static const ElfWord SHT_HIUSER = 0xffffffff; |
//sh_flags: |
static const ElfWord SHF_WRITE = 0x1; // section contains data that should be writable during process execution. |
static const ElfWord SHF_ALLOC = 0x2; // section occupies memory during process execution. |
static const ElfWord SHF_EXECINSTR = 0x4; // section contains executable machine instructions. |
static const ElfWord SHF_MASKPROC = 0xf0000000; // processor-specific sematic |
|
struct Elf32_Shdr { |
ElfWord sh_name;//Index in a header section table (gives name of section) |
ElfWord sh_type; |
ElfWord sh_flags; /* SHF_... */ |
ElfAddr32 sh_addr; |
ElfOff32 sh_offset; |
ElfWord sh_size; |
ElfWord sh_link; |
ElfWord sh_info; |
ElfWord sh_addralign; |
ElfWord sh_entsize; |
}; |
|
struct Elf64_Shdr { |
ElfWord sh_name;//Index in a header section table (gives name of section) |
ElfWord sh_type; |
ElfDWord sh_flags; |
ElfAddr64 sh_addr; |
ElfOff64 sh_offset; |
ElfDWord sh_size; |
ElfWord sh_link; |
ElfWord sh_info; |
ElfDWord sh_addralign; |
ElfDWord sh_entsize; |
}; |
|
class SectionHeaderType { |
public: |
SectionHeaderType(uint8_t *img, ElfHeaderType *h) { |
if (h->isElf32()) { |
Elf32_Shdr *sh = reinterpret_cast<Elf32_Shdr *>(img); |
if (h->isElfMsb()) { |
sh_name_ = SwapBytes(sh->sh_name); |
sh_type_ = SwapBytes(sh->sh_type); |
sh_flags_ = SwapBytes(sh->sh_flags); |
sh_addr_ = SwapBytes(sh->sh_addr); |
sh_offset_ = SwapBytes(sh->sh_offset); |
sh_size_ = SwapBytes(sh->sh_size); |
sh_entsize_ = SwapBytes(sh->sh_entsize); |
} else { |
sh_name_ = sh->sh_name; |
sh_type_ = sh->sh_type; |
sh_flags_ = sh->sh_flags; |
sh_addr_ = sh->sh_addr; |
sh_offset_ = sh->sh_offset; |
sh_size_ = sh->sh_size; |
sh_entsize_ = sh->sh_entsize; |
} |
} else { |
Elf64_Shdr *sh = reinterpret_cast<Elf64_Shdr *>(img); |
if (h->isElfMsb()) { |
sh_name_ = SwapBytes(sh->sh_name); |
sh_type_ = SwapBytes(sh->sh_type); |
sh_flags_ = SwapBytes(sh->sh_flags); |
sh_addr_ = SwapBytes(sh->sh_addr); |
sh_offset_ = SwapBytes(sh->sh_offset); |
sh_size_ = SwapBytes(sh->sh_size); |
sh_entsize_ = SwapBytes(sh->sh_entsize); |
} else { |
sh_name_ = sh->sh_name; |
sh_type_ = sh->sh_type; |
sh_flags_ = sh->sh_flags; |
sh_addr_ = sh->sh_addr; |
sh_offset_ = sh->sh_offset; |
sh_size_ = sh->sh_size; |
sh_entsize_ = sh->sh_entsize; |
} |
} |
} |
virtual ElfWord get_name() { return sh_name_; } |
virtual ElfWord get_type() { return sh_type_; } |
virtual uint64_t get_offset() { return sh_offset_; } |
virtual uint64_t get_size() { return sh_size_; } |
virtual uint64_t get_addr() { return sh_addr_; } |
virtual uint64_t get_flags() { return sh_flags_; } |
virtual uint64_t get_entsize() { return sh_entsize_; } |
protected: |
ElfWord sh_name_; |
ElfWord sh_type_; |
uint64_t sh_offset_; |
uint64_t sh_size_; |
uint64_t sh_addr_; |
uint64_t sh_flags_; |
uint64_t sh_entsize_; |
}; |
|
|
#define ELF32_ST_BIND(i) ((i)>>4) |
#define ELF32_ST_TYPE(i) ((i)&0xf) |
#define ELF32_ST_INFO(b,t) (((b)<<4) + ((t)&0xf)) |
|
static const unsigned char STB_LOCAL = 0; |
static const unsigned char STB_GLOBAL = 1; |
static const unsigned char STB_WEAK = 2; |
static const unsigned char STB_LOPROC = 13; |
static const unsigned char STB_HIPROC = 15; |
|
static const unsigned char STT_NOTYPE = 0; |
static const unsigned char STT_OBJECT = 1; |
static const unsigned char STT_FUNC = 2; |
static const unsigned char STT_SECTION = 3; |
static const unsigned char STT_FILE = 4; |
static const unsigned char STT_LOPROC = 13; |
static const unsigned char STT_HIPROC = 15; |
|
struct Elf32_Sym { |
ElfWord st_name; |
ElfAddr32 st_value; |
ElfWord st_size; |
unsigned char st_info; |
unsigned char st_other; |
ElfHalf st_shndx; |
}; |
|
struct Elf64_Sym { |
ElfWord st_name; |
unsigned char st_info; |
unsigned char st_other; |
ElfHalf st_shndx; |
ElfAddr64 st_value; |
ElfDWord st_size; |
}; |
|
class SymbolTableType { |
public: |
SymbolTableType(uint8_t *img, ElfHeaderType *h) { |
if (h->isElf32()) { |
Elf32_Sym *st = reinterpret_cast<Elf32_Sym *>(img); |
if (h->isElfMsb()) { |
st_name_ = SwapBytes(st->st_name); |
st_value_ = SwapBytes(st->st_value); |
st_size_ = SwapBytes(st->st_size); |
} else { |
st_name_ = st->st_name; |
st_value_ = st->st_value; |
st_size_ = st->st_size; |
} |
st_info_ = st->st_info; |
} else { |
Elf64_Sym *st = reinterpret_cast<Elf64_Sym *>(img); |
if (h->isElfMsb()) { |
st_name_ = SwapBytes(st->st_name); |
st_value_ = SwapBytes(st->st_value); |
st_size_ = SwapBytes(st->st_size); |
} else { |
st_name_ = st->st_name; |
st_value_ = st->st_value; |
st_size_ = st->st_size; |
} |
st_info_ = st->st_info; |
} |
} |
virtual ElfWord get_name() { return st_name_; } |
virtual uint64_t get_value() { return st_value_; } |
virtual uint64_t get_size() { return st_size_; } |
virtual unsigned char get_info() { return st_info_; } |
protected: |
ElfWord st_name_; |
unsigned char st_info_; |
uint64_t st_value_; |
uint64_t st_size_; |
}; |
|
|
//p_type: |
static const ElfWord PT_NULL = 0; |
static const ElfWord PT_LOAD = 1; |
static const ElfWord PT_DYNAMIC = 2; |
static const ElfWord PT_INTERP = 3; |
static const ElfWord PT_NOTE = 4; |
static const ElfWord PT_SHLIB = 5; |
static const ElfWord PT_PHDR = 6; |
static const ElfWord PT_LOPROC = 0x70000000; |
static const ElfWord PT_HIPROC = 0x7fffffff; |
|
typedef struct ProgramHeaderType64 |
{ |
uint32_t p_type; |
uint32_t p_offset; |
uint64_t p_vaddr; |
uint64_t p_paddr; |
#ifdef ARCH_64BITS |
ElfDWord p_filesz; |
ElfDWord p_memsz; |
ElfDWord p_flags; |
ElfDWord p_align; |
#else |
Elf32_Word p_filesz; |
Elf32_Word p_memsz; |
Elf32_Word p_flags; |
Elf32_Word p_align; |
#endif |
} ProgramHeaderType64; |
|
typedef struct ProgramHeaderType32 |
{ |
uint32_t p_type; |
uint32_t p_offset; |
ElfAddr32 p_vaddr; |
ElfAddr32 p_paddr; |
ElfWord p_filesz; |
ElfWord p_memsz; |
ElfWord p_flags; |
ElfWord p_align; |
} ProgramHeaderType32; |
|
} // namespace debugger |
|
#endif // __DEBUGGER_ELF_TYPES_H__ |
/elfreader.cpp
1,290 → 1,270
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief elf-file loader class implementation. |
*/ |
|
#include "elfreader.h" |
#include <iostream> |
|
namespace debugger { |
|
/** Class registration in the Core */ |
REGISTER_CLASS(ElfReaderService) |
|
ElfReaderService::ElfReaderService(const char *name) : IService(name) { |
registerInterface(static_cast<IElfReader *>(this)); |
image_ = NULL; |
sectionNames_ = NULL; |
symbolList_.make_list(0); |
loadSectionList_.make_list(0); |
} |
|
ElfReaderService::~ElfReaderService() { |
if (image_) { |
delete image_; |
} |
} |
|
void ElfReaderService::postinitService() { |
} |
|
int ElfReaderService::readFile(const char *filename) { |
FILE *fp = fopen(filename, "rb"); |
if (!fp) { |
RISCV_error("File '%s' not found", filename); |
return -1; |
} |
fseek(fp, 0, SEEK_END); |
int sz = ftell(fp); |
rewind(fp); |
|
if (image_) { |
delete image_; |
sectionNames_ = NULL; |
} |
image_ = new uint8_t[sz]; |
fread(image_, 1, sz, fp); |
|
if (readElfHeader() != 0) { |
fclose(fp); |
return 0; |
} |
|
if (!header_->e_shoff) { |
fclose(fp); |
return 0; |
} |
|
/** Init names */ |
SectionHeaderType *sh; |
sh_tbl_ = |
reinterpret_cast<SectionHeaderType *>(&image_[header_->e_shoff]); |
for (int i = 0; i < header_->e_shnum; i++) { |
sh = &sh_tbl_[i]; |
if (sh->sh_type == SHT_STRTAB) { |
processStringTable(sh); |
} |
} |
|
/** Direct loading via tap interface: */ |
int bytes_loaded = loadSections(); |
RISCV_info("Loaded: %d B", bytes_loaded); |
|
if (header_->e_phoff) { |
//readProgramHeader(); |
} |
|
fclose(fp); |
return 0; |
} |
|
int ElfReaderService::readElfHeader() { |
header_ = reinterpret_cast<ElfHeaderType *>(image_); |
for (int i = 0; i < 4; i++) { |
if (header_->e_ident[i] != MAGIC_BYTES[i]) { |
RISCV_error("File format is not ELF", NULL); |
return -1; |
} |
} |
return 0; |
} |
|
int ElfReaderService::loadSections() { |
SectionHeaderType *sh; |
uint64_t total_bytes = 0; |
AttributeType tsymb; |
|
for (int i = 0; i < header_->e_shnum; i++) { |
sh = &sh_tbl_[i]; |
|
if (sh->sh_size == 0) { |
continue; |
} |
|
if (sectionNames_ && (sh->sh_flags & SHF_ALLOC)) { |
RISCV_info("Reading '%s' section", §ionNames_[sh->sh_name]); |
} |
|
if (sh->sh_type == SHT_PROGBITS && (sh->sh_flags & SHF_ALLOC) != 0) { |
/** |
* @brief Instructions or other processor's information |
* @details This section holds information defined by the program, |
* whose format and meaning are determined solely by the |
* program. |
*/ |
AttributeType loadsec; |
loadsec.make_list(LoadSh_Total); |
if (sectionNames_) { |
loadsec[LoadSh_name].make_string(§ionNames_[sh->sh_name]); |
} else { |
loadsec[LoadSh_name].make_string("unknown"); |
} |
loadsec[LoadSh_addr].make_uint64(sh->sh_addr); |
loadsec[LoadSh_size].make_uint64(sh->sh_size); |
loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->sh_size), |
&image_[sh->sh_offset]); |
loadSectionList_.add_to_list(&loadsec); |
total_bytes += sh->sh_size; |
} else if (sh->sh_type == SHT_NOBITS |
&& (sh->sh_flags & SHF_ALLOC) != 0) { |
/** |
* @brief Initialized data |
* @details A section of this type occupies no space in the file |
* but otherwise resembles SHT_PROGBITS. Although this |
* section contains no bytes, the sh_offset member |
* contains the conceptual file offset. |
*/ |
AttributeType loadsec; |
loadsec.make_list(LoadSh_Total); |
if (sectionNames_) { |
loadsec[LoadSh_name].make_string(§ionNames_[sh->sh_name]); |
} else { |
loadsec[LoadSh_name].make_string("unknown"); |
} |
loadsec[LoadSh_addr].make_uint64(sh->sh_addr); |
loadsec[LoadSh_size].make_uint64(sh->sh_size); |
loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->sh_size)); |
memset(loadsec[LoadSh_data].data(), |
0, static_cast<size_t>(sh->sh_size)); |
loadSectionList_.add_to_list(&loadsec); |
total_bytes += sh->sh_size; |
} else if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) { |
processDebugSymbol(sh); |
} |
} |
symbolList_.sort(LoadSh_name); |
symbolListSortByAddr_ = symbolList_; |
symbolListSortByAddr_.sort(LoadSh_addr); |
return static_cast<int>(total_bytes); |
} |
|
void ElfReaderService::processStringTable(SectionHeaderType *sh) { |
if (sectionNames_ == NULL) { |
sectionNames_ = reinterpret_cast<char *>(&image_[sh->sh_offset]); |
if (strcmp(sectionNames_ + sh->sh_name, ".shstrtab") != 0) { |
/** This section holds section names. */ |
printf("err: undefined .shstrtab section\n"); |
sectionNames_ = NULL; |
} |
} else if (strcmp(sectionNames_ + sh->sh_name, ".strtab") == 0) { |
/** |
* This section holds strings, most commonly the strings that |
* represent the names associated with symbol table entries. |
* If the file has a loadable segment that includes the symbol |
* string table, the section's attributes will include the |
* SHF_ALLOC bit; otherwise, that bit will be turned off. |
*/ |
symbolNames_ = reinterpret_cast<char *>(&image_[sh->sh_offset]); |
} else { |
RISCV_error("Unsupported string section %s", |
sectionNames_ + sh->sh_name); |
} |
} |
|
void ElfReaderService::processDebugSymbol(SectionHeaderType *sh) { |
uint64_t symbol_off = 0; |
SymbolTableType *st; |
AttributeType tsymb; |
uint8_t st_type; |
const char *symb_name; |
//const char *file_name = 0; |
|
if (!symbolNames_) { |
return; |
} |
|
while (symbol_off < sh->sh_size) { |
st = reinterpret_cast<SymbolTableType *> |
(&image_[sh->sh_offset + symbol_off]); |
symb_name = &symbolNames_[st->st_name]; |
|
if (sh->sh_entsize) { |
// section with elements of fixed size |
symbol_off += sh->sh_entsize; |
} else if (st->st_size) { |
symbol_off += st->st_size; |
} else { |
symbol_off += sizeof(SymbolTableType); |
} |
|
st_type = st->st_info & 0xF; |
if ((st_type == STT_OBJECT || st_type == STT_FUNC) && st->st_value) { |
tsymb.make_list(Symbol_Total); |
tsymb[Symbol_Name].make_string(symb_name); |
tsymb[Symbol_Addr].make_uint64(st->st_value); |
tsymb[Symbol_Size].make_uint64(st->st_size); |
if (st_type == STT_FUNC) { |
tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_FUNCTION); |
} else { |
tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_DATA); |
} |
symbolList_.add_to_list(&tsymb); |
} else if (st_type == STT_FILE) { |
//file_name = symb_name; |
} |
} |
} |
|
void ElfReaderService::addressToSymbol(uint64_t addr, AttributeType *info) { |
uint64_t sadr, send; |
int sz = static_cast<int>(symbolListSortByAddr_.size()); |
|
info->make_list(2); |
(*info)[0u].make_string(""); |
(*info)[1].make_uint64(0); |
if (sz == 0) { |
return; |
} |
sadr = symbolListSortByAddr_[0u][Symbol_Addr].to_uint64(); |
if (addr < sadr) { |
return; |
} |
|
bool search = true; |
int dist, pos = sz / 2; |
dist = pos; |
while (search) { |
AttributeType &symb = symbolListSortByAddr_[pos]; |
sadr = symb[Symbol_Addr].to_uint64(); |
send = sadr + symb[Symbol_Size].to_uint64(); |
if (sadr <= addr && addr < send) { |
(*info)[0u] = symb[Symbol_Name]; |
(*info)[1].make_uint64(addr - sadr); |
return; |
} |
|
if (addr < sadr) { |
if (dist == 0 || pos == 0) { |
search = false; |
} else if (dist == 1) { |
dist = 0; |
pos--; |
} else { |
int incr = dist / 2; |
pos -= incr; |
dist = (dist / 2) + (dist & 0x1); |
if (pos < 0) { |
pos = 0; |
} |
} |
} else { |
if (dist == 0 || pos == (sz - 1)) { |
search = false; |
} else if (dist == 1) { |
dist = 0; |
pos++; |
} else { |
int incr = dist / 2; |
pos += incr; |
dist = (dist / 2) + (dist & 0x1); |
if (pos >= sz) { |
pos = sz - 1; |
} |
} |
} |
} |
} |
|
} // namespace debugger |
/* |
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com |
* |
* Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at |
* |
* http://www.apache.org/licenses/LICENSE-2.0 |
* |
* Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and |
* limitations under the License. |
*/ |
|
#include "elfreader.h" |
#include <iostream> |
|
namespace debugger { |
|
/** Class registration in the Core */ |
REGISTER_CLASS(ElfReaderService) |
|
ElfReaderService::ElfReaderService(const char *name) : IService(name) { |
registerInterface(static_cast<IElfReader *>(this)); |
registerAttribute("SourceProc", &sourceProc_); |
image_ = NULL; |
sectionNames_ = NULL; |
symbolList_.make_list(0); |
loadSectionList_.make_list(0); |
sourceProc_.make_string(""); |
isrc_ = 0; |
} |
|
ElfReaderService::~ElfReaderService() { |
if (image_) { |
delete image_; |
} |
} |
|
void ElfReaderService::postinitService() { |
isrc_ = static_cast<ISourceCode *>( |
RISCV_get_service_iface(sourceProc_.to_string(), |
IFACE_SOURCE_CODE)); |
if (!isrc_) { |
RISCV_error("SourceCode interface '%s' not found", |
sourceProc_.to_string()); |
} |
} |
|
int ElfReaderService::readFile(const char *filename) { |
FILE *fp = fopen(filename, "rb"); |
if (!fp) { |
RISCV_error("File '%s' not found", filename); |
return -1; |
} |
fseek(fp, 0, SEEK_END); |
int sz = ftell(fp); |
rewind(fp); |
|
if (image_) { |
delete image_; |
sectionNames_ = NULL; |
sourceProc_.make_list(0); |
symbolList_.make_list(0); |
loadSectionList_.make_list(0); |
} |
image_ = new uint8_t[sz]; |
fread(image_, 1, sz, fp); |
|
if (readElfHeader() != 0) { |
fclose(fp); |
return 0; |
} |
|
symbolNames_ = 0; |
if (!header_->get_shoff()) { |
fclose(fp); |
return 0; |
} |
|
sh_tbl_ = new SectionHeaderType *[header_->get_shnum()]; |
|
/** Search .shstrtab section */ |
uint8_t *psh = &image_[header_->get_shoff()]; |
for (int i = 0; i < header_->get_shnum(); i++) { |
sh_tbl_[i] = new SectionHeaderType(psh, header_); |
|
sectionNames_ = reinterpret_cast<char *>(&image_[sh_tbl_[i]->get_offset()]); |
if (sh_tbl_[i]->get_type() == SHT_STRTAB && |
strcmp(sectionNames_ + sh_tbl_[i]->get_name(), ".shstrtab") != 0) { |
sectionNames_ = NULL; |
} |
|
if (header_->isElf32()) { |
psh += sizeof(Elf32_Shdr); |
} else { |
psh += sizeof(Elf64_Shdr); |
} |
} |
if (!sectionNames_) { |
printf("err: section .shstrtab not found.\n"); |
} |
|
/** Search ".strtab" section with Debug symbols */ |
SectionHeaderType *sh; |
for (int i = 0; i < header_->get_shnum(); i++) { |
sh = sh_tbl_[i]; |
if (sectionNames_ == NULL || sh->get_type() != SHT_STRTAB) { |
continue; |
} |
if (strcmp(sectionNames_ + sh->get_name(), ".strtab")) { |
continue; |
} |
/** |
* This section holds strings, most commonly the strings that |
* represent the names associated with symbol table entries. |
* If the file has a loadable segment that includes the symbol |
* string table, the section's attributes will include the |
* SHF_ALLOC bit; otherwise, that bit will be turned off. |
*/ |
symbolNames_ = reinterpret_cast<char *>(&image_[sh->get_offset()]); |
} |
if (!symbolNames_) { |
printf("err: section .strtab not found. No debug symbols.\n"); |
} |
|
/** Direct loading via tap interface: */ |
int bytes_loaded = loadSections(); |
RISCV_info("Loaded: %d B", bytes_loaded); |
|
if (header_->get_phoff()) { |
//readProgramHeader(); |
} |
|
fclose(fp); |
return 0; |
} |
|
int ElfReaderService::readElfHeader() { |
header_ = new ElfHeaderType(image_); |
if (header_->isElf()) { |
return 0; |
} |
RISCV_error("File format is not ELF", NULL); |
return -1; |
} |
|
int ElfReaderService::loadSections() { |
SectionHeaderType *sh; |
uint64_t total_bytes = 0; |
AttributeType tsymb; |
|
for (int i = 0; i < header_->get_shnum(); i++) { |
sh = sh_tbl_[i]; |
|
if (sh->get_size() == 0) { |
continue; |
} |
|
if (sectionNames_ && (sh->get_flags() & SHF_ALLOC)) { |
RISCV_info("Reading '%s' section", §ionNames_[sh->get_name()]); |
} |
|
if (sh->get_type() == SHT_PROGBITS && (sh->get_flags() & SHF_ALLOC) != 0) { |
/** |
* @brief Instructions or other processor's information |
* @details This section holds information defined by the program, |
* whose format and meaning are determined solely by the |
* program. |
*/ |
AttributeType loadsec; |
loadsec.make_list(LoadSh_Total); |
if (sectionNames_) { |
loadsec[LoadSh_name].make_string(§ionNames_[sh->get_name()]); |
} else { |
loadsec[LoadSh_name].make_string("unknown"); |
} |
loadsec[LoadSh_addr].make_uint64(sh->get_addr()); |
loadsec[LoadSh_size].make_uint64(sh->get_size()); |
loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->get_size()), |
&image_[sh->get_offset()]); |
loadSectionList_.add_to_list(&loadsec); |
total_bytes += sh->get_size(); |
} else if (sh->get_type() == SHT_NOBITS |
&& (sh->get_flags() & SHF_ALLOC) != 0) { |
/** |
* @brief Initialized data |
* @details A section of this type occupies no space in the file |
* but otherwise resembles SHT_PROGBITS. Although this |
* section contains no bytes, the sh_offset member |
* contains the conceptual file offset. |
*/ |
AttributeType loadsec; |
loadsec.make_list(LoadSh_Total); |
if (sectionNames_) { |
loadsec[LoadSh_name].make_string(§ionNames_[sh->get_name()]); |
} else { |
loadsec[LoadSh_name].make_string("unknown"); |
} |
loadsec[LoadSh_addr].make_uint64(sh->get_addr()); |
loadsec[LoadSh_size].make_uint64(sh->get_size()); |
loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->get_size())); |
memset(loadsec[LoadSh_data].data(), |
0, static_cast<size_t>(sh->get_size())); |
loadSectionList_.add_to_list(&loadsec); |
total_bytes += sh->get_size(); |
} else if (sh->get_type() == SHT_SYMTAB || sh->get_type() == SHT_DYNSYM) { |
processDebugSymbol(sh); |
} |
} |
symbolList_.sort(LoadSh_name); |
if (isrc_) { |
isrc_->addSymbols(&symbolList_); |
} |
return static_cast<int>(total_bytes); |
} |
|
void ElfReaderService::processDebugSymbol(SectionHeaderType *sh) { |
uint64_t symbol_off = 0; |
SymbolTableType *st; |
AttributeType tsymb; |
uint8_t st_type; |
const char *symb_name; |
//const char *file_name = 0; |
|
if (!symbolNames_) { |
return; |
} |
|
while (symbol_off < sh->get_size()) { |
st = new SymbolTableType(&image_[sh->get_offset() + symbol_off], |
header_); |
|
symb_name = &symbolNames_[st->get_name()]; |
|
st_type = st->get_info() & 0xF; |
if ((st_type == STT_OBJECT || st_type == STT_FUNC) && st->get_value()) { |
tsymb.make_list(Symbol_Total); |
tsymb[Symbol_Name].make_string(symb_name); |
tsymb[Symbol_Addr].make_uint64(st->get_value()); |
tsymb[Symbol_Size].make_uint64(st->get_size()); |
if (st_type == STT_FUNC) { |
tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_FUNCTION); |
} else { |
tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_DATA); |
} |
symbolList_.add_to_list(&tsymb); |
} else if (st_type == STT_FILE) { |
//file_name = symb_name; |
} |
|
if (sh->get_entsize()) { |
// section with elements of fixed size |
symbol_off += sh->get_entsize(); |
} else if (st->get_size()) { |
symbol_off += st->get_size(); |
} else { |
if (header_->isElf32()) { |
symbol_off += sizeof(Elf32_Sym); |
} else { |
symbol_off += sizeof(Elf64_Sym); |
} |
} |
delete st; |
} |
} |
|
} // namespace debugger |
/elfreader.h
1,85 → 1,87
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief elf-file loader class declaration. |
*/ |
|
#ifndef __DEBUGGER_ELF_LOADER_H__ |
#define __DEBUGGER_ELF_LOADER_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/itap.h" |
#include "coreservices/ielfreader.h" |
#include "elf_types.h" |
|
namespace debugger { |
|
class ElfReaderService : public IService, |
public IElfReader { |
public: |
explicit ElfReaderService(const char *name); |
virtual ~ElfReaderService(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IElfReader interface */ |
virtual int readFile(const char *filename); |
|
virtual unsigned loadableSectionTotal() { |
return loadSectionList_.size(); |
} |
|
virtual const char *sectionName(unsigned idx) { |
return loadSectionList_[idx][LoadSh_name].to_string(); |
} |
|
virtual uint64_t sectionAddress(unsigned idx) { |
return loadSectionList_[idx][LoadSh_addr].to_uint64(); |
} |
|
virtual uint64_t sectionSize(unsigned idx) { |
return loadSectionList_[idx][LoadSh_size].to_uint64(); |
} |
|
virtual uint8_t *sectionData(unsigned idx) { |
return loadSectionList_[idx][LoadSh_data].data(); |
} |
|
virtual void getSymbols(AttributeType *list) { *list = symbolList_; } |
|
virtual void addressToSymbol(uint64_t addr, AttributeType *info); |
|
private: |
int readElfHeader(); |
int loadSections(); |
void processStringTable(SectionHeaderType *sh); |
void processDebugSymbol(SectionHeaderType *sh); |
|
private: |
enum ELoadSectionItem { |
LoadSh_name, |
LoadSh_addr, |
LoadSh_size, |
LoadSh_data, |
LoadSh_Total, |
}; |
|
AttributeType symbolList_; |
AttributeType symbolListSortByAddr_; |
AttributeType loadSectionList_; |
|
uint8_t *image_; |
ElfHeaderType *header_; |
SectionHeaderType *sh_tbl_; |
char *sectionNames_; |
char *symbolNames_; |
}; |
|
DECLARE_CLASS(ElfReaderService) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_ELF_LOADER_H__ |
/** |
* @file |
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. |
* @author Sergey Khabarov - sergeykhbr@gmail.com |
* @brief elf-file loader class declaration. |
*/ |
|
#ifndef __DEBUGGER_ELF_LOADER_H__ |
#define __DEBUGGER_ELF_LOADER_H__ |
|
#include "iclass.h" |
#include "iservice.h" |
#include "coreservices/itap.h" |
#include "coreservices/ielfreader.h" |
#include "coreservices/isrccode.h" |
#include "elf_types.h" |
|
namespace debugger { |
|
class ElfReaderService : public IService, |
public IElfReader { |
public: |
explicit ElfReaderService(const char *name); |
virtual ~ElfReaderService(); |
|
/** IService interface */ |
virtual void postinitService(); |
|
/** IElfReader interface */ |
virtual int readFile(const char *filename); |
|
virtual unsigned loadableSectionTotal() { |
return loadSectionList_.size(); |
} |
|
virtual const char *sectionName(unsigned idx) { |
return loadSectionList_[idx][LoadSh_name].to_string(); |
} |
|
virtual uint64_t sectionAddress(unsigned idx) { |
return loadSectionList_[idx][LoadSh_addr].to_uint64(); |
} |
|
virtual uint64_t sectionSize(unsigned idx) { |
return loadSectionList_[idx][LoadSh_size].to_uint64(); |
} |
|
virtual uint8_t *sectionData(unsigned idx) { |
return loadSectionList_[idx][LoadSh_data].data(); |
} |
|
private: |
int readElfHeader(); |
int loadSections(); |
void processDebugSymbol(SectionHeaderType *sh); |
|
private: |
enum ELoadSectionItem { |
LoadSh_name, |
LoadSh_addr, |
LoadSh_size, |
LoadSh_data, |
LoadSh_Total, |
}; |
|
enum EMode { |
Mode_32bits, |
Mode_64bits |
} emode_; |
|
AttributeType sourceProc_; |
AttributeType symbolList_; |
AttributeType loadSectionList_; |
|
ISourceCode *isrc_; |
uint8_t *image_; |
ElfHeaderType *header_; |
SectionHeaderType **sh_tbl_; |
char *sectionNames_; |
char *symbolNames_; |
}; |
|
DECLARE_CLASS(ElfReaderService) |
|
} // namespace debugger |
|
#endif // __DEBUGGER_ELF_LOADER_H__ |