OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [configtool/] [common/] [win32/] [memmap.cpp] - Blame information for rev 174

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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