Commit 8cc39ff2 by Vasiliy Fofanov Committed by Arnaud Charlet

gmem.c: Add support for timestamps on memory operations.

2007-04-20  Vasiliy Fofanov  <fofanov@adacore.com>

	* gmem.c: Add support for timestamps on memory operations.

	* memtrack.adb, gnatmem.adb: Add support for timestamps on memory
	operations (not used currently, just foundation for future
	enhancements). Add possibility to perform full dump of gmem.out file.
	(Print_Back_Traces): Declare accesses to root arrays constants since
	they aren't modified.
	(Print_Back_Traces): allocate root arrays on the heap rather than stack.

From-SVN: r125419
parent 9fd79385
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* * * *
* C Implementation File * * C Implementation File *
* * * *
* Copyright (C) 2000-2006, Free Software Foundation, Inc. * * Copyright (C) 2000-2007, Free Software Foundation, Inc. *
* * * *
* GNAT is free software; you can redistribute it and/or modify it under * * 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- * * terms of the GNU General Public License as published by the Free Soft- *
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
****************************************************************************/ ****************************************************************************/
/* This unit reads the allocation tracking log produced by augmented /* This unit reads the allocation tracking log produced by augmented
__gnat_malloc and __gnat_free procedures (see file a-raise.c) and __gnat_malloc and __gnat_free procedures (see file memtrack.adb) and
provides GNATMEM tool with gdb-compliant output. The output is provides GNATMEM tool with gdb-compliant output. The output is
processed by GNATMEM to detect dynamic memory allocation errors. processed by GNATMEM to detect dynamic memory allocation errors.
...@@ -43,9 +43,11 @@ ...@@ -43,9 +43,11 @@
GNU/Linux x86 GNU/Linux x86
Solaris (sparc and x86) (*) Solaris (sparc and x86) (*)
Windows 98/95/NT (x86) Windows 98/95/NT (x86)
Alpha OpenVMS
(*) on these targets, the compilation must be done with -funwind-tables to (*) on these targets, the compilation must be done with -funwind-tables to
be able to build the stack backtrace. be able to build the stack backtrace.
*/ */
#include <stdio.h> #include <stdio.h>
...@@ -65,6 +67,7 @@ struct struct_storage_elmt { ...@@ -65,6 +67,7 @@ struct struct_storage_elmt {
char Elmt; char Elmt;
void * Address; void * Address;
size_t Size; size_t Size;
long long Timestamp;
}; };
static void static void
...@@ -108,14 +111,15 @@ gmem_read_backtrace (void) ...@@ -108,14 +111,15 @@ gmem_read_backtrace (void)
cur_tb_pos = 0; cur_tb_pos = 0;
} }
/* initialize gmem feature from the dumpname file. It returns 1 if the /* initialize gmem feature from the dumpname file. It returns t0 timestamp
dumpname has been generated by GMEM (instrumented malloc/free) and 0 if not if the dumpname has been generated by GMEM (instrumented malloc/free)
(i.e. probably a GDB generated file). and 0 if not.
*/ */
int __gnat_gmem_initialize (char *dumpname) long long __gnat_gmem_initialize (char *dumpname)
{ {
char header [10]; char header [10];
long long t0;
gmemfile = fopen (dumpname, "rb"); gmemfile = fopen (dumpname, "rb");
fread (header, 10, 1, gmemfile); fread (header, 10, 1, gmemfile);
...@@ -127,7 +131,9 @@ int __gnat_gmem_initialize (char *dumpname) ...@@ -127,7 +131,9 @@ int __gnat_gmem_initialize (char *dumpname)
return 0; return 0;
} }
return 1; fread (&t0, sizeof (long long), 1, gmemfile);
return t0;
} }
/* initialize addr2line library */ /* initialize addr2line library */
...@@ -163,10 +169,12 @@ __gnat_gmem_read_next (struct struct_storage_elmt *buf) ...@@ -163,10 +169,12 @@ __gnat_gmem_read_next (struct struct_storage_elmt *buf)
buf->Elmt = LOG_ALLOC; buf->Elmt = LOG_ALLOC;
fread (&(buf->Address), sizeof (void *), 1, gmemfile); fread (&(buf->Address), sizeof (void *), 1, gmemfile);
fread (&(buf->Size), sizeof (size_t), 1, gmemfile); fread (&(buf->Size), sizeof (size_t), 1, gmemfile);
fread (&(buf->Timestamp), sizeof (long long), 1, gmemfile);
break; break;
case 'D' : case 'D' :
buf->Elmt = LOG_DEALL; buf->Elmt = LOG_DEALL;
fread (&(buf->Address), sizeof (void *), 1, gmemfile); fread (&(buf->Address), sizeof (void *), 1, gmemfile);
fread (&(buf->Timestamp), sizeof (long long), 1, gmemfile);
break; break;
default: default:
puts ("GNATMEM dump file corrupt"); puts ("GNATMEM dump file corrupt");
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- B o d y -- -- B o d y --
-- -- -- --
-- Copyright (C) 2001-2005 Free Software Foundation, Inc. -- -- Copyright (C) 2001-2007, Free Software Foundation, Inc. --
-- -- -- --
-- GNAT is free software; you can redistribute it and/or modify it under -- -- 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- -- -- terms of the GNU General Public License as published by the Free Soft- --
...@@ -64,6 +64,12 @@ ...@@ -64,6 +64,12 @@
-- Irix -- Irix
-- Solaris -- Solaris
-- Tru64 -- Tru64
-- Alpha OpenVMS
-- NOTE FOR FUTURE PLATFORMS SUPPORT: It is assumed that type Duration is
-- 64 bit. If the need arises to support architectures where this assumption
-- is incorrect, it will require changing the way timestamps of allocation
-- events are recorded.
pragma Source_File_Name (System.Memory, Body_File_Name => "memtrack.adb"); pragma Source_File_Name (System.Memory, Body_File_Name => "memtrack.adb");
...@@ -72,6 +78,7 @@ with System.Soft_Links; ...@@ -72,6 +78,7 @@ with System.Soft_Links;
with System.Traceback; with System.Traceback;
with System.Traceback_Entries; with System.Traceback_Entries;
with GNAT.IO; with GNAT.IO;
with System.OS_Primitives;
package body System.Memory is package body System.Memory is
...@@ -140,6 +147,9 @@ package body System.Memory is ...@@ -140,6 +147,9 @@ package body System.Memory is
Gmemfile : File_Ptr; Gmemfile : File_Ptr;
-- Global C file pointer to the allocation log -- Global C file pointer to the allocation log
Needs_Init : Boolean := True;
-- Reset after first call to Gmem_Initialize
procedure Gmem_Initialize; procedure Gmem_Initialize;
-- Initialization routine; opens the file and writes a header string. This -- Initialization routine; opens the file and writes a header string. This
-- header string is used as a magic-tag to know if the .out file is to be -- header string is used as a magic-tag to know if the .out file is to be
...@@ -157,6 +167,7 @@ package body System.Memory is ...@@ -157,6 +167,7 @@ package body System.Memory is
function Alloc (Size : size_t) return System.Address is function Alloc (Size : size_t) return System.Address is
Result : aliased System.Address; Result : aliased System.Address;
Actual_Size : aliased size_t := Size; Actual_Size : aliased size_t := Size;
Timestamp : aliased Duration;
begin begin
if Size = size_t'Last then if Size = size_t'Last then
...@@ -184,13 +195,19 @@ package body System.Memory is ...@@ -184,13 +195,19 @@ package body System.Memory is
First_Call := False; First_Call := False;
Gmem_Initialize; if Needs_Init then
Gmem_Initialize;
end if;
Timestamp := System.OS_Primitives.Clock;
Call_Chain (Tracebk'Address, Max_Call_Stack, Num_Calls, Call_Chain (Tracebk'Address, Max_Call_Stack, Num_Calls,
Skip_Frames => 2); Skip_Frames => 2);
fputc (Character'Pos ('A'), Gmemfile); fputc (Character'Pos ('A'), Gmemfile);
fwrite (Result'Address, Address_Size, 1, Gmemfile); fwrite (Result'Address, Address_Size, 1, Gmemfile);
fwrite (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements, 1, fwrite (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
Gmemfile); Gmemfile);
fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
Gmemfile);
fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1, fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
Gmemfile); Gmemfile);
...@@ -219,9 +236,6 @@ package body System.Memory is ...@@ -219,9 +236,6 @@ package body System.Memory is
-- Finalize -- -- Finalize --
-------------- --------------
Needs_Init : Boolean := True;
-- Reset after first call to Gmem_Initialize
procedure Finalize is procedure Finalize is
begin begin
if not Needs_Init then if not Needs_Init then
...@@ -234,7 +248,8 @@ package body System.Memory is ...@@ -234,7 +248,8 @@ package body System.Memory is
---------- ----------
procedure Free (Ptr : System.Address) is procedure Free (Ptr : System.Address) is
Addr : aliased constant System.Address := Ptr; Addr : aliased constant System.Address := Ptr;
Timestamp : aliased Duration;
begin begin
Lock_Task.all; Lock_Task.all;
...@@ -247,11 +262,17 @@ package body System.Memory is ...@@ -247,11 +262,17 @@ package body System.Memory is
First_Call := False; First_Call := False;
Gmem_Initialize; if Needs_Init then
Gmem_Initialize;
end if;
Call_Chain (Tracebk'Address, Max_Call_Stack, Num_Calls, Call_Chain (Tracebk'Address, Max_Call_Stack, Num_Calls,
Skip_Frames => 2); Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
fputc (Character'Pos ('D'), Gmemfile); fputc (Character'Pos ('D'), Gmemfile);
fwrite (Addr'Address, Address_Size, 1, Gmemfile); fwrite (Addr'Address, Address_Size, 1, Gmemfile);
fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
Gmemfile);
fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1, fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
Gmemfile); Gmemfile);
...@@ -276,9 +297,13 @@ package body System.Memory is ...@@ -276,9 +297,13 @@ package body System.Memory is
--------------------- ---------------------
procedure Gmem_Initialize is procedure Gmem_Initialize is
Timestamp : aliased Duration;
begin begin
if Needs_Init then if Needs_Init then
Needs_Init := False; Needs_Init := False;
System.OS_Primitives.Initialize;
Timestamp := System.OS_Primitives.Clock;
Gmemfile := fopen (Gmemfname, "wb" & ASCII.NUL); Gmemfile := fopen (Gmemfname, "wb" & ASCII.NUL);
if Gmemfile = System.Null_Address then if Gmemfile = System.Null_Address then
...@@ -287,6 +312,8 @@ package body System.Memory is ...@@ -287,6 +312,8 @@ package body System.Memory is
end if; end if;
fwrite ("GMEM DUMP" & ASCII.LF, 10, 1, Gmemfile); fwrite ("GMEM DUMP" & ASCII.LF, 10, 1, Gmemfile);
fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
Gmemfile);
end if; end if;
end Gmem_Initialize; end Gmem_Initialize;
...@@ -295,10 +322,12 @@ package body System.Memory is ...@@ -295,10 +322,12 @@ package body System.Memory is
------------- -------------
function Realloc function Realloc
(Ptr : System.Address; Size : size_t) return System.Address (Ptr : System.Address;
Size : size_t) return System.Address
is is
Addr : aliased constant System.Address := Ptr; Addr : aliased constant System.Address := Ptr;
Result : aliased System.Address; Result : aliased System.Address;
Timestamp : aliased Duration;
begin begin
-- For the purposes of allocations logging, we treat realloc as a free -- For the purposes of allocations logging, we treat realloc as a free
...@@ -317,11 +346,16 @@ package body System.Memory is ...@@ -317,11 +346,16 @@ package body System.Memory is
-- We first log deallocation call -- We first log deallocation call
Gmem_Initialize; if Needs_Init then
Gmem_Initialize;
end if;
Call_Chain (Tracebk'Address, Max_Call_Stack, Num_Calls, Call_Chain (Tracebk'Address, Max_Call_Stack, Num_Calls,
Skip_Frames => 2); Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
fputc (Character'Pos ('D'), Gmemfile); fputc (Character'Pos ('D'), Gmemfile);
fwrite (Addr'Address, Address_Size, 1, Gmemfile); fwrite (Addr'Address, Address_Size, 1, Gmemfile);
fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
Gmemfile);
fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1, fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
Gmemfile); Gmemfile);
...@@ -343,6 +377,8 @@ package body System.Memory is ...@@ -343,6 +377,8 @@ package body System.Memory is
fwrite (Result'Address, Address_Size, 1, Gmemfile); fwrite (Result'Address, Address_Size, 1, Gmemfile);
fwrite (Size'Address, size_t'Max_Size_In_Storage_Elements, 1, fwrite (Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
Gmemfile); Gmemfile);
fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
Gmemfile);
fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1, fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
Gmemfile); Gmemfile);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment