OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [host/] [tools/] [configtool/] [standalone/] [wxwin/] [memmap.cpp] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
// ####ECOSHOSTGPLCOPYRIGHTBEGIN####                                        
2
// -------------------------------------------                              
3
// This file is part of the eCos host tools.                                
4
// Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.            
5
//
6
// This program is free software; you can redistribute it and/or modify     
7
// it under the terms of the GNU General Public License as published by     
8
// the Free Software Foundation; either version 2 or (at your option) any   
9
// later version.                                                           
10
//
11
// This program is distributed in the hope that it 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
// General Public License for more details.                                 
15
//
16
// You should have received a copy of the GNU General Public License        
17
// along with this program; if not, write to the                            
18
// Free Software Foundation, Inc., 51 Franklin Street,                      
19
// Fifth Floor, Boston, MA  02110-1301, USA.                                
20
// -------------------------------------------                              
21
// ####ECOSHOSTGPLCOPYRIGHTEND####                                          
22
//=================================================================
23
//
24
//        memmap.cpp
25
//
26
//        Memory Layout Tool map data structure manipulation class
27
//
28
//=================================================================
29
//#####DESCRIPTIONBEGIN####
30
//
31
// Author(s):     John Dallaway
32
// Contact(s):    jld
33
// Date:          1998/07/29 $RcsDate$ {or whatever}
34
// Version:       0.00+  $RcsVersion$ {or whatever}
35
// Purpose:       Provides functions to create and destroy memory regions
36
//                and sections within the memory map.
37
// Description:   Each function manipulates data structures representing
38
//                memory regions, memory sections and the view of memory
39
//                sections as presented to the user. The section view
40
//                structure organises the sections by region and 
41
//                will contain two instances of each relocated section 
42
// Requires:      memmap.h
43
// Provides:      create_memory_region()
44
//                delete_memory_region()
45
//                edit_memory_region()
46
//                create_memory_section()
47
//                delete_memory_section()
48
//                edit_memory_section()
49
//                delete_all_memory_sections()
50
//                set_map_size()
51
//                section_list
52
//                region_list
53
// See also:      memmap.h
54
// Known bugs:    <UPDATE_ME_AT_RELEASE_TIME>
55
// WARNING:       Do not modify data structures other than by using the
56
//                provided functions
57
// Usage:         #include "memmap.h"
58
//                ...
59
//                status = set_map_size (0x8000);
60
//
61
//####DESCRIPTIONEND####
62
 
63
#pragma warning (disable:4514) /* unreferenced inline function */
64
#pragma warning (disable:4710) /* function not inlined */
65
 
66
// Includes other headers for precompiled compilation
67
#include "ecpch.h"
68
 
69
#ifdef __BORLANDC__
70
#pragma hdrstop
71
#endif
72
 
73
#include "memmap.h"
74
 
75
using namespace std;
76
 
77
//////////////////////////////////////////////////////////////////////
78
// Construction/Destruction
79
//////////////////////////////////////////////////////////////////////
80
 
81
mem_map::mem_map()
82
{
83
        map_modified_flag = true;
84
        map_size = (mem_address) 0;
85
}
86
 
87
mem_map::~mem_map()
88
{
89
 
90
}
91
 
92
mem_section::mem_section()
93
{
94
 
95
}
96
 
97
mem_section::~mem_section()
98
{
99
 
100
}
101
 
102
///////////////////////////////////////////////////////////////////////
103
// get_memory_region() retrieves the parameters of a memory region
104
 
105
bool mem_map::get_memory_region (std::string region_name, mem_address * region_address, mem_address * region_size, mem_type * region_type, std::string * note)
106
{
107
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end (); ++region)
108
        if (region->name == region_name)
109
        {
110
            *region_address = region->address;
111
            *region_size = region->size;
112
            *region_type = region->type;
113
            *note = region->note;
114
            return true;
115
        }
116
 
117
    return false;
118
}
119
 
120
 
121
///////////////////////////////////////////////////////////////////////
122
// create_memory_region() inserts a new item into the memory region list
123
// in order of memory address
124
 
125
int mem_map::create_memory_region (std::string new_region_name, mem_address new_region_address, mem_address new_region_size, mem_type new_region_type, std::string note)
126
{
127
    const mem_address new_region_end = new_region_address + new_region_size; // the byte after the new region end
128
 
129
    // check that the new region name is specified
130
 
131
    if (new_region_name == "")
132
        return ERR_MEMMAP_REGION_NONAME; // the new region name must be specified
133
 
134
    // check that the new region lies within the memory map
135
 
136
    if (new_region_end > map_size)
137
        return ERR_MEMMAP_REGION_MAPSIZE; // the new region does not lie within the memory map
138
 
139
    // check that the region end address hasn't exceeded the storage size
140
 
141
    if (new_region_end < new_region_address)
142
        return ERR_MEMMAP_REGION_MAPSIZE; // the new region does not lie within the memory map
143
 
144
    // initialise the insertion point for the new region
145
 
146
    list <mem_region>::iterator insertion_point = region_list.end ();
147
 
148
    // check that the new region does not overlap existing regions and does not already exist
149
 
150
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end (); ++region)
151
    {
152
        const mem_address region_end = region->address + region->size; // the byte after the region end
153
 
154
        if ((new_region_address >= region->address) && (new_region_address < region_end))
155
        {
156
            error_info = region->name;
157
            return ERR_MEMMAP_REGION_INTERSECT; // the start of the new region is within an existing region
158
        }
159
 
160
        if ((new_region_end > region->address) && (new_region_end <= region_end))
161
        {
162
            error_info = region->name;
163
            return ERR_MEMMAP_REGION_INTERSECT; // the end of the new region is within an existing region
164
        }
165
 
166
        if ((new_region_address < region->address) && (new_region_end > region_end))
167
        {
168
            error_info = region->name;
169
            return ERR_MEMMAP_REGION_INTERSECT; // an existing region lies within the new region
170
        }
171
 
172
        if (region->name == new_region_name)
173
            return ERR_MEMMAP_REGION_NAMEINUSE; // the new region name is not unique
174
 
175
        if ((insertion_point == region_list.end ()) && (region->address > new_region_address))
176
            insertion_point = region; // insert the new region here
177
    }
178
 
179
    // add the new region to the region list
180
 
181
    list <mem_region>::iterator new_region = region_list.insert (insertion_point);
182
    new_region->name = new_region_name;
183
    new_region->address = new_region_address;
184
    new_region->size = new_region_size;
185
    new_region->type = new_region_type;
186
    new_region->note = note;
187
 
188
    // initialise the section list for the new region
189
 
190
    calc_section_list (new_region);
191
 
192
        map_modified_flag = true;
193
    return 0;
194
}
195
 
196
 
197
///////////////////////////////////////////////////////////////////////
198
// edit_memory_region() edits an item in the memory region list
199
 
200
int mem_map::edit_memory_region (std::string old_region_name, std::string new_region_name, mem_address new_region_address, mem_address new_region_size, mem_type new_region_type, std::string note)
201
{
202
    list <mem_region>::iterator edit_region = find_memory_region (old_region_name);
203
    if (edit_region == NULL)
204
        return ERR_MEMMAP_REGION_NOTFOUND; // the region to be modified does not exist
205
 
206
    // check that the new region name is specified
207
 
208
    if (new_region_name == "")
209
        return ERR_MEMMAP_REGION_NONAME; // the new region name must be specified
210
 
211
    // check that the region end address hasn't exceeded the storage size
212
 
213
    if (new_region_address + new_region_size < new_region_address)
214
        return ERR_MEMMAP_REGION_MAPSIZE; // the new region does not lie within the memory map
215
 
216
    // check region name change
217
 
218
    if ((old_region_name != new_region_name) &&
219
        (find_memory_region (new_region_name) != NULL))
220
        return ERR_MEMMAP_REGION_NAMEINUSE; // new region name is not unique
221
 
222
    // check region address/size change wrt other regions
223
 
224
    const mem_address new_region_end = new_region_address + new_region_size;
225
    if ((new_region_address != edit_region->address) ||
226
        (new_region_size != edit_region->size))
227
    {
228
        for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end (); ++region)
229
            if (region != edit_region)
230
        {
231
            const mem_address region_end = region->address + region->size; // the byte after the region end
232
 
233
            if ((new_region_address >= region->address) && (new_region_address < region_end))
234
            {
235
                error_info = region->name;
236
                return ERR_MEMMAP_REGION_INTERSECT; // the start of the modified region is within another region
237
            }
238
 
239
            if ((new_region_end > region->address) && (new_region_end <= region_end))
240
            {
241
                error_info = region->name;
242
                return ERR_MEMMAP_REGION_INTERSECT; // the end of the modified region is within an existing region
243
            }
244
 
245
            if ((new_region_address < region->address) && (new_region_end > region_end))
246
            {
247
                error_info = region->name;
248
                return ERR_MEMMAP_REGION_INTERSECT; // another region lies within the modified region
249
            }
250
        }
251
    }
