OpenCores
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", &sectionNames_[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(&sectionNames_[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(&sectionNames_[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", &sectionNames_[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(&sectionNames_[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(&sectionNames_[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__

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.