------------------------------------------------------------------------------ -- -- -- GNAT RUN-TIME COMPONENTS -- -- -- -- G N A T . M E M O R Y _ D U M P -- -- -- -- B o d y -- -- -- -- Copyright (C) 2003-2024, AdaCore -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- -- ware Foundation; either version 3, or (at your option) any later ver- -- -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- -- or FITNESS FOR A PARTICULAR PURPOSE. -- -- -- -- As a special exception under Section 7 of GPL version 3, you are granted -- -- additional permissions described in the GCC Runtime Library Exception, -- -- version 3.1, as published by the Free Software Foundation. -- -- -- -- You should have received a copy of the GNU General Public License and -- -- a copy of the GCC Runtime Library Exception along with this program; -- -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- -- . -- -- -- -- GNAT was originally developed by the GNAT team at New York University. -- -- Extensive contributions were provided by Ada Core Technologies Inc. -- -- -- ------------------------------------------------------------------------------ with System; use System; with System.Img_BIU; use System.Img_BIU; with System.Storage_Elements; use System.Storage_Elements; with GNAT.IO; use GNAT.IO; with GNAT.Debug_Utilities; use GNAT.Debug_Utilities; with Ada.Unchecked_Conversion; package body GNAT.Memory_Dump is ---------- -- Dump -- ---------- procedure Dump (Addr : Address; Count : Natural) is begin Dump (Addr, Count, Prefix => Absolute_Address); end Dump; procedure Dump (Addr : Address; Count : Natural; Prefix : Prefix_Type) is Ctr : Natural := Count; -- Count of bytes left to output Offset_Buf : String (1 .. Standard'Address_Size / 4 + 4); Offset_Last : Natural; -- Buffer for prefix in Offset mode Adr : Address := Addr; -- Current address N : Natural := 0; -- Number of bytes output on current line C : Character; -- Character at current storage address AIL : Natural; -- Number of chars in prefix (including colon and space) Line_Len : Natural; -- Line length for entire line Hex : constant array (0 .. 15) of Character := "0123456789ABCDEF"; type Char_Ptr is access all Character; function To_Char_Ptr is new Ada.Unchecked_Conversion (Address, Char_Ptr); begin case Prefix is when Absolute_Address => AIL := Address_Image_Length - 4 + 2; when Offset => Offset_Last := Offset_Buf'First - 1; Set_Image_Based_Integer (Ctr, 16, 0, Offset_Buf, Offset_Last); AIL := Offset_Last - 4 + 2; when None => AIL := 0; end case; Line_Len := AIL + 3 * 16 + 2 + 16; declare Line_Buf : String (1 .. Line_Len); begin while Ctr /= 0 loop -- Start of line processing if N = 0 then case Prefix is when Absolute_Address => declare S : constant String := Image (Adr); begin Line_Buf (1 .. AIL) := S (4 .. S'Length - 1) & ": "; end; when Offset => declare Last : Natural := 0; Len : Natural; begin Set_Image_Based_Integer (Count - Ctr, 16, 0, Offset_Buf, Last); Len := Last - 4; Line_Buf (1 .. AIL - Len - 2) := [others => '0']; Line_Buf (AIL - Len - 1 .. AIL - 2) := Offset_Buf (4 .. Last - 1); Line_Buf (AIL - 1 .. AIL) := ": "; end; when None => null; end case; Line_Buf (AIL + 1 .. Line_Buf'Last) := [others => ' ']; Line_Buf (AIL + 3 * 16 + 1) := '"'; end if; -- Add one character to current line C := To_Char_Ptr (Adr).all; Adr := Adr + 1; Ctr := Ctr - 1; Line_Buf (AIL + 3 * N + 1) := Hex (Character'Pos (C) / 16); Line_Buf (AIL + 3 * N + 2) := Hex (Character'Pos (C) mod 16); if C < ' ' or else C = Character'Val (16#7F#) then C := '?'; end if; Line_Buf (AIL + 3 * 16 + 2 + N) := C; N := N + 1; -- End of line processing if N = 16 then Line_Buf (Line_Buf'Last) := '"'; GNAT.IO.Put_Line (Line_Buf); N := 0; end if; end loop; -- Deal with possible last partial line if N /= 0 then Line_Buf (AIL + 3 * 16 + 2 + N) := '"'; GNAT.IO.Put_Line (Line_Buf (1 .. AIL + 3 * 16 + 2 + N)); end if; end; end Dump; end GNAT.Memory_Dump;