252
 
253
    // check region size change wrt sections within region (if any)
254
 
255
    for (list <mem_section_view>::iterator section_view = edit_region->section_view_list.begin (); section_view != edit_region->section_view_list.end (); ++section_view)
256
        if (section_view->section != NULL)
257
    {
258
        if ((section_view->section_location == final_location) || (section_view->section_location == fixed_location))
259
            if (section_view->section->final_location->anchor == absolute)
260
                if (section_view->section->final_location->address + section_view->section->size - edit_region->address > new_region_size)
261
                    return ERR_MEMMAP_REGION_SIZE; // region is now too small
262
 
263
        if (section_view->section_location == initial_location)
264
            if (section_view->section->initial_location->anchor == absolute)
265
                if (section_view->section->initial_location->address + section_view->section->size - edit_region->address > new_region_size)
266
                    return ERR_MEMMAP_REGION_SIZE; // region is now too small
267
    }
268
 
269
    // check region read-only change FIXME
270
 
271
    // move sections within the region having absolute anchors
272
 
273
    for (section_view = edit_region->section_view_list.begin (); section_view != edit_region->section_view_list.end (); ++section_view)
274
        if (section_view->section != NULL)
275
    {
276
        if ((section_view->section_location == final_location) || (section_view->section_location == fixed_location))
277
            if (section_view->section->final_location->anchor == absolute)
278
                section_view->section->final_location->address += (new_region_address - edit_region->address);
279
 
280
        if ((section_view->section_location == initial_location) || (section_view->section_location == fixed_location))
281
            if (section_view->section->initial_location->anchor == absolute)
282
                section_view->section->initial_location->address += (new_region_address - edit_region->address);
283
    }
284
 
285
    // deleteZ(the region and recreate it to make sure the region list is ordered correctly)
286
 
287
    region_list.erase (edit_region);
288
    if (create_memory_region (new_region_name, new_region_address, new_region_size, new_region_type, note))
289
        return ERR_MEMMAP_ALLOC;
290
 
291
        map_modified_flag = true;
292
    return 0;
293
}
294
 
295
 
296
//////////////////////////////////////////////////////////////////
297
// delete_memory_region() removes an existing item from the memory
298
// region list
299
 
300
bool mem_map::delete_memory_region (std::string name)
301
{
302
    // make sure that there are no used sections in this region before deleting it
303
 
304
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end (); ++region)
305
    {
306
        if ((region->name == name) && (region->section_view_list.size () == 1) &&  (region->section_view_list.front ().section == NULL))
307
        {
308
            region_list.erase (region);
309
                        map_modified_flag = true;
310
            return true;
311
        }
312
    }
313
 
314
    return false;
315
}
316
 
317
///////////////////////////////////////////////////////////////////
318
// set_map_size() sets the maximum permitted address for the end
319
// of any memory region
320
 
321
bool mem_map::set_map_size (mem_address new_map_size)
322
{
323
    // check that the new size is sufficient for all previously defined memory regions
324
 
325
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end (); ++region)
326
    {
327
        if (region->address + region->size > new_map_size)
328
            return false; // the new map size is too small
329
    }
330
 
331
    // set the map size
332
 
333
    map_size = new_map_size;
334
 
335
    return true;
336
}
337
 
338
 
339
////////////////////////////////////////////////////////////////////
340
// edit_memory_section() edits an item to the memory section map
341
 
342
int mem_map::edit_memory_section (std::string old_section_name, std::string new_section_name, mem_address section_size, mem_address section_alignment, mem_anchor initial_section_anchor, std::string initial_anchor_section_name, mem_address initial_anchor_address, mem_anchor final_section_anchor, std::string final_anchor_section_name, mem_address final_anchor_address, bool relocates, bool anchor_to_initial_location, bool linker_defined, std::string note)
343
{
344
    // do all the parameter validation
345
 
346
    if (new_section_name == "") // the new section name must be specified
347
        return ERR_MEMMAP_SECTION_NONAME;
348
 
349
    if ((new_section_name != old_section_name) &&
350
        (find_memory_section (new_section_name) != NULL))
351
        return ERR_MEMMAP_SECTION_NAMEINUSE; // the new section name is not unique
352
 
353
    list <mem_section>::iterator section = find_memory_section (old_section_name);
354
    if (section == NULL)
355
        return ERR_MEMMAP_SECTION_NOTFOUND; // the specified old section name could not be found
356
 
357
    // check that the LMA (if absolute) is within a memory region
358
 
359
    list <mem_region>::iterator region;
360
    if (initial_section_anchor == absolute)
361
    {
362
        region = find_region_by_address (initial_anchor_address);
363
        if (region == NULL)
364
            return ERR_MEMMAP_SECTION_LMA_NOTINREGION; // section LMA is not within a memory region
365
        if ((section_size > 0) && (initial_anchor_address + section_size > region->address + region->size))
366
            return ERR_MEMMAP_SECTION_LMA_NOTINREGION; // end of section is not within the memory region
367
        if (relocates && (region->type == read_write))
368
            return ERR_MEMMAP_SECTION_LMA_READWRITE; // section LMA must be in a read-only memory region
369
    }
370
 
371
    // check that the VMA (if absolute) is within a memory region
372
 
373
    if (final_section_anchor == absolute)
374
    {
375
        region = find_region_by_address (final_anchor_address);
376
        if (region == NULL)
377
            return ERR_MEMMAP_SECTION_VMA_NOTINREGION; // section VMA is not within a memory region
378
        if ((section_size > 0) && (final_anchor_address + section_size > region->address + region->size))
379
            return ERR_MEMMAP_SECTION_VMA_NOTINREGION; // end of section is not within the memory region
380
        if (relocates && (region->type == read_only))
381
            return ERR_MEMMAP_SECTION_VMA_READONLY; // section VMA must be in a read/write memory region
382
    }
383
 
384
    // check relative location information as appropriate
385
 
386
    if (relocates) // only check the initial parent section if the section relocates
387
    {
388
        if (initial_section_anchor == relative)
389
        {
390
            list <mem_section>::iterator parent_section = find_memory_section (initial_anchor_section_name);
391
            if (parent_section == section_list.end ())
392
                return ERR_MEMMAP_SECTION_LMA_ANCHORNOTFOUND; // initial anchor name not found
393
 
394
            if ((parent_section->initial_location->following_section != section) && (parent_section->initial_location->following_section != NULL))
395
                return ERR_MEMMAP_SECTION_LMA_ANCHORNOTAVAIL; // initial anchor specified has changed and is unavailable
396
 
397
            if ((parent_section->size == 0) && (! parent_section->linker_defined))
398
                return ERR_MEMMAP_SECTION_LMA_ANCHORNOTAVAIL; // initial anchor specified expands to fit available space
399
 
400
            if (find_region_by_section (parent_section, initial_location)->type == read_write)
401
                return ERR_MEMMAP_SECTION_LMA_READWRITE; // initial anchor must be in a read-only memory region
402
        }
403
    }
404
 
405
    if (final_section_anchor == relative)
406
    {
407
        list <mem_section>::iterator parent_section = find_memory_section (final_anchor_section_name);
408
        if (parent_section == NULL)
409
            return ERR_MEMMAP_SECTION_VMA_ANCHORNOTFOUND; // final anchor name not found
410
 
411
        if ((parent_section->size == 0) && (! parent_section->linker_defined))
412
            return ERR_MEMMAP_SECTION_VMA_ANCHORNOTAVAIL; // final anchor specified expands to fit available space
413
 
414
        if ((!relocates) && anchor_to_initial_location) // final anchor to initial location of parent section
415
        {
416
            if ((parent_section->initial_location->following_section != section) && (parent_section->initial_location->following_section != NULL))
417
                return ERR_MEMMAP_SECTION_VMA_ANCHORNOTAVAIL; // final anchor specified has changed and is unavailable
418
        }
419
        else
420
        {
421
            if ((parent_section->final_location->following_section != section) && (parent_section->final_location->following_section != NULL))
422
                return ERR_MEMMAP_SECTION_VMA_ANCHORNOTAVAIL; // final anchor specified has changed and is unavailable
423
        }
424
 
425
        if (relocates && (find_region_by_section (parent_section, final_location)->type == read_only))
426
            return ERR_MEMMAP_SECTION_VMA_READONLY; // final anchor of relocating section must be in a read/write memory region
427
    }
428
 
429
        // check for a non-relocating section changing to relocating where the final
430
        // location moves from a read_only region to a read_write region and there
431
        // is a following non-relocating section
432
 
433
    if (relocates && (! section->relocates) &&
434
                (find_region_by_section (section, fixed_location)->type == read_only) &&
435
                (section->final_location->following_section != NULL) &&
436
                (! section->final_location->following_section->relocates))
437
        {
438
                return ERR_MEMMAP_SECTION_ILLEGAL_RELOCATION;
439
        }
440
 
441
    // FIXME check for overlap of absolute sections
442
 
443
    // modify the initial section location data
444
 
445
    if (section->initial_location->anchor == relative) // initial section anchor was relative
446
        find_preceding_section (section, true)->initial_location->following_section = NULL;
447
 
448
    if (initial_section_anchor == absolute) // initial location now absolute
449
        section->initial_location->address = initial_anchor_address;
450
    else // initial location now relative
451
    {
452
        list <mem_section>::iterator initial_parent = find_memory_section (initial_anchor_section_name);
453
        if (relocates || (! initial_parent->relocates))
454
            initial_parent->initial_location->following_section = section;
455
    }
456
 
457
    // modify the final section location data
458
 
459
    if (section->final_location->anchor == relative) // final section anchor was relative
460
        find_preceding_section (section, false)->final_location->following_section = NULL;
461
 
462
    if (final_section_anchor == absolute) // final location now absolute
463
        section->final_location->address = final_anchor_address;
464
    else // final location now relative
465
    {
466
        list <mem_section>::iterator final_parent = find_memory_section (final_anchor_section_name);
467
        final_parent->final_location->following_section = section;
468
    }
469
 
470
    // handle relocation changes
471
 
472
    if (relocates && (! section->relocates)) // section was non-relocating but now relocates
473
        {
474
                if (find_region_by_section (section, fixed_location)->type == read_only) // the section was in a read_only region
475
                   section->final_location->following_section = NULL; // there is now no section following the final location
476
                else
477
                   section->initial_location->following_section = NULL; // there is now no section following the initial location
478
        }
479
 
480
    else if ((! relocates) && section->relocates) // section was relocating but is now non-relocating
481
        {
482
                // determine the type of memory region in which the section now resides
483
 
484
                mem_type type;
485
                if ((final_section_anchor == relative) && anchor_to_initial_location)
486
                        type = find_region_by_section (find_memory_section (final_anchor_section_name), initial_location)->type;
487
                else if (final_section_anchor == relative) // anchored to final location of preceding section
488
                        type = find_region_by_section (find_memory_section (final_anchor_section_name), final_location)->type;
489
                else // final_section_anchor must be absolute
490
                        type = find_region_by_address (final_anchor_address)->type;
491
 
492
                if (type == read_only) // the section is now in a read-only memory region
493
                {
494
                        if ((section->initial_location->following_section != NULL) && ! section->initial_location->following_section->relocates)
495
                                section->final_location->following_section = section->initial_location->following_section;
496
                        else
497
                                section->final_location->following_section = NULL;
498
                }
499
                else // the section is now in a read-write memory region
500
                {
501
                        if ((section->final_location->following_section != NULL) && ! section->final_location->following_section->relocates)
502
                                section->initial_location->following_section = section->final_location->following_section;
503
                        else
504
                                section->initial_location->following_section = NULL;
505
                }
506
        }
507
 
508
    // modify the remaining section data
509
 
510
    section->name = new_section_name;
511
    section->size = section_size;
512
    section->alignment = section_alignment;
513
    section->relocates = relocates;
514
    section->note = note;
515
    section->linker_defined = linker_defined;
516
    section->initial_location->anchor = initial_section_anchor;
517
    section->final_location->anchor = final_section_anchor;
518
 
519
    // recalculate section lists for all regions
520
 
521
    calc_section_lists ();
522
 
523
        map_modified_flag = true;
524
    return 0;
525
}
526
 
