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

Last change on this file since 212 was 212, checked in by karaoui, 12 years ago

add the support for replication of code to MeMo?

File size: 21.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    /* loading map_info blob */
54    m_data = std::malloc(bin_size(m_path));
55    if ( !m_data )
56        throw exception::RunTimeError("malloc failed... No memory space");
57
58    m_size = load_bin(m_path, m_data);
59
60    /* checking signature */
61    mapping_header_t*   header = (mapping_header_t*)m_data; 
62    //assert((IN_MAPPING_SIGNATURE == header->signature) and "wrong signature");
63    if((IN_MAPPING_SIGNATURE != header->signature))
64    {
65        std::cout  << "wrong signature " << std::hex <<header->signature << ", should be:"<< IN_MAPPING_SIGNATURE << std::endl;
66        exit(1);
67    }
68   
69   
70
71#ifdef MOVER_DEBUG
72    std::cout << "Binary file path: " << m_path << std::endl;
73    print_mapping_info(m_data);
74#endif
75
76    buildMap(m_data);
77   
78#ifdef MOVER_DEBUG
79    std::cout << "parsing done" << std::endl ;
80#endif
81
82#ifdef MOVER_DEBUG
83    print_mapping();
84    std::cout << *this << std::endl;
85#endif
86
87    m_psegh.check();
88#ifdef MOVER_DEBUG
89    std::cout << "checking done" << std::endl ;
90#endif
91
92}
93
94void MeMo::print( std::ostream &o ) const
95{
96    std::cout << "All sections:" << std::endl;
97    FOREACH( sect, m_generator->get_section_table() )
98    {
99        assert(&*sect != NULL);
100        std::cout << *sect << std::endl; 
101    }
102}
103
104void MeMo::print_mapping() const
105{
106    std::cout << m_psegh << std::endl;
107}
108
109elfpp::section* MeMo::get_sect_by_addr(elfpp::object *loader, unsigned int addr)
110{
111    FOREACH( sect, loader->get_section_table() )
112    {
113        assert(&*sect != NULL);
114        elfpp::sh_flags_e eflags = sect->get_flags();
115        if ( !(eflags & elfpp::SHF_ALLOC) )
116            continue;
117        if(sect->get_load_address() == addr) //load_addr ?
118        {
119            return (&*sect);
120        }
121    }
122    return NULL;
123}
124
125
126void MeMo::buildSoft(const std::string &filename)
127{
128    if(!m_ginit)
129        throw exception::RunTimeError(std::string("Can't get generator! ") );
130
131    m_generator->write(filename);
132
133}
134
135/* Load the content of filename in buffer, and send the size */
136////////////////////////////////////////////////////////
137size_t MeMo::load_bin(std::string filename, void* buffer)
138{
139
140#ifdef MOVER_DEBUG
141    std::cout  << "Trying to load the binary blob from file '" << filename << "'" << std::endl;
142#endif
143
144    std::ifstream input(filename.c_str(), std::ios_base::binary|std::ios_base::in);
145
146    if ( ! input.good() )
147        throw exception::RunTimeError(std::string("Can't open the file: ") + filename);
148
149    input.seekg( 0, std::ifstream::end );
150    size_t size = input.tellg();
151    input.seekg( 0, std::ifstream::beg );
152
153    if ( !buffer )
154        throw exception::RunTimeError("Empty buffer!");
155
156    input.read( (char*)buffer, size );
157
158    input.close();
159
160    return size;
161}
162
163
164/* get the size of the content of the filename */
165//////////////////////////////////////////
166size_t MeMo::bin_size(std::string filename)
167{
168
169#ifdef MOVER_DEBUG
170    std::cout  << "Trying to get the size of the binary blob '" << filename << "'" << std::endl;
171#endif
172
173    std::ifstream input(filename.c_str(), std::ios_base::binary|std::ios_base::in);
174
175    if ( ! input.good() )
176        throw exception::RunTimeError(std::string("Can't open the file: ") + filename);
177
178    input.seekg( 0, std::ifstream::end );
179    size_t size = input.tellg();
180    input.seekg( 0, std::ifstream::beg );
181
182    input.close();
183
184    return size;
185}
186
187
188/////////////
189MeMo::~MeMo()
190{
191    //std::cout << "Deleted MeMo " << *this << std::endl;
192    //std::free(m_data);//should be done by the elfpp driver since we passed the pointer
193    std::map<std::string, elfpp::object*>::iterator l;
194    for(l = m_loaders.begin(); l != m_loaders.end(); l++)
195    {
196        delete (*l).second;
197    }
198    //delete m_generator;
199}
200
201
202/////////////////////////////////////////////////////////////////////////////
203// various mapping_info data structure access functions
204/////////////////////////////////////////////////////////////////////////////
205mapping_cluster_t* MeMo::get_cluster_base( mapping_header_t* header )
206{
207    return   (mapping_cluster_t*) ((char*)header +
208                                  MAPPING_HEADER_SIZE);
209}
210/////////////////////////////////////////////////////////////////////////////
211mapping_pseg_t* MeMo::get_pseg_base( mapping_header_t* header )
212{
213    return   (mapping_pseg_t*)    ((char*)header +
214                                  MAPPING_HEADER_SIZE +
215                                  MAPPING_CLUSTER_SIZE*header->clusters);
216}
217/////////////////////////////////////////////////////////////////////////////
218mapping_vspace_t* MeMo::get_vspace_base( mapping_header_t* header )
219{
220    return   (mapping_vspace_t*)  ((char*)header +
221                                  MAPPING_HEADER_SIZE +
222                                  MAPPING_CLUSTER_SIZE*header->clusters +
223                                  MAPPING_PSEG_SIZE*header->psegs);
224}
225/////////////////////////////////////////////////////////////////////////////
226mapping_vseg_t* MeMo::get_vseg_base( mapping_header_t* header )
227{
228    return   (mapping_vseg_t*)    ((char*)header +
229                                  MAPPING_HEADER_SIZE +
230                                  MAPPING_CLUSTER_SIZE*header->clusters +
231                                  MAPPING_PSEG_SIZE*header->psegs +
232                                  MAPPING_VSPACE_SIZE*header->vspaces);
233}
234/////////////////////////////////////////////////////////////////////////////
235mapping_vobj_t* MeMo::get_vobj_base( mapping_header_t* header )
236{
237    return   (mapping_vobj_t*)    ((char*)header +
238                                  MAPPING_HEADER_SIZE +
239                                  MAPPING_CLUSTER_SIZE*header->clusters +
240                                  MAPPING_PSEG_SIZE*header->psegs +
241                                  MAPPING_VSPACE_SIZE*header->vspaces +
242                                  MAPPING_VSEG_SIZE*header->vsegs);
243}
244
245/////////////////////////////////////////////////////////////////////////////
246// print the content of the mapping_info data structure
247////////////////////////////////////////////////////////////////////////
248void MeMo::print_mapping_info(void* desc)
249{
250    mapping_header_t*   header = (mapping_header_t*)desc; 
251
252    mapping_pseg_t*         pseg    = get_pseg_base( header );;
253    mapping_vspace_t*   vspace  = get_vspace_base ( header );;
254    mapping_vseg_t*         vseg    = get_vseg_base ( header );
255    mapping_vobj_t*         vobj    = get_vobj_base ( header );
256
257    // header
258    std::cout << std::hex << "mapping_info" << std::dec << std::endl
259              << " + signature = " << header->signature << std::endl
260              << " + name      = " << header->name      << std::endl
261              << " + clusters  = " << header->clusters  << std::endl
262              << " + psegs     = " << header->psegs     << std::endl
263              << " + vspaces   = " << header->vspaces   << std::endl
264              << " + globals   = " << header->globals   << std::endl
265              << " + vsegs     = " << header->vsegs     << std::endl
266              << " + vobjs     = " << header->vsegs     << std::endl
267              << " + tasks     = " << header->tasks     << std::endl;
268
269    // psegs
270    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
271    {
272        std::cout << "pseg " << pseg[pseg_id].name << std::hex << std::endl
273                  << " + base   = " << pseg[pseg_id].base   << std::endl
274                  << " + length = " << pseg[pseg_id].length << std::endl ;
275    }
276
277    // globals
278    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
279    {
280        std::cout << std::endl;
281        std::cout << "global vseg "   << vseg[vseg_id].name << std::hex << std::endl
282                  << " + vbase    = " << vseg[vseg_id].vbase << std::endl
283                  << " + length   = " << vseg[vseg_id].length << std::endl
284                  << " + mode     = " << (size_t)vseg[vseg_id].mode << std::endl
285                  << " + ident    = " << (bool)vseg[vseg_id].ident << std::endl
286                  << " + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
287        for( size_t vobj_id = vseg[vseg_id].vobj_offset ; 
288                    vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
289                    vobj_id++ )
290        {
291            std::cout << "\t vobj "        << vobj[vobj_id].name    << std::endl
292                      << "\t + index   = " << std::dec << vobj_id   << std::endl
293                      << "\t + type    = " << vobj[vobj_id].type    << std::endl
294                      << "\t + length  = " << vobj[vobj_id].length  << std::endl
295                      << "\t + align   = " << vobj[vobj_id].align   << std::endl
296                      << "\t + binpath = " << vobj[vobj_id].binpath << std::endl
297                      << "\t + init    = " << vobj[vobj_id].init    << std::endl;
298        }
299    }
300
301    // vspaces
302    for ( size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
303    {
304        std::cout << "***vspace "  << vspace[vspace_id].name   << std::endl
305                  << " + vsegs = " <<  vspace[vspace_id].vsegs << std::endl
306                  << " + vobjs = " <<  vspace[vspace_id].vobjs << std::endl
307                  << " + tasks = " <<  vspace[vspace_id].tasks << std::endl;
308
309        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
310              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
311              vseg_id++ )
312        {
313            std::cout << "\t vseg " << vseg[vseg_id].name  << std::endl
314                      << "\t + vbase    = " << vseg[vseg_id].vbase             << std::endl
315                      << "\t + length   = " << vseg[vseg_id].length            << std::endl
316                      << "\t + mode     = " << (size_t)vseg[vseg_id].mode      << std::endl
317                      << "\t + ident    = " << (bool)vseg[vseg_id].ident       << std::endl
318                      << "\t + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
319            for(size_t vobj_id = vseg[vseg_id].vobj_offset ; 
320                       vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
321                       vobj_id++ )
322            {
323                std::cout << "\t\t vobj "      << vobj[vobj_id].name      << std::endl
324                          << "\t\t + index   = " << std::dec << vobj_id   << std::endl
325                          << "\t\t + type    = " << vobj[vobj_id].type    << std::endl
326                          << "\t\t + length  = " << vobj[vobj_id].length  << std::endl
327                          << "\t\t + align   = " << vobj[vobj_id].align   << std::endl
328                          << "\t\t + binpath = " << vobj[vobj_id].binpath << std::endl
329                          << "\t\t + init    = " << vobj[vobj_id].init    << std::endl;
330            }
331        }
332
333    }
334} // end print_mapping_info()
335
336
337//////////////////////////////////////////
338void MeMo::vseg_map( mapping_vseg_t* vseg)
339{
340    mapping_vobj_t*     vobj   = get_vobj_base( (mapping_header_t*) m_data );
341    PSeg *ps = &(m_psegh.get(vseg->psegid));// get physical segment pointer(PSegHandler::get)
342    elfpp::section* sect = NULL;
343    size_t cur_vaddr;
344    size_t cur_paddr;
345    bool first = true;
346    bool aligned = false;
347
348    VSeg   *vSO = new VSeg;
349
350    vSO->m_name = std::string(vseg->name);
351    vSO->m_vma = vseg->vbase;
352    vSO->m_lma = ps->nextLma();
353
354    cur_vaddr = vseg->vbase;
355    cur_paddr = ps->nextLma();
356
357    mapping_vobj_t* cur_vobj;
358    size_t simple_size = 0; //for debug
359
360#ifdef MOVER_DEBUG
361    std::cout << "--------------------vseg_map "<< vseg->name <<"---------------------" << std::endl;
362#endif
363
364    for ( size_t vobj_id = vseg->vobj_offset ; vobj_id < (vseg->vobj_offset + vseg->vobjs) ; vobj_id++ )
365    {
366        cur_vobj = &vobj[vobj_id];
367
368#ifdef MOVER_DEBUG
369        std::cout << std::hex << "current vobj("<< vobj_id <<"): " << cur_vobj->name << " (" <<cur_vobj->vaddr << ")"
370                        << " size: "<< cur_vobj->length << " type: " <<  cur_vobj->type << std::endl;
371#endif
372        if(cur_vobj->type == VOBJ_TYPE_BLOB)
373        {
374            size_t blob_size;
375            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
376
377#ifdef MOVER_DEBUG
378            std::cout << std::hex << "Handling: " << filePath << " ..." << std::endl;
379#endif
380
381            if(!filePath.compare(m_path))    //local blob: map_info
382            {
383#ifdef MOVER_DEBUG
384                std::cout << "Found the vseg of the mapping info" << std::endl;
385#endif
386                blob_size = this->m_size;
387                assert((blob_size >0) and "MAPPING INFO file is empty !?");
388            }
389            else
390            {
391#ifdef MOVER_DEBUG
392                std::cout << "Found an BLOB vseg" << std::endl;
393#endif
394                blob_size = bin_size(filePath);
395            }
396
397
398            /**creating a new section */
399            sect = new elfpp::section(*m_generator, elfpp::SHT_PROGBITS);
400
401            sect->set_name(std::string(cur_vobj->name));
402            sect->set_flags(elfpp::SHF_ALLOC | elfpp::SHF_WRITE);
403            sect->set_size(blob_size);//do the malloc for the get_content fonction
404
405            assert(sect->get_content());//check allocation
406
407            if(!filePath.compare(m_path))    //local blob: map_info
408                //memcpy(sect->get_content(), m_data, sect->get_size());
409                /* this way the modification of the elf size are propageted to the giet */
410                sect->set_content(this->m_data);
411            else
412                load_bin(filePath, sect->get_content());
413
414
415            if(blob_size > cur_vobj->length)
416            {
417                std::cout << std::hex << "!!! Warning, specified blob type vobj ("<<
418                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
419                << blob_size  << " !!!" <<std::endl;
420                assert(0 and "blob vobj length smaller than the actual content" );//???
421            }
422
423            cur_vobj->length = blob_size;//set the true size of this BLOB vobj
424
425            vSO->m_file = filePath;
426            vSO->m_loadable = true;
427        }
428        else if(cur_vobj->type == VOBJ_TYPE_ELF)
429        {
430            if(!first)
431                throw exception::RunTimeError(std::string("elf vobj type, must be placed first in a vseg"));
432
433            size_t elf_size;
434            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
435#ifdef MOVER_DEBUG
436            std::cout << "Handling: " << filePath << " ..." << std::endl;
437            std::cout << "Found an ELF vseg" << std::endl;
438#endif
439            if(m_loaders.count(filePath) == 0 )
440                m_loaders[filePath] = new elfpp::object(filePath);
441            elfpp::object* loader = m_loaders[filePath];//TODO:free!?
442
443            sect =  new elfpp::section(*get_sect_by_addr(loader, cur_vaddr));//copy: for the case we replicate the code
444            if (!sect)
445            {
446                std::cerr << "No section found for " << cur_vobj->name << " at "<< cur_vaddr << std::endl;
447                exit(-1);
448            }
449
450            sect->set_name(std::string(cur_vobj->name));
451
452
453            elf_size = sect->get_size();
454            assert((elf_size > 0) and "ELF section empty ?");
455
456            if(!m_ginit)
457            {
458                /** Initailising the header of the generator from the first binary,
459                ** we suppose that the header is the same for all the binarys **/
460                m_generator->copy_info(*loader);
461                m_ginit=true;
462            }
463
464            if(elf_size > cur_vobj->length)
465            {
466                std::cout << "Warning, specified elf type vobj ("<<
467                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
468                << elf_size  << std::endl;
469                //assert((elf_size < cur_vobj->length) and "elf vobj length smaller than the actual content" );//???
470                assert((0) and "elf vobj length smaller than the actual content" );//???
471            }
472
473            cur_vobj->length = elf_size;//set the true size of this ELF vobj
474
475            vSO->m_file = filePath;
476            vSO->m_loadable = true;
477        }
478
479        //aligning the vobj->paddr if necessary
480        //
481        if(cur_vobj->align)
482        {
483            cur_paddr = PSeg::align(cur_paddr, cur_vobj->align);
484            aligned = true;
485        }
486
487        cur_vaddr += cur_vobj->length;
488        cur_paddr += cur_vobj->length;
489        simple_size += cur_vobj->length;
490        first = false;
491    }
492
493    assert((cur_vaddr >= vseg->vbase ));
494    assert((cur_paddr >= ps->nextLma() ));
495
496    vSO->m_length = (cur_paddr - ps->nextLma()); //pageAlign is done by the psegs
497
498#ifdef MOVER_DEBUG
499    if(aligned)
500    {
501        std::cout << "vseg base "<< std::hex << ps->nextLma()
502        <<(ps->nextLma()+simple_size)  <<" size " << std::dec << simple_size <<
503        std::endl;
504
505        std::cout << "vseg aligned to: base: " << std::hex << ps->nextLma()
506        <<" to "<< std::hex << ps->nextLma()+vSO->m_length<< " size " << std::dec <<
507        vSO->m_length << std::endl;
508    }
509#endif
510
511    vSO->m_ident = vseg->ident;
512
513    //should we check that we have the same type for the pseg and vobj?
514    if(ps->type() != PSEG_TYPE_PERI)//take into acount only vseg who are not of the peri type
515    {
516        //set the lma
517        if ( vseg->ident != 0 )            // identity mapping required
518            ps->addIdent( *vSO );
519        else
520            ps->add( *vSO );
521    }
522    if(!sect)
523        return;
524
525#ifdef MOVER_DEBUG
526    std::cout << "section: "<< *sect <<"\n seted to: " << (*vSO) << std::endl;
527#endif
528
529    sect->set_vaddr((*vSO).lma());
530    m_generator->add_section(*sect);
531
532} // end vseg_map()
533 
534
535///////////////////////////////
536void MeMo::buildMap(void* desc)
537{
538    mapping_header_t*   header = (mapping_header_t*)desc; 
539
540    mapping_cluster_t*  cluster = get_cluster_base( header );     
541    mapping_vspace_t*   vspace = get_vspace_base( header );     
542    mapping_pseg_t*     pseg   = get_pseg_base( header ); 
543    mapping_vseg_t*     vseg   = get_vseg_base( header );
544
545    // get the psegs
546
547#ifdef MOVER_DEBUG
548std::cout << "\n******* Storing Pseg information *********\n" << std::endl;
549#endif
550
551#ifdef DISTRIBUTED_SCHEDULERS
552    char found;
553#endif
554
555    for ( size_t cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
556    {
557
558#ifdef DISTRIBUTED_SCHEDULERS
559        found    = 0;
560#endif
561
562        for ( size_t pseg_id = cluster[cluster_id].pseg_offset ;
563              pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs ;
564              pseg_id++ )
565        {
566            //build pseg
567            std::string name(pseg[pseg_id].name);
568            PSeg *ps = new PSeg(name, pseg[pseg_id].base, pseg[pseg_id].length, pseg[pseg_id].type);
569
570#ifdef DISTRIBUTED_SCHEDULERS
571            if ( (pseg[pseg_id].type == PSEG_TYPE_RAM) && (found == 0) )
572            {
573                ps->incNextLma( (cluster[cluster_id].procs << 12) );
574                found  = 1;
575            }
576            if(!found){/* we could imagine a cluster without proc, let the giet choose*/ }
577#endif
578            m_psegh.m_pSegs.push_back(*ps);
579
580        }
581    }
582
583    // map global vsegs
584
585#ifdef MOVER_DEBUG
586std::cout << "\n******* mapping global vsegs *********\n" << std::endl;
587#endif
588
589    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
590    {
591        vseg_map( &vseg[vseg_id]);
592    }
593
594    // loop on virtual spaces to map private vsegs
595    for (size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
596    {
597
598#ifdef MOVER_DEBUG
599std::cout << "\n******* mapping all vsegs of " << vspace[vspace_id].name << " *********\n" << std::endl;
600#endif
601           
602        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
603              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
604              vseg_id++ )
605        {
606            vseg_map( &vseg[vseg_id]); 
607        }
608    } 
609
610} // end buildMap()
611
612
613
614// Local Variables:
615// tab-width: 4
616// c-basic-offset: 4
617// c-file-offsets:((innamespace . 0)(inline-open . 0))
618// indent-tabs-mode: nil
619// End:
620
621// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
622
Note: See TracBrowser for help on using the repository browser.