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

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

changing mover to memo
changing soft.bin to soft.elf
...

File size: 17.4 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
42//#define MOVER_DEBUG
43
44MeMo::MeMo( const std::string &filename, 
45        const size_t pageSize)
46        :m_path(filename),
47        m_pathHandler(filename),
48        m_ginit(false),
49        m_generator(new elfpp::object())
50{
51   
52    PSeg::setPageSize(pageSize);
53
54    load_bin(m_path);
55
56#ifdef MOVER_DEBUG
57    std::cout << "Binary file path: " << m_path << std::endl;
58    //print_mapping_info(m_data);
59#endif
60
61    buildMap(m_data);
62   
63#ifdef MOVER_DEBUG
64    std::cout << "parsing done" << std::endl ;
65#endif
66
67#ifdef MOVER_DEBUG
68    print_mapping();
69    std::cout << *this << std::endl;
70#endif
71
72    m_psegh.check();
73#ifdef MOVER_DEBUG
74    std::cout << "checking done" << std::endl ;
75#endif
76
77}
78
79void MeMo::print( std::ostream &o ) const
80{
81    std::cout << "All sections:" << std::endl;
82    FOREACH( sect, m_generator->get_section_table() )
83    {
84        assert(&*sect != NULL);
85        std::cout << *sect << std::endl; 
86    }
87}
88
89void MeMo::print_mapping() const
90{
91    std::cout << m_psegh << std::endl;
92}
93
94elfpp::section* MeMo::get_sect_by_addr(elfpp::object *loader, unsigned int addr)
95{
96    FOREACH( sect, loader->get_section_table() )
97    {
98        assert(&*sect != NULL);
99        elfpp::sh_flags_e eflags = sect->get_flags();
100        if ( !(eflags & elfpp::SHF_ALLOC) )
101            continue;
102        if(sect->get_load_address() == addr) //load_addr ?
103        {
104            return (&*sect);
105        }
106    }
107    return NULL;
108}
109
110//TODO:delete
111elfpp::section* MeMo::get_sect_by_name(elfpp::object *loader, std::string name)
112{
113#ifdef MOVER_DEBUG
114    std::cout << "get_sect_by_name " << name << std::endl;
115#endif
116    FOREACH( sect, loader->get_section_table() )
117    {
118        assert(&*sect != NULL);
119        elfpp::sh_flags_e eflags = sect->get_flags();
120        if ( !(eflags & elfpp::SHF_ALLOC) )
121            continue;
122
123#ifdef MOVER_DEBUG
124        std::cout << "Trying " << sect->get_name() << std::endl;
125#endif
126        if(!(sect->get_name()).compare(name)) 
127        {
128            return (&*sect);
129        }
130    }
131    return NULL;
132}
133
134void MeMo::buildSoft(const std::string &filename)
135{
136    if(!m_ginit)
137        throw soclib::exception::RunTimeError(std::string("Can't get generator! ") );
138
139    m_generator->write(filename);
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->vsegs +
219                                  MAPPING_VSPACE_SIZE*header->vspaces);
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::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             << " + vspaces = " << header->vspaces  << std::endl
242             << " + globals = " << header->globals  << std::endl
243             << " + vsegs = " << header->vsegs  << std::endl
244             << " + tasks = " << header->tasks  << std::endl;
245
246    // psegs
247    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
248    {
249        std::cout << "pseg " << pseg_id << std::endl
250         << " + name = " << pseg[pseg_id].name << std::endl
251         << " + base = " << pseg[pseg_id].base << std::endl
252         << " + length = " << pseg[pseg_id].length << std::endl ;
253    }
254
255    // globals
256    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
257    {
258        std::cout << "global vseg: " << vseg_id << std::endl
259         << " + name = " << vseg[vseg_id].name << std::endl
260         << " + vbase = " << vseg[vseg_id].vbase << std::endl
261         << " + length = " << vseg[vseg_id].length << std::endl
262         << " + mode = " << (size_t)vseg[vseg_id].mode << std::endl
263         << " + ident = " << (bool)vseg[vseg_id].ident << std::endl
264         << " + psegname" << pseg[vseg[vseg_id].psegid].name << std::endl;
265        for(size_t vobj_id = vseg[vseg_id].vobj_offset ; vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; vobj_id++ )
266        {
267            std::cout << "\t vobjs     = "<<     vobj[vobj_id].name << std::endl;
268            std::cout<<"\t name     =" << vobj[vobj_id].name <<std::endl;
269            std::cout<<"\t type     =" << vobj[vobj_id].type <<std::endl;
270            std::cout<<"\t length   =" << vobj[vobj_id].length <<std::endl;
271            std::cout<<"\t align    =" << vobj[vobj_id].align <<std::endl;
272            std::cout<<"\t binpath  =" << vobj[vobj_id].binpath <<std::endl;
273            std::cout<<"\t \n";
274        }
275    }
276
277
278    // vspaces
279    for ( size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
280    {
281        std::cout << "***vspace: " << vspace_id << "***" << std::endl
282         << " + name = " <<  vspace[vspace_id].name  << std::endl
283         << " + ttys = " <<  vspace[vspace_id].ttys  << std::endl;
284
285        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
286              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
287              vseg_id++ )
288        {
289            std::cout << "private vseg: ";
290            std::cout <<  vseg_id  << std::endl
291             << " + name = " <<  vseg[vseg_id].name  << std::endl
292             << " + vbase = " <<  vseg[vseg_id].vbase  << std::endl
293             << " + length = " <<  vseg[vseg_id].length  << std::endl
294             << " + mode = " <<  (size_t)vseg[vseg_id].mode  << std::endl
295             << " + ident = " <<  (bool)vseg[vseg_id].ident  << std::endl
296             << " + psegname = " << pseg[vseg[vseg_id].psegid].name  << std::endl << std::endl;
297            for(size_t vobj_id = vseg[vseg_id].vobj_offset ; vobj_id < vseg[vseg_id].vobj_offset + vseg[vseg_id].vobjs ; vobj_id++ )
298            {
299                std::cout<<"\t\t vobjs     =" << vobj[vobj_id].name <<std::endl;
300                std::cout<<"\t\t name     =" << vobj[vobj_id].name <<std::endl;
301                std::cout<<"\t\t type     =" << vobj[vobj_id].type <<std::endl;
302                std::cout<<"\t\t length   =" << vobj[vobj_id].length <<std::endl;
303                std::cout<<"\t\t align    =" << vobj[vobj_id].align <<std::endl;
304                std::cout<<"\t\t binpath  =" << vobj[vobj_id].binpath <<std::endl;
305            }
306        }
307
308    }
309} // end print_mapping_info()
310
311///////////////////////////////////////////////////////////////////////////
312void MeMo::pseg_map( mapping_pseg_t* pseg) 
313{
314    std::string name(pseg->name);
315    m_psegh.m_pSegs.push_back(PSeg(name, pseg->base, pseg->length));
316}
317
318
319///////////////////////////////////////////////////////////////////////////
320void MeMo::vseg_map( mapping_vseg_t* vseg) 
321{
322
323    mapping_vobj_t*     vobj   = get_vobj_base( (mapping_header_t*) m_data ); 
324    PSeg *ps = &(m_psegh.get(vseg->psegid));// get physical segment pointer(PSegHandler::get)
325    elfpp::section* sect = NULL;
326    size_t cur_vaddr;
327    size_t cur_paddr;
328    bool first = true;
329    bool aligned = false;
330
331    VSeg   *vSO = new VSeg;
332
333    vSO->m_name = std::string(vseg->name);
334    vSO->m_vma = vseg->vbase;
335    vSO->m_lma = ps->nextLma();
336
337    cur_vaddr = vseg->vbase;
338    cur_paddr = ps->nextLma();
339
340    mapping_vobj_t* cur_vobj;
341    size_t simple_size = 0; //for debug
342   
343#ifdef MOVER_DEBUG
344    std::cout << "--------------------vseg_map "<< vseg->name <<"---------------------" << std::endl;
345#endif
346   
347    for ( size_t vobj_id = vseg->vobj_offset ; vobj_id < (vseg->vobj_offset + vseg->vobjs) ; vobj_id++ )
348    {
349        cur_vobj = &vobj[vobj_id];
350
351#ifdef MOVER_DEBUG
352        std::cout << "current vobj("<< vobj_id <<"): " << cur_vobj->name << " (" <<cur_vobj->vaddr << ")" 
353                        << " size: "<< cur_vobj->length << " type: " <<  cur_vobj->type << std::endl;
354#endif
355
356        if(cur_vobj->type == ELF)
357        {
358            if(!first) 
359                throw soclib::exception::RunTimeError(std::string("elf vobj type, must be placed first in a vseg"));
360
361            size_t elf_size;
362            std::string filePath(m_pathHandler.getFullPath(std::string(cur_vobj->binpath)));
363#ifdef MOVER_DEBUG
364            std::cout << "Handling: " << filePath << " ..." << std::endl;
365#endif
366            if(!filePath.compare(m_path))    //local blob: map_info
367            {
368#ifdef MOVER_DEBUG
369                std::cout << "Found the vseg of the mapping info" << std::endl;
370#endif
371                /**creating a new section */
372                sect = new elfpp::section(*m_generator, elfpp::SHT_PROGBITS);
373
374                sect->set_name(std::string(cur_vobj->name));
375                sect->set_flags(elfpp::SHF_ALLOC | elfpp::SHF_WRITE);
376                sect->set_size(this->m_size);
377                sect->set_content(this->m_data);               
378
379                elf_size = this->m_size;       
380                assert((elf_size >0) and "MAPPING INFO file is empty !?");
381            }
382            else
383            { 
384#ifdef MOVER_DEBUG
385                std::cout << "Found an ELF vseg" << std::endl;
386#endif
387                if(m_loaders.count(filePath) == 0 )
388                    m_loaders[filePath] = new elfpp::object(filePath);
389                elfpp::object* loader = m_loaders[filePath];//TODO:free!?
390
391                //TODO: delete
392                //sect =  get_sect_by_name(loader, std::string(cur_vobj->name));
393                //assert(( sect->get_vaddr() == cur_vaddr) and "Vaddr doesn't match!");
394
395                sect =  get_sect_by_addr(loader, cur_vaddr);
396                assert(sect and "No section found");
397
398                sect->set_name(std::string(cur_vobj->name));
399
400
401                elf_size = sect->get_size();
402                assert((elf_size >0) and "ELF section empty ?");
403
404                if(!m_ginit)
405                {
406                    /** Initailising the header of the generator from the first binary,
407                    * we suppose that the header is the same for all the binarys
408                    * */
409                    m_generator->copy_info(*loader);
410                    m_ginit=true;
411                }
412            }
413
414            if(elf_size > cur_vobj->length)
415                std::cout << "Warning, specified elf type vobj ("<<
416                cur_vobj->name  <<") size is "<< cur_vobj->length << ", the actual size is "
417                << elf_size  << std::endl;
418
419            cur_vobj->length = elf_size;//set the true size of this ELF vobj
420
421            vSO->m_file = filePath;
422            vSO->m_loadable = true;       
423        }
424        first = false;
425
426        //aligning the vobj->paddr if necessary
427        if(cur_vobj->align)
428        {
429            cur_paddr = PSeg::align(cur_paddr, cur_vobj->align);
430            aligned = true;
431        }
432
433        cur_vaddr += cur_vobj->length;
434        cur_paddr += cur_vobj->length;
435        simple_size += cur_vobj->length;
436    }
437
438    assert((cur_vaddr >= vseg->vbase ));
439    assert((cur_paddr >= ps->nextLma() ));
440
441    vSO->m_length = (cur_paddr - ps->nextLma()); //pageAlign is done by the psegs
442
443#ifdef MOVER_DEBUG
444    if(aligned)
445    {
446        std::cout << "vseg base "<< std::hex << ps->nextLma()
447        <<(ps->nextLma()+simple_size)  <<" size " << std::dec << simple_size <<
448        std::endl; 
449
450        std::cout << "vseg aligned to: base: " << std::hex << ps->nextLma()
451        <<" to "<< std::hex << ps->nextLma()+vSO->m_length<< " size " << std::dec <<
452        vSO->m_length << std::endl;
453    }
454#endif
455     
456    vSO->m_ident = vseg->ident;     
457
458    //set the lma
459    if ( vseg->ident != 0 )            // identity mapping required
460        ps->addIdent( *vSO );
461    else
462        ps->add( *vSO );
463   
464    if(!sect)
465        return;
466
467#ifdef MOVER_DEBUG
468    std::cout << "section: "<< *sect <<"\n seted to: " << (*vSO) << std::endl;
469#endif
470
471    sect->set_vaddr((*vSO).lma());
472    m_generator->add_section(*(new elfpp::section(*sect)));
473
474} // end vseg_map()
475
476
477/////////////////////////////////////////////////////////////////////
478void MeMo::buildMap(void* desc)
479{
480    mapping_header_t*   header = (mapping_header_t*)desc; 
481
482    mapping_vspace_t*   vspace = get_vspace_base( header );     
483    mapping_pseg_t*     pseg   = get_pseg_base( header ); 
484    mapping_vseg_t*     vseg   = get_vseg_base( header );
485
486    // get the psegs
487#ifdef MOVER_DEBUG
488std::cout << "\n******* Storing Pseg information *********\n" << std::endl;
489#endif
490    for ( size_t pseg_id = 0 ; pseg_id < header->psegs ; pseg_id++ )
491    {
492        pseg_map( &pseg[pseg_id]);
493    }
494
495    // map global vsegs
496#ifdef MOVER_DEBUG
497std::cout << "\n******* mapping global vsegs *********\n" << std::endl;
498#endif
499    for ( size_t vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
500    {
501        vseg_map( &vseg[vseg_id]);
502    }
503
504    // second loop on virtual spaces to map private vsegs
505    for (size_t vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
506    {
507
508#ifdef MOVER_DEBUG
509std::cout << "\n******* mapping all vsegs of " << vspace[vspace_id].name << " *********\n" << std::endl;
510#endif
511           
512        for ( size_t vseg_id = vspace[vspace_id].vseg_offset ; 
513              vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs) ; 
514              vseg_id++ )
515        {
516            vseg_map( &vseg[vseg_id]); 
517        }
518    } 
519
520} // end buildMap()
521
522
523
524// Local Variables:
525// tab-width: 4
526// c-basic-offset: 4
527// c-file-offsets:((innamespace . 0)(inline-open . 0))
528// indent-tabs-mode: nil
529// End:
530
531// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
532
Note: See TracBrowser for help on using the repository browser.