527
 
528
////////////////////////////////////////////////////////////////////
529
// create_memory_section() adds a new item to the memory section map
530
// either a section name (for relative locations) or an anchor address
531
// (for absolute locations) must be specified
532
 
533
int mem_map::create_memory_section (std::string section_name, mem_address section_size, mem_address section_alignment, mem_anchor initial_section_anchor, std::string initial_anchor_section_name, mem_address initial_anchor_address, mem_anchor final_section_anchor, std::string final_anchor_section_name, mem_address final_anchor_address, bool relocates, bool anchor_to_initial_location, bool linker_defined, std::string note)
534
{
535
    list <mem_region>::iterator region;
536
 
537
    // check that the new section name is specified
538
 
539
    if (section_name == "")
540
        return ERR_MEMMAP_SECTION_NONAME; // the new section name must be specified
541
 
542
    // check that the new section name is unique
543
 
544
    if (find_memory_section (section_name) != NULL)
545
        return ERR_MEMMAP_SECTION_NAMEINUSE; // the new section name is not unique
546
 
547
    // check that the LMA (if absolute) is within a memory region
548
 
549
    if (initial_section_anchor == absolute)
550
    {
551
        region = find_region_by_address (initial_anchor_address);
552
        if (region == NULL)
553
            return ERR_MEMMAP_SECTION_LMA_NOTINREGION; // section LMA is not within a memory region
554
        if ((section_size > 0) && (initial_anchor_address + section_size > region->address + region->size))
555
            return ERR_MEMMAP_SECTION_LMA_NOTINREGION; // end of section is not within the memory region
556
        if (relocates && (region->type == read_write))
557
            return ERR_MEMMAP_SECTION_LMA_READWRITE; // section LMA must be in a read-only memory region
558
    }
559
 
560
    // check that the VMA (if absolute) is within a memory region
561
 
562
    if (final_section_anchor == absolute)
563
    {
564
        region = find_region_by_address (final_anchor_address);
565
        if (region == NULL)
566
            return ERR_MEMMAP_SECTION_VMA_NOTINREGION; // section VMA is not within a memory region
567
        if ((section_size > 0) && (final_anchor_address + section_size > region->address + region->size))
568
            return ERR_MEMMAP_SECTION_VMA_NOTINREGION; // end of section is not within the memory region
569
        if (relocates && (region->type == read_only))
570
            return ERR_MEMMAP_SECTION_VMA_READONLY; // section VMA must be in a read/write memory region
571
    }
572
 
573
    // FIXME check for overlap of absolute sections
574
 
575
    // check that specified parent(s) (for relative anchors) are available
576
 
577
    if (relocates) // only check the initial parent section if the section relocates
578
    {
579
        if (initial_section_anchor == relative)
580
        {
581
            list <mem_section>::iterator parent_section = find_memory_section (initial_anchor_section_name);
582
            if (parent_section == section_list.end ())
583
                return ERR_MEMMAP_SECTION_LMA_ANCHORNOTFOUND; // initial anchor name not found
584
/*
585
            if (parent_section->initial_location->following_section != NULL)
586
                return ERR_MEMMAP_SECTION_LMA_ANCHORNOTAVAIL; // initial anchor specified is unavailable
587
*/
588
            if ((parent_section->size == 0) && (! parent_section->linker_defined))
589
                return ERR_MEMMAP_SECTION_LMA_ANCHORNOTAVAIL; // initial anchor specified expands to fit available space
590
 
591
            if (find_region_by_section (parent_section, initial_location)->type == read_write)
592
                return ERR_MEMMAP_SECTION_LMA_READWRITE; // initial anchor must be in a read-only memory region
593
        }
594
    }
595
 
596
    if (final_section_anchor == relative)
597
    {
598
        list <mem_section>::iterator parent_section = find_memory_section (final_anchor_section_name);
599
        if (parent_section == NULL)
600
            return ERR_MEMMAP_SECTION_VMA_ANCHORNOTFOUND; // final anchor name not found
601
 
602
        if ((parent_section->size == 0) && (! parent_section->linker_defined))
603
            return ERR_MEMMAP_SECTION_VMA_ANCHORNOTAVAIL; // final anchor specified expands to fit available space
604
/*
605
        if ((!relocates) && anchor_to_initial_location) // final anchor to initial location of parent section
606
        {
607
            if (parent_section->initial_location->following_section != NULL)
608
                return ERR_MEMMAP_SECTION_VMA_ANCHORNOTAVAIL; // final anchor specified is unavailable
609
        }
610
        else
611
        {
612
            if (parent_section->final_location->following_section != NULL)
613
                return ERR_MEMMAP_SECTION_VMA_ANCHORNOTAVAIL; // final anchor specified is unavailable
614
        }
615
*/
616
        if (relocates && (find_region_by_section (parent_section, final_location)->type == read_only))
617
            return ERR_MEMMAP_SECTION_VMA_READONLY; // final anchor of relocating section must be in a read/write memory region
618
    }
619
 
620
    // add the new section to the section map
621
 
622
    mem_section new_mem_section;
623
    list <mem_section>::iterator new_section = section_list.insert (section_list.begin (), new_mem_section);
624
    new_section->name = section_name;
625
    new_section->size = section_size;
626
    new_section->alignment = section_alignment;
627
    new_section->relocates = relocates;
628
    new_section->note = note;
629
    new_section->linker_defined = linker_defined;
630
    new_section->initial_location = new mem_location;
631
    new_section->final_location = new mem_location;
632
    new_section->initial_location->following_section = NULL; // initialize struct
633
    new_section->final_location->following_section = NULL; // initialize struct
634
    new_section->initial_location->anchor = initial_section_anchor;
635
    new_section->final_location->anchor = final_section_anchor;
636
 
637
    if ((initial_section_anchor == relative) &&
638
        (!relocates) && (find_memory_section (initial_anchor_section_name)->relocates))
639
    {
640
        // a non-relocating relative section anchored to a relocating section
641
 
642
        if (anchor_to_initial_location) // new section is anchored to the initial location of a relocating section
643
        {
644
            list <mem_section>::iterator anchor_section = find_memory_section (initial_anchor_section_name);
645
            new_section->initial_location->following_section = anchor_section->initial_location->following_section;
646
            anchor_section->initial_location->following_section = new_section;
647
        }
648
        else // new section is anchored to the final location of a relocating section
649
        {
650
            list <mem_section>::iterator anchor_section = find_memory_section (initial_anchor_section_name);
651
            new_section->final_location->following_section = anchor_section->final_location->following_section;
652
            anchor_section->final_location->following_section = new_section;
653
        }
654
    }
655
    else
656
    {
657
        // copy initial location data
658
 
659
        if (initial_section_anchor == relative) // new section follows the named anchor section
660
        {
661
            list <mem_section>::iterator anchor_section = find_memory_section (initial_anchor_section_name);
662
            new_section->initial_location->following_section = anchor_section->initial_location->following_section; // move anchor of the following section
663
            anchor_section->initial_location->following_section = new_section; // anchor the new section
664
        }
665
        else // new section has an absolute anchor
666
            new_section->initial_location->address = initial_anchor_address;
667
 
668
        // copy final location data
669
 
670
        if (final_section_anchor == relative) // new section follows the named anchor section
671
        {
672
            list <mem_section>::iterator anchor_section = find_memory_section (final_anchor_section_name);
673
            new_section->final_location->following_section = anchor_section->final_location->following_section; // move anchor of the following section
674
            anchor_section->final_location->following_section = new_section; // anchor the new section
675
        }
676
        else // new section has an absolute anchor
677
            new_section->final_location->address = final_anchor_address;
678
    }
679
 
680
    // recalculate section lists for all regions
681
 
682
    calc_section_lists ();
683
 
684
        map_modified_flag = true;
685
    return 0;
686
}
687
 
