]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
MdeModulePkg/EbcDxe: add EBC Debugger
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcDebugger / EdbSymbol.c
CommitLineData
748edcd5
PB
1/*++\r
2\r
3Copyright (c) 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 EdbSymbol.c\r
15\r
16Abstract:\r
17\r
18\r
19--*/\r
20\r
21#include "Edb.h"\r
22\r
23EFI_STATUS\r
24EdbLoadSymbolSingleEntry (\r
25 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,\r
26 IN CHAR8 *Name,\r
27 IN CHAR8 *ObjName,\r
28 IN UINTN Address,\r
29 IN EFI_DEBUGGER_SYMBOL_TYPE Type\r
30 )\r
31/*++\r
32\r
33Routine Description:\r
34\r
35 Load single symbol entry\r
36\r
37Arguments:\r
38\r
39 Object - Symbol file object\r
40 Name - Symbol name\r
41 ObjName - Object name\r
42 Address - Symbol address\r
43 Type - Symbol type\r
44\r
45Returns:\r
46\r
47 EFI_SUCCESS - add single symbol entry successfully\r
48\r
49--*/\r
50{\r
51 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;\r
52\r
53 //\r
54 // Check Count VS MaxCount\r
55 //\r
56 if (Object->EntryCount >= Object->MaxEntryCount) {\r
57 //\r
58 // reallocate (for codebuffer too)\r
59 // TBD\r
60 //\r
61 return EFI_OUT_OF_RESOURCES;\r
62 }\r
63\r
64 Entry = &Object->Entry[Object->EntryCount];\r
65\r
66 //\r
67 // Print Debug info\r
68 //\r
69 if (sizeof (UINTN) == sizeof(UINT64)) {\r
70 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));\r
71 } else {\r
72 DEBUG ((DEBUG_ERROR, " Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));\r
73 }\r
74\r
75 //\r
76 // Fill the entry - name, RVA, type\r
77 //\r
78 AsciiStrnCpyS (Entry->Name, sizeof(Entry->Name), Name, sizeof(Entry->Name) - 1);\r
79 if (ObjName != NULL) {\r
80 AsciiStrnCpyS (Entry->ObjName, sizeof(Entry->ObjName), ObjName, sizeof(Entry->ObjName) - 1);\r
81 }\r
82 Entry->RVA = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;\r
83 Entry->Type = Type;\r
84\r
85 //\r
86 // Increase Count\r
87 //\r
88 Object->EntryCount++;\r
89\r
90 //\r
91 // Done\r
92 //\r
93 return EFI_SUCCESS;\r
94}\r
95\r
96typedef enum {\r
97 EdbEbcMapParseStateUninitialized,\r
98 EdbEbcMapParseStateSymbolStart,\r
99 EdbEbcMapParseStateSeHandlerSymbol,\r
100 EdbEbcMapParseStateFunctionSymbol,\r
101 EdbEbcMapParseStateVarbssInitSymbol,\r
102 EdbEbcMapParseStateCrtSymbol,\r
103 EdbEbcMapParseStateVariableSymbol,\r
104 EdbEbcMapParseStateStaticFunctionSymbol,\r
105 EdbEbcMapParseStateMax,\r
106} EDB_EBC_MAP_PARSE_STATE;\r
107\r
108typedef enum {\r
109 EdbEbcSymbolParseStateUninitialized,\r
110 EdbEbcSymbolParseStateReadyForName,\r
111 EdbEbcSymbolParseStateReadyForRVA,\r
112 EdbEbcSymbolParseStateReadyForType,\r
113 EdbEbcSymbolParseStateReadyForObject,\r
114 EdbEbcSymbolParseStateMax,\r
115} EDB_EBC_SYMBOL_PARSE_STATE;\r
116\r
117/*++\r
118\r
119 The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).\r
120\r
121 Sample as follows: EbcTest.map\r
122===============================================================================\r
123 EbcTest\r
124\r
125 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)\r
126\r
127 Preferred load address is 10000000\r
128\r
129 Start Length Name Class\r
130 0001:00000000 00000370H .text CODE\r
131 0002:00000000 00000030H _VARBSS_INIT CODE\r
132 0003:00000000 00000004H .CRT$TSA DATA\r
133 0003:00000004 00000004H .CRT$TSC DATA\r
134 0003:00000008 00000004H .CRT$X DATA\r
135 0003:0000000c 00000008H .CRT$XCU DATA\r
136 0003:00000014 00000004H .CRT$Z DATA\r
137 0003:00000020 0000001cH .rdata DATA\r
138 0003:0000003c 00000000H .edata DATA\r
139 0003:0000003c 00000056H .rdata$debug DATA\r
140 0004:00000000 00000070H .data DATA\r
141 0004:00000070 00000020H .bss DATA\r
142\r
143 Address Publics by Value Rva+Base Lib:Object\r
144\r
145 0000:00000000 ___safe_se_handler_table 00000000 <absolute>\r
146 0000:00000000 ___safe_se_handler_count 00000000 <absolute>\r
147 0001:00000042 TestSubRoutine 10000442 f EbcTest.obj\r
148 0001:0000011a EfiMain 1000051a f EbcTest.obj\r
149 0001:00000200 TestSubRoutineSub 10000600 f EbcTestSub.obj\r
150 0001:00000220 EfiStart 10000620 f EbcLib:EbcLib.obj\r
151 0002:00000000 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f EbcTest.obj\r
152 0002:00000020 varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f EbcTestSub.obj\r
153 0003:00000000 CrtThunkBegin 10000a00 EbcLib:EbcLib.obj\r
154 0003:00000004 CrtThunkEnd 10000a04 EbcLib:EbcLib.obj\r
155 0003:00000008 CrtBegin 10000a08 EbcLib:EbcLib.obj\r
156 0003:00000014 CrtEnd 10000a14 EbcLib:EbcLib.obj\r
157 0004:00000070 TestStr 10000c70 EbcTest.obj\r
158 0004:00000078 TestVariable1 10000c78 EbcTest.obj\r
159 0004:00000080 TestSubVariableSub 10000c80 EbcTestSub.obj\r
160\r
161 entry point at 0001:00000220\r
162\r
163 Static symbols\r
164\r
165 0001:00000000 TestSubRoutine2 10000400 f EbcTest.obj\r
166===============================================================================\r
167\r
168--*/\r
169EFI_STATUS\r
170EdbLoadSymbolEntryByIec (\r
171 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,\r
172 IN UINTN BufferSize,\r
173 IN VOID *Buffer\r
174 )\r
175/*++\r
176\r
177Routine Description:\r
178\r
179 Load symbol entry by Iec\r
180\r
181Arguments:\r
182\r
183 DebuggerPrivate - EBC Debugger private data structure\r
184 Object - Symbol file object\r
185 BufferSize - Symbol file buffer size\r
186 Buffer - Symbol file buffer\r
187\r
188Returns:\r
189\r
190 EFI_SUCCESS - add symbol entry successfully\r
191\r
192--*/\r
193{\r
194 CHAR8 *LineBuffer;\r
195 CHAR8 *FieldBuffer;\r
196 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;\r
197 EDB_EBC_MAP_PARSE_STATE MapParseState;\r
198 EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;\r
199 CHAR8 *Name;\r
200 CHAR8 *ObjName;\r
201 UINTN Address;\r
202 EFI_DEBUGGER_SYMBOL_TYPE Type;\r
203\r
204 Entry = Object->Entry;\r
205\r
206 //\r
207 // Begin to parse the Buffer\r
208 //\r
209 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");\r
210 MapParseState = EdbEbcMapParseStateUninitialized;\r
211 //\r
212 // Check each line\r
213 //\r
214 while (LineBuffer != NULL) {\r
215 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, " ");\r
216 SymbolParseState = EdbEbcSymbolParseStateUninitialized;\r
217 //\r
218 // Init entry value\r
219 //\r
220 Name = NULL;\r
221 ObjName = NULL;\r
222 Address = 0;\r
223 Type = EfiDebuggerSymbolTypeMax;\r
224 //\r
225 // Check each field\r
226 //\r
227 while (FieldBuffer != NULL) {\r
228 if (AsciiStrCmp (FieldBuffer, "") == 0) {\r
229 FieldBuffer = AsciiStrGetNextTokenField (" ");\r
230 continue;\r
231 }\r
232 //\r
233 // check "Address"\r
234 //\r
235 if (AsciiStrCmp (FieldBuffer, "Address") == 0) {\r
236 MapParseState = EdbEbcMapParseStateSymbolStart;\r
237 break;\r
238 }\r
239 //\r
240 // check "Static"\r
241 //\r
242 if (AsciiStrCmp (FieldBuffer, "Static") == 0) {\r
243 MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;\r
244 break;\r
245 }\r
246\r
247 if (MapParseState == EdbEbcMapParseStateUninitialized) {\r
248 //\r
249 // Do not parse anything until get "Address" or "Static"\r
250 //\r
251 break;\r
252 }\r
253 if (AsciiStrCmp (FieldBuffer, "entry") == 0) {\r
254 //\r
255 // Skip entry point\r
256 //\r
257 break;\r
258 }\r
259\r
260 //\r
261 // Now we start to parse this line for Name, Address, and Object\r
262 //\r
263 switch (SymbolParseState) {\r
264 case EdbEbcSymbolParseStateUninitialized:\r
265 //\r
266 // Get the Address\r
267 //\r
268 SymbolParseState = EdbEbcSymbolParseStateReadyForName;\r
269 break;\r
270 case EdbEbcSymbolParseStateReadyForName:\r
271 //\r
272 // Get the Name\r
273 //\r
274 if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {\r
275 //\r
276 // skip SeHandler\r
277 //\r
278 MapParseState = EdbEbcMapParseStateSeHandlerSymbol;\r
279 goto ExitFieldParse;\r
280 } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {\r
281 //\r
282 // check VarbssInit\r
283 //\r
284 MapParseState = EdbEbcMapParseStateVarbssInitSymbol;\r
285// goto ExitFieldParse;\r
286 Name = FieldBuffer;\r
287 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;\r
288 } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {\r
289 //\r
290 // check Crt\r
291 //\r
292 MapParseState = EdbEbcMapParseStateCrtSymbol;\r
293// goto ExitFieldParse;\r
294 Name = FieldBuffer;\r
295 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;\r
296 } else {\r
297 //\r
298 // Now, it is normal function\r
299 //\r
300 switch (MapParseState) {\r
301 case EdbEbcMapParseStateSeHandlerSymbol:\r
302 MapParseState = EdbEbcMapParseStateFunctionSymbol;\r
303 break;\r
304 case EdbEbcMapParseStateCrtSymbol:\r
305 MapParseState = EdbEbcMapParseStateVariableSymbol;\r
306 break;\r
307 case EdbEbcMapParseStateFunctionSymbol:\r
308 case EdbEbcMapParseStateVariableSymbol:\r
309 case EdbEbcMapParseStateStaticFunctionSymbol:\r
310 break;\r
311 default:\r
312 ASSERT (FALSE);\r
313 break;\r
314 }\r
315 Name = FieldBuffer;\r
316 SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;\r
317 }\r
318 break;\r
319 case EdbEbcSymbolParseStateReadyForRVA:\r
320 //\r
321 // Get the RVA\r
322 //\r
323 Address = AsciiXtoi (FieldBuffer);\r
324 SymbolParseState = EdbEbcSymbolParseStateReadyForType;\r
325 break;\r
326 case EdbEbcSymbolParseStateReadyForType:\r
327 //\r
328 // Get the Type. This is optional, only for "f".\r
329 //\r
330 if (AsciiStrCmp (FieldBuffer, "f") == 0) {\r
331 SymbolParseState = EdbEbcSymbolParseStateReadyForObject;\r
332 switch (MapParseState) {\r
333 case EdbEbcMapParseStateFunctionSymbol:\r
334 case EdbEbcMapParseStateVarbssInitSymbol:\r
335 Type = EfiDebuggerSymbolFunction;\r
336 break;\r
337 case EdbEbcMapParseStateStaticFunctionSymbol:\r
338 Type = EfiDebuggerSymbolStaticFunction;\r
339 break;\r
340 default:\r
341 ASSERT (FALSE);\r
342 break;\r
343 }\r
344 break;\r
345 }\r
346 //\r
347 // Else it should be Object.\r
348 // let it bypass here\r
349 //\r
350 case EdbEbcSymbolParseStateReadyForObject:\r
351 switch (Type) {\r
352 case EfiDebuggerSymbolTypeMax:\r
353 switch (MapParseState) {\r
354 case EdbEbcMapParseStateVariableSymbol:\r
355 case EdbEbcMapParseStateCrtSymbol:\r
356 Type = EfiDebuggerSymbolGlobalVariable;\r
357 break;\r
358 case EdbEbcMapParseStateSeHandlerSymbol:\r
359 //\r
360 // do nothing here\r
361 //\r
362 break;\r
363 default:\r
364 ASSERT (FALSE);\r
365 break;\r
366 }\r
367 break;\r
368 case EfiDebuggerSymbolFunction:\r
369 case EfiDebuggerSymbolStaticFunction:\r
370 break;\r
371 default:\r
372 ASSERT (FALSE);\r
373 break;\r
374 }\r
375 //\r
376 // Get the Object\r
377 //\r
378 ObjName = FieldBuffer;\r
379 SymbolParseState = EdbEbcSymbolParseStateUninitialized;\r
380 break;\r
381 default:\r
382 ASSERT (FALSE);\r
383 break;\r
384 }\r
385\r
386 //\r
387 // Get the next field\r
388 //\r
389 FieldBuffer = AsciiStrGetNextTokenField (" ");\r
390 }\r
391\r
392 //\r
393 // Add the entry if we get everything.\r
394 //\r
395 if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {\r
396 EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);\r
397 }\r
398\r
399ExitFieldParse:\r
400 //\r
401 // Get the next line\r
402 //\r
403 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");\r
404 }\r
405\r
406 //\r
407 // Done\r
408 //\r
409 return EFI_SUCCESS;\r
410}\r
411\r
412EFI_STATUS\r
413EdbLoadSymbolEntry (\r
414 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,\r
415 IN UINTN BufferSize,\r
416 IN VOID *Buffer\r
417 )\r
418/*++\r
419\r
420Routine Description:\r
421\r
422 Load symbol entry\r
423\r
424Arguments:\r
425\r
426 Object - Symbol file object\r
427 BufferSize - Symbol file buffer size\r
428 Buffer - Symbol file buffer\r
429\r
430Returns:\r
431\r
432 EFI_SUCCESS - add symbol entry successfully\r
433\r
434--*/\r
435{\r
436 //\r
437 // MAP file format depends on the compiler (actually linker).\r
438 //\r
439 // It is possible to check the different MAP file format in this routine.\r
440 // Now only IEC is supported.\r
441 //\r
442 return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);\r
443}\r
444\r
445EFI_DEBUGGER_SYMBOL_OBJECT *\r
446EdbFindSymbolFile (\r
447 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
448 IN CHAR16 *FileName,\r
449 IN OUT UINTN *Index OPTIONAL\r
450 )\r
451/*++\r
452\r
453Routine Description:\r
454\r
455 Find symbol file by name\r
456\r
457Arguments:\r
458\r
459 DebuggerPrivate - EBC Debugger private data structure\r
460 FileName - Symbol file name\r
461 Index - Symbol file index\r
462\r
463Returns:\r
464\r
465 Object\r
466\r
467--*/\r
468{\r
469 UINTN ObjectIndex;\r
470\r
471 //\r
472 // Check each Object\r
473 //\r
474 for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {\r
475 if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {\r
476 //\r
477 // Name match, found it\r
478 //\r
479 if (Index != NULL) {\r
480 *Index = ObjectIndex;\r
481 }\r
482 return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];\r
483 }\r
484 }\r
485\r
486 //\r
487 // Not found\r
488 //\r
489 return NULL;\r
490}\r
491\r
492UINTN\r
493EbdFindSymbolAddress (\r
494 IN UINTN Address,\r
495 IN EDB_MATCH_SYMBOL_TYPE Type,\r
496 OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,\r
497 OUT EFI_DEBUGGER_SYMBOL_ENTRY **RetEntry\r
498 )\r
499/*++\r
500\r
501Routine Description:\r
502\r
503 Find symbol by address\r
504\r
505Arguments:\r
506\r
507 Address - Symbol address\r
508 Type - Search type\r
509 RetObject - Symbol object\r
510 RetEntry - Symbol entry\r
511\r
512Returns:\r
513\r
514 Nearest symbol address\r
515\r
516--*/\r
517{\r
518 UINTN Index;\r
519 UINTN SubIndex;\r
520 UINTN CandidateLowerAddress;\r
521 UINTN CandidateUpperAddress;\r
522 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
523 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;\r
524 EFI_DEBUGGER_SYMBOL_ENTRY *LowEntry;\r
525 EFI_DEBUGGER_SYMBOL_ENTRY *UpperEntry;\r
526 EFI_DEBUGGER_SYMBOL_OBJECT *LowObject;\r
527 EFI_DEBUGGER_SYMBOL_OBJECT *UpperObject;\r
528\r
529 if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {\r
530 return 0;\r
531 }\r
532\r
533 //\r
534 // Init\r
535 //\r
536 CandidateLowerAddress = 0;\r
537 CandidateUpperAddress = (UINTN)-1;\r
538 LowEntry = NULL;\r
539 UpperEntry = NULL;\r
540 LowObject = NULL;\r
541 UpperObject = NULL;\r
542\r
543 //\r
544 // Go through each object\r
545 //\r
546 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;\r
547 for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {\r
548 if (Object->EntryCount == 0) {\r
549 continue;\r
550 }\r
551 //\r
552 // Go through each entry\r
553 //\r
554 Entry = Object->Entry;\r
555 for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {\r
556 if (Address != Entry->RVA + Object->BaseAddress) {\r
557 //\r
558 // Check for nearest address\r
559 //\r
560 if (Address > Entry->RVA + Object->BaseAddress) {\r
561 //\r
562 // Record it if Current RVA < Address\r
563 //\r
564 if (CandidateLowerAddress < Entry->RVA + Object->BaseAddress) {\r
565 CandidateLowerAddress = Entry->RVA + Object->BaseAddress;\r
566 LowEntry = Entry;\r
567 LowObject = Object;\r
568 }\r
569 } else {\r
570 //\r
571 // Record it if Current RVA > Address\r
572 //\r
573 if (CandidateUpperAddress > Entry->RVA + Object->BaseAddress) {\r
574 CandidateUpperAddress = Entry->RVA + Object->BaseAddress;\r
575 UpperEntry = Entry;\r
576 UpperObject = Object;\r
577 }\r
578 }\r
579 continue;\r
580 }\r
581 //\r
582 // address match, return directly\r
583 //\r
584 *RetEntry = Entry;\r
585 *RetObject = Object;\r
586 return Address;\r
587 }\r
588 }\r
589\r
590 //\r
591 // No Match, provide latest symbol\r
592 //\r
593\r
594 if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {\r
595 //\r
596 // Check for lower address\r
597 //\r
598 if (((Type == EdbMatchSymbolTypeNearestAddress) &&\r
599 ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||\r
600 (Type == EdbMatchSymbolTypeLowerAddress)) {\r
601 //\r
602 // return nearest lower address\r
603 //\r
604 *RetEntry = LowEntry;\r
605 *RetObject = LowObject;\r
606 return CandidateLowerAddress;\r
607 }\r
608 }\r
609\r
610 if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {\r
611 //\r
612 // Check for upper address\r
613 //\r
614 if (((Type == EdbMatchSymbolTypeNearestAddress) &&\r
615 ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||\r
616 (Type == EdbMatchSymbolTypeUpperAddress)) {\r
617 //\r
618 // return nearest upper address\r
619 //\r
620 *RetEntry = UpperEntry;\r
621 *RetObject = UpperObject;\r
622 return CandidateUpperAddress;\r
623 }\r
624 }\r
625\r
626 //\r
627 // No match and nearest one, return NULL\r
628 //\r
629 return 0;\r
630}\r
631\r
632EFI_STATUS\r
633EdbUnloadSymbol (\r
634 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
635 IN CHAR16 *FileName\r
636 )\r
637/*++\r
638\r
639Routine Description:\r
640\r
641 Unload symbol file by name\r
642\r
643Arguments:\r
644\r
645 DebuggerPrivate - EBC Debugger private data structure\r
646 FileName - Symbol file name\r
647\r
648Returns:\r
649\r
650 EFI_SUCCESS - unload symbol successfully\r
651\r
652--*/\r
653{\r
654 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
655 UINTN ObjectIndex;\r
656 UINTN Index;\r
657 EFI_DEBUGGER_SYMBOL_ENTRY *OldEntry;\r
658 UINTN OldEntryCount;\r
659 UINTN MaxEntryCount;\r
660 VOID **OldSourceBuffer;\r
661\r
662 //\r
663 // Find Symbol\r
664 //\r
665 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);\r
666 if (Object == NULL) {\r
667 EDBPrint (L"SymbolFile is not loaded!\n");\r
668 return EFI_DEBUG_CONTINUE;\r
669 }\r
670\r
671 //\r
672 // Record old data\r
673 //\r
674 Object = DebuggerPrivate->DebuggerSymbolContext.Object;\r
675 OldEntry = Object->Entry;\r
676 OldSourceBuffer = Object->SourceBuffer;\r
677 MaxEntryCount = Object->MaxEntryCount;\r
678 OldEntryCount = Object->EntryCount;\r
679\r
680 //\r
681 // Remove the matched Object\r
682 //\r
683 for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {\r
684 CopyMem (&Object[Index], &Object[Index + 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT));\r
685 }\r
686 ZeroMem (&Object[Index], sizeof(Object[Index]));\r
687\r
688 //\r
689 // Move old data to new place\r
690 //\r
691 Object[Index].Entry = OldEntry;\r
692 Object[Index].SourceBuffer = OldSourceBuffer;\r
693 Object[Index].MaxEntryCount = MaxEntryCount;\r
694 DebuggerPrivate->DebuggerSymbolContext.ObjectCount --;\r
695\r
696 //\r
697 // Clean old entry data\r
698 //\r
699 for (Index = 0; Index < OldEntryCount; Index++) {\r
700 ZeroMem (&OldEntry[Index], sizeof(OldEntry[Index]));\r
701 }\r
702\r
703 //\r
704 // Free OldSourceBuffer\r
705 //\r
706 for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {\r
707 gBS->FreePool (OldSourceBuffer[Index]);\r
708 OldSourceBuffer[Index] = NULL;\r
709 }\r
710\r
711 return EFI_SUCCESS;\r
712}\r
713\r
714EFI_STATUS\r
715EdbLoadSymbol (\r
716 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
717 IN CHAR16 *FileName,\r
718 IN UINTN BufferSize,\r
719 IN VOID *Buffer\r
720 )\r
721/*++\r
722\r
723Routine Description:\r
724\r
725 Load symbol file by name\r
726\r
727Arguments:\r
728\r
729 DebuggerPrivate - EBC Debugger private data structure\r
730 FileName - Symbol file name\r
731 BufferSize - Symbol file buffer size\r
732 Buffer - Symbol file buffer\r
733\r
734Returns:\r
735\r
736 EFI_SUCCESS - load symbol successfully\r
737\r
738--*/\r
739{\r
740 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
741 EFI_STATUS Status;\r
742\r
743 //\r
744 // Check duplicated File\r
745 //\r
746 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);\r
747 if (Object != NULL) {\r
748 Status = EdbUnloadSymbol (DebuggerPrivate, FileName);\r
749 if (EFI_ERROR(Status)) {\r
750 DEBUG ((DEBUG_ERROR, "Unload Duplicated Symbol File Error!\n"));\r
751 return Status;\r
752 }\r
753 }\r
754\r
755 //\r
756 // Check Count VS MaxCount\r
757 //\r
758 if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {\r
759 //\r
760 // reallocate\r
761 // TBD\r
762 //\r
763 return EFI_OUT_OF_RESOURCES;\r
764 }\r
765\r
766 Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];\r
767\r
768 //\r
769 // Init Object\r
770 //\r
771 Object->EntryCount = 0;\r
772 Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;\r
773\r
774 //\r
775 // Load SymbolEntry\r
776 //\r
777 DEBUG ((DEBUG_ERROR, "Symbol File: %s\n", FileName));\r
778 Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);\r
779 if (EFI_ERROR (Status)) {\r
780 return Status;\r
781 }\r
782\r
783 //\r
784 // Fill Object value\r
785 //\r
786 StrnCpyS (Object->Name, sizeof(Object->Name) / sizeof(CHAR16),\r
787 FileName, (sizeof(Object->Name) / sizeof(CHAR16)) - 1);\r
788 Object->BaseAddress = 0;\r
789\r
790 //\r
791 // Increase the object count\r
792 //\r
793 DebuggerPrivate->DebuggerSymbolContext.ObjectCount ++;\r
794\r
795 return EFI_SUCCESS;\r
796}\r
797\r
798CHAR8 *\r
799GetPdbPath (\r
800 VOID *ImageBase\r
801 )\r
802/*++\r
803\r
804Routine Description:\r
805\r
806 Located PDB path name in PE image\r
807\r
808Arguments:\r
809\r
810 ImageBase - base of PE to search\r
811\r
812Returns:\r
813\r
814 Pointer into image at offset of PDB file name if PDB file name is found,\r
815 Otherwise a pointer to an empty string.\r
816\r
817--*/\r
818{\r
819 CHAR8 *PdbPath;\r
820 UINT32 DirCount;\r
821 EFI_IMAGE_DOS_HEADER *DosHdr;\r
822 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
823 EFI_IMAGE_OPTIONAL_HEADER32 *OptionalHdr32;\r
824 EFI_IMAGE_OPTIONAL_HEADER64 *OptionalHdr64;\r
825 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
826 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
827 VOID *CodeViewEntryPointer;\r
828\r
829 //\r
830 // Init value\r
831 //\r
832 CodeViewEntryPointer = NULL;\r
833 PdbPath = NULL;\r
834 DosHdr = ImageBase;\r
835\r
836 //\r
837 // Check magic\r
838 //\r
839 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
840 return NULL;\r
841 }\r
842 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);\r
843 //\r
844 // Check Machine, filter for EBC\r
845 //\r
846 if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {\r
847 //\r
848 // If not EBC, return NULL\r
849 //\r
850 return NULL;\r
851 }\r
852\r
853 //\r
854 // Get DirectoryEntry\r
855 // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.\r
856 //\r
857 if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
858 OptionalHdr32 = (VOID *) &NtHdr->Pe32.OptionalHeader;\r
859 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
860 } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
861 OptionalHdr64 = (VOID *) &NtHdr->Pe32Plus.OptionalHeader;\r
862 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
863 } else {\r
864 return NULL;\r
865 }\r
866 if (DirectoryEntry->VirtualAddress == 0) {\r
867 return NULL;\r
868 }\r
869 //\r
870 // Go through DirectoryEntry\r
871 //\r
872 for (DirCount = 0;\r
873 (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;\r
874 DirCount++\r
875 ) {\r
876 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
877 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
878 //\r
879 // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.\r
880 //\r
881 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);\r
882 switch (*(UINT32 *) CodeViewEntryPointer) {\r
883 case CODEVIEW_SIGNATURE_NB10:\r
884 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
885 break;\r
886 case CODEVIEW_SIGNATURE_RSDS:\r
887 PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
888 break;\r
889 default:\r
890 break;\r
891 }\r
892 }\r
893 }\r
894\r
895 //\r
896 // Done successfully\r
897 //\r
898 return PdbPath;\r
899}\r
900\r
901BOOLEAN\r
902MatchPdbAndMap (\r
903 IN CHAR8 *PdbFileName,\r
904 IN CHAR16 *MapFileName\r
905 )\r
906/*++\r
907\r
908Routine Description:\r
909\r
910 Check whether PDB file and MAP file have same name\r
911\r
912Arguments:\r
913\r
914 PdbFileName - PDB file name\r
915 MapFileName - MAP file name\r
916\r
917Returns:\r
918\r
919 TRUE - PDB and MAP file name match\r
920 FALSE - PDB and MAP file name not match\r
921\r
922--*/\r
923{\r
924 UINTN PdbNameSize;\r
925 UINTN MapNameSize;\r
926 CHAR8 *PurePdbFileName;\r
927 UINTN Index;\r
928\r
929 //\r
930 // remove dir name\r
931 //\r
932 PurePdbFileName = PdbFileName;\r
933 for (Index = 0; PdbFileName[Index] != 0; Index++) {\r
934 if (PdbFileName[Index] == '\\') {\r
935 PurePdbFileName = &PdbFileName[Index + 1];\r
936 }\r
937 }\r
938 PdbFileName = PurePdbFileName;\r
939\r
940 //\r
941 // get size\r
942 //\r
943 PdbNameSize = AsciiStrLen (PdbFileName);\r
944 MapNameSize = StrLen (MapFileName);\r
945\r
946 if (PdbNameSize != MapNameSize) {\r
947 return FALSE;\r
948 }\r
949\r
950 //\r
951 // check the name\r
952 //\r
953 for (Index = 0; Index < MapNameSize - 4; Index++) {\r
954 if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {\r
955 return FALSE;\r
956 }\r
957 }\r
958\r
959 return TRUE;\r
960}\r
961\r
962//\r
963// BUGBUG: work-around start\r
964//\r
965typedef struct {\r
966 EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable;\r
967 volatile UINT32 UpdateStatus;\r
968 UINT32 TableSize;\r
969} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;\r
970\r
971EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugImageInfoTableHeader;\r
972\r
973VOID\r
974EdbFixDebugImageInfoTable (\r
975 IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader\r
976 )\r
977/*\r
978For compatibility consideration, we handle 2 cases:\r
979\r
9801) IA32:\r
981 Old: New:\r
982 +------------------------+ +------------------------+\r
983 | EfiDebugImageInfoTable | | UpdateStatus |\r
984 +------------------------+ +------------------------+\r
985 | UpdateStatus | | TableSize |\r
986 +------------------------+ +------------------------+\r
987 | TableSize | | EfiDebugImageInfoTable |\r
988 +------------------------+ +------------------------+\r
989\r
9902) X64 and IPF:\r
991 Old: New:\r
992 +------------------------+ +------------------------+\r
993 | EfiDebugImageInfoTable | | UpdateStatus |\r
994 | | +------------------------+\r
995 | | | TableSize |\r
996 +------------------------+ +------------------------+\r
997 | UpdateStatus | | EfiDebugImageInfoTable |\r
998 +------------------------+ | |\r
999 | TableSize | | |\r
1000 +------------------------+ +------------------------+\r
1001\r
1002*/\r
1003{\r
1004 mDebugImageInfoTableHeader.EfiDebugImageInfoTable = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->EfiDebugImageInfoTable;\r
1005 mDebugImageInfoTableHeader.UpdateStatus = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->UpdateStatus;\r
1006 mDebugImageInfoTableHeader.TableSize = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->TableSize;\r
1007\r
1008 if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {\r
1009 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;\r
1010 return ;\r
1011 }\r
1012\r
1013 if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {\r
1014 *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;\r
1015 return ;\r
1016 }\r
1017\r
1018 return ;\r
1019}\r
1020//\r
1021// BUGBUG: work-around end\r
1022//\r
1023\r
1024EFI_STATUS\r
1025EdbPatchSymbolRVA (\r
1026 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
1027 IN CHAR16 *FileName,\r
1028 IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType\r
1029 )\r
1030/*++\r
1031\r
1032Routine Description:\r
1033\r
1034 Patch symbol RVA\r
1035\r
1036Arguments:\r
1037\r
1038 DebuggerPrivate - EBC Debugger private data structure\r
1039 FileName - Symbol file name\r
1040 SearchType - Search type for Object\r
1041\r
1042Returns:\r
1043\r
1044 EFI_SUCCESS - Patch symbol RVA successfully\r
1045 EFI_NOT_FOUND - Symbol RVA base not found\r
1046\r
1047--*/\r
1048{\r
1049 EFI_STATUS Status;\r
1050 UINTN ImageNumber;\r
1051 EFI_DEBUG_IMAGE_INFO *ImageTable;\r
1052 CHAR8 *PdbPath;\r
1053 VOID *ImageBase;\r
1054 VOID *CandidateImageBase;\r
1055 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
1056\r
1057 if (SearchType < 0 || SearchType >= EdbEbcImageRvaSearchTypeMax) {\r
1058 return EFI_INVALID_PARAMETER;\r
1059 }\r
1060\r
1061 //\r
1062 // Get the related object\r
1063 //\r
1064 Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);\r
1065 if (Object == NULL) {\r
1066 return EFI_NOT_FOUND;\r
1067 }\r
1068\r
1069 //\r
1070 // Try again to get DebugImageInfoTable\r
1071 //\r
1072 if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {\r
1073 Status = EfiGetSystemConfigurationTable (\r
1074 &gEfiDebugImageInfoTableGuid,\r
1075 (VOID **) &mDebuggerPrivate.DebugImageInfoTableHeader\r
1076 );\r
1077 if (EFI_ERROR (Status)) {\r
1078 EDBPrint (L"DebugImageInfoTable not found!\n");\r
1079 return Status;\r
1080 }\r
1081 }\r
1082 DEBUG ((DEBUG_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));\r
1083\r
1084 //\r
1085 // BUGBUG: work-around start\r
1086 //\r
1087 EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);\r
1088 //\r
1089 // BUGBUG: work-around end\r
1090 //\r
1091\r
1092 //\r
1093 // Go through DebugImageInfoTable for each Image\r
1094 //\r
1095 CandidateImageBase = NULL;\r
1096 ImageTable = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;\r
1097 for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {\r
1098 if (ImageTable[ImageNumber].NormalImage == NULL) {\r
1099 continue;\r
1100 }\r
1101 ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;\r
1102 //\r
1103 // Get PDB path\r
1104 //\r
1105 PdbPath = GetPdbPath (ImageBase);\r
1106 if (PdbPath == NULL) {\r
1107 continue;\r
1108 }\r
1109 //\r
1110 // Check PDB name\r
1111 //\r
1112 if (!MatchPdbAndMap (PdbPath, FileName)) {\r
1113 continue;\r
1114 }\r
1115 DEBUG ((DEBUG_ERROR, "ImageBase: %x\n", ImageBase));\r
1116\r
1117 //\r
1118 // Check SearchType\r
1119 //\r
1120 if (SearchType == EdbEbcImageRvaSearchTypeAny || SearchType == EdbEbcImageRvaSearchTypeFirst) {\r
1121 //\r
1122 // Assign base address and return\r
1123 //\r
1124 Object->BaseAddress = (UINTN)ImageBase;\r
1125 return EFI_SUCCESS;\r
1126 }\r
1127\r
1128 //\r
1129 // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast\r
1130 //\r
1131 CandidateImageBase = ImageBase;\r
1132 }\r
1133\r
1134 //\r
1135 // Check EdbEbcImageRvaSearchTypeLast\r
1136 //\r
1137 if (SearchType == EdbEbcImageRvaSearchTypeLast) {\r
1138 if (CandidateImageBase == NULL) {\r
1139 return EFI_NOT_FOUND;\r
1140 }\r
1141 //\r
1142 // Assign base address and return\r
1143 //\r
1144 Object->BaseAddress = (UINTN)CandidateImageBase;\r
1145 return EFI_SUCCESS;\r
1146 }\r
1147\r
1148 //\r
1149 // No match\r
1150 //\r
1151 return EFI_NOT_FOUND;\r
1152}\r
1153\r
1154BOOLEAN\r
1155MatchObjAndCod (\r
1156 IN CHAR8 *ObjFileName,\r
1157 IN CHAR16 *CodFileName\r
1158 )\r
1159/*++\r
1160\r
1161Routine Description:\r
1162\r
1163 Check whether OBJ file and COD file have same name\r
1164\r
1165Arguments:\r
1166\r
1167 ObjFileName - OBJ file name\r
1168 CodFileName - COD file name\r
1169\r
1170Returns:\r
1171\r
1172 TRUE - OBJ and COD file name match\r
1173 FALSE - OBJ and COD file name not match\r
1174\r
1175--*/\r
1176{\r
1177 UINTN ObjNameSize;\r
1178 UINTN CodNameSize;\r
1179 CHAR8 *PureObjFileName;\r
1180 UINTN Index;\r
1181\r
1182 //\r
1183 // remove library name\r
1184 //\r
1185 PureObjFileName = ObjFileName;\r
1186 for (Index = 0; ObjFileName[Index] != 0; Index++) {\r
1187 if (ObjFileName[Index] == ':') {\r
1188 PureObjFileName = &ObjFileName[Index + 1];\r
1189 break;\r
1190 }\r
1191 }\r
1192 ObjFileName = PureObjFileName;\r
1193\r
1194 //\r
1195 // get size\r
1196 //\r
1197 ObjNameSize = AsciiStrLen (ObjFileName);\r
1198 CodNameSize = StrLen (CodFileName);\r
1199\r
1200 if (ObjNameSize != CodNameSize) {\r
1201 return FALSE;\r
1202 }\r
1203\r
1204 //\r
1205 // check the name\r
1206 //\r
1207 for (Index = 0; Index < CodNameSize - 4; Index++) {\r
1208 if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {\r
1209 return FALSE;\r
1210 }\r
1211 }\r
1212\r
1213 return TRUE;\r
1214}\r
1215\r
1216typedef enum {\r
1217 EdbEbcCodParseStateUninitialized,\r
1218 EdbEbcCodParseStateSymbolInitialized,\r
1219 EdbEbcCodParseStateSymbolStart,\r
1220 EdbEbcCodParseStateSymbolEnd,\r
1221 EdbEbcCodParseStateMax,\r
1222} EDB_EBC_COD_PARSE_STATE;\r
1223\r
1224/*++\r
1225\r
1226 The following code depends on the COD file generated by IEC compiler.\r
1227\r
1228 Sample as follows: EbcTest.cod\r
1229===============================================================================\r
1230; -- Machine type EFI\r
1231; mark_description "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123";\r
1232; mark_description "XXX";\r
1233;ident "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123"\r
1234;ident "XXX"\r
1235 .686P\r
1236 .387\r
1237_TEXT SEGMENT PARA PUBLIC USE32 'CODE'\r
1238_TEXT ENDS\r
1239_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1240 ALIGN 010H\r
1241_DATA ENDS\r
1242_BSS SEGMENT PARA PUBLIC USE32 'BSS'\r
1243 ALIGN 010H\r
1244_BSS ENDS\r
1245_VARBSS SEGMENT PARA PUBLIC USE32 'BSS'\r
1246 ALIGN 010H\r
1247_VARBSS ENDS\r
1248 ASSUME CS:FLAT,DS:FLAT,SS:FLAT\r
1249_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1250TestVariable2 DD 000000003H,000000000H ; u64\r
1251_DATA ENDS\r
1252_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1253_DATA ENDS\r
1254_TEXT SEGMENT PARA PUBLIC USE32 'CODE'\r
1255; -- Begin EfiMain\r
1256; mark_begin;\r
1257 PUBLIC EfiMain\r
1258EfiMain PROC NEAR\r
1259$B3$1:; 11a\r
1260$LN45:\r
1261\r
1262;117 ; {\r
1263\r
1264 0011a 60 00 70 80 MOVqw R0, R0(+0,-112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:117\r
1265$LN46:\r
1266\r
1267;118 ; UINT16 test = 0x1234;\r
1268\r
1269 0011e 77 58 58 00 34\r
1270 12 MOVIww @R0(+0,+88), +4660 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:118\r
1271$LN47:\r
1272\r
1273;121 ; EFI_STATUS Status;\r
1274;121 ;\r
1275;121 ; SystemTable->ConOut->OutputString (\r
1276\r
1277 00124 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121\r
1278 00128 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121\r
1279$LN48:\r
1280\r
1281;122 ; SystemTable->ConOut,\r
1282\r
1283 0012c 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122\r
1284 00130 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122\r
1285 00134 b9 34 00 00 00\r
1286 00 MOVreld R4, __STRING$1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122\r
1287 0013a b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122\r
1288 0013e 83 2f 01 00 00\r
1289 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122\r
1290$B3$2:; 144\r
1291$LN49:\r
1292\r
1293;125 ; L"Hello EBC Test!\n\r"\r
1294;125 ; );\r
1295;125 ; EFI_BREAKPOINT ();\r
1296\r
1297 00144 00 03 BREAK 3 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:125\r
1298$B3$3:; 146\r
1299$LN50:\r
1300\r
1301;126 ; TestVariable1 = 6;\r
1302\r
1303 00146 b9 37 00 00 00\r
1304 00 MOVreld R7, TestVariable1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126\r
1305 0014c 78 0f 06 00 MOVInw @R7, (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126\r
1306$LN51:\r
1307\r
1308;127 ; TestSubRoutineSub (1, 5);\r
1309\r
1310 00150 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127\r
1311 00154 78 48 01 10 05\r
1312 00 MOVInw @R0(1,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127\r
1313 0015a 83 10 00 00 00\r
1314 00 CALL TestSubRoutineSub ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127\r
1315$B3$4:; 160\r
1316$LN52:\r
1317\r
1318;129 ;\r
1319;129 ; SystemTable->ConOut->OutputString (\r
1320\r
1321 00160 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129\r
1322 00164 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129\r
1323$LN53:\r
1324\r
1325;130 ; SystemTable->ConOut,\r
1326\r
1327 00168 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130\r
1328 0016c 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130\r
1329$LN54:\r
1330\r
1331;131 ; TestStr\r
1332\r
1333 00170 b9 34 00 00 00\r
1334 00 MOVreld R4, TestStr ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131\r
1335 00176 b2 c8 01 10 MOVnw @R0(+1, +0), @R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131\r
1336 0017a 83 2f 01 00 00\r
1337 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131\r
1338$B3$5:; 180\r
1339$LN55:\r
1340\r
1341;134 ; );\r
1342;134 ;\r
1343;134 ; test = test & 0xFF;\r
1344\r
1345 00180 de 88 58 00 58\r
1346 00 MOVww @R0(+0,+88), @R0(+0,+88) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:134\r
1347$LN56:\r
1348\r
1349;139 ; if (test != 0x34) {\r
1350;139 ; // EFI_BREAKPOINT ();\r
1351;139 ; }\r
1352;139 ;\r
1353;139 ; Status = TestSubRoutine (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\r
1354\r
1355 00186 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1356 0018a 78 48 01 10 02\r
1357 00 MOVInw @R0(1,0), (0,2) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1358 00190 78 48 02 10 03\r
1359 00 MOVInw @R0(2,0), (0,3) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1360 00196 78 48 03 10 04\r
1361 00 MOVInw @R0(3,0), (0,4) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1362 0019c 78 48 04 20 05\r
1363 00 MOVInw @R0(4,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1364 001a2 78 48 05 20 06\r
1365 00 MOVInw @R0(5,0), (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1366 001a8 78 48 06 20 07\r
1367 00 MOVInw @R0(6,0), (0,7) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1368 001ae 78 48 07 20 08\r
1369 00 MOVInw @R0(7,0), (0,8) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1370 001b4 78 48 08 20 09\r
1371 00 MOVInw @R0(8,0), (0,9) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1372 001ba 78 48 09 20 0a\r
1373 00 MOVInw @R0(9,0), (0,10) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1374 001c0 83 10 00 00 00\r
1375 00 CALL TestSubRoutine ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1376$B3$10:; 1c6\r
1377 001c6 b2 78 60 00 MOVnw @R0(+0,+96), R7 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1378$B3$6:; 1ca\r
1379$LN57:\r
1380 001ca f2 88 50 00 60\r
1381 00 MOVnw @R0(+0,+80), @R0(+0,+96) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139\r
1382$LN58:\r
1383\r
1384;141 ;\r
1385;141 ; SystemTable->ConOut->OutputString (\r
1386\r
1387 001d0 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141\r
1388 001d4 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141\r
1389$LN59:\r
1390\r
1391;142 ; SystemTable->ConOut,\r
1392\r
1393 001d8 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142\r
1394 001dc 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142\r
1395 001e0 b9 34 00 00 00\r
1396 00 MOVreld R4, __STRING$2 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142\r
1397 001e6 b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142\r
1398 001ea 83 2f 01 00 00\r
1399 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142\r
1400$B3$7:; 1f0\r
1401$LN60:\r
1402\r
1403;146 ; L"Goodbye EBC Test!\n\r"\r
1404;146 ; );\r
1405;146 ;\r
1406;146 ; return Status;\r
1407\r
1408 001f0 72 87 50 00 MOVnw R7, @R0(+0,+80) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146\r
1409 001f4 60 00 70 00 MOVqw R0, R0(+0,+112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146\r
1410 001f8 04 00 RET ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146\r
1411; mark_end;\r
1412EfiMain ENDP\r
1413_TEXT ENDS\r
1414_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1415 DB 3 DUP (0) ; pad\r
1416__STRING$2 DW 71 ; u16\r
1417 DW 111 ; u16\r
1418 DW 111 ; u16\r
1419 DW 100 ; u16\r
1420 DW 98 ; u16\r
1421 DW 121 ; u16\r
1422 DW 101 ; u16\r
1423 DW 32 ; u16\r
1424 DW 69 ; u16\r
1425 DW 66 ; u16\r
1426 DW 67 ; u16\r
1427 DW 32 ; u16\r
1428 DW 84 ; u16\r
1429 DW 101 ; u16\r
1430 DW 115 ; u16\r
1431 DW 116 ; u16\r
1432 DW 33 ; u16\r
1433 DW 10 ; u16\r
1434 DW 13 ; u16\r
1435 DW 0 ; u16\r
1436__STRING$1 DW 72 ; u16\r
1437 DW 101 ; u16\r
1438 DW 108 ; u16\r
1439 DW 108 ; u16\r
1440 DW 111 ; u16\r
1441 DW 32 ; u16\r
1442 DW 69 ; u16\r
1443 DW 66 ; u16\r
1444 DW 67 ; u16\r
1445 DW 32 ; u16\r
1446 DW 84 ; u16\r
1447 DW 101 ; u16\r
1448 DW 115 ; u16\r
1449 DW 116 ; u16\r
1450 DW 33 ; u16\r
1451 DW 10 ; u16\r
1452 DW 13 ; u16\r
1453 DW 0 ; u16\r
1454_DATA ENDS\r
1455_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1456_DATA ENDS\r
1457; -- End EfiMain\r
1458_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1459__STRING$0 DW 55 ; u16\r
1460 DW 56 ; u16\r
1461 DW 57 ; u16\r
1462 DW 52 ; u16\r
1463 DW 53 ; u16\r
1464 DW 54 ; u16\r
1465 DW 49 ; u16\r
1466 DW 50 ; u16\r
1467 DW 51 ; u16\r
1468 DW 13 ; u16\r
1469 DW 10 ; u16\r
1470 DW 0 ; u16\r
1471_DATA ENDS\r
1472_VARBSS SEGMENT PARA PUBLIC USE32 'BSS'\r
1473 PUBLIC TestStr\r
1474TestStr DD 2 DUP (?) ; pad\r
1475 PUBLIC TestVariable1\r
1476TestVariable1 DD 2 DUP (?) ; pad\r
1477_VARBSS ENDS\r
1478_VARBSS_INIT SEGMENT DWORD PUBLIC USE32 'CODE'\r
1479; -- Begin varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2\r
1480 PUBLIC varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2\r
1481varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2 PROC NEAR\r
1482 00000 b9 34 00 00 00\r
1483 00 MOVreld R4, TestStr\r
1484 00006 b9 35 00 00 00\r
1485 00 MOVreld R5, __STRING$0\r
1486 0000c 33 5c MOVnd @R4, R5\r
1487 0000e b9 34 00 00 00\r
1488 00 MOVreld R4, TestVariable1\r
1489 00014 78 0c 04 00 MOVInw @R4, (0,4)\r
1490 00018 04 00 RET\r
1491; -- End varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2\r
1492_VARBSS_INIT ENDS\r
1493_DATA SEGMENT PARA PUBLIC USE32 'DATA'\r
1494_DATA ENDS\r
1495EXTRN TestSubRoutineSub:PROC\r
1496 END\r
1497\r
1498===============================================================================\r
1499\r
1500--*/\r
1501CHAR8 *\r
1502EdbLoadCodBySymbolByIec (\r
1503 IN CHAR8 *Name,\r
1504 IN VOID *Buffer,\r
1505 IN UINTN BufferSize,\r
1506 OUT UINTN *CodeBufferSize,\r
1507 OUT UINTN *FuncOffset\r
1508 )\r
1509/*++\r
1510\r
1511Routine Description:\r
1512\r
1513 Load code by symbol by Iec\r
1514\r
1515Arguments:\r
1516\r
1517 Name - Symbol file name\r
1518 BufferSize - Symbol file buffer size\r
1519 Buffer - Symbol file buffer\r
1520 CodeBufferSize - Code buffer size\r
1521 FuncOffset - Code funcion offset\r
1522\r
1523Returns:\r
1524\r
1525 CodeBuffer\r
1526\r
1527--*/\r
1528{\r
1529 CHAR8 *LineBuffer;\r
1530 CHAR8 *FieldBuffer;\r
1531 VOID *BufferStart;\r
1532 VOID *BufferEnd;\r
1533 UINTN Offset;\r
1534 EDB_EBC_COD_PARSE_STATE CodParseState;\r
1535 CHAR8 Char[2] = {9, 0};\r
1536\r
1537 //\r
1538 // Init\r
1539 //\r
1540 LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");\r
1541 Offset = (UINTN)-1;\r
1542 BufferStart = NULL;\r
1543 BufferEnd = NULL;\r
1544 CodParseState = EdbEbcCodParseStateUninitialized;\r
1545\r
1546 //\r
1547 // Check each line\r
1548 //\r
1549 while (LineBuffer != NULL) {\r
1550 switch (CodParseState) {\r
1551 case EdbEbcCodParseStateUninitialized:\r
1552 //\r
1553 // check mark_begin, begin to check line after this match\r
1554 //\r
1555 if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {\r
1556 CodParseState = EdbEbcCodParseStateSymbolInitialized;\r
1557 }\r
1558 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");\r
1559 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
1560 break;\r
1561\r
1562 case EdbEbcCodParseStateSymbolInitialized:\r
1563 //\r
1564 // check mark_end, not check line after this match\r
1565 //\r
1566 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {\r
1567 CodParseState = EdbEbcCodParseStateUninitialized;\r
1568 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");\r
1569 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
1570 break;\r
1571 }\r
1572\r
1573 //\r
1574 // not check this line if the first char is as follows\r
1575 //\r
1576 if ((*LineBuffer == 0) ||\r
1577 (*LineBuffer == '$') ||\r
1578 (*LineBuffer == ';') ||\r
1579 (*LineBuffer == '_') ||\r
1580 (*LineBuffer == ' ')) {\r
1581 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");\r
1582 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
1583 break;\r
1584 }\r
1585\r
1586 //\r
1587 // get function name, function name is followed by char 0x09.\r
1588 //\r
1589 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);\r
1590 if (AsciiStriCmp (FieldBuffer, Name) == 0) {\r
1591 BufferStart = FieldBuffer;\r
1592 CodParseState = EdbEbcCodParseStateSymbolStart;\r
1593 }\r
1594 PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);\r
1595\r
1596 //\r
1597 // Get next line\r
1598 //\r
1599 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");\r
1600 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
1601 break;\r
1602\r
1603 case EdbEbcCodParseStateSymbolStart:\r
1604 //\r
1605 // check mark_end, if this match, means the function is found successfully.\r
1606 //\r
1607 if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {\r
1608 CodParseState = EdbEbcCodParseStateSymbolEnd;\r
1609 //\r
1610 // prepare CodeBufferSize, FuncOffset, and FuncStart to return\r
1611 //\r
1612 BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;\r
1613 *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;\r
1614 *FuncOffset = Offset;\r
1615 PatchForAsciiStrTokenAfter (LineBuffer, '\n');\r
1616 return BufferStart;\r
1617 }\r
1618\r
1619 //\r
1620 // Get function offset\r
1621 //\r
1622 if ((Offset == (UINTN)-1) &&\r
1623 (*LineBuffer == ' ')) {\r
1624 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");\r
1625 Offset = AsciiXtoi (FieldBuffer);\r
1626 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');\r
1627 }\r
1628\r
1629 //\r
1630 // Get next line\r
1631 //\r
1632 LineBuffer = AsciiStrGetNextTokenLine ("\n\r");\r
1633 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
1634 break;\r
1635\r
1636 case EdbEbcCodParseStateSymbolEnd:\r
1637 break;\r
1638\r
1639 default:\r
1640 break;\r
1641 }\r
1642 }\r
1643\r
1644 //\r
1645 // no function found\r
1646 //\r
1647 return NULL;\r
1648}\r
1649\r
1650CHAR8 *\r
1651EdbLoadCodBySymbol (\r
1652 IN CHAR8 *Name,\r
1653 IN VOID *Buffer,\r
1654 IN UINTN BufferSize,\r
1655 OUT UINTN *CodeBufferSize,\r
1656 OUT UINTN *FuncOffset\r
1657 )\r
1658/*++\r
1659\r
1660Routine Description:\r
1661\r
1662 Load code by symbol\r
1663\r
1664Arguments:\r
1665\r
1666 Name - Symbol file name\r
1667 BufferSize - Symbol file buffer size\r
1668 Buffer - Symbol file buffer\r
1669 CodeBufferSize - Code buffer size\r
1670 FuncOffset - Code funcion offset\r
1671\r
1672Returns:\r
1673\r
1674 CodeBuffer\r
1675\r
1676--*/\r
1677{\r
1678 //\r
1679 // COD file format depends on the compiler.\r
1680 //\r
1681 // It is possible to check the different COD file format in this routine.\r
1682 // Now only IEC is supported.\r
1683 //\r
1684 return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);\r
1685}\r
1686\r
1687VOID *\r
1688EdbFindCodeFromObject (\r
1689 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
1690 IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,\r
1691 IN CHAR16 *FileName\r
1692 )\r
1693/*++\r
1694\r
1695Routine Description:\r
1696\r
1697 Find code from object\r
1698\r
1699Arguments:\r
1700\r
1701 Object - Symbol object\r
1702 FileName - File name\r
1703\r
1704Returns:\r
1705\r
1706 CodeBuffer\r
1707\r
1708--*/\r
1709{\r
1710 UINTN EntryIndex;\r
1711\r
1712 //\r
1713 // Go througn each Entry in this Object\r
1714 //\r
1715 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {\r
1716 //\r
1717 // This check is for Function only\r
1718 //\r
1719 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&\r
1720 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {\r
1721 continue;\r
1722 }\r
1723 //\r
1724 // Skip match varbss_init function, because they has no source code\r
1725 //\r
1726 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {\r
1727 continue;\r
1728 }\r
1729 //\r
1730 // check the name\r
1731 //\r
1732 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {\r
1733 continue;\r
1734 }\r
1735 //\r
1736 // found it, return source buffer\r
1737 //\r
1738 if (Object->Entry[EntryIndex].CodBuffer != NULL) {\r
1739 return Object->Entry[EntryIndex].SourceBuffer;\r
1740 }\r
1741 }\r
1742\r
1743 //\r
1744 // not found\r
1745 //\r
1746 return NULL;\r
1747}\r
1748\r
1749EFI_STATUS\r
1750EdbLoadCode (\r
1751 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
1752 IN CHAR16 *MapFileName,\r
1753 IN CHAR16 *FileName,\r
1754 IN UINTN BufferSize,\r
1755 IN VOID *Buffer\r
1756 )\r
1757/*++\r
1758\r
1759Routine Description:\r
1760\r
1761 Load code\r
1762\r
1763Arguments:\r
1764\r
1765 DebuggerPrivate - EBC Debugger private data structure\r
1766 MapFileName - Symbol file name\r
1767 FileName - Code file name\r
1768 BufferSize - Code file buffer size\r
1769 Buffer - Code file buffer\r
1770\r
1771Returns:\r
1772\r
1773 EFI_SUCCESS - Code loaded successfully\r
1774\r
1775--*/\r
1776{\r
1777 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
1778 UINTN ObjectIndex;\r
1779 UINTN EntryIndex;\r
1780 VOID *SourceBuffer;\r
1781 EFI_STATUS Status;\r
1782\r
1783 //\r
1784 // Find Symbol\r
1785 //\r
1786 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);\r
1787 if (Object == NULL) {\r
1788 EDBPrint (L"SymbolFile is not loaded!\n");\r
1789 return EFI_NOT_FOUND;\r
1790 } else {\r
1791 //\r
1792 // Check duplicated File\r
1793 //\r
1794 SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);\r
1795 if (SourceBuffer != NULL) {\r
1796 //\r
1797 // unnload duplicated code\r
1798 //\r
1799 Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);\r
1800 if (EFI_ERROR(Status)) {\r
1801 DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));\r
1802 return Status;\r
1803 }\r
1804 Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);\r
1805 if (EFI_ERROR(Status)) {\r
1806 DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));\r
1807 return Status;\r
1808 }\r
1809 }\r
1810 }\r
1811\r
1812 //\r
1813 // Go through each SymbolEntry\r
1814 //\r
1815 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {\r
1816 //\r
1817 // load symbol for function only\r
1818 //\r
1819 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&\r
1820 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {\r
1821 continue;\r
1822 }\r
1823 //\r
1824 // skip varbss_init\r
1825 //\r
1826 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {\r
1827 continue;\r
1828 }\r
1829 //\r
1830 // Check the name\r
1831 //\r
1832 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {\r
1833 continue;\r
1834 }\r
1835 //\r
1836 // load code for this symbol\r
1837 //\r
1838 Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (\r
1839 Object->Entry[EntryIndex].Name,\r
1840 Buffer,\r
1841 BufferSize,\r
1842 &Object->Entry[EntryIndex].CodBufferSize,\r
1843 &Object->Entry[EntryIndex].FuncOffsetBase\r
1844 );\r
1845 if (Object->Entry[EntryIndex].CodBuffer != NULL) {\r
1846 Object->Entry[EntryIndex].SourceBuffer = Buffer;\r
1847 }\r
1848 }\r
1849\r
1850 //\r
1851 // patch end '\0' for each code buffer\r
1852 //\r
1853 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {\r
1854 if (Object->Entry[EntryIndex].CodBuffer != NULL) {\r
1855 *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;\r
1856 DEBUG ((DEBUG_ERROR, " CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));\r
1857// DEBUG ((DEBUG_ERROR, " [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));\r
1858 }\r
1859 }\r
1860\r
1861 //\r
1862 // Done\r
1863 //\r
1864 return EFI_SUCCESS;\r
1865}\r
1866\r
1867EFI_STATUS\r
1868EdbUnloadCode (\r
1869 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
1870 IN CHAR16 *MapFileName,\r
1871 IN CHAR16 *FileName,\r
1872 OUT VOID **Buffer\r
1873 )\r
1874/*++\r
1875\r
1876Routine Description:\r
1877\r
1878 Unload code\r
1879\r
1880Arguments:\r
1881\r
1882 DebuggerPrivate - EBC Debugger private data structure\r
1883 MapFileName - Symbol file name\r
1884 FileName - Code file name\r
1885 Buffer - Code file buffer\r
1886\r
1887Returns:\r
1888\r
1889 EFI_SUCCESS - Code unloaded successfully\r
1890\r
1891--*/\r
1892{\r
1893 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
1894 UINTN ObjectIndex;\r
1895 UINTN EntryIndex;\r
1896\r
1897 //\r
1898 // Find Symbol\r
1899 //\r
1900 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);\r
1901 if (Object == NULL) {\r
1902 EDBPrint (L"SymbolFile is not loaded!\n");\r
1903 return EFI_NOT_FOUND;\r
1904 }\r
1905\r
1906 //\r
1907 // Find code\r
1908 //\r
1909 *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);\r
1910 if (*Buffer == NULL) {\r
1911 EDBPrint (L"CodeFile is not loaded!\n");\r
1912 return EFI_NOT_FOUND;\r
1913 }\r
1914\r
1915 //\r
1916 // go through each entry\r
1917 //\r
1918 for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {\r
1919 if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&\r
1920 (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {\r
1921 continue;\r
1922 }\r
1923 if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {\r
1924 continue;\r
1925 }\r
1926 if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {\r
1927 continue;\r
1928 }\r
1929 //\r
1930 // clean up the buffer\r
1931 //\r
1932 Object->Entry[EntryIndex].CodBuffer = NULL;\r
1933 Object->Entry[EntryIndex].CodBufferSize = 0;\r
1934 Object->Entry[EntryIndex].FuncOffsetBase = 0;\r
1935 Object->Entry[EntryIndex].SourceBuffer = NULL;\r
1936 }\r
1937\r
1938 //\r
1939 // Done\r
1940 //\r
1941 return EFI_SUCCESS;\r
1942}\r
1943\r
1944EFI_STATUS\r
1945EdbAddCodeBuffer (\r
1946 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
1947 IN CHAR16 *MapFileName,\r
1948 IN CHAR16 *CodeFileName,\r
1949 IN UINTN SourceBufferSize,\r
1950 IN VOID *SourceBuffer\r
1951 )\r
1952/*++\r
1953\r
1954Routine Description:\r
1955\r
1956 Add code buffer\r
1957\r
1958Arguments:\r
1959\r
1960 DebuggerPrivate - EBC Debugger private data structure\r
1961 MapFileName - Symbol file name\r
1962 CodeFileName - Code file name\r
1963 SourceBufferSize- Code buffer size\r
1964 SourceBuffer - Code buffer\r
1965\r
1966Returns:\r
1967\r
1968 EFI_SUCCESS - CodeBuffer added successfully\r
1969\r
1970--*/\r
1971{\r
1972 UINTN Index;\r
1973 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
1974\r
1975 //\r
1976 // Find Symbol\r
1977 //\r
1978 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);\r
1979 if (Object == NULL) {\r
1980 EDBPrint (L"SymbolFile is not loaded!\n");\r
1981 return EFI_NOT_FOUND;\r
1982 }\r
1983\r
1984 //\r
1985 // Add it to last entry\r
1986 //\r
1987 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {\r
1988 ;\r
1989 }\r
1990 Object->SourceBuffer[Index] = SourceBuffer;\r
1991\r
1992 return EFI_SUCCESS;\r
1993}\r
1994\r
1995EFI_STATUS\r
1996EdbDeleteCodeBuffer (\r
1997 IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,\r
1998 IN CHAR16 *MapFileName,\r
1999 IN CHAR16 *CodeFileName,\r
2000 IN VOID *SourceBuffer\r
2001 )\r
2002/*++\r
2003\r
2004Routine Description:\r
2005\r
2006 Delete code buffer\r
2007\r
2008Arguments:\r
2009\r
2010 DebuggerPrivate - EBC Debugger private data structure\r
2011 MapFileName - Symbol file name\r
2012 CodeFileName - Code file name\r
2013 SourceBuffer - Code buffer\r
2014\r
2015Returns:\r
2016\r
2017 EFI_SUCCESS - CodeBuffer deleted successfully\r
2018\r
2019--*/\r
2020{\r
2021 UINTN Index;\r
2022 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
2023\r
2024 //\r
2025 // Find Symbol\r
2026 //\r
2027 Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);\r
2028 if (Object == NULL) {\r
2029 EDBPrint (L"SymbolFile is not loaded!\n");\r
2030 return EFI_NOT_FOUND;\r
2031 }\r
2032\r
2033 for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {\r
2034 //\r
2035 // free the buffer if match\r
2036 //\r
2037 if (Object->SourceBuffer[Index] == SourceBuffer) {\r
2038 gBS->FreePool (SourceBuffer);\r
2039 break;\r
2040 }\r
2041 }\r
2042\r
2043 if (Object->SourceBuffer[Index] == NULL) {\r
2044 //\r
2045 // not return NOT_FOUND\r
2046 //\r
2047 return EFI_SUCCESS;\r
2048 }\r
2049\r
2050 //\r
2051 // remove the entry\r
2052 //\r
2053 Object->SourceBuffer[Index] = NULL;\r
2054 for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {\r
2055 Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];\r
2056 }\r
2057 Object->SourceBuffer[Index - 1] = NULL;\r
2058\r
2059 return EFI_SUCCESS;\r
2060}\r
2061\r
2062CHAR8 *\r
2063FindSymbolStr (\r
2064 IN UINTN Address\r
2065 )\r
2066/*++\r
2067\r
2068Routine Description:\r
2069\r
2070 Find the symbol string according to address\r
2071\r
2072Arguments:\r
2073\r
2074 Address - Symbol address\r
2075\r
2076Returns:\r
2077\r
2078 Symbol string\r
2079\r
2080--*/\r
2081{\r
2082 UINTN ObjectIndex;\r
2083 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
2084 UINTN EntryIndex;\r
2085 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;\r
2086\r
2087 //\r
2088 // need we display symbol\r
2089 //\r
2090 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {\r
2091 return NULL;\r
2092 }\r
2093\r
2094 //\r
2095 // Go through each object and entry\r
2096 //\r
2097 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;\r
2098 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {\r
2099 Entry = Object[ObjectIndex].Entry;\r
2100 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {\r
2101 //\r
2102 // if Address match, return Name\r
2103 //\r
2104 if (Address == (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress)) {\r
2105 return Entry[EntryIndex].Name;\r
2106 }\r
2107 }\r
2108 }\r
2109\r
2110 //\r
2111 // not found\r
2112 //\r
2113 return NULL;\r
2114}\r
2115\r
2116UINTN\r
2117EdbGetLineNumberAndOffsetFromThisLine (\r
2118 IN VOID *Line,\r
2119 OUT UINTN *Offset\r
2120 )\r
2121/*++\r
2122\r
2123Routine Description:\r
2124\r
2125 Get line number and offset from this line in code file\r
2126\r
2127Arguments:\r
2128\r
2129 Line - Line buffer in code file\r
2130 Offset - Offset to functin entry\r
2131\r
2132Returns:\r
2133\r
2134 Line number\r
2135\r
2136--*/\r
2137{\r
2138 UINTN LineNumber;\r
2139 CHAR8 *LineBuffer;\r
2140 CHAR8 *FieldBuffer;\r
2141\r
2142 LineNumber = (UINTN)-1;\r
2143 LineBuffer = Line;\r
2144 *Offset = (UINTN)-1;\r
2145\r
2146 while (LineBuffer != NULL) {\r
2147 //\r
2148 // Check candidate\r
2149 //\r
2150 if (*LineBuffer != ' ') {\r
2151 return (UINTN)-1;\r
2152 }\r
2153\r
2154 //\r
2155 // Get Offset\r
2156 //\r
2157 if (*(LineBuffer + 2) != ' ') {\r
2158 if (*Offset == (UINTN)-1) {\r
2159 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");\r
2160 *Offset = AsciiXtoi (FieldBuffer);\r
2161 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');\r
2162 }\r
2163 }\r
2164\r
2165 //\r
2166 // 1. assembly instruction\r
2167 //\r
2168 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");\r
2169 //\r
2170 // 2. file path\r
2171 //\r
2172 FieldBuffer = AsciiStrGetNextTokenField (":");\r
2173 PatchForAsciiStrTokenBefore (FieldBuffer, ':');\r
2174 if (FieldBuffer == NULL) {\r
2175 //\r
2176 // candidate found\r
2177 //\r
2178 LineNumber = 0;\r
2179 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2180 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2181 continue;\r
2182 }\r
2183 //\r
2184 // 3. line number\r
2185 //\r
2186 FieldBuffer = AsciiStrGetNextTokenField (":");\r
2187 PatchForAsciiStrTokenBefore (FieldBuffer, ':');\r
2188 if (FieldBuffer == NULL) {\r
2189 //\r
2190 // impossible, TBD?\r
2191 //\r
2192 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2193 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2194 continue;\r
2195 }\r
2196\r
2197 LineNumber = AsciiAtoi (FieldBuffer);\r
2198 //\r
2199 // Not patch after\r
2200 //\r
2201\r
2202 return LineNumber;\r
2203 }\r
2204\r
2205 return (UINTN)-1;\r
2206}\r
2207\r
2208typedef enum {\r
2209 EdbEbcLineSearchTypeAny,\r
2210 EdbEbcLineSearchTypeFirst,\r
2211 EdbEbcLineSearchTypeLast,\r
2212 EdbEbcLineSearchTypeMax,\r
2213} EDB_EBC_LINE_SEARCH_TYPE;\r
2214\r
2215UINTN\r
2216EdbGetLineNumberFromCode (\r
2217 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,\r
2218 IN UINTN FuncOffset,\r
2219 IN EDB_EBC_LINE_SEARCH_TYPE SearchType\r
2220 )\r
2221/*++\r
2222\r
2223Routine Description:\r
2224\r
2225 Get line number from this code file\r
2226\r
2227Arguments:\r
2228\r
2229 Entry - Symbol entry\r
2230 FuncOffset - Offset to functin entry\r
2231 SearchType - Search type for the code\r
2232\r
2233Returns:\r
2234\r
2235 Line number\r
2236\r
2237--*/\r
2238{\r
2239 CHAR8 *LineBuffer;\r
2240 UINTN LineNumber;\r
2241 UINTN Offset;\r
2242 UINTN CandidateLineNumber;\r
2243 UINTN CandidateOffset;\r
2244\r
2245 if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {\r
2246 return (UINTN)-1;\r
2247 }\r
2248\r
2249 LineNumber = (UINTN)-1;\r
2250 CandidateLineNumber = (UINTN)-1;\r
2251 CandidateOffset = (UINTN)-1;\r
2252 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");\r
2253 while (LineBuffer != NULL) {\r
2254 if (*LineBuffer != ' ') {\r
2255 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2256 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2257 continue;\r
2258 }\r
2259\r
2260 //\r
2261 // Get Info\r
2262 //\r
2263 LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);\r
2264\r
2265 //\r
2266 // Check offset\r
2267 //\r
2268 if (Offset != FuncOffset) {\r
2269 //\r
2270 // Check last offset match\r
2271 //\r
2272 if (CandidateOffset == FuncOffset) {\r
2273 if (SearchType == EdbEbcLineSearchTypeLast) {\r
2274 PatchForAsciiStrTokenAfter (LineBuffer, '\n');\r
2275 if (CandidateLineNumber != LineNumber) {\r
2276 return CandidateLineNumber;\r
2277 } else {\r
2278 return (UINTN)-1;\r
2279 }\r
2280 } else {\r
2281 //\r
2282 // impossible, TBD?\r
2283 //\r
2284 }\r
2285 }\r
2286\r
2287 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2288 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2289 CandidateLineNumber = LineNumber;\r
2290 continue;\r
2291 }\r
2292\r
2293 //\r
2294 // Offset match, more check\r
2295 //\r
2296 if (SearchType == EdbEbcLineSearchTypeAny) {\r
2297 PatchForAsciiStrTokenAfter (LineBuffer, '\n');\r
2298 return LineNumber;\r
2299 }\r
2300\r
2301 if (SearchType == EdbEbcLineSearchTypeFirst) {\r
2302 //\r
2303 // Check last line\r
2304 //\r
2305 PatchForAsciiStrTokenAfter (LineBuffer, '\n');\r
2306 if (CandidateLineNumber != LineNumber) {\r
2307 return LineNumber;\r
2308 } else {\r
2309 return (UINTN)-1;\r
2310 }\r
2311 }\r
2312\r
2313 CandidateLineNumber = LineNumber;\r
2314 CandidateOffset = Offset;\r
2315\r
2316 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2317 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2318 }\r
2319\r
2320 //\r
2321 // Check last offset match\r
2322 //\r
2323 if (CandidateOffset == FuncOffset) {\r
2324 if (SearchType == EdbEbcLineSearchTypeLast) {\r
2325 return CandidateLineNumber;\r
2326 }\r
2327 }\r
2328\r
2329 return (UINTN)-1;\r
2330}\r
2331\r
2332VOID *\r
2333EdbGetSourceStrFromCodeByLine (\r
2334 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,\r
2335 IN UINTN LineNumber,\r
2336 IN VOID **FuncEnd\r
2337 )\r
2338/*++\r
2339\r
2340Routine Description:\r
2341\r
2342 Get the source string from this code file by line\r
2343\r
2344Arguments:\r
2345\r
2346 Entry - Symbol entry\r
2347 LineNumber - line number\r
2348 FuncEnd - Function end\r
2349\r
2350Returns:\r
2351\r
2352 Funtion start\r
2353\r
2354--*/\r
2355{\r
2356 CHAR8 *LineBuffer;\r
2357 CHAR8 *FieldBuffer;\r
2358 VOID *FuncStart;\r
2359 UINTN Number;\r
2360\r
2361 FuncStart = NULL;\r
2362 LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");\r
2363 while (LineBuffer != NULL) {\r
2364 if (*LineBuffer != ';') {\r
2365 if (FuncStart != NULL) {\r
2366 //\r
2367 // Over\r
2368 //\r
2369 *FuncEnd = LineBuffer - 1;\r
2370 PatchForAsciiStrTokenAfter (LineBuffer, '\n');\r
2371 return FuncStart;\r
2372 }\r
2373 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2374 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2375 continue;\r
2376 }\r
2377\r
2378 //\r
2379 // Check LineNumber\r
2380 //\r
2381 FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");\r
2382 Number = AsciiAtoi (FieldBuffer);\r
2383 PatchForAsciiStrTokenAfter (FieldBuffer, ' ');\r
2384 if (Number != LineNumber) {\r
2385 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2386 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2387 continue;\r
2388 }\r
2389\r
2390 //\r
2391 // Line match, get line number\r
2392 //\r
2393 if (FuncStart == NULL) {\r
2394 FuncStart = LineBuffer;\r
2395 }\r
2396\r
2397 LineBuffer = AsciiStrGetNextTokenLine ("\n");\r
2398 PatchForAsciiStrTokenBefore (LineBuffer, '\n');\r
2399 }\r
2400\r
2401 return NULL;\r
2402}\r
2403\r
2404VOID *\r
2405EdbGetSourceStrFromCode (\r
2406 IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,\r
2407 IN UINTN FuncOffset,\r
2408 IN VOID **FuncEnd\r
2409 )\r
2410/*++\r
2411\r
2412Routine Description:\r
2413\r
2414 Get source string from this code file\r
2415\r
2416Arguments:\r
2417\r
2418 Entry - Symbol entry\r
2419 FuncOffset - Offset to functin entry\r
2420 FuncEnd - Function end\r
2421\r
2422Returns:\r
2423\r
2424 Funtion start\r
2425\r
2426--*/\r
2427{\r
2428 UINTN LineNumber;\r
2429\r
2430 //\r
2431 // Only search the last line, then display\r
2432 //\r
2433 LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);\r
2434 if (LineNumber == (UINTN)-1) {\r
2435 return NULL;\r
2436 }\r
2437\r
2438 return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);\r
2439}\r
2440\r
2441UINTN\r
2442EdbPrintSource (\r
2443 IN UINTN Address,\r
2444 IN BOOLEAN IsPrint\r
2445 )\r
2446/*++\r
2447\r
2448Routine Description:\r
2449\r
2450 Print source\r
2451\r
2452Arguments:\r
2453\r
2454 Address - Instruction address\r
2455 IsPrint - Whether need to print\r
2456\r
2457Returns:\r
2458\r
2459 1 - find the source\r
2460 0 - not find the source\r
2461\r
2462--*/\r
2463{\r
2464 UINTN SymbolAddress;\r
2465 EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;\r
2466 EFI_DEBUGGER_SYMBOL_ENTRY *RetEntry;\r
2467 UINTN FuncOffset;\r
2468 UINT8 *FuncStart;\r
2469 UINT8 *FuncEnd;\r
2470 UINT8 *FuncIndex;\r
2471 CHAR8 Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];\r
2472 UINTN BufferSize;\r
2473\r
2474 //\r
2475 // need we display symbol\r
2476 //\r
2477 if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {\r
2478 return 0 ;\r
2479 }\r
2480\r
2481 //\r
2482 // find the symbol address\r
2483 //\r
2484 SymbolAddress = EbdFindSymbolAddress (\r
2485 Address,\r
2486 EdbMatchSymbolTypeLowerAddress,\r
2487 &RetObject,\r
2488 &RetEntry\r
2489 );\r
2490 if (SymbolAddress == 0) {\r
2491 return 0 ;\r
2492 }\r
2493\r
2494 FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;\r
2495\r
2496 //\r
2497 // Get Func String\r
2498 //\r
2499 FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);\r
2500 if (FuncStart == NULL) {\r
2501 return 0 ;\r
2502 }\r
2503\r
2504 //\r
2505 // check whether need to real print\r
2506 //\r
2507 if (!IsPrint) {\r
2508 return 1;\r
2509 }\r
2510\r
2511 *(UINT8 *)FuncEnd = 0;\r
2512\r
2513 //\r
2514 // seperate buffer by \n, so that \r can be added.\r
2515 //\r
2516 FuncIndex = FuncStart;\r
2517 while (*FuncIndex != 0) {\r
2518 if (*FuncIndex == '\n') {\r
2519 if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {\r
2520 BufferSize = FuncIndex - FuncStart;\r
2521 } else {\r
2522 BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;\r
2523 }\r
2524 if (BufferSize != 0) {\r
2525 CopyMem (Buffer, FuncStart, BufferSize);\r
2526 }\r
2527 Buffer[BufferSize] = 0;\r
2528 EDBPrint (L"%a\n", Buffer);\r
2529 FuncStart = FuncIndex + 1;\r
2530 FuncIndex = FuncStart;\r
2531 } else {\r
2532 FuncIndex ++;\r
2533 }\r
2534 }\r
2535\r
2536 //\r
2537 // Patch the end\r
2538 //\r
2539 *(UINT8 *)FuncEnd = '\n';\r
2540\r
2541 return 1 ;\r
2542}\r
2543\r
2544VOID\r
2545GetMapfileAndSymbol (\r
2546 IN CHAR16 *Symbol,\r
2547 OUT CHAR16 **MapfileName,\r
2548 OUT CHAR16 **SymbolName\r
2549 )\r
2550/*++\r
2551\r
2552Routine Description:\r
2553\r
2554 Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName\r
2555\r
2556Arguments:\r
2557\r
2558 Symbol - whole Symbol name\r
2559 MapfileName - the mapfile name in the symbol\r
2560 SymbolName - the symbol name in the symbol\r
2561\r
2562Returns:\r
2563\r
2564 None\r
2565\r
2566--*/\r
2567{\r
2568 CHAR16 *Ch;\r
2569\r
2570 *MapfileName = NULL;\r
2571 *SymbolName = Symbol;\r
2572\r
2573 for (Ch = Symbol; *Ch != 0; Ch++) {\r
2574 //\r
2575 // Find split char\r
2576 //\r
2577 if (*Ch == L':') {\r
2578 *MapfileName = Symbol;\r
2579 *Ch = 0;\r
2580 *SymbolName = Ch + 1;\r
2581 break;\r
2582 }\r
2583 }\r
2584\r
2585 return ;\r
2586}\r
2587\r
2588EFI_STATUS\r
2589Symboltoi (\r
2590 IN CHAR16 *Symbol,\r
2591 OUT UINTN *Address\r
2592 )\r
2593/*++\r
2594\r
2595Routine Description:\r
2596\r
2597 Convert a symbol to an address\r
2598\r
2599Arguments:\r
2600\r
2601 Symbol - Symbol name\r
2602 Address - Symbol address\r
2603\r
2604Returns:\r
2605\r
2606 EFI_SUCCESS - symbol found and address returned.\r
2607 EFI_NOT_FOUND - symbol not found\r
2608 EFI_NO_MAPPING - duplicated symbol not found\r
2609\r
2610--*/\r
2611{\r
2612 UINTN ObjectIndex;\r
2613 EFI_DEBUGGER_SYMBOL_OBJECT *Object;\r
2614 UINTN EntryIndex;\r
2615 EFI_DEBUGGER_SYMBOL_ENTRY *Entry;\r
2616 CHAR16 *SymbolName;\r
2617 CHAR16 *MapfileName;\r
2618\r
2619 //\r
2620 // Split one symbol to mapfile name and symbol name\r
2621 //\r
2622 GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);\r
2623\r
2624 *Address = 0;\r
2625 //\r
2626 // Go through each object\r
2627 //\r
2628 Object = mDebuggerPrivate.DebuggerSymbolContext.Object;\r
2629 for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {\r
2630 //\r
2631 // Check MapfileName\r
2632 //\r
2633 if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {\r
2634 continue;\r
2635 }\r
2636 //\r
2637 // Go through each entry\r
2638 //\r
2639 Entry = Object[ObjectIndex].Entry;\r
2640 for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {\r
2641 //\r
2642 // Check SymbolName (case sensitive)\r
2643 //\r
2644 if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {\r
2645 if ((*Address != 0) && (MapfileName == NULL)) {\r
2646 //\r
2647 // Find the duplicated symbol\r
2648 //\r
2649 EDBPrint (L"Duplicated Symbol found!\n");\r
2650 return EFI_NO_MAPPING;\r
2651 } else {\r
2652 //\r
2653 // record Address\r
2654 //\r
2655 *Address = (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress);\r
2656 }\r
2657 }\r
2658 }\r
2659 }\r
2660\r
2661 if (*Address == 0) {\r
2662 //\r
2663 // Not found\r
2664 //\r
2665 return EFI_NOT_FOUND;\r
2666 }\r
2667\r
2668 return EFI_SUCCESS;\r
2669}\r