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

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

Cleaning unused files
Simplifying Makefile
adding missing include

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