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

Subversion Repositories openrisc

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

powered by: WebSVN 2.1.0

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