Recent

Author Topic: Display of bitpacked arrays in the debugger  (Read 3686 times)

440bx

  • Hero Member
  • *****
  • Posts: 4015
Display of bitpacked arrays in the debugger
« on: June 04, 2021, 12:12:43 pm »
Hello,

What the debugger shows for a bitpacked array of boolean isn't what I'm expecting and, I'm wondering if I am missing/misinterpreting something.

The debugger's DRIVEMAP shows true(205), false, false, true(2), true(2), etc.

I cannot figure out what the "205" and the "2"s mean.

Also, I expected the DRIVEMAP to show: true, false, true, true... etc (see the black screenshot output)
but the debugger shows an extra "false" between the first two instances of true. 

Am I missing something or is there something wrong in what is displayed by the debugger ?

The program that produces those results is : (hover over the "ProcessDeviceMapData" parameter after the call to the Nt... function - parameter line is highlighted.)
Code: Pascal  [Select][+][-]
  1. {$APPTYPE      CONSOLE}
  2.  
  3. {$TYPEDADDRESS ON}
  4.  
  5. program _QueryInformationProcess;
  6.  
  7.  
  8. uses
  9.   Windows,
  10.   sysutils
  11.   ;
  12.  
  13. {$ifdef VER90}
  14. type
  15.   DWORD = longint;
  16.   PDWORD = ^DWORD;
  17. {$endif}
  18.  
  19. type
  20.   NTSTATUS = DWORD;
  21.  
  22.  
  23. const
  24.    { 17   23 } ProcessDeviceMap = 23;  { PROCESS_DEVICEMAP_INFORMATION        }
  25.                                        { PROCESS_DEVICEMAP_INFORMATION_EX     }
  26.  
  27.   ntdll = 'ntdll';
  28.  
  29.   PROCESS_ALL_ACCESS        = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $FFFF;
  30.  
  31.   STATUS_SUCCESS            = 0;
  32.  
  33.  
  34. function NtQueryInformationProcess(ProcessHandle            : THANDLE;
  35.                                    ProcessInformationClass  : DWORD;
  36.                                    ProcessInformation       : pointer;
  37.                                    ProcessInformationLength : DWORD;
  38.                                    ReturnLength             : PDWORD)
  39.          : NTSTATUS; stdcall; external ntdll;
  40.  
  41.  
  42. function IsDebuggerPresent {$ifdef FPC} () {$endif}
  43.        : BOOL; stdcall external kernel32;
  44.  
  45.  
  46. function _itoa
  47.              (
  48.               { _in_  } In32bitInteger  : integer;
  49.               { _out_ } OutAsciizString : pchar;
  50.               { _in_  } InRadix         : DWORD
  51.              )
  52.          : pchar; cdecl external ntdll;                            { !! CDECL }
  53.  
  54.  
  55. type
  56.   { _PROCESS_DEVICEMAP_INFORMATION                                            }
  57.  
  58.   PPROCESS_DEVICEMAP_INFORMATION = ^TPROCESS_DEVICEMAP_INFORMATION;
  59.   TPROCESS_DEVICEMAP_INFORMATION = record
  60.     case integer of
  61.       {$ifdef WIN64}
  62.       0 : (
  63.            { record size must be a multiple of 16 in 64bit                    }
  64.  
  65.            ForceSize                 : packed array[0..5] of pointer;
  66.           );
  67.       {$endif}
  68.  
  69.       1 : (
  70.            SetMap                    : record
  71.              DirectoryHandle             : THANDLE;
  72.            end;
  73.           );
  74.  
  75.       2 : (
  76.            QueryMap                  : record
  77.              DriveMap                    : DWORD;
  78.              DriveType                   : packed array[0..31] of byte;
  79.            end;
  80.           );
  81.       {$ifdef FPC}
  82.       3 : (
  83.            BitMap                    : record
  84.              DriveMap                    : bitpacked array[0..31] of boolean;
  85.              DriveType                   : packed array[0..31]    of byte;
  86.            end;
  87.           );
  88.       {$endif}
  89.   end;
  90.  
  91. var
  92.   ProcessHandle                   : THANDLE;
  93.  
  94.   ProcessDeviceMapData            : TPROCESS_DEVICEMAP_INFORMATION;
  95.  
  96.  
  97.   BufferSize    : DWORD;
  98.  
  99.   ReturnLength  : DWORD;
  100.  
  101.   Status        : NTSTATUS;
  102.  
  103.  
  104.   itoa_buf      : packed array[0..127] of char;
  105.  
  106.  
  107. begin
  108.   writeln;
  109.  
  110.   // since we are dealing with our own process we can specify PROCESS_ALL_ACCESS
  111.  
  112.   ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS,
  113.                                FALSE,
  114.                                GetCurrentProcessId());
  115.  
  116.   if ProcessHandle = 0 then Halt(1);
  117.  
  118.     writeln;
  119.     writeln;
  120.     writeln('  ProcessDeviceMap : ', ord(ProcessDeviceMap), ' (d) ',
  121.                IntToHex(ord(ProcessDeviceMap), 0), ' (h)');
  122.  
  123.     BufferSize   := sizeof(ProcessDeviceMapData);
  124.     ReturnLength := 0;
  125.  
  126.     writeln;
  127.     writeln;
  128.     writeln('  Buffer size : ', BufferSize);
  129.  
  130.     ZeroMemory(@ProcessDeviceMapData, sizeof(ProcessDeviceMapData));
  131.  
  132.     if IsDebuggerPresent then DebugBreak();
  133.     Status := NtQueryInformationProcess(ProcessHandle,
  134.                                         ProcessDeviceMap,
  135.                                        @ProcessDeviceMapData,
  136.                                         BufferSize,
  137.                                        @ReturnLength);
  138.  
  139.     if IsDebuggerPresent then DebugBreak();
  140.     if Status <> STATUS_SUCCESS then
  141.     begin
  142.       writeln;
  143.       writeln;
  144.       writeln('  NtQueryInformationProcess failed.  NTSTATUS : ',
  145.                  IntToHex(Status, 0));
  146.     end;
  147.  
  148.  
  149.     writeln;
  150.     writeln;
  151.  
  152.     writeln('  ', _itoa(ProcessDeviceMapData.QueryMap.DriveMap, itoa_buf, 2));
  153.     writeln;
  154.     writeln('  returned length : ', ReturnLength);
  155.  
  156.   writeln;
  157.   writeln('Press <enter>/<result> to end this program.');
  158.   readln;
  159. end.
  160.  