688
 
689
////////////////////////////////////////////////////////////////////////
690
// calc_section_lists() updates the lists of memory sections for all
691
// memory regions
692
 
693
bool mem_map::calc_section_lists ()
694
{
695
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end(); ++region)
696
        calc_section_list (region);
697
 
698
    return true;
699
}
700
 
701
 
702
////////////////////////////////////////////////////////////////////////
703
// calc_section_list() updates the list of memory sections which reside 
704
// in the specified memory region. It is called whenever the section
705
// map is modified.
706
 
707
bool mem_map::calc_section_list (list <mem_region>::iterator region)
708
{
709
    // clear the old list (if any)
710
 
711
        //TRACE (_T("Calculating section list for region '%s'\n"), CString (region->name.c_str()));
712
    region->section_view_list.clear ();
713
 
714
    // add the initial and final locations of each absolute section as necessary
715
 
716
    for (list <mem_section>::iterator section = section_list.begin (); section != section_list.end (); ++section)
717
    {
718
        if (section->relocates) // the section is relocated and must be added to the view twice
719
        {
720
            add_absolute_section_to_list (region, section, initial_location);
721
            add_absolute_section_to_list (region, section, final_location);
722
        }
723
        else // the section is not relocated and must be added to the view once only
724
            add_absolute_section_to_list (region, section, fixed_location);
725
    }
726
 
727
    // add unused sections to section view list where appropriate
728
 
729
    list <mem_section_view>::iterator previous_section_view = region->section_view_list.begin ();
730
 
731
    if (previous_section_view == region->section_view_list.end ()) // no used sections in this region
732
    {
733
        // add a single unused section to the section view list
734
 
735
        mem_section_view new_section_view;
736
        new_section_view.section = NULL; // an unused section
737
        region->section_view_list.push_back (new_section_view); // add to the section list for this region
738
    }
739
    else // there are used sections in this region
740
    {
741
        list <mem_section_view>::iterator second_section_view = region->section_view_list.begin ();
742
        ++second_section_view;
743
 
744
        // add unused sections between used sections where they do not meet in either initial or final locations
745
 
746
        for (list <mem_section_view>::iterator section_view = second_section_view; section_view != region->section_view_list.end (); ++section_view)
747
        {
748
            if (! (absolute_sections_meet (previous_section_view->section, section_view->section)))
749
            {
750
                list <mem_section_view>::iterator new_section_view = region->section_view_list.insert (section_view); // add an unused section
751
                new_section_view->section = NULL;
752
            }
753
 
754
            previous_section_view = section_view;
755
        }
756
 
757
        // add an unused section to end of region if the last section does not reach the end of the region in initial or final locations
758
 
759
        if (! at_end_of_region (region->section_view_list.back().section, region))
760
        {
761
            mem_section_view new_section_view;
762
            new_section_view.section = NULL; // an unused section
763
            region->section_view_list.push_back (new_section_view); // add an unused section
764
        }
765
 
766
        // add an unused section to start of region if the first section does not start at the start of the region in initial or final locations
767
 
768
        if (! at_start_of_region (region->section_view_list.front().section, region))
769
        {
770
            mem_section_view new_section_view;
771
            new_section_view.section = NULL; // an unused section
772
            region->section_view_list.push_front (new_section_view); // add an unused section
773
        }
774
    }
775
 
776
    // add the initial and final locations of the each relative section as necessary
777
 
778
    for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
779
        if (section_view->section != NULL) // if section is used
780
    {
781
        list <mem_section>::iterator section = section_view->section;
782
/*
783
                TRACE (_T("Calculating relative sections for section view '%s' %s\n"), CString (section->name.c_str ()),
784
                        section_view->section_location == final_location ? _T("(final)") :
785
                        section_view->section_location == initial_location ? _T("(initial)") : _T("(fixed)"));
786
*/
787
 
788
        if (section_view->section_location == final_location)
789
        {
790
            if (section->final_location->anchor == absolute)
791
                add_relative_sections_to_list (region, section_view, final_location);
792
        }
793
 
794
        else if (section_view->section_location == initial_location)
795
        {
796
            if (section->initial_location->anchor == absolute)
797
                add_relative_sections_to_list (region, section_view, initial_location);
798
        }
799
 
800
        else // section_view->section_location == fixed_location
801
        {
802
            if (section->initial_location->anchor == absolute)
803
                add_relative_sections_to_list (region, section_view, initial_location);
804
            if (section->final_location->anchor == absolute)
805
                add_relative_sections_to_list (region, section_view, final_location);
806
        }
807
    }
808
 
809
    // remove unused sections where user-defined section of unknown size will be placed
810
 
811
    section_view = region->section_view_list.begin ();
812
    while (section_view != region->section_view_list.end ())
813
    {
814
        bool expanding_section = false;
815
        if ((section_view->section != NULL) &&
816
            (section_view->section->size == 0) &&
817
            (! section_view->section->linker_defined))
818
            expanding_section = true;
819
 
820
        ++section_view;
821
 
822
        if (expanding_section && (section_view != region->section_view_list.end ()) && (section_view->section == NULL))
823
            section_view = region->section_view_list.erase (section_view);
824
    }
825
 
826
    return true;
827
}
828
 
829
/////////////////////////////////////////////////////////////////////
830
// add_relative_sections_to_list() inserts the sections defined relative
831
// to the specified section list item to the section list for the
832
// specified region in the appropriate order
833
 
