OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [elfloader/] [elfreader.cpp] - Diff between revs 2 and 4

Show entire file | Details | Blame | View Log

Rev 2 Rev 4
Line 1... Line 1...
/**
/*
 * @file
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
 *
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
 *  Licensed under the Apache License, Version 2.0 (the "License");
 * @brief      elf-file loader class implementation.
 *  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 "elfreader.h"
#include <iostream>
#include <iostream>
 
 
Line 13... Line 22...
/** Class registration in the Core */
/** Class registration in the Core */
REGISTER_CLASS(ElfReaderService)
REGISTER_CLASS(ElfReaderService)
 
 
ElfReaderService::ElfReaderService(const char *name) : IService(name) {
ElfReaderService::ElfReaderService(const char *name) : IService(name) {
    registerInterface(static_cast<IElfReader *>(this));
    registerInterface(static_cast<IElfReader *>(this));
 
    registerAttribute("SourceProc", &sourceProc_);
    image_ = NULL;
    image_ = NULL;
    sectionNames_ = NULL;
    sectionNames_ = NULL;
    symbolList_.make_list(0);
    symbolList_.make_list(0);
    loadSectionList_.make_list(0);
    loadSectionList_.make_list(0);
 
    sourceProc_.make_string("");
 
    isrc_ = 0;
}
}
 
 
ElfReaderService::~ElfReaderService() {
ElfReaderService::~ElfReaderService() {
    if (image_) {
    if (image_) {
        delete image_;
        delete image_;
    }
    }
}
}
 
 
void ElfReaderService::postinitService() {
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) {
int ElfReaderService::readFile(const char *filename) {
    FILE *fp = fopen(filename, "rb");
    FILE *fp = fopen(filename, "rb");
    if (!fp) {
    if (!fp) {
Line 41... Line 60...
    rewind(fp);
    rewind(fp);
 
 
    if (image_) {
    if (image_) {
        delete image_;
        delete image_;
        sectionNames_ = NULL;
        sectionNames_ = NULL;
 
        sourceProc_.make_list(0);
 
        symbolList_.make_list(0);
 
        loadSectionList_.make_list(0);
    }
    }
    image_ = new uint8_t[sz];
    image_ = new uint8_t[sz];
    fread(image_, 1, sz, fp);
    fread(image_, 1, sz, fp);
 
 
    if (readElfHeader() != 0) {
    if (readElfHeader() != 0) {
        fclose(fp);
        fclose(fp);
        return 0;
        return 0;
    }
    }
 
 
    if (!header_->e_shoff) {
    symbolNames_ = 0;
 
    if (!header_->get_shoff()) {
        fclose(fp);
        fclose(fp);
        return 0;
        return 0;
    }
    }
 
 
    /** Init names */
    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;
    SectionHeaderType *sh;
    sh_tbl_ =
    for (int i = 0; i < header_->get_shnum(); i++) {
        reinterpret_cast<SectionHeaderType *>(&image_[header_->e_shoff]);
        sh = sh_tbl_[i];
    for (int i = 0; i < header_->e_shnum; i++) {
        if (sectionNames_ == NULL || sh->get_type() != SHT_STRTAB) {
        sh = &sh_tbl_[i];
            continue;
        if (sh->sh_type == SHT_STRTAB) {
 
            processStringTable(sh);
 
        }
        }
 
        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: */
    /** Direct loading via tap interface: */
    int bytes_loaded = loadSections();
    int bytes_loaded = loadSections();
    RISCV_info("Loaded: %d B", bytes_loaded);
    RISCV_info("Loaded: %d B", bytes_loaded);
 
 
    if (header_->e_phoff) {
    if (header_->get_phoff()) {
        //readProgramHeader();
        //readProgramHeader();
    }
    }
 
 
    fclose(fp);
    fclose(fp);
    return 0;
    return 0;
}
}
 
 
int ElfReaderService::readElfHeader() {
int ElfReaderService::readElfHeader() {
    header_ = reinterpret_cast<ElfHeaderType *>(image_);
    header_ = new ElfHeaderType(image_);
    for (int i = 0; i < 4; i++) {
    if (header_->isElf()) {
        if (header_->e_ident[i] != MAGIC_BYTES[i]) {
        return 0;
 
    }
            RISCV_error("File format is not ELF", NULL);
            RISCV_error("File format is not ELF", NULL);
            return -1;
            return -1;
        }
        }
    }
 
    return 0;
 
}
 
 
 
int ElfReaderService::loadSections() {
int ElfReaderService::loadSections() {
    SectionHeaderType *sh;
    SectionHeaderType *sh;
    uint64_t total_bytes = 0;
    uint64_t total_bytes = 0;
    AttributeType tsymb;
    AttributeType tsymb;
 
 
    for (int i = 0; i < header_->e_shnum; i++) {
    for (int i = 0; i < header_->get_shnum(); i++) {
        sh = &sh_tbl_[i];
        sh = sh_tbl_[i];
 
 
        if (sh->sh_size == 0) {
        if (sh->get_size() == 0) {
            continue;
            continue;
        }
        }
 
 
        if (sectionNames_ && (sh->sh_flags & SHF_ALLOC)) {
        if (sectionNames_ && (sh->get_flags() & SHF_ALLOC)) {
            RISCV_info("Reading '%s' section", &sectionNames_[sh->sh_name]);
            RISCV_info("Reading '%s' section", &sectionNames_[sh->get_name()]);
        }
        }
 
 
        if (sh->sh_type == SHT_PROGBITS && (sh->sh_flags & SHF_ALLOC) != 0) {
        if (sh->get_type() == SHT_PROGBITS && (sh->get_flags() & SHF_ALLOC) != 0) {
            /**
            /**
             * @brief   Instructions or other processor's information
             * @brief   Instructions or other processor's information
             * @details This section holds information defined by the program,
             * @details This section holds information defined by the program,
             *          whose format and meaning are determined solely by the
             *          whose format and meaning are determined solely by the
             *          program.
             *          program.
             */
             */
            AttributeType loadsec;
            AttributeType loadsec;
            loadsec.make_list(LoadSh_Total);
            loadsec.make_list(LoadSh_Total);
            if (sectionNames_) {
            if (sectionNames_) {
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->sh_name]);
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->get_name()]);
            } else {
            } else {
                loadsec[LoadSh_name].make_string("unknown");
                loadsec[LoadSh_name].make_string("unknown");
            }
            }
            loadsec[LoadSh_addr].make_uint64(sh->sh_addr);
            loadsec[LoadSh_addr].make_uint64(sh->get_addr());
            loadsec[LoadSh_size].make_uint64(sh->sh_size);
            loadsec[LoadSh_size].make_uint64(sh->get_size());
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->sh_size),
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->get_size()),
                                           &image_[sh->sh_offset]);
                                           &image_[sh->get_offset()]);
            loadSectionList_.add_to_list(&loadsec);
            loadSectionList_.add_to_list(&loadsec);
            total_bytes += sh->sh_size;
            total_bytes += sh->get_size();
        } else if (sh->sh_type == SHT_NOBITS
        } else if (sh->get_type() == SHT_NOBITS
                    && (sh->sh_flags & SHF_ALLOC) != 0) {
                    && (sh->get_flags() & SHF_ALLOC) != 0) {
            /**
            /**
             * @brief   Initialized data
             * @brief   Initialized data
             * @details A section of this type occupies no space in  the file
             * @details A section of this type occupies no space in  the file
             *          but otherwise resembles SHT_PROGBITS.  Although this
             *          but otherwise resembles SHT_PROGBITS.  Although this
             *          section contains no bytes, the sh_offset member
             *          section contains no bytes, the sh_offset member
             *          contains the conceptual file offset.
             *          contains the conceptual file offset.
             */
             */
            AttributeType loadsec;
            AttributeType loadsec;
            loadsec.make_list(LoadSh_Total);
            loadsec.make_list(LoadSh_Total);
            if (sectionNames_) {
            if (sectionNames_) {
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->sh_name]);
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->get_name()]);
            } else {
            } else {
                loadsec[LoadSh_name].make_string("unknown");
                loadsec[LoadSh_name].make_string("unknown");
            }
            }
            loadsec[LoadSh_addr].make_uint64(sh->sh_addr);
            loadsec[LoadSh_addr].make_uint64(sh->get_addr());
            loadsec[LoadSh_size].make_uint64(sh->sh_size);
            loadsec[LoadSh_size].make_uint64(sh->get_size());
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->sh_size));
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->get_size()));
            memset(loadsec[LoadSh_data].data(),
            memset(loadsec[LoadSh_data].data(),
                        0, static_cast<size_t>(sh->sh_size));
                        0, static_cast<size_t>(sh->get_size()));
            loadSectionList_.add_to_list(&loadsec);
            loadSectionList_.add_to_list(&loadsec);
            total_bytes += sh->sh_size;
            total_bytes += sh->get_size();
        } else if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) {
        } else if (sh->get_type() == SHT_SYMTAB || sh->get_type() == SHT_DYNSYM) {
            processDebugSymbol(sh);
            processDebugSymbol(sh);
        }
        }
    }
    }
    symbolList_.sort(LoadSh_name);
    symbolList_.sort(LoadSh_name);
    symbolListSortByAddr_ = symbolList_;
    if (isrc_) {
    symbolListSortByAddr_.sort(LoadSh_addr);
        isrc_->addSymbols(&symbolList_);
    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);
 
    }
    }
 
    return static_cast<int>(total_bytes);
}
}
 
 
void ElfReaderService::processDebugSymbol(SectionHeaderType *sh) {
void ElfReaderService::processDebugSymbol(SectionHeaderType *sh) {
    uint64_t symbol_off = 0;
    uint64_t symbol_off = 0;
    SymbolTableType *st;
    SymbolTableType *st;
Line 193... Line 227...
 
 
    if (!symbolNames_) {
    if (!symbolNames_) {
        return;
        return;
    }
    }
 
 
    while (symbol_off < sh->sh_size) {
    while (symbol_off < sh->get_size()) {
        st = reinterpret_cast<SymbolTableType *>
        st = new SymbolTableType(&image_[sh->get_offset() + symbol_off],
                    (&image_[sh->sh_offset + symbol_off]);
                                header_);
        symb_name = &symbolNames_[st->st_name];
 
 
 
        if (sh->sh_entsize) {
        symb_name = &symbolNames_[st->get_name()];
            // 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;
        st_type = st->get_info() & 0xF;
        if ((st_type == STT_OBJECT || st_type == STT_FUNC) && st->st_value) {
        if ((st_type == STT_OBJECT || st_type == STT_FUNC) && st->get_value()) {
            tsymb.make_list(Symbol_Total);
            tsymb.make_list(Symbol_Total);
            tsymb[Symbol_Name].make_string(symb_name);
            tsymb[Symbol_Name].make_string(symb_name);
            tsymb[Symbol_Addr].make_uint64(st->st_value);
            tsymb[Symbol_Addr].make_uint64(st->get_value());
            tsymb[Symbol_Size].make_uint64(st->st_size);
            tsymb[Symbol_Size].make_uint64(st->get_size());
            if (st_type == STT_FUNC) {
            if (st_type == STT_FUNC) {
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_FUNCTION);
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_FUNCTION);
            } else {
            } else {
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_DATA);
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_DATA);
            }
            }
            symbolList_.add_to_list(&tsymb);
            symbolList_.add_to_list(&tsymb);
        } else if (st_type == STT_FILE) {
        } else if (st_type == STT_FILE) {
            //file_name = symb_name;
            //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;
        if (sh->get_entsize()) {
    int dist, pos = sz / 2;
            // section with elements of fixed size
    dist = pos;
            symbol_off += sh->get_entsize();
    while (search) {
        } else if (st->get_size()) {
        AttributeType &symb = symbolListSortByAddr_[pos];
            symbol_off += st->get_size();
        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 {
        } else {
            if (dist == 0 || pos == (sz - 1)) {
            if (header_->isElf32()) {
                search = false;
                symbol_off += sizeof(Elf32_Sym);
            } else if (dist == 1) {
 
                dist = 0;
 
                pos++;
 
            } else {
            } else {
                int incr = dist / 2;
                symbol_off += sizeof(Elf64_Sym);
                pos += incr;
 
                dist = (dist / 2) + (dist & 0x1);
 
                if (pos >= sz) {
 
                    pos = sz - 1;
 
                }
 
            }
            }
        }
        }
 
        delete st;
    }
    }
}
}
 
 
}  // namespace debugger
}  // namespace debugger
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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