Thank you for your help.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9857
  • Debugger - SynEdit - and more
    • wiki
Re: Display of bitpacked arrays in the debugger
« Reply #1 on: June 04, 2021, 12:26:30 pm »
Which Debugger?

Last time I tested, GDB had issues with packed data. That needs to be fixed in gdb (not yet tested gdb 10, but that has other issues)

FpDebug: not sure about 2.0.x
But in trunk it works.  Though for the hint, it shortens the embedded arrays.
Code: [Select]
ForceSize: ($03030300020227DE, $0005020202020003, $0000030000000300, $0000030000000000, nil, nil)
SetMap: {record} (217020505612494814)
QueryMap: {record} (33695710;
 (0, 3, 3, {29 more elements}))
BitMap: {record} ((False, True, True, {29 more elements});
 (0, 3, 3, {29 more elements}))

A watch on ProcessDeviceMapData.BitMap
Code: [Select]
DriveMap: (False, True, True, True, True, False, True, True, True, True, {22 more elements})
DriveType: (0, 3, 3, 3, 3, 0, 2, 2, 2, 2, {22 more elements})

And if you enter ProcessDeviceMapData.BitMap.DriveMap you see the data.

You can open ProcessDeviceMapData in "inspect dialog" (afaik Alt F5), then click through the path, and (in latest trunk) hit the "add watch" button.