834
bool mem_map::add_relative_sections_to_list (list <mem_region>::iterator region, list <mem_section_view>::iterator section_view, section_location_type location_type)
835
{
836
    // insert following relative sections of type 'location_type' in region_view.section_view_list
837
 
838
    list <mem_section>::iterator new_section = section_view->section;
839
    mem_location * new_section_location = (location_type == initial_location ? new_section->initial_location : new_section->final_location);
840
    list <mem_section_view>::iterator insertion_point = section_view;
841
    ++insertion_point;
842
    bool no_relocation = true;
843
 
844
    while (new_section_location->following_section != NULL)
845
    {
846
        // add the new section to the section view list
847
 
848
        mem_section_view new_section_view;
849
        new_section_view.section = new_section_location->following_section;
850
                const bool section_relocates = new_section->relocates;
851
        new_section = new_section_view.section;
852
        new_section_view.section_location = (new_section->relocates ? location_type : fixed_location);
853
        if ((new_section_view.section_location == fixed_location) && (location_type == final_location) && (! section_view->section->relocates) && (! section_relocates) && no_relocation)
854
        {
855
            // section already added to the view so add nothing but
856
            // increment insertion point for following sections
857
            // TRACE (_T("Skipping section %s %s location (relative) preceding %s\n"), CString (new_section_location->following_section->name.c_str()), location_type == initial_location ? _T("initial") : _T("final"), ((insertion_point != region->section_view_list.end ()) && (insertion_point->section != NULL)) ? CString (insertion_point->section->name.c_str()) : _T("(null)"));
858
            ++insertion_point;
859
        }
860
        else
861
        {
862
            // TRACE (_T("Inserting section %s %s location (relative) preceding %s\n"), CString (new_section_location->following_section->name.c_str()), location_type == initial_location ? _T("initial") : _T("final"), ((insertion_point != region->section_view_list.end ()) && (insertion_point->section != NULL)) ? CString (insertion_point->section->name.c_str()) : _T("(null)"));
863
            region->section_view_list.insert (insertion_point, new_section_view);
864
            no_relocation = no_relocation && ! new_section_view.section->relocates;
865
        }
866
        new_section_location = (location_type == initial_location ? new_section->initial_location : new_section->final_location);
867
    }
868
 
869
    return true;
870
}
871
 
872
/////////////////////////////////////////////////////////////////////
873
// add_absolute_section_to_list() inserts the specified section to the
874
// specified section list at the appropriate place if it has an
875
// absolute location and that location is within the specified memory
876
// region
877
 
878
bool mem_map::add_absolute_section_to_list (list <mem_region>::iterator region, list <mem_section>::iterator additional_section, section_location_type location_type)
879
{
880
    // get location of new section
881
    mem_location * new_section_location = (location_type == initial_location ? additional_section->initial_location : additional_section->final_location);
882
 
883
    if ((new_section_location->anchor == absolute) && (new_section_location->address >= region->address) && (new_section_location->address < region->address + region->size))
884
        {
885
        // the section lies in the region
886
 
887
        // initialise the insertion point for the new section
888
        list <mem_section_view>::iterator insertion_point = region->section_view_list.end ();
889
 
890
        for (list <mem_section_view>::iterator section = region->section_view_list.begin (); section != region->section_view_list.end (); ++section)
891
        {
892
            // get location of section
893
            mem_location * section_location  = (section->section_location == initial_location ? section->section->initial_location : section->section->final_location);
894
 
895
            // compare with location of new section
896
            if ((new_section_location->anchor == absolute) && (section_location->address >= new_section_location->address))
897
            {
898
                // insert new section here if the current section has a higher address
899
                insertion_point = section;
900
                break;
901
            }
902
        }
903
 
904
        // add the new section to the section view list
905
 
906
                // TRACE (_T("Inserting section %s %s location (absolute) preceding %s\n"), CString (additional_section->name.c_str()), location_type == initial_location ? _T("initial") : _T("final"), insertion_point != region->section_view_list.end () ? CString (insertion_point->section->name.c_str()) : _T("(end)"));
907
        mem_section_view new_section_view;
908
        new_section_view.section = additional_section;
909
        new_section_view.section_location = location_type;
910
        region->section_view_list.insert (insertion_point, new_section_view);
911
    }
912
 
913
    return true;
914
}
915
 
916
 
917
////////////////////////////////////////////////////////////////////
918
// absolute_sections_meet() determines whether the specified
919
// absolute memory sections meet. It assumes that section2 comes
920
// after section1 in the memory map.
921
 
922
bool mem_map::absolute_sections_meet(list <mem_section>::iterator section1, list <mem_section>::iterator section2)
923
{
924
    if (section1->size == 0) // size of section1 is unknown
925
        return false;
926
 
927
    // check if initial section locations meet
928
 
929
    if ((section1->initial_location->anchor == absolute) &&
930
        ((section2->initial_location->anchor == absolute) &&
931
        section1->initial_location->address + section1->size == section2->initial_location->address))
932
        return true;
933
 
934
    // check if final section locations meet
935
 
936
    if ((section1->final_location->anchor == absolute) &&
937
        ((section2->final_location->anchor == absolute) &&
938
        section1->final_location->address + section1->size == section2->final_location->address))
939
        return true;
940
 
941
    return false;
942
}
943
 
944
 
945
//////////////////////////////////////////////////////////////
946
// at_start_of_region() determines whether the specified section
947
// is located at the very start of the specified region
948
 
949
bool mem_map::at_start_of_region (list <mem_section>::iterator section, list <mem_region>::iterator region)
950
{
951
    // check initial section location
952
 
953
    if ((section->initial_location->anchor == absolute) &&
954
        (section->initial_location->address == region->address))
955
        return true;
956
 
957
    // check final section location
958
 
959
    if ((section->final_location->anchor == absolute) &&
960
        (section->final_location->address == region->address))
961
        return true;
962
 
963
    return false;
964
}
965
 
966
//////////////////////////////////////////////////////////////
967
// at_end_of_region() determines whether the specified section
968
// is located at the very end of the specified region
969
 
970
bool mem_map::at_end_of_region (list <mem_section>::iterator section, list <mem_region>::iterator region)
971
{
972
    if (section->size == 0) // size of section is unknown
973
        return false;
974
 
975
    // check initial section location
976
 
977
    if ((section->initial_location->anchor == absolute) &&
978
        section->initial_location->address + section->size == region->address + region->size)
979
        return true;
980
 
981
    // check final section location
982
 
983
    if ((section->final_location->anchor == absolute) &&
984
        section->final_location->address + section->size == region->address + region->size)
985
        return true;
986
 
987
    return false;
988
}
989
 
990
////////////////////////////////////////////////////////////////////////
991
// find_preceding_section() finds the preceding section in the
992
// memory section list
993
 
994
list <mem_section>::iterator mem_map::find_preceding_section (list <mem_section>::iterator reference_section, bool initial_location)
995
{
996
    for (list <mem_section>::iterator section = section_list.begin (); section != section_list.end (); ++section)
997
    {
998
        if (reference_section == (reference_section->relocates && initial_location ? section->initial_location->following_section : section->final_location->following_section)) // if preceding section found
999
            return section; // return the section iterator
1000
    }
1001
    return NULL; // section not found
1002
}
1003
 
1004
////////////////////////////////////////////////////////////////////////
1005
// find_memory_section() finds an existing section in the
1006
// memory section list
1007
 
1008
list <mem_section>::iterator mem_map::find_memory_section (std::string section_name)
1009
{
1010
    for (list <mem_section>::iterator section = section_list.begin (); section != section_list.end (); ++section)
1011
        if (section->name == section_name) // if section found
1012
            return section; // return the section iterator
1013
 
1014
    return NULL; // section not found
1015
}
1016
 
1017
 
1018
////////////////////////////////////////////////////////////////////////
1019
// find_memory_region() finds an existing region in the
1020
// memory region list
1021
 
1022
list <mem_region>::iterator mem_map::find_memory_region (std::string region_name)
1023
{
1024
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end (); ++region)
1025
        if (region->name == region_name) // if region found
1026
            return region; // return the region iterator
1027
 
1028
    return NULL; // region not found
1029
}
1030
 
1031
 
1032
////////////////////////////////////////////////////////////////////////
1033
// delete_memory_section() removes an existing item from the
1034
// memory section map
1035
 
