source: soft/giet_vm/memo/src/memo.cpp @ 165

Last change on this file since 165 was 165, checked in by alain, 12 years ago

Introducing various modifications in kernel initialisation

File size: 18.0 KB
Line 
1/* -*- c++ -*-
2 *
3 * SOCLIB_LGPL_HEADER_BEGIN
4 *
5 * This file is part of SoCLib, GNU LGPLv2.1.
6 *
7 * SoCLib is free software; you can redistribute vSO and/or modify vSO
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; version 2.1 of the License.
10 *
11 * SoCLib is distributed in the hope that vSO will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with SoCLib; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * 02110-1301 USA
20 *
21 * SOCLIB_LGPL_HEADER_END
22 *
23 * Copyright (c) UPMC, Lip6, SoC
24 *         Mohamed Lamine KARAOUI <Mohamed.Karaoui@lip6.fr>, 2012
25 */
26
27#include <string.h>
28#include <cassert>
29#include <sstream>
30#include <fstream>
31#include <ios>
32#include <iostream>
33#include <cstdarg>
34#include <cassert>
35#include <iomanip>
36
37
38#include "exception.h"
39#include "memo.h"
40
41//#define MOVER_DEBUG
42
43MeMo::MeMo( const std::string &filename, 
44        const size_t pageSize)
45        :m_path(filename),
46        m_pathHandler(filename),
47        m_ginit(false),
48        m_generator(new elfpp::object())
49{
50   
51    PSeg::setPageSize(pageSize);
52
53    load_bin(m_path);
54
55#ifdef MOVER_DEBUG
56    std::cout << "Binary file path: " << m_path << std::endl;
57    print_mapping_info(m_data);
58#endif
59
60    buildMap(m_data);
61   
62#ifdef MOVER_DEBUG
63    std::cout << "parsing done" << std::endl ;
64#endif
65
66#ifdef MOVER_DEBUG
67    print_mapping();
68    std::cout << *this << std::endl;
69#endif
70
71    m_psegh.check();
72#ifdef MOVER_DEBUG
73    std::cout << "checking done" << std::endl ;
74#endif
75
76}
77
78void MeMo::print( std::ostream &o ) const
79{
80    std::cout << "All sections:" << std::endl;
81    FOREACH( sect, m_generator->get_section_table() )
82    {
83        assert(&*sect != NULL);
84        std::cout << *sect << std::endl; 
85    }
86}
87
88void MeMo::print_mapping() const
89{
90    std::cout << m_psegh << std::endl;
91}
92
93elfpp::section* MeMo::get_sect_by_addr(elfpp::object *loader, unsigned int addr)
94{
95    FOREACH( sect, loader->get_section_table() )
96    {
97        assert(&*sect != NULL);
98        elfpp::sh_flags_e eflags = sect->get_flags();
99        if ( !(eflags & elfpp::SHF_ALLOC) )
100            continue;
101        if(sect->get_load_address() == addr) //load_addr ?
102        {
103            return (&*sect);
104        }
105    }
106    return NULL;
107}
108
109//TODO:delete
110elfpp::section* MeMo::get_sect_by_name(elfpp::object *loader, std::string name)
111{
112#ifdef MOVER_DEBUG
113    std::cout << "get_sect_by_name " << name << std::endl;
114#endif
115    FOREACH( sect, loader->get_section_table() )
116    {
117        assert(&*sect != NULL);
118        elfpp::sh_flags_e eflags = sect->get_flags();
119        if ( !(eflags & elfpp::SHF_ALLOC) )
120            continue;
121
122#ifdef MOVER_DEBUG
123        std::cout << "Trying " << sect->get_name() << std::endl;
124#endif
125        if(!(sect->get_name()).compare(name)) 
126        {
127            return (&*sect);
128        }
129    }
130    return NULL;
131}
132
133void MeMo::buildSoft(const std::string &filename)
134{
135    if(!m_ginit)
136        throw soclib::exception::RunTimeError(std::string("Can't get generator! ") );
137
138    m_generator->write(filename);
139
140}
141
142//////////////////////////////////////////
143void* MeMo::load_bin(std::string filename)
144{
145   
146#ifdef MOVER_DEBUG
147    std::cout  << "Trying to load the binary blob from file '" << m_path << "'" << std::endl;
148#endif
149
150    std::ifstream input(m_path.c_str(), std::ios_base::binary|std::ios_base::in);
151
152    if ( ! input.good() )
153        throw soclib::exception::RunTimeError(std::string("Can't open the file: ") + m_path);
154
155    input.seekg( 0, std::ifstream::end );
156    m_size = input.tellg();
157    input.seekg( 0, std::ifstream::beg );
158
159    //m_data = new void*[m_size];
160    m_data = std::malloc(m_size);
161    if ( !m_data )
162        throw soclib::exception::RunTimeError("malloc failed... No memory space");
163
164    input.read( (char*)m_data, m_size );
165   
166    return m_data;
167}
168
169/////////////
170MeMo::~MeMo()
171{
172    //std::cout << "Deleted MeMo " << *this << std::endl;
173    std::free(m_data);
174    std::map<std::string, elfpp::object*>::iterator l;
175    for(l = m_loaders.begin(); l != m_loaders.end(); l++)
176    {
177        delete (*l).second;
178    }
179    //delete m_generator;
180}
181
182
183/////////////////////////////////////////////////////////////////////////////
184// various mapping_info data structure access functions
185/////////////////////////////////////////////////////////////////////////////
186
187/////////////////////////////////////////////////////////////////////////////
188mapping_pseg_t* MeMo::get_pseg_base( mapping_header_t* header )
189{
190    return   (mapping_pseg_t*)    ((char*)header +
191                                  MAPPING_HEADER_SIZE +
192                                  MAPPING_CLUSTER_SIZE*header->clusters);
193}
194/////////////////////////////////////////////////////////////////////////////
195mapping_vspace_t* MeMo::get_vspace_base( mapping_header_t* header )
196{
197    return   (mapping_vspace_t*)  ((char*)header +
198                                  MAPPING_HEADER_SIZE +
199                                  MAPPING_CLUSTER_SIZE*header->clusters +
200                                  MAPPING_PSEG_SIZE*header->psegs);
201}
202/////////////////////////////////////////////////////////////////////////////
203mapping_vseg_t* MeMo::get_vseg_base( mapping_header_t* header )
204{
205    return   (mapping_vseg_t*)    ((char*)header +
206                                  MAPPING_HEADER_SIZE +
207                                  MAPPING_CLUSTER_SIZE*header->clusters +
208                                  MAPPING_PSEG_SIZE*header->psegs +
209                                  MAPPING_VSPACE_SIZE*header->vspaces);
210}
211/////////////////////////////////////////////////////////////////////////////
212mapping_vobj_t* MeMo::get_vobj_base( mapping_header_t* header )
213{
214    return   (mapping_vobj_t*)    ((char*)header +
215                                  MAPPING_HEADER_SIZE +
216                                  MAPPING_CLUSTER_SIZE*header->clusters +
217                                  MAPPING_PSEG_SIZE*header->psegs +
218                                  MAPPING_VSPACE_SIZE*header->vspaces +
219                                  MAPPING_VSEG_SIZE*header->vsegs);
220}
221
222/////////////////////////////////////////////////////////////////////////////
223// print the content of the mapping_info data structure
224////////////////////////////////////////////////////////////////////////
225void MeMo::print_mapping_info(void* desc)
226{
227    mapping_header_t*   header = (mapping_header_t*)desc; 
228
229    mapping_pseg_t*         pseg    = get_pseg_base( header );;
230    mapping_vspace_t*   vspace  = get_vspace_base ( header );;
231    mapping_vseg_t*         vseg    = get_vseg_base ( header );
232    mapping_vobj_t*         vobj    = get_vobj_base ( header );
233
234    // header
235    std::cout << std::hex << "mapping_info" << std::dec << std::endl
236              << " + signature = " << header->signature << std::endl
237              << " + name      = " << header->name      << std::endl
238              << " + clusters  = " << header->clusters  << std::endl
239              << " + psegs     = " << header->psegs     << std::endl
240              << " + ttys      = " << header->ttys      << std::endl
241              << " + fbs       = " << header->fbs       << std::endl
242              << " + vspaces   = " << header->vspaces   << std::endl
243              << " + globals   = " << header->globals   << std::endl
244              << " + vsegs     = " << header->vsegs     << std::endl
245              << " + vobjs     = " << header->vsegs     << std::endl
246              << " + tasks     = " << header->tasks     << std::endl;
247
248    // psegs
249    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
250    {
251        std::cout << "pseg " << pseg[pseg_id].name << std::hex << std::endl
252                  << " + base   = " << pseg[pseg_id].base   << std::endl
253                  << " + length = " << pseg[pseg_id].length << std::endl ;
254    }
255
256    // globals
257    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
258    {
259        std::cout << std::endl;
260        std::cout << "global vseg "   << vseg[vseg_id].name << std::hex << std::endl
261                  << " + vbase    = " << vseg[vseg_id].vbase << std::endl
262                  << " + length   = " << vseg[vseg_id].length << std::endl
263                  << " + mode     = " << (size_t)vseg[vseg_id].mode << std::endl
264                  << " + ident    = " << (bool)vseg[vseg_id].ident << std::endl
265                  << " + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
266        for( size_t vobj_id = vseg[vseg_id].vobj_offset ; 
267                    vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
268                    vobj_id++ )
269        {
270            std::cout << "\t vobj "        << vobj[vobj_id].name    << std::endl
271                      << "\t + index   = " << std::dec << vobj_id   << std::endl
272                      << "\t + type    = " << vobj[vobj_id].type    << std::endl
273                      << "\t + length  = " << vobj[vobj_id].length  << std::endl
274                      << "\t + align   = " << vobj[vobj_id].align   << std::endl
275                      << "\t + binpath = " << vobj[vobj_id].binpath << std::endl
276                      << "\t + init    = " << vobj[vobj_id].init    << std::endl;
277        }
278    }
279
280    // vspaces
281    for ( size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
282    {
283        std::cout << "***vspace "  << vspace[vspace_id].name   << std::endl
284                  << " + vsegs = " <<  vspace[vspace_id].vsegs << std::endl
285                  << " + vobjs = " <<  vspace[vspace_id].vobjs << std::endl
286                  << " + tasks = " <<  vspace[vspace_id].tasks << std::endl;
287
288        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
289              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
290              vseg_id++ )
291        {
292            std::cout << "\t vseg " << vseg[vseg_id].name  << std::endl
293                      << "\t + vbase    = " << vseg[vseg_id].vbase             << std::endl
294                      << "\t + length   = " << vseg[vseg_id].length            << std::endl
295                      << "\t + mode     = " << (size_t)vseg[vseg_id].mode      << std::endl
296                      << "\t + ident    = " << (bool)vseg[vseg_id].ident       << std::endl
297                      << "\t + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
298            for(size_t vobj_id = vseg[vseg_id].vobj_offset ; 
299                       vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
300                       vobj_id++ )
301            {
302                std::cout << "\t\t vobj "      << vobj[vobj_id].name      << std::endl
303                          << "\t\t + index   = " << std::dec << vobj_id   << std::endl
304                          << "\t\t + type    = " << vobj[vobj_id].type    << std::endl
305                          << "\t\t + length  = " << vobj[vobj_id].length  << std::endl
306                          << "\t\t + align   = " << vobj[vobj_id].align   << std::endl
307                          << "\t\t + binpath = " << vobj[vobj_id].binpath << std::endl
308                          << "\t\t + init    = " << vobj[vobj_id].init    << std::endl;
309            }
310        }
311
312    }
313} // end print_mapping_info()
314
315//////////////////////////////////////////
316void MeMo::pseg_map( mapping_pseg_t* pseg) 
317{
318    std::string name(pseg->name);
319    m_psegh.m_pSegs.push_back(PSeg(name, pseg->base, pseg->length));
320}
321
322
323//////////////////////////////////////////
324void MeMo::vseg_map( mapping_vseg_t* vseg) 
325{
326    mapping_vobj_t*     vobj   = get_vobj_base( (mapping_header_t*) m_data ); 
327    PSeg *ps = &(m_psegh.get(vseg->psegid));// get physical segment pointer(PSegHandler::get)
328    elfpp::section* sect = NULL;
329    size_t cur_vaddr;
330    size_t cur_paddr;
331    bool first = true;
332    bool aligned = false;
333
334    VSeg   *vSO = new VSeg;
335
336    vSO->m_name = std::string(vseg->name);
337    vSO->m_vma = vseg->vbase;
338    vSO->m_lma = ps->nextLma();
339
340    cur_vaddr = vseg->vbase;
341    cur_paddr = ps->nextLma();
342
343    mapping_vobj_t* cur_vobj;
344    size_t simple_size = 0; //for debug
345   
346#ifdef MOVER_DEBUG
347    std::cout << "--------------------vseg_map "<< vseg->name <<"---------------------" << std::endl;
348#endif
349   
350    for ( size_t vobj_id = vseg->vobj_offset ; vobj_id < (vseg->vobj_offset + vseg->vobjs) ; vobj_id++ )
351    {
352        cur_vobj = &vobj[vobj_id];
353
354#ifdef MOVER_DEBUG
355        std::cout << "current vobj("<< vobj_id <<"): " << cur_vobj->name << " (" <<cur_vobj->vaddr << ")" 
356                        << " size: "<< cur_vobj->length << " type: " <<  cur_vobj->type << std::endl;
357#endif
358
359        if(cur_vobj->type == VOBJ_TYPE_ELF)
360        {
361            if(!first) 
362                throw soclib::exception::RunTimeError(std::string("elf vobj type, must be placed first in a vseg"));
363
364            size_t elf_size;
365            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
366#ifdef MOVER_DEBUG
367            std::cout << "Handling: " << filePath << " ..." << std::endl;
368#endif
369            if(!filePath.compare(m_path))    //local blob: map_info
370            {
371#ifdef MOVER_DEBUG
372                std::cout << "Found the vseg of the mapping info" << std::endl;
373#endif
374                /**creating a new section */
375                sect = new elfpp::section(*m_generator, elfpp::SHT_PROGBITS);
376
377                sect->set_name(std::string(cur_vobj->name));
378                sect->set_flags(elfpp::SHF_ALLOC | elfpp::SHF_WRITE);
379                sect->set_size(this->m_size);
380                sect->set_content(this->m_data);               
381
382                elf_size = this->m_size;       
383                assert((elf_size >0) and "MAPPING INFO file is empty !?");
384            }
385            else
386            { 
387#ifdef MOVER_DEBUG
388                std::cout << "Found an ELF vseg" << std::endl;
389#endif
390                if(m_loaders.count(filePath) == 0 )
391                    m_loaders[filePath] = new elfpp::object(filePath);
392                elfpp::object* loader = m_loaders[filePath];//TODO:free!?
393
394                //TODO: delete
395                //sect =  get_sect_by_name(loader, std::string(cur_vobj->name));
396                //assert(( sect->get_vaddr() == cur_vaddr) and "Vaddr doesn't match!");
397
398                sect =  get_sect_by_addr(loader, cur_vaddr);
399                assert(sect and "No section found");
400
401                sect->set_name(std::string(cur_vobj->name));
402
403
404                elf_size = sect->get_size();
405                assert((elf_size >0) and "ELF section empty ?");
406
407                if(!m_ginit)
408                {
409                    /** Initailising the header of the generator from the first binary,
410                    * we suppose that the header is the same for all the binarys
411                    * */
412                    m_generator->copy_info(*loader);
413                    m_ginit=true;
414                }
415            }
416
417            if(elf_size > cur_vobj->length)
418                std::cout << "Warning, specified elf type vobj ("<<
419                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
420                << elf_size  << std::endl;
421
422            cur_vobj->length = elf_size;//set the true size of this ELF vobj
423
424            vSO->m_file = filePath;
425            vSO->m_loadable = true;       
426        }
427        first = false;
428
429        //aligning the vobj->paddr if necessary
430        if(cur_vobj->align)
431        {
432            cur_paddr = PSeg::align(cur_paddr, cur_vobj->align);
433            aligned = true;
434        }
435
436        cur_vaddr += cur_vobj->length;
437        cur_paddr += cur_vobj->length;
438        simple_size += cur_vobj->length;
439    }
440
441    assert((cur_vaddr >= vseg->vbase ));
442    assert((cur_paddr >= ps->nextLma() ));
443
444    vSO->m_length = (cur_paddr - ps->nextLma()); //pageAlign is done by the psegs
445
446#ifdef MOVER_DEBUG
447    if(aligned)
448    {
449        std::cout << "vseg base "<< std::hex << ps->nextLma()
450        <<(ps->nextLma()+simple_size)  <<" size " << std::dec << simple_size <<
451        std::endl; 
452
453        std::cout << "vseg aligned to: base: " << std::hex << ps->nextLma()
454        <<" to "<< std::hex << ps->nextLma()+vSO->m_length<< " size " << std::dec <<
455        vSO->m_length << std::endl;
456    }
457#endif
458     
459    vSO->m_ident = vseg->ident;     
460
461    //set the lma
462    if ( vseg->ident != 0 )            // identity mapping required
463        ps->addIdent( *vSO );
464    else
465        ps->add( *vSO );
466   
467    if(!sect)
468        return;
469
470#ifdef MOVER_DEBUG
471    std::cout << "section: "<< *sect <<"\n seted to: " << (*vSO) << std::endl;
472#endif
473
474    sect->set_vaddr((*vSO).lma());
475    m_generator->add_section(*(new elfpp::section(*sect)));
476
477} // end vseg_map()
478
479
480///////////////////////////////
481void MeMo::buildMap(void* desc)
482{
483    mapping_header_t*   header = (mapping_header_t*)desc; 
484
485    mapping_vspace_t*   vspace = get_vspace_base( header );     
486    mapping_pseg_t*     pseg   = get_pseg_base( header ); 
487    mapping_vseg_t*     vseg   = get_vseg_base( header );
488
489    // get the psegs
490
491#ifdef MOVER_DEBUG
492std::cout << "\n******* Storing Pseg information *********\n" << std::endl;
493#endif
494
495    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
496    {
497        pseg_map( &pseg[pseg_id]);
498    }
499
500    // map global vsegs
501
502#ifdef MOVER_DEBUG
503std::cout << "\n******* mapping global vsegs *********\n" << std::endl;
504#endif
505
506    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
507    {
508        vseg_map( &vseg[vseg_id]);
509    }
510
511    // loop on virtual spaces to map private vsegs
512    for (size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
513    {
514
515#ifdef MOVER_DEBUG
516std::cout << "\n******* mapping all vsegs of " << vspace[vspace_id].name << " *********\n" << std::endl;
517#endif
518           
519        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
520              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
521              vseg_id++ )
522        {
523            vseg_map( &vseg[vseg_id]); 
524        }
525    } 
526
527} // end buildMap()
528
529
530
531// Local Variables:
532// tab-width: 4
533// c-basic-offset: 4
534// c-file-offsets:((innamespace . 0)(inline-open . 0))
535// indent-tabs-mode: nil
536// End:
537
538// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
539
Note: See TracBrowser for help on using the repository browser.