---
I did recently notice that packed sets do not yet work in FpDebug.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9857
  • Debugger - SynEdit - and more
    • wiki
Re: Display of bitpacked arrays in the debugger
« Reply #2 on: June 04, 2021, 12:30:53 pm »
Note that it may not be entirely gdb's fault (though I think it happens with fpc trunk and gdb too)

https://bugs.freepascal.org/view.php?id=36144 (and maybe others)
Not sure in which version that was fixed.

However, IIRC FpDebug works around that. So FpDebug should work with older fpc too.


MarkMLl

  • Hero Member
  • *****
  • Posts: 6683
Re: Display of bitpacked arrays in the debugger
« Reply #3 on: June 04, 2021, 12:33:11 pm »
What's generating the Boolean? If it's C then it might be assuming that non-zero is universally recognised as true, and the debugger's alerting you to the fact.

Some of my own code has arrays or bytebools (?), and yesterday I noticed that the numeric value was either 0 or 255.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 4015
Re: Display of bitpacked arrays in the debugger
« Reply #4 on: June 04, 2021, 12:44:42 pm »
Which Debugger?

sorry, I forgot to mention the debugger version, it is v7.2 (old version but, it usually works well for what I do)

Last time I tested, GDB had issues with packed data. That needs to be fixed in gdb (not yet tested gdb 10, but that has other issues)
I've experienced a few issues with GDB and bitpacked data but, this one was different than the ones I've seen in the past.  Thought I'd ask just in case.

I really have to check out FpDebug sometime and, a newer version of Lazarus than the one I'm using.  The output you showed looked enticing :)



What's generating the Boolean? If it's C then it might be assuming that non-zero is universally recognised as true, and the debugger's alerting you to the fact.
It's C but, it is a bitmap returned in a DWORD.  It's the same DWORD returned by GetLogicalDrives (GetLogicalDrives calls that NT function get the DWORD it returns.)  It's not an array of bytebool it's definitely a bit array (as _itoa showed.)


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9857
  • Debugger - SynEdit - and more
    • wiki
Re: Display of bitpacked arrays in the debugger
« Reply #5 on: June 04, 2021, 12:45:54 pm »
What's generating the Boolean? If it's C then it might be assuming that non-zero is universally recognised as true, and the debugger's alerting you to the fact.

Some of my own code has arrays or bytebools (?), and yesterday I noticed that the numeric value was either 0 or 255.

"packed array of boolean" has only a single bit. So there is on 255.

But
- fpc did write incorrect bit access info
- afaik gdb does not use that info correct (even after the fpc fix) / but that needs double checking

So gdb interprets this as an "array of bytebool" => and that yield diff results.

-------------
On that note / IIRC

a: Boolean;  // 0 or 1 => 255 will be accepted but is out of range
b: LongBool; // 0 or any other

However, the debug info has no diff for those 2 types. So even fpdebug will show the (xxx) for any none 0 or 1 value.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9857
  • Debugger - SynEdit - and more
    • wiki
Re: Display of bitpacked arrays in the debugger
« Reply #6 on: June 04, 2021, 12:58:03 pm »
I really have to check out FpDebug sometime and, a newer version of Lazarus than the one I'm using.  The output you showed looked enticing :)
There is an overview, what works in which debugger.
https://wiki.lazarus.freepascal.org/Debugger_Status

Though it does not go into the level of individual data types.

440bx

  • Hero Member
  • *****
  • Posts: 4015
Re: Display of bitpacked arrays in the debugger
« Reply #7 on: June 04, 2021, 01:06:26 pm »
There is an overview, what works in which debugger.
https://wiki.lazarus.freepascal.org/Debugger_Status

Though it does not go into the level of individual data types.
I just checked it out (the page only) and, I have to say, you guys seem to be making really good progress.  It's looking good.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018