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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [configtool/] [standalone/] [wxwin/] [memmap.cpp] - Blame information for rev 574

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

powered by: WebSVN 2.1.0

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