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