@@ -341,6 +341,18 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
341341 LineLogger.Error(Reader.LineNumber, ' Invalid integer number: "%s"' , [Copy(s, Offset+1 , MaxInt)]);
342342 end ;
343343
344+ function RequiredPos (const SubStr, Str: string; Offset: integer; const ErrorMsg: string): integer; overload;
345+ begin
346+ Result := Pos(SubStr, Str, Offset);
347+ if (Result = 0 ) then
348+ LineLogger.Error(Reader.LineNumber, ErrorMsg+#13 #10 +Reader.LineBuffer);
349+ end ;
350+
351+ function RequiredPos (const SubStr: string; Offset: integer; const ErrorMsg: string): integer; overload;
352+ begin
353+ Result := RequiredPos(SubStr, Reader.LineBuffer, Offset, ErrorMsg);
354+ end ;
355+
344356begin
345357 Logger.Info(' Reading MAP file' );
346358
@@ -362,22 +374,32 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
362374
363375 var LegacyMapFile := False;
364376
377+ // Delphi:
365378 // " 0001:00401000 000F47FCH .text CODE"
379+ // " 0001:0000000000301000 001FD57CH .text CODE"
380+ //
381+ // C++ Builder:
382+ // " 0001:00401000 000212EF0H _TEXT CODE"
366383 while (not Reader.CurrentLine.IsEmpty) do
367384 begin
368385 var n: integer := 0 ;
369386 var SegmentID: Cardinal := DecToInt32(Reader.LineBuffer, n);
370387
371- n := Pos (' :' , Reader.LineBuffer, n+1 );
388+ n := RequiredPos (' :' , n+1 , ' Missing address/segment separator ' );
372389 var Offset: TDebugInfoOffset := HexToInt64(Reader.LineBuffer, n);
373390
374- n := Pos (' ' , Reader.LineBuffer, n+1 );
391+ n := RequiredPos (' ' , n+1 , ' Missing address/segment delimiter ' );
375392 var Size: TDebugInfoOffset := HexToInt32(Reader.LineBuffer, n);
376393
377- n := Pos(' .' , Reader.LineBuffer, n+1 );
378- var n2 := Pos(' ' , Reader.LineBuffer, n+1 );
379- var Name := Copy(Reader.LineBuffer, n, n2-n);
380- if (Name .IsEmpty) then
394+ var n2 := Pos(' .' , Reader.LineBuffer, n+1 );
395+ if (n2 = 0 ) then
396+ n2 := Pos(' _' , Reader.LineBuffer, n+1 );
397+ if (n2 = 0 ) then
398+ LineLogger.Error(Reader.LineNumber, ' Missing segment name' #13 #10 ' %s' , [Reader.LineBuffer]);
399+ n := n2;
400+ n2 := RequiredPos(' ' , n+1 , ' Missing segment delimiter' );
401+ var SegmentName := Copy(Reader.LineBuffer, n, n2-n);
402+ if (SegmentName.IsEmpty) then
381403 LineLogger.Error(Reader.LineNumber, ' Invalid segment name' #13 #10 ' %s' , [Reader.LineBuffer]);
382404
383405 var ClassName := Copy(Reader.LineBuffer, n2+1 , MaxInt).Trim;
@@ -398,29 +420,29 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
398420 if (ConflictingSegment <> nil ) then
399421 begin
400422 LineLogger.Warning(Reader.LineNumber, ' Overlapping segments: %s [%.4X:%.16X] and %s [%.4X:%.16X]' ,
401- [Name , SegmentID, Offset, ConflictingSegment.Name , ConflictingSegment.Index, ConflictingSegment.Offset]);
423+ [SegmentName , SegmentID, Offset, ConflictingSegment.Name , ConflictingSegment.Index, ConflictingSegment.Offset]);
402424 // Calculate a bogus offset so we can get on with it
403425 for var Segment in DebugInfo.Segments do
404426 Offset := Max(Offset, Segment .Offset + Segment .Size);
405427 // Align to $1000
406428 Offset := (Offset + $0FFF) and (not $0FFF);
407- LineLogger.Warning(Reader.LineNumber, ' Calculated segment offset assigned: %s [%.4X:%.16X]' , [Name , SegmentID, Offset]);
429+ LineLogger.Warning(Reader.LineNumber, ' Calculated segment offset assigned: %s [%.4X:%.16X]' , [SegmentName , SegmentID, Offset]);
408430 end ;
409431
410432 ConflictingSegment := DebugInfo.Segments.FindByIndex(SegmentID);
411433 if (ConflictingSegment <> nil ) then
412434 begin
413435 LineLogger.Warning(Reader.LineNumber, ' Duplicate segment index: %s [%.4X:%.16X] and %s [%.4X:%.16X]' ,
414- [Name , SegmentID, Offset, ConflictingSegment.Name , ConflictingSegment.Index, ConflictingSegment.Offset]);
436+ [SegmentName , SegmentID, Offset, ConflictingSegment.Name , ConflictingSegment.Index, ConflictingSegment.Offset]);
415437 // Calculate a bogus index
416438 for var Segment in DebugInfo.Segments do
417439 SegmentID := Max(SegmentID, Segment .Index+1 );
418- LineLogger.Warning(Reader.LineNumber, ' Calculated segment index assigned: %s [%.4X:%.16X]' , [Name , SegmentID, Offset]);
440+ LineLogger.Warning(Reader.LineNumber, ' Calculated segment index assigned: %s [%.4X:%.16X]' , [SegmentName , SegmentID, Offset]);
419441 end ;
420442 end ;
421443
422444 var SegmentClass := TDebugInfoSegment.GuessClassType(ClassName);
423- var Segment := DebugInfo.Segments.Add(SegmentID, Name , SegmentClass);
445+ var Segment := DebugInfo.Segments.Add(SegmentID, SegmentName , SegmentClass);
424446
425447 Segment .Offset := Offset;
426448 Segment .Size := Size;
@@ -433,7 +455,7 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
433455 // "0005:00000000 OtlCommon.Utils.LastThreadName"
434456 // "0005:00000100 SysInit.TlsLast"
435457 if (Size = 0 ) then
436- LineLogger.Warning(Reader.LineNumber, ' Empty segment: %s [%.4d:%.16X]' , [Name , SegmentID, Segment .Offset]);
458+ LineLogger.Warning(Reader.LineNumber, ' Empty segment: %s [%.4d:%.16X]' , [SegmentName , SegmentID, Segment .Offset]);
437459
438460 // Check for non-fatal overlapping segments (specifically .tls):
439461 // "0001:0000000000401000 006CD7B8H .text CODE"
@@ -462,25 +484,65 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
462484 if (Reader.NextLine(True).IsEmpty) then
463485 Exit;
464486
487+ // Delphi:
465488 // " 0001:00000000 0000F684 C=CODE S=.text G=(none) M=System ACBP=A9"
489+ // " 0001:00000000 0001640C C=CODE S=.text G=(none) M=System ALIGN=4"
490+ //
491+ // C++ Builder:
492+ // " 0001:000035F4 0000014D C=CODE S=_TEXT G=(none) M=C:\PROGRAM FILES (X86)\EMBARCADERO\STUDIO\23.0\LIB\WIN32C\DEBUG\C0W32W.OBJ ACBP=A9"
493+ // " 0001:00003741 00000713 C=CODE S=_TEXT G=(none) M=C:\PROGRAM FILES (X86)\EMBARCADERO\STUDIO\23.0\LIB\WIN32\DEBUG\RTL.BPI|Winapi.Windows.pas ACBP=A9"
466494 while (not Reader.CurrentLine.IsEmpty) do
467495 begin
468- var n := Pos(' C=' , Reader.LineBuffer);
469- var ClassName := Copy(Reader.LineBuffer, n+2 , Pos(' ' , Reader.LineBuffer, n+2 )-n-2 );
496+ var n := RequiredPos(' C=' , 1 , ' Missing class name marker' );
497+ var n2 := RequiredPos(' ' , n+2 , ' Missing segment type separator' );
498+ var ClassName := Copy(Reader.LineBuffer, n+2 , n2-n-2 );
470499 var Address := Copy(Reader.LineBuffer, 1 , n-1 );
471500
472- n := Pos(' M=' , Reader.LineBuffer);
473- var Name := Copy(Reader.LineBuffer, n+2 , Pos(' ' , Reader.LineBuffer, n+2 )-n-2 );
501+ n := RequiredPos(' M=' , n+3 , ' Missing module name marker' );
502+ var StartOfName := n+2 ;
503+ // Find last ' ALIGN=' on line
504+ n2 := StartOfName;
505+ var EndOfName: integer;
506+ repeat
507+ EndOfName := n2;
508+ n2 := Pos(' ALIGN=' , Reader.LineBuffer, n2+1 );
509+ until (n2 = 0 );
510+ // No "ALIGN"? Find last ' ACBP' on line instead
511+ if (EndOfName = StartOfName) then
512+ begin
513+ n2 := StartOfName;
514+ repeat
515+ EndOfName := n2;
516+ n2 := Pos(' ACBP=' , Reader.LineBuffer, n2+1 );
517+ until (n2 = 0 );
518+ end ;
519+ if (EndOfName = StartOfName) then
520+ LineLogger.Error(Reader.LineNumber, ' Missing module ALIGN/ACBP marker' #13 #10 ' %s' , [Reader.LineBuffer]);
521+
522+ // Trim trailing space
523+ while (EndOfName > StartOfName) and (Reader.LineBuffer[EndOfName] = ' ' ) do
524+ Dec(EndOfName);
525+ // Trim leading path
526+ n2 := EndOfName;
527+ n := StartOfName;
528+ while (n2 >= StartOfName) and (not CharInSet(Reader.LineBuffer[n2], [' \' , ' /' , ' |' ])) do
529+ begin
530+ n := n2;
531+ Dec(n2);
532+ end ;
533+ StartOfName := n;
534+
535+ var Name := Copy(Reader.LineBuffer, StartOfName, EndOfName-StartOfName+1 );
474536 if (Name .IsEmpty) then
475537 LineLogger.Error(Reader.LineNumber, ' Invalid module name' #13 #10 ' %s' , [Reader.LineBuffer]);
476538
477539 n := 0 ;
478540 var SegmentID: Cardinal := DecToInt32(Address, n);
479541
480- n := Pos (' :' , Address, n+1 );
542+ n := RequiredPos (' :' , Address, n+1 , ' Malformed module address ' );
481543 var Offset: TDebugInfoOffset := HexToInt64(Address, n);
482544
483- n := Pos (' ' , Address, n+1 );
545+ n := RequiredPos (' ' , Address, n+1 , ' Missing module size separator ' );
484546 var Size: TDebugInfoOffset := HexToInt32(Address, n);
485547 if (Size = 0 ) then
486548 LineLogger.Error(Reader.LineNumber, ' Invalid module size' #13 #10 ' %s' , [Reader.LineBuffer]);
@@ -498,14 +560,15 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
498560
499561 // Look for existing module
500562 var Module := DebugInfo.Modules.FindOverlap(Segment , Offset, Size);
501- if (Module <> nil ) then
502- LineLogger.Error(Reader.LineNumber, ' Modules overlap: %s, %s' #13 #10 ' %s' , [Module .Name , Name , Reader.LineBuffer]);
503-
504- // Add new module
505- if (Offset + Size <= Segment .Size) then
506- DebugInfo.Modules.Add(Name , Segment , Offset, Size)
507- else
508- LineLogger.Warning(Reader.LineNumber, ' Module exceed segment bounds - ignored: %s [%.4d:%.16X+%d]' , [Name , SegmentID, Offset, Size]);
563+ if (Module = nil ) then
564+ begin
565+ // Add new module
566+ if (Offset + Size <= Segment .Size) then
567+ DebugInfo.Modules.Add(Name , Segment , Offset, Size)
568+ else
569+ LineLogger.Warning(Reader.LineNumber, ' Module exceed segment bounds - ignored: %s [%.4d:%.16X+%d]' , [Name , SegmentID, Offset, Size]);
570+ end else
571+ LineLogger.Warning(Reader.LineNumber, ' Modules overlap: %s, %s' #13 #10 ' %s' , [Module .Name , Name , Reader.LineBuffer]);
509572
510573 Reader.NextLine;
511574 end ;
@@ -610,19 +673,13 @@ procedure TDebugInfoMapReader.LoadFromStream(Stream: TStream; DebugInfo: TDebugI
610673 if (not Reader.HasData) then
611674 break;
612675
613- var n := Pos(' (' , Reader.LineBuffer);
614- if (n = 0 ) then
615- LineLogger.Error(Reader.LineNumber, ' Source file start marker "(" not found' #13 #10 ' %s' , [Reader.LineBuffer]);
676+ var n := RequiredPos(' (' , 1 , ' Source file start marker "(" not found' );
616677 var ModuleName := Copy(Reader.LineBuffer, Length(sPrefix)+1 , n-1 -Length(sPrefix));
617678
618- var n2 := Pos(' )' , Reader.LineBuffer, n+1 );
619- if (n2 = 0 ) then
620- LineLogger.Error(Reader.LineNumber, ' Source file end marker ")" not found' #13 #10 ' %s' , [Reader.LineBuffer]);
679+ var n2 := RequiredPos(' )' , n+1 , ' Source file end marker ")" not found' );
621680 var Filename := Copy(Reader.LineBuffer, n+1 , n2-n-1 );
622681
623- n := Pos(' segment' , Reader.LineBuffer, n2+1 );
624- if (n = 0 ) then
625- LineLogger.Error(Reader.LineNumber, ' Source file segment marker "segment" not found' #13 #10 ' %s' , [Reader.LineBuffer]);
682+ n := RequiredPos(' segment' , n2+1 , ' Source file segment marker "segment" not found' );
626683 Inc(n, 7 );
627684 while (Reader.LineBuffer[n] = ' ' ) do
628685 Inc(n);
0 commit comments