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

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

Introducing support for distributed schedulers in the "memo" tool.

File size: 20.7 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              << " + ttys      = " << header->ttys      << std::endl
264              << " + fbs       = " << header->fbs       << std::endl
265              << " + vspaces   = " << header->vspaces   << std::endl
266              << " + globals   = " << header->globals   << std::endl
267              << " + vsegs     = " << header->vsegs     << std::endl
268              << " + vobjs     = " << header->vsegs     << std::endl
269              << " + tasks     = " << header->tasks     << std::endl;
270
271    // psegs
272    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
273    {
274        std::cout << "pseg " << pseg[pseg_id].name << std::hex << std::endl
275                  << " + base   = " << pseg[pseg_id].base   << std::endl
276                  << " + length = " << pseg[pseg_id].length << std::endl ;
277    }
278
279    // globals
280    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
281    {
282        std::cout << std::endl;
283        std::cout << "global vseg "   << vseg[vseg_id].name << std::hex << std::endl
284                  << " + vbase    = " << vseg[vseg_id].vbase << std::endl
285                  << " + length   = " << vseg[vseg_id].length << std::endl
286                  << " + mode     = " << (size_t)vseg[vseg_id].mode << std::endl
287                  << " + ident    = " << (bool)vseg[vseg_id].ident << std::endl
288                  << " + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
289        for( size_t vobj_id = vseg[vseg_id].vobj_offset ; 
290                    vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
291                    vobj_id++ )
292        {
293            std::cout << "\t vobj "        << vobj[vobj_id].name    << std::endl
294                      << "\t + index   = " << std::dec << vobj_id   << std::endl
295                      << "\t + type    = " << vobj[vobj_id].type    << std::endl
296                      << "\t + length  = " << vobj[vobj_id].length  << std::endl
297                      << "\t + align   = " << vobj[vobj_id].align   << std::endl
298                      << "\t + binpath = " << vobj[vobj_id].binpath << std::endl
299                      << "\t + init    = " << vobj[vobj_id].init    << std::endl;
300        }
301    }
302
303    // vspaces
304    for ( size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
305    {
306        std::cout << "***vspace "  << vspace[vspace_id].name   << std::endl
307                  << " + vsegs = " <<  vspace[vspace_id].vsegs << std::endl
308                  << " + vobjs = " <<  vspace[vspace_id].vobjs << std::endl
309                  << " + tasks = " <<  vspace[vspace_id].tasks << std::endl;
310
311        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
312              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
313              vseg_id++ )
314        {
315            std::cout << "\t vseg " << vseg[vseg_id].name  << std::endl
316                      << "\t + vbase    = " << vseg[vseg_id].vbase             << std::endl
317                      << "\t + length   = " << vseg[vseg_id].length            << std::endl
318                      << "\t + mode     = " << (size_t)vseg[vseg_id].mode      << std::endl
319                      << "\t + ident    = " << (bool)vseg[vseg_id].ident       << std::endl
320                      << "\t + psegname = " << pseg[vseg[vseg_id].psegid].name << std::endl;
321            for(size_t vobj_id = vseg[vseg_id].vobj_offset ; 
322                       vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; 
323                       vobj_id++ )
324            {
325                std::cout << "\t\t vobj "      << vobj[vobj_id].name      << std::endl
326                          << "\t\t + index   = " << std::dec << vobj_id   << std::endl
327                          << "\t\t + type    = " << vobj[vobj_id].type    << std::endl
328                          << "\t\t + length  = " << vobj[vobj_id].length  << std::endl
329                          << "\t\t + align   = " << vobj[vobj_id].align   << std::endl
330                          << "\t\t + binpath = " << vobj[vobj_id].binpath << std::endl
331                          << "\t\t + init    = " << vobj[vobj_id].init    << std::endl;
332            }
333        }
334
335    }
336} // end print_mapping_info()
337
338
339//////////////////////////////////////////
340void MeMo::vseg_map( mapping_vseg_t* vseg)
341{
342    mapping_vobj_t*     vobj   = get_vobj_base( (mapping_header_t*) m_data );
343    PSeg *ps = &(m_psegh.get(vseg->psegid));// get physical segment pointer(PSegHandler::get)
344    elfpp::section* sect = NULL;
345    size_t cur_vaddr;
346    size_t cur_paddr;
347    bool first = true;
348    bool aligned = false;
349
350    VSeg   *vSO = new VSeg;
351
352    vSO->m_name = std::string(vseg->name);
353    vSO->m_vma = vseg->vbase;
354    vSO->m_lma = ps->nextLma();
355
356    cur_vaddr = vseg->vbase;
357    cur_paddr = ps->nextLma();
358
359    mapping_vobj_t* cur_vobj;
360    size_t simple_size = 0; //for debug
361
362#ifdef MOVER_DEBUG
363    std::cout << "--------------------vseg_map "<< vseg->name <<"---------------------" << std::endl;
364#endif
365
366    for ( size_t vobj_id = vseg->vobj_offset ; vobj_id < (vseg->vobj_offset + vseg->vobjs) ; vobj_id++ )
367    {
368        cur_vobj = &vobj[vobj_id];
369
370#ifdef MOVER_DEBUG
371        std::cout << std::hex << "current vobj("<< vobj_id <<"): " << cur_vobj->name << " (" <<cur_vobj->vaddr << ")"
372                        << " size: "<< cur_vobj->length << " type: " <<  cur_vobj->type << std::endl;
373#endif
374        if(cur_vobj->type == VOBJ_TYPE_BLOB)
375        {
376            size_t blob_size;
377            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
378
379#ifdef MOVER_DEBUG
380            std::cout << std::hex << "Handling: " << filePath << " ..." << std::endl;
381#endif
382
383            if(!filePath.compare(m_path))    //local blob: map_info
384            {
385#ifdef MOVER_DEBUG
386                std::cout << "Found the vseg of the mapping info" << std::endl;
387#endif
388                blob_size = this->m_size;
389                assert((blob_size >0) and "MAPPING INFO file is empty !?");
390            }
391            else
392            {
393#ifdef MOVER_DEBUG
394                std::cout << "Found an BLOB vseg" << std::endl;
395#endif
396                blob_size = bin_size(filePath);
397            }
398
399
400            /**creating a new section */
401            sect = new elfpp::section(*m_generator, elfpp::SHT_PROGBITS);
402
403            sect->set_name(std::string(cur_vobj->name));
404            sect->set_flags(elfpp::SHF_ALLOC | elfpp::SHF_WRITE);
405            sect->set_size(blob_size);//do the malloc for the get_content fonction
406
407            assert(sect->get_content());//check allocation
408
409            if(!filePath.compare(m_path))    //local blob: map_info
410                //memcpy(sect->get_content(), m_data, sect->get_size());
411                /* this way the modification of the elf size are propageted to the giet */
412                sect->set_content(this->m_data);
413            else
414                load_bin(filePath, sect->get_content());
415
416
417            if(blob_size > cur_vobj->length)
418            {
419                std::cout << std::hex << "!!! Warning, specified blob type vobj ("<<
420                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
421                << blob_size  << " !!!" <<std::endl;
422                assert(0 and "blob vobj length smaller than the actual content" );//???
423            }
424
425            cur_vobj->length = blob_size;//set the true size of this BLOB vobj
426
427            vSO->m_file = filePath;
428            vSO->m_loadable = true;
429        }
430        else if(cur_vobj->type == VOBJ_TYPE_ELF)
431        {
432            if(!first)
433                throw exception::RunTimeError(std::string("elf vobj type, must be placed first in a vseg"));
434
435            size_t elf_size;
436            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
437#ifdef MOVER_DEBUG
438            std::cout << "Handling: " << filePath << " ..." << std::endl;
439            std::cout << "Found an ELF vseg" << std::endl;
440#endif
441            if(m_loaders.count(filePath) == 0 )
442                m_loaders[filePath] = new elfpp::object(filePath);
443            elfpp::object* loader = m_loaders[filePath];//TODO:free!?
444
445            sect =  get_sect_by_addr(loader, cur_vaddr);
446            assert(sect and "No section found");
447
448            sect->set_name(std::string(cur_vobj->name));
449
450
451            elf_size = sect->get_size();
452            assert((elf_size > 0) and "ELF section empty ?");
453
454            if(!m_ginit)
455            {
456                /** Initailising the header of the generator from the first binary,
457                ** we suppose that the header is the same for all the binarys **/
458                m_generator->copy_info(*loader);
459                m_ginit=true;
460            }
461
462            if(elf_size > cur_vobj->length)
463            {
464                std::cout << "Warning, specified elf type vobj ("<<
465                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
466                << elf_size  << std::endl;
467                //assert((elf_size < cur_vobj->length) and "elf vobj length smaller than the actual content" );//???
468                assert((0) and "elf vobj length smaller than the actual content" );//???
469            }
470
471            cur_vobj->length = elf_size;//set the true size of this ELF vobj
472
473            vSO->m_file = filePath;
474            vSO->m_loadable = true;
475        }
476
477        //aligning the vobj->paddr if necessary
478        //
479        if(cur_vobj->align)
480        {
481            cur_paddr = PSeg::align(cur_paddr, cur_vobj->align);
482            aligned = true;
483        }
484
485        cur_vaddr += cur_vobj->length;
486        cur_paddr += cur_vobj->length;
487        simple_size += cur_vobj->length;
488        first = false;
489    }
490
491    assert((cur_vaddr >= vseg->vbase ));
492    assert((cur_paddr >= ps->nextLma() ));
493
494    vSO->m_length = (cur_paddr - ps->nextLma()); //pageAlign is done by the psegs
495
496#ifdef MOVER_DEBUG
497    if(aligned)
498    {
499        std::cout << "vseg base "<< std::hex << ps->nextLma()
500        <<(ps->nextLma()+simple_size)  <<" size " << std::dec << simple_size <<
501        std::endl;
502
503        std::cout << "vseg aligned to: base: " << std::hex << ps->nextLma()
504        <<" to "<< std::hex << ps->nextLma()+vSO->m_length<< " size " << std::dec <<
505        vSO->m_length << std::endl;
506    }
507#endif
508
509    vSO->m_ident = vseg->ident;
510
511    //set the lma
512    if ( vseg->ident != 0 )            // identity mapping required
513        ps->addIdent( *vSO );
514    else
515        ps->add( *vSO );
516
517    if(!sect)
518        return;
519
520#ifdef MOVER_DEBUG
521    std::cout << "section: "<< *sect <<"\n seted to: " << (*vSO) << std::endl;
522#endif
523
524    sect->set_vaddr((*vSO).lma());
525    m_generator->add_section(*(new elfpp::section(*sect)));
526
527} // end vseg_map()
528 
529
530///////////////////////////////
531void MeMo::buildMap(void* desc)
532{
533    mapping_header_t*   header = (mapping_header_t*)desc; 
534
535    mapping_cluster_t*  cluster = get_cluster_base( header );     
536    mapping_vspace_t*   vspace = get_vspace_base( header );     
537    mapping_pseg_t*     pseg   = get_pseg_base( header ); 
538    mapping_vseg_t*     vseg   = get_vseg_base( header );
539
540    // get the psegs
541
542#ifdef MOVER_DEBUG
543std::cout << "\n******* Storing Pseg information *********\n" << std::endl;
544#endif
545
546#ifdef DISTRIBUTED_SCHEDULERS
547    char found;
548#endif
549
550    for ( size_t cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
551    {
552
553#ifdef DISTRIBUTED_SCHEDULERS
554        found    = 0;
555#endif
556
557        for ( size_t pseg_id = cluster[cluster_id].pseg_offset ;
558              pseg_id < cluster[cluster_id].pseg_offset + cluster[cluster_id].psegs ;
559              pseg_id++ )
560        {
561            //build pseg
562            std::string name(pseg[pseg_id].name);
563            PSeg *ps = new PSeg(name, pseg[pseg_id].base, pseg[pseg_id].length);
564
565#ifdef DISTRIBUTED_SCHEDULERS
566            if ( (pseg[pseg_id].type == PSEG_TYPE_RAM) && (found == 0) )
567            {
568                ps->incNextLma( (cluster[cluster_id].procs << 12) );
569                found  = 1;
570            }
571#endif
572            m_psegh.m_pSegs.push_back(*ps);
573
574        }
575    }
576
577    // map global vsegs
578
579#ifdef MOVER_DEBUG
580std::cout << "\n******* mapping global vsegs *********\n" << std::endl;
581#endif
582
583    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
584    {
585        vseg_map( &vseg[vseg_id]);
586    }
587
588    // loop on virtual spaces to map private vsegs
589    for (size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
590    {
591
592#ifdef MOVER_DEBUG
593std::cout << "\n******* mapping all vsegs of " << vspace[vspace_id].name << " *********\n" << std::endl;
594#endif
595           
596        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
597              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
598              vseg_id++ )
599        {
600            vseg_map( &vseg[vseg_id]); 
601        }
602    } 
603
604} // end buildMap()
605
606
607
608// Local Variables:
609// tab-width: 4
610// c-basic-offset: 4
611// c-file-offsets:((innamespace . 0)(inline-open . 0))
612// indent-tabs-mode: nil
613// End:
614
615// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
616
Note: See TracBrowser for help on using the repository browser.