1036
bool mem_map::delete_memory_section (std::string name)
1037
{
1038
    // make sure that the section exists
1039
 
1040
    list <mem_section>::iterator section = find_memory_section (name);
1041
    if (section == NULL)
1042
        return false; // there is no section with this name
1043
 
1044
/*
1045
    // make sure that there are no sections defined relative to this section before deleting it
1046
 
1047
    if (section->initial_location->following_section != NULL)
1048
        return false;
1049
 
1050
    if (section->final_location->following_section != NULL)
1051
        return false;
1052
*/
1053
 
1054
    // if section is absolute, copy the initial and final location information to
1055
    // the following sections (if any)
1056
 
1057
    if ((section->initial_location->anchor == absolute) && (section->initial_location->following_section != NULL))
1058
    {
1059
        section->initial_location->following_section->initial_location->anchor = absolute;
1060
        section->initial_location->following_section->initial_location->address = section->initial_location->address;
1061
        // FIXME adjust new address of following section for alignment here
1062
    }
1063
 
1064
    if ((section->final_location->anchor == absolute) && (section->final_location->following_section != NULL))
1065
    {
1066
        section->final_location->following_section->final_location->anchor = absolute;
1067
        section->final_location->following_section->final_location->address = section->final_location->address;
1068
        // FIXME adjust new address of following section for alignment here
1069
    }
1070
 
1071
    // if section is relative, find the initial and final sections to which it is attached
1072
    // and set their pointers to the sections following the one to be deleted (if any)
1073
 
1074
    list <mem_section>::iterator related_section;
1075
 
1076
    if (section->initial_location->anchor == relative)
1077
        for (related_section = section_list.begin (); related_section != section_list.end (); ++related_section)
1078
            if (related_section->initial_location->following_section == section)
1079
                related_section->initial_location->following_section = section->initial_location->following_section;
1080
 
1081
    if (section->final_location->anchor == relative)
1082
        for (related_section = section_list.begin (); related_section != section_list.end (); ++related_section)
1083
            if (related_section->final_location->following_section == section)
1084
                related_section->final_location->following_section = section->final_location->following_section;
1085
 
1086
    // delete the section
1087
 
1088
    delete section->initial_location;
1089
    section->initial_location = NULL;
1090
 
1091
    delete section->final_location;
1092
    section->final_location = NULL;
1093
 
1094
    section_list.erase (section);
1095
 
1096
    // recalculate section lists for all regions
1097
 
1098
    calc_section_lists ();
1099
 
1100
        map_modified_flag = true;
1101
    return true;
1102
}
1103
 
1104
 
1105
////////////////////////////////////////////////////////////////////////
1106
// delete_memory_sections() deletes all memory sections in preparation
1107
// for layout loading or application closure
1108
 
1109
bool mem_map::delete_all_memory_sections ()
1110
{
1111
    // deleteZ(each section in turn)
1112
 
1113
    while (section_list.size () > 0)
1114
    {
1115
        list <mem_section>::iterator section = section_list.begin ();
1116
        delete section->initial_location;
1117
        section->initial_location = NULL;
1118
 
1119
        delete section->final_location;
1120
        section->final_location = NULL;
1121
 
1122
        section_list.erase (section);
1123
    }
1124
//    section_list.clear ();
1125
 
1126
    // recalculate section view lists for all regions
1127
 
1128
    calc_section_lists ();
1129
 
1130
        map_modified_flag = true;
1131
    return true;
1132
}
1133
 
1134
 
1135
////////////////////////////////////////////////////////////////////////
1136
// export_sections() exports section-related info for regions of the
1137
// specified type to the linker script fragment and header file
1138
 
1139
bool mem_map::export_sections (FILE * script_stream, FILE * header_stream, mem_type type)
1140
{
1141
    for (list <mem_region>::iterator region = region_list.begin (); region != region_list.end(); ++region)
1142
        if (region->type == type)
1143
    {
1144
        for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
1145
        {
1146
            if ((section_view->section != NULL) && (section_view->section_location != initial_location))
1147
            {
1148
                if (section_view->section->linker_defined) // section is linker-defined
1149
                {
1150
                    // output section name and region name
1151
                    fprintf (script_stream, "    SECTION_%s (%s, ",
1152
                        encode_section_name (section_view->section->name).c_str (), region->name.c_str ());
1153
 
1154
                    // output VMA
1155
                    if (section_view->section->final_location->anchor == absolute) // an absolute VMA
1156
                        fprintf (script_stream, "%#lx, ", section_view->section->final_location->address); // specify absolute address
1157
                    else // a relative VMA
1158
                        fprintf (script_stream, "ALIGN (%#lx), ", section_view->section->alignment); // specify alignment
1159
 
1160
                    // output LMA
1161
                    if (! section_view->section->relocates) // section does not relocate so LMA == VMA
1162
                        fprintf (script_stream, "LMA_EQ_VMA)");
1163
                    else if (section_view->section->initial_location->anchor == absolute) // an absolute LMA
1164
                        fprintf (script_stream, "AT (%#lx))", section_view->section->initial_location->address);
1165
                    else // a relative LMA
1166
                    {
1167
                        list <mem_section>::iterator parent_section;
1168
                        for (parent_section = section_list.begin (); parent_section != section_list.end (); ++parent_section)
1169
                            if (parent_section->initial_location->following_section == section_view->section)
1170
                                break;
1171
 
1172
                        if (parent_section->linker_defined) // parent section is linker-defined
1173
                            fprintf (script_stream, "FOLLOWING (.%s))", parent_section->name.c_str ());
1174
                        else // parent section is user-defined
1175
                            fprintf (script_stream, "AT (__%s + %#lx))", parent_section->name.c_str (), parent_section->size);
1176
                    }
1177
                }
1178
                else // section is user-defined
1179
                {
1180
                    // output section symbol
1181
                    if (section_view->section->final_location->anchor == absolute) // an absolute VMA
1182
                        fprintf (script_stream, "    CYG_LABEL_DEFN(__%s) = %#lx;", section_view->section->name.c_str (), section_view->section->final_location->address);
1183
                    else // a relative VMA
1184
                        fprintf (script_stream, "    CYG_LABEL_DEFN(__%s) = ALIGN (%#lx);", section_view->section->name.c_str (), section_view->section->alignment);
1185
 
1186
                    // update current location pointer
1187
                    if (section_view->section->size != 0) // size is known
1188
                        fprintf (script_stream, " . = CYG_LABEL_DEFN(__%s) + %#lx;", section_view->section->name.c_str (), section_view->section->size);
1189
 
1190
                    // output reference to symbol in header file
1191
                    fprintf (header_stream, "#ifndef __ASSEMBLER__\nextern char CYG_LABEL_NAME (__%s) [];\n#endif\n", section_view->section->name.c_str ());
1192
                    fprintf (header_stream, "#define CYGMEM_SECTION_%s (CYG_LABEL_NAME (__%s))\n", section_view->section->name.c_str (), section_view->section->name.c_str ());
1193
                    if (section_view->section->size == 0) // a section of unknown size
1194
                    {
1195
                        mem_address section_end_address;
1196
 
1197
                        ++section_view; // move to next section_view
1198
                        if (section_view == region->section_view_list.end ()) // section continues to end of region
1199
                            section_end_address = region->address + region->size;
1200
                        else // section continues to next section with an absolute location
1201
                            section_end_address = section_view->section->final_location->address;
1202
                        --section_view; // move back to previous section view
1203
 
1204
                        fprintf (header_stream, "#define CYGMEM_SECTION_%s_SIZE (%#lx - (size_t) CYG_LABEL_NAME (__%s))\n", section_view->section->name.c_str (), section_end_address, section_view->section->name.c_str ());
1205
                    }
1206
                    else // a section of known size
1207
                        fprintf (header_stream, "#define CYGMEM_SECTION_%s_SIZE (%#lx)\n", section_view->section->name.c_str (), section_view->section->size);
1208
                }
1209
 
1210
                // end of section description
1211
 
1212
                fprintf (script_stream, "\n"); // new line
1213
            }
1214
        }
1215
    }
1216
    return true;
1217
}
1218
 
1219
 
1220
////////////////////////////////////////////////////////////////////////
1221
// export_files() creates a fragment of linker script and a header file
1222
// describing the memory layout
1223
 
