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