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

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

Adding BLOB type for vobj.
Don't forget to set as BLOB type the mapping_info vobj in the xml.

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