|
1 /* |
|
2 * Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Area-related classes implementation |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "r_areaset.h" |
|
21 #include "r_global.h" |
|
22 #include "r_rom.h" |
|
23 |
|
24 extern TBool gGenDepGraph; |
|
25 extern char* gDepInfoFile; |
|
26 |
|
27 using namespace std; |
|
28 |
|
29 //////////////////////////////////////////////////////////////////////// |
|
30 |
|
31 Area::Area(const char* aName, TLinAddr aDestBaseAddr, TUint aMaxSize, Area* aNext) |
|
32 : iFirstPagedCode(0), |
|
33 iName(strdup(aName)), |
|
34 iDestBaseAddr(aDestBaseAddr), |
|
35 iSrcBaseAddr(0), |
|
36 iSrcLimitAddr(0), |
|
37 iMaxSize(aMaxSize), |
|
38 iIsDefault(strcmp(aName, AreaSet::KDefaultAreaName) == 0), |
|
39 iFiles(0), |
|
40 iNextFilePtrPtr(&iFiles), |
|
41 iNextArea(aNext) |
|
42 |
|
43 { |
|
44 } |
|
45 |
|
46 |
|
47 Area::~Area() |
|
48 { |
|
49 ReleaseAllFiles(); |
|
50 free(const_cast<char*>(iName)); // allocated with strdup() |
|
51 } |
|
52 |
|
53 |
|
54 /** |
|
55 Increase the size of the area. |
|
56 |
|
57 The reallocation must not exceed the area maximum size. |
|
58 |
|
59 @param aSrcLimitAddr New source top address |
|
60 |
|
61 @param aOverflow Number of overflow bytes if failure. |
|
62 |
|
63 @return success indication |
|
64 */ |
|
65 |
|
66 TBool Area::ExtendSrcLimitAddr(TLinAddr aSrcLimitAddr, TUint& aOverflow) |
|
67 { |
|
68 // must have been set before |
|
69 assert(iSrcBaseAddr != 0); |
|
70 // can only allocate more |
|
71 assert(aSrcLimitAddr > iSrcBaseAddr); |
|
72 |
|
73 if (aSrcLimitAddr-iSrcBaseAddr > iMaxSize) |
|
74 { |
|
75 aOverflow = aSrcLimitAddr-iSrcBaseAddr-iMaxSize; |
|
76 return EFalse; |
|
77 } |
|
78 |
|
79 iSrcLimitAddr = aSrcLimitAddr; |
|
80 return ETrue; |
|
81 } |
|
82 |
|
83 |
|
84 /** |
|
85 Add a file at end of the list of files contained in this area. |
|
86 |
|
87 @param aFile File to add. Must be allocated on the heap. Ownership |
|
88 is transfered from the caller to the callee. |
|
89 */ |
|
90 |
|
91 void Area::AddFile(TRomBuilderEntry* aFile) |
|
92 { |
|
93 assert(aFile != 0); |
|
94 |
|
95 *iNextFilePtrPtr = aFile; |
|
96 iNextFilePtrPtr = &(aFile->iNextInArea); |
|
97 } |
|
98 |
|
99 |
|
100 void Area::ReleaseAllFiles() |
|
101 { |
|
102 for (TRomBuilderEntry *next = 0, *current = iFiles; |
|
103 current != 0; |
|
104 current = next) |
|
105 { |
|
106 next = current->iNextInArea; |
|
107 delete current; |
|
108 } |
|
109 |
|
110 iFiles = 0; |
|
111 iNextFilePtrPtr = &iFiles; |
|
112 } |
|
113 |
|
114 //////////////////////////////////////////////////////////////////////// |
|
115 |
|
116 void FilesInAreaIterator::GoToNext() |
|
117 { |
|
118 assert(iCurrentFile!=0); |
|
119 iCurrentFile = iCurrentFile->iNextInArea; |
|
120 } |
|
121 |
|
122 //////////////////////////////////////////////////////////////////////// |
|
123 |
|
124 const char AreaSet::KDefaultAreaName[] = "DEFAULT AREA"; |
|
125 |
|
126 AreaSet::AreaSet() |
|
127 : iNonDefaultAreas(0), |
|
128 iDefaultArea(0), |
|
129 iAreaCount(0) |
|
130 { |
|
131 } |
|
132 |
|
133 |
|
134 AreaSet::~AreaSet() |
|
135 { |
|
136 ReleaseAllAreas(); |
|
137 } |
|
138 |
|
139 |
|
140 inline TBool IsInRange(TLinAddr aAddr, TLinAddr aDestBaseAddr, TLinAddr aEndAddr) |
|
141 { |
|
142 return aDestBaseAddr <= aAddr && aAddr <= aEndAddr; |
|
143 } |
|
144 |
|
145 |
|
146 /** |
|
147 Add a new area. |
|
148 |
|
149 Areas must have unique name, not overlap one another and not overflow |
|
150 the 32-bit address range. |
|
151 |
|
152 @param aOverlappingArea On return ptr to name of overlapping area if |
|
153 any, 0 otherwise. |
|
154 |
|
155 @return EAdded if success, an error code otherwise. |
|
156 */ |
|
157 |
|
158 AreaSet::TAddResult AreaSet::AddArea(const char* aNewName, |
|
159 TLinAddr aNewDestBaseAddr, |
|
160 TUint aNewMaxSize, |
|
161 const char*& aOverlappingArea) |
|
162 { |
|
163 assert(aNewName != 0 && strlen(aNewName) > 0); |
|
164 assert(aNewMaxSize > 0); |
|
165 |
|
166 aOverlappingArea = 0; |
|
167 |
|
168 // |
|
169 // Checking new area validity |
|
170 // |
|
171 |
|
172 if (aNewDestBaseAddr+aNewMaxSize <= aNewDestBaseAddr) |
|
173 return EOverflow; |
|
174 |
|
175 TLinAddr newEndAddr = aNewDestBaseAddr+aNewMaxSize-1; |
|
176 |
|
177 // iterate non default areas first, then the default one if any |
|
178 Area* area=iNonDefaultAreas; |
|
179 while (area != 0) |
|
180 { |
|
181 if (strcmp(area->Name(), aNewName) == 0) |
|
182 return EDuplicateName; |
|
183 |
|
184 TLinAddr curDestBaseAddr = area->DestBaseAddr(); |
|
185 TLinAddr curEndAddr = area->DestBaseAddr()+area->MaxSize()-1; |
|
186 |
|
187 if (IsInRange(newEndAddr, curDestBaseAddr, curEndAddr) || |
|
188 IsInRange(aNewDestBaseAddr, curDestBaseAddr, curEndAddr) || |
|
189 IsInRange(curDestBaseAddr, aNewDestBaseAddr, newEndAddr)) |
|
190 { |
|
191 aOverlappingArea = area->Name(); |
|
192 return EOverlap; |
|
193 } |
|
194 |
|
195 if (area->iNextArea == 0 && area != iDefaultArea) |
|
196 area = iDefaultArea; |
|
197 else |
|
198 area = area->iNextArea; |
|
199 } |
|
200 |
|
201 // |
|
202 // Adding new area |
|
203 // |
|
204 |
|
205 if (strcmp(KDefaultAreaName, aNewName) == 0) |
|
206 iDefaultArea = new Area(aNewName, aNewDestBaseAddr, aNewMaxSize); |
|
207 else |
|
208 iNonDefaultAreas = new Area(aNewName, aNewDestBaseAddr, aNewMaxSize, iNonDefaultAreas); |
|
209 ++iAreaCount; |
|
210 |
|
211 return EAdded; |
|
212 } |
|
213 |
|
214 |
|
215 /** |
|
216 Remove every area added to the set. |
|
217 |
|
218 As a side-effect every file added to the areas is deleted. |
|
219 */ |
|
220 |
|
221 void AreaSet::ReleaseAllAreas() |
|
222 { |
|
223 for (Area *next = 0, *current = iNonDefaultAreas; current != 0; current = next) |
|
224 { |
|
225 next = current->iNextArea; |
|
226 delete current; |
|
227 } |
|
228 |
|
229 iNonDefaultAreas = 0; |
|
230 |
|
231 delete iDefaultArea; |
|
232 iDefaultArea = 0; |
|
233 } |
|
234 |
|
235 |
|
236 /** |
|
237 Find an area from its name. |
|
238 |
|
239 @return A pointer to the area or 0 if the name is unknown. The |
|
240 returned pointer becomes invalid when "this" is destructed. |
|
241 */ |
|
242 |
|
243 Area* AreaSet::FindByName(const char* aName) const |
|
244 { |
|
245 assert(aName != 0 && strlen(aName) > 0); |
|
246 |
|
247 if (iDefaultArea && strcmp(iDefaultArea->Name(), aName) == 0) |
|
248 return iDefaultArea; |
|
249 |
|
250 for (Area* area=iNonDefaultAreas; area != 0; area = area->iNextArea) |
|
251 { |
|
252 if (strcmp(area->Name(), aName) == 0) |
|
253 return area; |
|
254 } |
|
255 |
|
256 return 0; |
|
257 } |
|
258 |
|
259 |
|
260 //////////////////////////////////////////////////////////////////////// |
|
261 |
|
262 void NonDefaultAreasIterator::GoToNext() |
|
263 { |
|
264 assert(iCurrentArea!=0); |
|
265 iCurrentArea = iCurrentArea->iNextArea; |
|
266 } |
|
267 |
|
268 TInt Area::SortFilesForPagedRom() |
|
269 { |
|
270 Print(ELog,"Sorting files to paged/unpaged.\n"); |
|
271 TRomBuilderEntry* extention[2] = {0,0}; |
|
272 TRomBuilderEntry* unpaged[2] = {0,0}; |
|
273 TRomBuilderEntry* normal[2] = {0,0}; |
|
274 TRomBuilderEntry* current = iFiles; |
|
275 while(current) |
|
276 { |
|
277 TRomBuilderEntry** list; |
|
278 if((current->iRomImageFlags & (KRomImageFlagPrimary|KRomImageFlagVariant|KRomImageFlagExtension|KRomImageFlagDevice)) || |
|
279 current->HCRDataFile()) |
|
280 list = extention; |
|
281 else if(current->iRomImageFlags&(KRomImageFlagCodeUnpaged)) |
|
282 list = unpaged; |
|
283 else if(current->iResource && (current->iOverrideFlags&KOverrideCodeUnpaged) && gPagedRom) |
|
284 list = unpaged; |
|
285 else |
|
286 list = normal; |
|
287 |
|
288 if(list!=normal) |
|
289 { |
|
290 Print(ELog, "Unpaged file %s\n",current->iRomNode->BareName()); |
|
291 } |
|
292 |
|
293 if(!list[0]) |
|
294 list[0] = current; |
|
295 else |
|
296 list[1]->iNextInArea = current; |
|
297 list[1] = current; |
|
298 |
|
299 current = current->iNext; |
|
300 } |
|
301 |
|
302 if(extention[1]) |
|
303 { |
|
304 if(unpaged[0]) |
|
305 { |
|
306 extention[1]->iNextInArea = unpaged[0]; |
|
307 unpaged[1]->iNextInArea = normal[0]; |
|
308 } |
|
309 else |
|
310 extention[1]->iNextInArea = normal[0]; |
|
311 |
|
312 if (normal[1]) |
|
313 normal[1]->iNextInArea = 0; |
|
314 |
|
315 iFiles = extention[0]; |
|
316 } |
|
317 else{ |
|
318 Print(EError,"No primary files.\n"); |
|
319 return KErrGeneral; |
|
320 } |
|
321 |
|
322 iFirstPagedCode = normal[0]; |
|
323 Print(ELog,"\n"); |
|
324 if(gGenDepGraph) |
|
325 WriteDependenceGraph(); |
|
326 return KErrNone; |
|
327 } |
|
328 |
|
329 |
|
330 void Area::WriteDependenceGraph() |
|
331 { |
|
332 TDepInfoList::iterator infoIt; |
|
333 TStringList::iterator strIt; |
|
334 TDepInfoList myDepInfoList; |
|
335 TRomBuilderEntry* e = iFirstPagedCode; |
|
336 char buffer[255]; |
|
337 TInt count = 0; |
|
338 TStringList nameList; |
|
339 while(e) |
|
340 { |
|
341 DepInfo tmpDepInfo; |
|
342 TRomNode* rn = e->iRomNode; |
|
343 TInt ll = rn->FullNameLength(); |
|
344 char* mm = (char*) malloc(ll+1); |
|
345 rn->GetFullName(mm); |
|
346 sprintf(buffer, "f%d", count); |
|
347 tmpDepInfo.portName = buffer; |
|
348 tmpDepInfo.index = count; |
|
349 myDepInfoList[mm] = tmpDepInfo; |
|
350 nameList.push_back(mm); |
|
351 free(mm); |
|
352 e = e->iNextInArea; |
|
353 count++; |
|
354 } |
|
355 e = iFirstPagedCode; |
|
356 count = 0; |
|
357 while(e) |
|
358 { |
|
359 TRomNode* rn = e->iRomNode; |
|
360 TRomFile* rf = rn->iRomFile; |
|
361 TInt j; |
|
362 TStringList depFiles; |
|
363 for(j=0; j < rf->iNumDeps; ++j) |
|
364 { |
|
365 TRomFile* f=rf->iDeps[j]; |
|
366 TRomBuilderEntry* start = iFiles; |
|
367 while(start && start->iRomNode->iRomFile != f) |
|
368 start = start->iNextInArea; |
|
369 if(start && (start->iRomNode->iRomFile == f)) |
|
370 { |
|
371 TRomNode* target = start->iRomNode; |
|
372 TInt l = target->FullNameLength(); |
|
373 char* fname = (char *) malloc(l+1); |
|
374 target->GetFullName(fname); |
|
375 if(myDepInfoList.find(fname) != myDepInfoList.end()) |
|
376 { |
|
377 depFiles.push_back(fname); |
|
378 myDepInfoList[fname].beenDepended = ETrue; |
|
379 } |
|
380 free(fname); |
|
381 } |
|
382 } |
|
383 if(depFiles.size() > 0) |
|
384 { |
|
385 myDepInfoList[nameList[count]].depFilesList=depFiles; |
|
386 myDepInfoList[nameList[count]].dependOthers = ETrue; |
|
387 } |
|
388 count++; |
|
389 e=e->iNextInArea; |
|
390 } |
|
391 ofstream os; |
|
392 string filename(gDepInfoFile, strlen(gDepInfoFile) - 3); |
|
393 filename = filename + "dot"; |
|
394 os.open(filename.c_str()); |
|
395 os << "digraph ROM {\n"; |
|
396 os << "rankdir = LR;\n"; |
|
397 os << "fontsize = 10;\n"; |
|
398 os << "fontname = \"Courier New\";\n"; |
|
399 os << "label = \"ROM DEPENDENCE GRAPH DOT FILE\";\n"; |
|
400 os << "node[shape = plaintext];\n"; |
|
401 os << "dependence[label=<<FONT FACE=\"Courier new\" POINT-SIZE=\"10pt\">\n"; |
|
402 os << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n"; |
|
403 //for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++) |
|
404 for(strIt = nameList.begin(); strIt != nameList.end(); strIt++) |
|
405 { |
|
406 string tmp = *strIt; |
|
407 string::iterator charIt; |
|
408 for(charIt=tmp.begin(); charIt != tmp.end(); charIt++) |
|
409 { |
|
410 if(*charIt == '\\') |
|
411 *charIt = '/'; |
|
412 } |
|
413 if(myDepInfoList[*strIt].beenDepended && myDepInfoList[*strIt].dependOthers) |
|
414 { |
|
415 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"yellow\">\n"; |
|
416 os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n"; |
|
417 os << "\t</TD></TR>\n"; |
|
418 } |
|
419 else if(myDepInfoList[*strIt].beenDepended) |
|
420 { |
|
421 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"gray\">\n"; |
|
422 os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n"; |
|
423 os << "\t</TD></TR>\n"; |
|
424 } |
|
425 else if(myDepInfoList[*strIt].dependOthers) |
|
426 { |
|
427 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"cyan\">\n"; |
|
428 os << "\t<FONT COLOR=\"blue\">" << tmp << "</FONT>\n"; |
|
429 os << "\t</TD></TR>\n"; |
|
430 } |
|
431 else |
|
432 { |
|
433 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\">"; |
|
434 os << tmp; |
|
435 os << "</TD></TR>\n"; |
|
436 } |
|
437 } |
|
438 os << "</TABLE>\n"; |
|
439 os << "</FONT>>]\n"; |
|
440 TBool lastEdge = ETrue; |
|
441 TBool first = ETrue; |
|
442 for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++) |
|
443 { |
|
444 if(!infoIt->second.dependOthers) |
|
445 { |
|
446 continue; |
|
447 } |
|
448 for(strIt = infoIt->second.depFilesList.begin(); strIt != infoIt->second.depFilesList.end(); strIt++) |
|
449 { |
|
450 TBool tmpEdge = ETrue; |
|
451 if(infoIt->second.index < myDepInfoList[*strIt].index) |
|
452 { |
|
453 tmpEdge = EFalse; |
|
454 } |
|
455 if(first) |
|
456 { |
|
457 lastEdge = tmpEdge; |
|
458 first = EFalse; |
|
459 if(lastEdge) |
|
460 { |
|
461 os << "edge[color=forestgreen];\n"; |
|
462 } |
|
463 else |
|
464 { |
|
465 os << "edge[color=red];\n"; |
|
466 } |
|
467 } |
|
468 else |
|
469 { |
|
470 if(lastEdge != tmpEdge) |
|
471 { |
|
472 lastEdge = tmpEdge; |
|
473 if(lastEdge) |
|
474 { |
|
475 os << "edge[color=forestgreen];\n"; |
|
476 } |
|
477 else |
|
478 { |
|
479 os << "edge[color=red];\n"; |
|
480 } |
|
481 } |
|
482 } |
|
483 os << "dependence: " << infoIt->second.portName << " -> dependence: " << myDepInfoList[*strIt].portName << ";\n"; |
|
484 } |
|
485 } |
|
486 os << "}\n"; |
|
487 os.close(); |
|
488 filename = filename.substr(0, filename.size()-4); |
|
489 filename = filename + ".backwarddep.dot"; |
|
490 os.open(filename.c_str()); |
|
491 os << "digraph ROM {\n"; |
|
492 os << "rankdir = LR;\n"; |
|
493 os << "fontsize = 10;\n"; |
|
494 os << "fontname = \"Courier New\";\n"; |
|
495 os << "label = \"ROM FORWARD DEPENDENCE GRAPH DOT FILE\";\n"; |
|
496 os << "node[shape = plaintext];\n"; |
|
497 os << "dependence[label=<<FONT FACE=\"Courier new\" POINT-SIZE=\"10pt\">\n"; |
|
498 os << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n"; |
|
499 //for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++) |
|
500 for(strIt = nameList.begin(); strIt != nameList.end(); strIt++) |
|
501 { |
|
502 string tmp = *strIt; |
|
503 string::iterator charIt; |
|
504 for(charIt=tmp.begin(); charIt != tmp.end(); charIt++) |
|
505 { |
|
506 if(*charIt == '\\') |
|
507 *charIt = '/'; |
|
508 } |
|
509 if(myDepInfoList[*strIt].beenDepended && myDepInfoList[*strIt].dependOthers) |
|
510 { |
|
511 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"yellow\">\n"; |
|
512 os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n"; |
|
513 os << "\t</TD></TR>\n"; |
|
514 } |
|
515 else if(myDepInfoList[*strIt].beenDepended) |
|
516 { |
|
517 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"gray\">\n"; |
|
518 os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n"; |
|
519 os << "\t</TD></TR>\n"; |
|
520 } |
|
521 else if(myDepInfoList[*strIt].dependOthers) |
|
522 { |
|
523 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"cyan\">\n"; |
|
524 os << "\t<FONT COLOR=\"blue\">" << tmp << "</FONT>\n"; |
|
525 os << "\t</TD></TR>\n"; |
|
526 } |
|
527 else |
|
528 { |
|
529 os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\">"; |
|
530 os << tmp; |
|
531 os << "</TD></TR>\n"; |
|
532 } |
|
533 } |
|
534 os << "</TABLE>\n"; |
|
535 os << "</FONT>>]\n"; |
|
536 os << "edge[color=red];\n"; |
|
537 for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++) |
|
538 { |
|
539 if(!infoIt->second.dependOthers) |
|
540 { |
|
541 continue; |
|
542 } |
|
543 for(strIt = infoIt->second.depFilesList.begin(); strIt != infoIt->second.depFilesList.end(); strIt++) |
|
544 { |
|
545 if(infoIt->second.index < myDepInfoList[*strIt].index) |
|
546 { |
|
547 os << "dependence: " << infoIt->second.portName << " -> dependence: " << myDepInfoList[*strIt].portName << ";\n"; |
|
548 } |
|
549 } |
|
550 } |
|
551 os << "}\n"; |
|
552 os.close(); |
|
553 } |
|
554 |