1224
bool mem_map::export_files (const wxChar* script_name, const wxChar* header_name)
1225
{
1226
    FILE * script_stream;
1227
    FILE * header_stream;
1228
    list <mem_region>::iterator region;
1229
 
1230
        // do not export files if the memory layout is empty
1231
        // assume that there are default LDI files available
1232
 
1233
        if (region_list.size () == 0)
1234
                return false;
1235
 
1236
    // open the script fragment file for writing
1237
 
1238
    script_stream = _tfopen (script_name, _T("wt"));
1239
    if (script_stream == NULL)
1240
        return false;
1241
 
1242
    // open the header file for writing
1243
 
1244
    header_stream = _tfopen (header_name, _T("wt"));
1245
    if (header_stream == NULL)
1246
    {
1247
        fclose (script_stream);
1248
        return false;
1249
    }
1250
 
1251
    // output the linker script fragment header
1252
 
1253
    time_t export_time;
1254
    time (&export_time);
1255
    struct tm * local = localtime (&export_time);
1256
    fprintf (script_stream, "// eCos memory layout - %s\n%s\n\n", asctime (local), MLT_GENERATED_WARNING);
1257
    fprintf (script_stream, "#include <cyg/infra/cyg_type.inc>\n\n");
1258
 
1259
    // output the header file header
1260
 
1261
    fprintf (header_stream, "// eCos memory layout - %s\n%s\n\n", asctime (local), MLT_GENERATED_WARNING);
1262
        fprintf (header_stream, "#ifndef __ASSEMBLER__\n");
1263
        fprintf (header_stream, "#include <cyg/infra/cyg_type.h>\n"); // for the CYG_LABEL_NAME macro definition
1264
        fprintf (header_stream, "#include <stddef.h>\n\n"); // for size_t
1265
        fprintf (header_stream, "#endif\n");
1266
 
1267
    // output the MEMORY block
1268
 
1269
    fprintf (script_stream, "MEMORY\n{\n"); // start of MEMORY block
1270
    for (region = region_list.begin (); region != region_list.end(); ++region)
1271
    {
1272
        fprintf (script_stream, "    %s : ORIGIN = %#lx, LENGTH = %#lx\n", region->name.c_str(), region->address, region->size);
1273
        fprintf (header_stream, "#define CYGMEM_REGION_%s (%#lx)\n", region->name.c_str(), region->address);
1274
        fprintf (header_stream, "#define CYGMEM_REGION_%s_SIZE (%#lx)\n", region->name.c_str(), region->size);
1275
        fprintf (header_stream, "#define CYGMEM_REGION_%s_ATTR (CYGMEM_REGION_ATTR_R%s)\n", region->name.c_str(), (read_write == region->type) ? " | CYGMEM_REGION_ATTR_W" : "");
1276
    }
1277
    fprintf (script_stream, "}\n\n"); // end of MEMORY block
1278
 
1279
    // output the SECTIONS block
1280
 
1281
    fprintf (script_stream, "SECTIONS\n{\n"); // start of SECTIONS block
1282
    fprintf (script_stream, "    SECTIONS_BEGIN\n"); // SECTIONS block initial script macro call
1283
    export_sections (script_stream, header_stream, read_only); // export sections in read-only regions first
1284
    export_sections (script_stream, header_stream, read_write); // followed by sections in read-write regions
1285
    fprintf (script_stream, "    SECTIONS_END\n"); // SECTIONS block final script macro call
1286
    fprintf (script_stream, "}\n"); // end of SECTIONS block
1287
 
1288
    // close the files
1289
 
1290
    fclose (script_stream);
1291
    fclose (header_stream);
1292
 
1293
    return true;
1294
}
1295
 
1296
 
1297
////////////////////////////////////////////////////////////////////////
1298
// import_linker_defined_sections() reads a the linker-defined section
1299
// names from the "SECTION_*" CPP macro definitions within the linker
1300
// script
1301
 
1302
bool mem_map::import_linker_defined_sections (const wxChar* filename)
1303
{
1304
    // clear the linker-defined section name list
1305
 
1306
    linker_defined_section_list.clear ();
1307
 
1308
    // open the linker script file for reading
1309
 
1310
    FILE * stream;
1311
    stream = _tfopen (filename, _T("rt"));
1312
    if (stream == NULL)
1313
        return false;
1314
 
1315
    bool macro = false; // not reading a CPP macro definition initially
1316
    char input_string [32];
1317
    while (! feof (stream))
1318
    {
1319
        if (macro)
1320
        {
1321
            if (fscanf (stream, "%8s", input_string) == EOF) // read the next 8 chars (not including whitespace)
1322
                break;
1323
 
1324
            if (strcmp (input_string, "SECTION_") == 0) // an MLT section macro definition
1325
            {
1326
                if (fscanf (stream, "%31[^(]", input_string) == EOF) // read the section name up to the '(' character
1327
                    break;
1328
 
1329
                std::string section_name = decode_section_name (input_string);
1330
                if (find (linker_defined_section_list.begin (), linker_defined_section_list.end (), section_name) == linker_defined_section_list.end ()) // if section name is unique
1331
                    linker_defined_section_list.push_back (section_name);
1332
            }
1333
 
1334
            macro = false;
1335
        }
1336
 
1337
        else
1338
        {
1339
            if (fscanf (stream, "%31s", input_string) == EOF)
1340
                break;
1341
 
1342
            if (strcmp (input_string, "#define") == 0)
1343
                macro = true; // macro starts with "#define"
1344
        }
1345
 
1346
    }
1347
 
1348
    // close the file
1349
 
1350
    if (fclose (stream))
1351
        return false;
1352
 
1353
    return true;
1354
}
1355
 
1356
////////////////////////////////////////////////////////////////////////
1357
// encode_note() encodes newlines in note
1358
 
1359
std::string mem_map::encode_note (std::string in)
1360
{
1361
    std::string out = "!"; // dummy first character to ensure output string length > 0
1362
 
1363
    for (unsigned int item = 0; item < in.size (); item++)
1364
        if (in [item] == _TCHAR('\n')) // an LF character
1365
            out += "\x07F"; // output substitution character 0x7F instead
1366
        else if (in [item] != _TCHAR('\r')) // ignore the CR (present under Win32 only)
1367
            out += in [item]; // copy other characters to output string unprocessed
1368
 
1369
    return out;
1370
}
1371
 
1372
////////////////////////////////////////////////////////////////////////
1373
// decode_note() decodes newlines in note
1374
 
1375
std::string mem_map::decode_note (std::string in)
1376
{
1377
    std::string out;
1378
 
1379
    for (unsigned int item = 1; item < in.size (); item++) // ignore dummy first character
1380
        if (in [item] == _TCHAR('\x07F')) // the newline substitution character
1381
            out += "\r\n"; // output CRLF instead
1382
        else
1383
            out += in [item];
1384
 
1385
    return out;
1386
}
1387
 
1388
////////////////////////////////////////////////////////////////////////
1389
// encode_section_name() encodes period -> double underscore in section name
1390
 
1391
std::string mem_map::encode_section_name (std::string in)
1392
{
1393
    std::string out;
1394
 
1395
    for (unsigned int item = 0; item < in.size (); item++)
1396
        if (in [item] == '.') // a period character
1397
                        out += "__"; // output a double underscore instead
1398
        else
1399
            out += in [item];
1400
 
1401
    return out;
1402
}
1403
 
1404
////////////////////////////////////////////////////////////////////////
1405
// decode_section_name() decodes double underscore -> period in section name
1406
 
1407
std::string mem_map::decode_section_name (std::string in)
1408
{
1409
    std::string out;
1410
 
1411
    for (unsigned int item = 0; item < in.size (); item++)
1412
        if ((item + 1 < in.size ()) && (in [item] == '_') && (in [item + 1] == '_')) // two consecutive underscore characters
1413
                {
1414
                        out += "."; // output a period instead
1415
                        item++; // skip the second underscore
1416
                }
1417
        else
1418
            out += in [item];
1419
 
1420
    return out;
1421
}
1422
 
1423
////////////////////////////////////////////////////////////////////////
1424
// save_memory_layout() saves the memory layout to file for later use
1425
 
1426
bool mem_map::save_memory_layout (const wxChar* filename)
1427
{
1428
    FILE * stream;
1429
    list <mem_region>::iterator region;
1430
 
1431
    // open the save file for writing
1432
 
1433
    stream = _tfopen (filename, _T("wt"));
1434
    if (stream == NULL)
1435
        return false;
1436
 
1437
    // write the save file format version number
1438
 
1439
        fprintf (stream, "version %u\n", (unsigned int) MLT_FILE_VERSION);
1440
 
1441
    // save the memory region data in address order
1442
 
1443
    for (region = region_list.begin (); region != region_list.end (); ++region)
1444
        fprintf (stream, "region %s %lx %lx %d %s\n", region->name.c_str (),
1445
            region->address, region->size, (region->type == read_only), encode_note (region->note).c_str ());
1446
 
1447
    // save the memory section data in VMA order
1448
 
1449
    for (region = region_list.begin (); region != region_list.end(); ++region)
1450
    {
1451
        for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
1452
        {
1453
            if ((section_view->section != NULL) && (section_view->section_location != initial_location))
1454
            {
1455
                list <mem_section>::iterator section = section_view->section;
1456
                fprintf (stream, "section %s %lx %lx %d %d %d %d %d %d",
1457
                    section->name.c_str (), section->size, section->alignment,
1458
                    section->relocates, section->linker_defined,
1459
                    section->final_location->anchor == absolute,
1460
                    section->final_location->following_section != NULL,
1461
                    section->initial_location->anchor == absolute,
1462
                    section->initial_location->following_section != NULL);
1463
 
1464
                if (section->final_location->anchor == absolute)
1465
                    fprintf (stream, " %lx", section->final_location->address);
1466
 
1467
                if (section->initial_location->anchor == absolute)
1468
                    fprintf (stream, " %lx", section->initial_location->address);
1469
 
1470
                if (section->final_location->following_section != NULL)
1471
                    fprintf (stream, " %s", section->final_location->following_section->name.c_str ());
1472
 
1473
                if (section->initial_location->following_section != NULL)
1474
                    fprintf (stream, " %s", section->initial_location->following_section->name.c_str ());
1475
 
1476
                fprintf (stream, " %s", encode_note (section->note).c_str ());
1477
 
1478
                // end of section description
1479
 
1480
                fprintf (stream, "\n"); // new line
1481
            }
1482
        }
1483
    }
1484
 
1485
    // close the file
1486
 
1487
    if (fclose (stream))
1488
        return false;
1489
 
1490
        map_modified_flag = false;
1491
    return true;
1492
}
1493
 
