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