source: soft/giet_vm/mover/src/mover.cpp @ 160

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

giet-vm new version

File size: 16.3 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 vs and/or modify vs
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 vs 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 "mover.h"
40
41
42//#define MOVER_DEBUG
43
44Mover::Mover( const std::string &filename, 
45        const size_t pageSize)
46        :m_path(filename),
47        m_pathh(filename),
48        m_ginit(false),
49        m_generator(new elfpp::object())
50{
51    //m_generator = new elfpp::object();
52   
53    //m_pathh =
54 
55    PSeg::setPageSize(pageSize);
56
57    load_bin(m_path);
58#ifdef MOVER_DEBUG
59    std::cout << "Binary file path: " << m_path << std::endl;
60    //print_mapping_info(m_data);
61#endif
62
63    buildMap(m_data);
64   
65#ifdef MOVER_DEBUG
66    std::cout << "parsing done" << std::endl ;
67#endif
68
69#ifdef MOVER_DEBUG
70    print_mapping();
71    std::cout << *this << std::endl;
72#endif
73
74    m_psegh.check();
75#ifdef MOVER_DEBUG
76    std::cout << "checking done" << std::endl ;
77#endif
78
79}
80
81void Mover::print( std::ostream &o ) const
82{
83    std::cout << "All sections:" << std::endl;
84    FOREACH( sect, m_generator->get_section_table() )
85    {
86        assert(&*sect != NULL);
87        std::cout << *sect << std::endl; 
88    }
89}
90
91void Mover::print_mapping() const
92{
93    std::cout << m_psegh << std::endl;
94}
95
96elfpp::section* Mover::get_sect_by_addr(elfpp::object *loader, unsigned int addr)
97{
98    FOREACH( sect, loader->get_section_table() )
99    {
100        assert(&*sect != NULL);
101        elfpp::sh_flags_e eflags = sect->get_flags();
102        if ( !(eflags & elfpp::SHF_ALLOC) )
103            continue;
104        if(sect->get_load_address() == addr) //load_addr ?
105        {
106            return (&*sect);
107        }
108    }
109    return NULL;
110}
111
112void Mover::buildSoft(const std::string &filename)
113{
114    if(!m_ginit)
115        throw soclib::exception::RunTimeError(std::string("Can't get generator! ") );
116
117    m_generator->write(filename);
118
119}
120
121void* Mover::load_bin(std::string filename)
122{
123   
124#ifdef MOVER_DEBUG
125    std::cout  << "Trying to load the binary blob from file '" << m_path << "'" << std::endl;
126#endif
127
128    std::ifstream input(m_path.c_str(), std::ios_base::binary|std::ios_base::in);
129
130    if ( ! input.good() )
131        throw soclib::exception::RunTimeError(std::string("Can't open the file: ") + m_path);
132
133    input.seekg( 0, std::ifstream::end );
134    m_size = input.tellg();
135    input.seekg( 0, std::ifstream::beg );
136
137    //m_data = new void*[m_size];
138    m_data = std::malloc(m_size);
139    if ( !m_data )
140        throw soclib::exception::RunTimeError("malloc failed... No memory space");
141
142    input.read( (char*)m_data, m_size );
143   
144    return m_data;
145}
146
147
148Mover::~Mover()
149{
150    //std::cout << "Deleted Mover " << *this << std::endl;
151    std::free(m_data);
152    std::map<std::string, elfpp::object*>::iterator l;
153    for(l = m_loaders.begin(); l != m_loaders.end(); l++)
154    {
155        delete (*l).second;
156    }
157    //delete m_generator;
158}
159
160
161/////////////////////////////////////////////////////////////////////////////
162// various mapping_info data structure access functions
163/////////////////////////////////////////////////////////////////////////////
164
165/////////////////////////////////////////////////////////////////////////////
166mapping_pseg_t* Mover::get_pseg_base( mapping_header_t* header )
167{
168    return   (mapping_pseg_t*)    ((char*)header +
169                                  MAPPING_HEADER_SIZE +
170                                  MAPPING_CLUSTER_SIZE*header->clusters);
171}
172/////////////////////////////////////////////////////////////////////////////
173mapping_vspace_t* Mover::get_vspace_base( mapping_header_t* header )
174{
175    return   (mapping_vspace_t*)  ((char*)header +
176                                  MAPPING_HEADER_SIZE +
177                                  MAPPING_CLUSTER_SIZE*header->clusters +
178                                  MAPPING_PSEG_SIZE*header->psegs);
179}
180/////////////////////////////////////////////////////////////////////////////
181mapping_vseg_t* Mover::get_vseg_base( mapping_header_t* header )
182{
183    return   (mapping_vseg_t*)    ((char*)header +
184                                  MAPPING_HEADER_SIZE +
185                                  MAPPING_CLUSTER_SIZE*header->clusters +
186                                  MAPPING_PSEG_SIZE*header->psegs +
187                                  MAPPING_VSPACE_SIZE*header->vspaces);
188}
189/////////////////////////////////////////////////////////////////////////////
190mapping_vobj_t* Mover::get_vobj_base( mapping_header_t* header )
191{
192    return   (mapping_vobj_t*)    ((char*)header +
193                                  MAPPING_HEADER_SIZE +
194                                  MAPPING_CLUSTER_SIZE*header->clusters +
195                                  MAPPING_PSEG_SIZE*header->psegs +
196                                  MAPPING_VSPACE_SIZE*header->vsegs +
197                                  MAPPING_VSPACE_SIZE*header->vspaces);
198}
199
200/////////////////////////////////////////////////////////////////////////////
201// print the content of the mapping_info data structure
202////////////////////////////////////////////////////////////////////////
203void Mover::print_mapping_info(void* desc)
204{
205    mapping_header_t*   header = (mapping_header_t*)desc; 
206
207    mapping_pseg_t*         pseg    = get_pseg_base( header );;
208    mapping_vspace_t*   vspace  = get_vspace_base ( header );;
209    mapping_vseg_t*         vseg    = get_vseg_base ( header );
210
211    // header
212    std::cout << std::hex << "mapping_info" << std::endl
213              << " + signature = " << header->signature << std::endl
214              << " + name = " << header->name << std::endl
215              << " + clusters = " << header->clusters << std::endl
216              << " + psegs = " << header->psegs << std::endl
217             << " + ttys = " << header->ttys  << std::endl
218             << " + vspaces = " << header->vspaces  << std::endl
219             << " + globals = " << header->globals  << std::endl
220             << " + vsegs = " << header->vsegs  << std::endl
221             << " + tasks = " << header->tasks  << std::endl;
222
223    // psegs
224    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
225    {
226        std::cout << "pseg " << pseg_id << std::endl
227         << " + name = " << pseg[pseg_id].name << std::endl
228         << " + base = " << pseg[pseg_id].base << std::endl
229         << " + length = " << pseg[pseg_id].length << std::endl ;
230    }
231
232    // globals
233    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
234    {
235        std::cout << "global vseg: " << vseg_id << std::endl
236         << " + name = " << vseg[vseg_id].name << std::endl
237         << " + vbase = " << vseg[vseg_id].vbase << std::endl
238         << " + length = " << vseg[vseg_id].length << std::endl
239         << " + mode = " << (size_t)vseg[vseg_id].mode << std::endl
240         << " + ident = " << (bool)vseg[vseg_id].ident << std::endl
241         << " + psegname" << pseg[vseg[vseg_id].psegid].name << std::endl;
242        //TODO print vobjs
243        /*
244        for ( vobj_id = vseg[vseg_id].vobj_offset ; vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; vobj_id++ )
245        {
246            _tty_printf("\t vobjs     = \"%s\"\n",     vobj[vobj_id].name);
247            _tty_printf("\t name     = \"%s\"\n",     vobj[vobj_id].name);
248            _tty_printf("\t type     = \"%s\" \n", vobj[vobj_id].type);
249            _tty_printf("\t length   = \"0x%x\" \n",   vobj[vobj_id].length);
250            _tty_printf("\t align    = \"%d\" \n",   vobj[vobj_id].align);
251            _tty_printf("\t binpath  = \"%s\" \n",   vobj[vobj_id].binpath);
252            _tty_printf("\t \n");
253        }*/
254    }
255
256
257    // vspaces
258    for ( size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
259    {
260        std::cout << "***vspace: " << vspace_id << "***" << std::endl
261         << " + name = " <<  vspace[vspace_id].name  << std::endl
262         << " + ttys = " <<  vspace[vspace_id].ttys  << std::endl;
263
264        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
265              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
266              vseg_id++ )
267        {
268            std::cout << "private vseg: ";
269            std::cout <<  vseg_id  << std::endl
270             << " + name = " <<  vseg[vseg_id].name  << std::endl
271             << " + vbase = " <<  vseg[vseg_id].vbase  << std::endl
272             << " + length = " <<  vseg[vseg_id].length  << std::endl
273             << " + mode = " <<  (size_t)vseg[vseg_id].mode  << std::endl
274             << " + ident = " <<  (bool)vseg[vseg_id].ident  << std::endl
275             << " + psegname = " << pseg[vseg[vseg_id].psegid].name  << std::endl << std::endl;
276        //TODO print vobjs
277        /*
278            for ( vobj_id = vseg[vseg_id].vobj_offset ; vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; vobj_id++ )
279            {
280                _tty_printf("\t\t vobjs     = \"%s\"\n",     vobj[vobj_id].name);
281                _tty_printf("\t\t name     = \"%s\"\n",     vobj[vobj_id].name);
282                _tty_printf("\t\t type     = \"%s\" \n", vobj[vobj_id].type);
283                _tty_printf("\t\t length   = \"0x%x\" \n",   vobj[vobj_id].length);
284                _tty_printf("\t\t align    = \"%d\" \n",   vobj[vobj_id].align);
285                _tty_printf("\t\t binpath  = \"%s\" \n\n",   vobj[vobj_id].binpath);
286            }
287        */
288        }
289
290    }
291} // end print_mapping_info()
292
293///////////////////////////////////////////////////////////////////////////
294void Mover::pseg_map( mapping_pseg_t* pseg) 
295{
296    std::string name(pseg->name);
297    m_psegh.m_pSegs.push_back(PSeg(name, pseg->base, pseg->length));
298}
299
300
301///////////////////////////////////////////////////////////////////////////
302void Mover::vseg_map( mapping_vseg_t* vseg) 
303{
304
305    mapping_vobj_t*     vobj   = get_vobj_base( (mapping_header_t*) m_data ); 
306    PSeg *ps = &(m_psegh.get(vseg->psegid));// get physical segment pointer(PSegHandler::get)
307    elfpp::section* sect = NULL;
308    size_t cur_vaddr;
309    size_t cur_paddr;
310    bool first = true;
311    bool aligned = false;
312
313    VSeg     * vs = new VSeg;
314    std::string s(vseg->name);
315    vs->m_name = s;
316
317    vs->m_vma = vseg->vbase;
318
319    cur_vaddr = vseg->vbase;
320    cur_paddr = ps->nextLma();
321   
322    vs->m_length = 0;
323    mapping_vobj_t* cur_vobj;
324
325    size_t simple_size = 0; //for debug
326   
327#ifdef MOVER_DEBUG
328    std::cout << "--------------------vseg_map---------------------" << std::endl;
329#endif
330   
331    for ( size_t vobj_id = vseg->vobj_offset ; vobj_id < (vseg->vobj_offset + vseg->vobjs) ; vobj_id++ )
332    {
333        cur_vobj = &vobj[vobj_id];
334
335#ifdef MOVER_DEBUG
336        std::cout << "cur vobj("<< vobj_id <<"): " << cur_vobj->name << " (" <<cur_vobj->vaddr << ")" 
337                        << " size "<< cur_vobj->length << " type " <<  cur_vobj->type << std::endl;
338#endif
339
340        if(cur_vobj->type == ELF)
341        {
342
343            if(!first) 
344                throw soclib::exception::RunTimeError(std::string("elf vobj type, must be placed first in a vseg"));
345
346            std::string f(m_pathh.getFullName(std::string(cur_vobj->binpath)));
347            size_t elf_size;
348#ifdef MOVER_DEBUG
349            std::cout << "Handling: " << f << " ..." << std::endl;
350#endif
351            if(!f.compare(m_path))    //local blob: map_info
352            {
353                /**creating a new session */
354                sect = new elfpp::section(*m_generator, elfpp::SHT_PROGBITS);
355
356                sect->set_name(std::string("seg_mapping_info"));
357                sect->set_flags(elfpp::SHF_ALLOC | elfpp::SHF_WRITE);
358                sect->set_size(this->m_size);
359
360                sect->set_content(m_data);               
361
362                elf_size = this->m_size;       
363                assert((elf_size >0) and "MAPINFO file empty !?");
364            }
365            else
366            { 
367#ifdef MOVER_DEBUG
368                std::cout << "ELF vseg found " << std::endl;
369#endif
370                if(m_loaders.count(f) == 0 )
371                    m_loaders[f] = new elfpp::object(f);
372                elfpp::object* loader = m_loaders[f];
373                //elfpp::object* loader = (new elfpp::object(f));//TODO:free!
374
375                sect =  get_sect_by_addr(loader, cur_vaddr);
376                assert(sect and "No section found");
377
378                elf_size = sect->get_size();
379
380                assert((elf_size >0) and "ELF section empty ?");
381                if(!m_ginit)
382                {
383                    //we suppose the header is the same for the all the bins
384                    m_generator->copy_info(*loader);
385                    m_ginit=true;
386                }
387            }
388            cur_vobj->length = elf_size;//set the actual size
389            if(elf_size > cur_vobj->length)
390               std::cout << "Warning, specified elf type vobj ("<< cur_vobj->name  <<") size is "<< cur_vobj->length
391                         << ", the actual size is "  << elf_size  << std::endl;
392
393            vs->m_file = f;
394            vs->m_loadable = true;       
395        }
396        first = false;
397
398        if(cur_vobj->align)
399        {
400            cur_paddr = PSeg::align(cur_paddr, cur_vobj->align);
401            aligned = true;
402        }
403
404
405        cur_vaddr += cur_vobj->length;
406        cur_paddr += cur_vobj->length;
407        simple_size += cur_vobj->length;
408    }
409
410    assert((cur_vaddr >= vseg->vbase ));
411    assert((cur_paddr >= ps->nextLma() ));
412
413    vs->m_length = (cur_paddr - ps->nextLma()); //pageAlign is done by the psegs
414
415#ifdef MOVER_DEBUG
416    if(aligned)
417    {
418        std::cout << "vseg base "<< std::hex << ps->nextLma() <<(ps->nextLma()+simple_size)  <<" size " << std::dec << simple_size << std::endl;
419        std::cout << "vseg aligned to: base: " << std::hex << ps->nextLma() 
420            <<" to "<< std::hex << ps->nextLma()+vs->m_length<< " size " << std::dec << vs->m_length << std::endl;
421    }
422#endif
423     
424    vs->m_ident = vseg->ident;     
425
426    //set the lma
427    if ( vseg->ident != 0 )            // identity mapping required
428        ps->addIdent( *vs );
429    else
430        ps->add( *vs );
431   
432    if(!sect)
433        return;
434
435    //std::cout << "section: "<< *sect <<"\n seted to: " << (*vs) << std::endl;
436    sect->set_vaddr((*vs).lma());
437    m_generator->add_section(*(new elfpp::section(*sect)));
438
439} // end vseg_map()
440
441
442/////////////////////////////////////////////////////////////////////
443void Mover::buildMap(void* desc)
444{
445    mapping_header_t*   header = (mapping_header_t*)desc; 
446
447    mapping_vspace_t*   vspace = get_vspace_base( header );     
448    mapping_pseg_t*     pseg   = get_pseg_base( header ); 
449    mapping_vseg_t*     vseg   = get_vseg_base( header );
450
451    // get the psegs
452#ifdef MOVER_DEBUG
453std::cout << "\n******* Storing Pseg information *********\n" << std::endl;
454#endif
455    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
456    {
457        pseg_map( &pseg[pseg_id]);
458    }
459
460    // map global vsegs
461#ifdef MOVER_DEBUG
462std::cout << "\n******* mapping global vsegs *********\n" << std::endl;
463#endif
464    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
465    {
466        vseg_map( &vseg[vseg_id]);
467    }
468
469    // second loop on virtual spaces to map private vsegs
470    for (size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
471    {
472
473#ifdef MOVER_DEBUG
474std::cout << "\n******* mapping all vsegs of " << vspace[vspace_id].name << " *********\n" << std::endl;
475#endif
476           
477        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
478              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
479              vseg_id++ )
480        {
481            vseg_map( &vseg[vseg_id]); 
482        }
483    } 
484
485} // end buildMap()
486
487
488
489// Local Variables:
490// tab-width: 4
491// c-basic-offset: 4
492// c-file-offsets:((innamespace . 0)(inline-open . 0))
493// indent-tabs-mode: nil
494// End:
495
496// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
497
Note: See TracBrowser for help on using the repository browser.