1494
 
1495
////////////////////////////////////////////////////////////////////////
1496
// load_memory_layout() loads a previously saved memory layout from file
1497
 
1498
bool mem_map::load_memory_layout (const wxChar* filename)
1499
{
1500
    FILE * stream;
1501
 
1502
    // open the save file for reading
1503
 
1504
    stream = _tfopen (filename, _T("rt"));
1505
    if (stream == NULL)
1506
        return false;
1507
 
1508
        // read the file version
1509
 
1510
        unsigned int file_version;
1511
        if ((fscanf (stream, "%*s %u", &file_version) != 1) ||
1512
                (file_version != MLT_FILE_VERSION))
1513
        {
1514
                fclose (stream); // missing or incorrect file version
1515
        return false;
1516
        }
1517
 
1518
    new_memory_layout ();
1519
 
1520
    // read the new memory layout (first pass)
1521
 
1522
    while (! feof (stream))
1523
    {
1524
        char record_type [32];
1525
        if (fscanf (stream, "%31s", record_type) == EOF)
1526
            break;
1527
 
1528
        if (strcmp (record_type, "section") == 0) // a section record
1529
        {
1530
            if (! load_memory_section_1 (stream))
1531
                break;
1532
        }
1533
        else if (strcmp (record_type, "region") == 0) // a region record
1534
        {
1535
            mem_address address, size;
1536
            bool read_only_region;
1537
            char name [32];
1538
            char note [1024];
1539
 
1540
            fscanf (stream, "%s %lx %lx %d %1023[^\n]", name, &address, &size, &read_only_region, note);
1541
 
1542
            if (create_memory_region (name, address, size, (read_only_region ? read_only : read_write), decode_note (note)))
1543
                break;
1544
        }
1545
        else // an unknown record type
1546
            break;
1547
    }
1548
 
1549
        // quit if the end of the file was not reached (due to an error)
1550
 
1551
        if (! feof (stream))
1552
        {
1553
                new_memory_layout ();
1554
                fclose (stream);
1555
                return false;
1556
        }
1557
 
1558
    // move the file pointer back to the beginning of the file
1559
 
1560
    fseek (stream, 0, SEEK_SET);
1561
 
1562
    while (! feof (stream)) // read the memory layout (second pass)
1563
    {
1564
        char record_type [32];
1565
        if (fscanf (stream, "%31s", record_type) == EOF)
1566
            break;
1567
 
1568
        if ((strcmp (record_type, "section") == 0) && (! load_memory_section_2 (stream)))
1569
            break;
1570
    }
1571
 
1572
    // close the file
1573
 
1574
    if (fclose (stream))
1575
        {
1576
                new_memory_layout ();
1577
        return false;
1578
        }
1579
 
1580
    // recalculate section view lists for all regions
1581
 
1582
    calc_section_lists ();
1583
 
1584
        map_modified_flag = false;
1585
    return true;
1586
}
1587
 
1588
 
1589
////////////////////////////////////////////////////////////////////////
1590
// load_memory_section_1() loads a previously saved memory section from
1591
// file (first pass)
1592
 
1593
bool mem_map::load_memory_section_1 (FILE * stream)
1594
{
1595
    char section_name [32];
1596
    int relocates, linker_defined;
1597
    int final_absolute, initial_absolute, final_following, initial_following;
1598
    mem_section new_section;
1599
 
1600
    new_section.initial_location = new mem_location;
1601
    new_section.initial_location->following_section = NULL;
1602
    new_section.final_location = new mem_location;
1603
    new_section.final_location->following_section = NULL;
1604
 
1605
    fscanf (stream,"%31s %lx %lx %d %d %d %d %d %d",
1606
        section_name, &new_section.size, &new_section.alignment,
1607
        &relocates, &linker_defined, &final_absolute, &final_following,
1608
        &initial_absolute, &initial_following);
1609
 
1610
    new_section.name = section_name;
1611
    new_section.relocates = (relocates != 0);
1612
    new_section.linker_defined = (linker_defined != 0);
1613
 
1614
    new_section.final_location->anchor = (final_absolute ? absolute : relative);
1615
    if (final_absolute) // final location is absolute
1616
        fscanf (stream, "%lx", &new_section.final_location->address);
1617
 
1618
    new_section.initial_location->anchor = (initial_absolute ? absolute : relative);
1619
    if (initial_absolute) // initial location is absolute
1620
        fscanf (stream, "%lx", &new_section.initial_location->address);
1621
 
1622
    if (final_following)
1623
        fscanf (stream, "%*s"); // skip the final following section field on first pass
1624
 
1625
    if (initial_following)
1626
        fscanf (stream, "%*s"); // skip the initial following section field on first pass
1627
 
1628
    char note [1024];
1629
    fscanf (stream, " %1023[^\n]", note);
1630
    new_section.note = decode_note (note);
1631
 
1632
    // add the new section to the section map
1633
 
1634
    section_list.push_front (new_section);
1635
 
1636
    return true;
1637
}
1638
 
1639
 
1640
////////////////////////////////////////////////////////////////////////
1641
// load_memory_section_2() loads a previously saved memory section from
1642
// file (second pass)
1643
 
1644
bool mem_map::load_memory_section_2 (FILE * stream)
1645
{
1646
    char section_name [32];
1647
    char following_section_name [32];
1648
    int final_absolute, initial_absolute, final_following, initial_following;
1649
 
1650
    fscanf (stream,"%31s %*lx %*lx %*d %*d %d %d %d %d",
1651
        section_name, &final_absolute, &final_following,
1652
        &initial_absolute, &initial_following);
1653
 
1654
    if (final_absolute) // final location is absolute
1655
        fscanf (stream, "%*lx"); // skip the final location
1656
 
1657
    if (initial_absolute) // initial location is absolute
1658
        fscanf (stream, "%*lx"); // skip the initial location
1659
 
1660
    if (initial_following || final_following) // the section is a parent
1661
    {
1662
        list <mem_section>::iterator section = find_memory_section (section_name);
1663
 
1664
        if (final_following)
1665
        {
1666
            fscanf (stream, "%31s", following_section_name); // read the final following section name
1667
            section->final_location->following_section =
1668
                find_memory_section (following_section_name);
1669
        }
1670
 
1671
        if (initial_following)
1672
        {
1673
            fscanf (stream, "%31s", following_section_name); // read the initial following section name
1674
            section->initial_location->following_section =
1675
                find_memory_section (following_section_name);
1676
        }
1677
    }
1678
 
1679
    fscanf (stream, "%*1023[^\n]"); // skip the note
1680
 
1681
    return true;
1682
}
1683
 
1684
 
1685
////////////////////////////////////////////////////////////////////////
1686
// new_memory_layout() clears the memory layout
1687
 
1688
bool mem_map::new_memory_layout ()
1689
{
1690
    delete_all_memory_sections ();
1691
//    section_list.clear ();
1692
    region_list.clear ();
1693
 
1694
        map_modified_flag = false; // no need to save an empty memory layout
1695
    return true;
1696
}
1697
 
1698
 
1699
////////////////////////////////////////////////////////////////////////
1700
// section_exists() determines if the specified section is defined
1701
 
1702
bool mem_map::section_exists (std::string section_name)
1703
{
1704
    return (find_memory_section (section_name) != NULL);
1705
}
1706
 
1707
 
1708
////////////////////////////////////////////////////////////////////////
1709
// find_region_by_address() finds the region containing the specified
1710
// memory address
1711
 
1712
list <mem_region>::iterator mem_map::find_region_by_address (mem_address address)
1713
{
1714
    for (list <mem_region>::iterator region = region_list.begin (); region !=region_list.end(); ++region)
1715
        if ((address >= region->address) && (address < region->address + region->size))
1716
            return region;
1717
 
1718
    return NULL; // the specified address is not in a memory region
1719
}
1720
 
1721
 
1722
////////////////////////////////////////////////////////////////////////
1723
// find_region_by_section() finds the region containing the specified
1724
// section
1725
 
1726
list <mem_region>::iterator mem_map::find_region_by_section (list <mem_section>::iterator section, section_location_type location_type)
1727
{
1728
    for (list <mem_region>::iterator region = region_list.begin (); region !=region_list.end(); ++region)
1729
        for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
1730
            if ((section_view->section != NULL) && (section_view->section == section) &&
1731
                (section_view->section_location == (section_view->section->relocates ? location_type : fixed_location)))
1732
                return region;
1733
 
1734
    return NULL; // the specified section location type was not found (you probably searched for the fixed_location of a relocating section)
1735
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.