Commit c99c095f by Olivier Hainque Committed by Arnaud Charlet

adaint.c:

2007-04-06  Olivier Hainque  <hainque@adacore.com>

	* adaint.c: 
	(convert_addresses): Adjust prototype and dummy definition to expect an
	 extra file_name argument.

	* gmem.c (__gnat_convert_addresses): Wrapper to convert_addresses,
	filling the now expected file_name argument with the appropriate
	argv[0] expansion.
	(__gnat_gmem_a2l_initialize, __gnat_gmem_read_next_frame): Use it.
	(tracebk): Array of void * instead of char *, corresponding to what
	 convert_addresses expects.
	(exename): New static global, to hold the executable file name to be
	used in all convert_addresses invocations.
	(gmem_read_backtrace, __gnat_gmem_symbolic): Account for tracebk type
	change.
	(__gnat_gmem_a2l_initialize): Resolve exename.
	(__gnat_convert_addresses): Use exename as the convert_addresses
	file_name argument.

	* g-trasym.adb (Symbolic_Traceback): Adjust signature of imported
	"convert_addresses", now expecting a filename argument. Import the
	necessary entities to compute the filename to use and pass it to
	convert_addresses.

From-SVN: r123544
parent 42907632
...@@ -324,6 +324,14 @@ to_ptr32 (char **ptr64) ...@@ -324,6 +324,14 @@ to_ptr32 (char **ptr64)
#define MAYBE_TO_PTR32(argv) argv #define MAYBE_TO_PTR32(argv) argv
#endif #endif
OS_Time
__gnat_current_time
(void)
{
time_t res = time (NULL);
return (OS_Time) res;
}
void void
__gnat_to_gm_time __gnat_to_gm_time
(OS_Time *p_time, (OS_Time *p_time,
...@@ -418,8 +426,8 @@ __gnat_try_lock (char *dir, char *file) ...@@ -418,8 +426,8 @@ __gnat_try_lock (char *dir, char *file)
TCHAR wfile[GNAT_MAX_PATH_LEN]; TCHAR wfile[GNAT_MAX_PATH_LEN];
TCHAR wdir[GNAT_MAX_PATH_LEN]; TCHAR wdir[GNAT_MAX_PATH_LEN];
S2WS (wdir, dir, GNAT_MAX_PATH_LEN); S2WSU (wdir, dir, GNAT_MAX_PATH_LEN);
S2WS (wfile, file, GNAT_MAX_PATH_LEN); S2WSU (wfile, file, GNAT_MAX_PATH_LEN);
_stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile); _stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
fd = _topen (wfull_path, O_CREAT | O_EXCL, 0600); fd = _topen (wfull_path, O_CREAT | O_EXCL, 0600);
...@@ -542,7 +550,7 @@ __gnat_get_current_dir (char *dir, int *length) ...@@ -542,7 +550,7 @@ __gnat_get_current_dir (char *dir, int *length)
_tgetcwd (wdir, *length); _tgetcwd (wdir, *length);
WS2S (dir, wdir, GNAT_MAX_PATH_LEN); WS2SU (dir, wdir, GNAT_MAX_PATH_LEN);
#elif defined (VMS) #elif defined (VMS)
/* Force Unix style, which is what GNAT uses internally. */ /* Force Unix style, which is what GNAT uses internally. */
...@@ -612,31 +620,44 @@ __gnat_get_debuggable_suffix_ptr (int *len, const char **value) ...@@ -612,31 +620,44 @@ __gnat_get_debuggable_suffix_ptr (int *len, const char **value)
} }
FILE * FILE *
__gnat_fopen (char *path, char *mode) __gnat_fopen (char *path, char *mode, int encoding)
{ {
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE) #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
TCHAR wmode[10]; TCHAR wmode[10];
S2WS (wpath, path, GNAT_MAX_PATH_LEN);
S2WS (wmode, mode, 10); S2WS (wmode, mode, 10);
if (encoding == Encoding_UTF8)
S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
else
S2WS (wpath, path, GNAT_MAX_PATH_LEN);
return _tfopen (wpath, wmode); return _tfopen (wpath, wmode);
#elif defined (VMS)
return decc$fopen (path, mode);
#else #else
return fopen (path, mode); return fopen (path, mode);
#endif #endif
} }
FILE * FILE *
__gnat_freopen (char *path, char *mode, FILE *stream) __gnat_freopen (char *path, char *mode, FILE *stream, int encoding)
{ {
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE) #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
TCHAR wmode[10]; TCHAR wmode[10];
S2WS (wpath, path, GNAT_MAX_PATH_LEN);
S2WS (wmode, mode, 10); S2WS (wmode, mode, 10);
if (encoding == Encoding_UTF8)
S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
else
S2WS (wpath, path, GNAT_MAX_PATH_LEN);
return _tfreopen (wpath, wmode, stream); return _tfreopen (wpath, wmode, stream);
#elif defined (VMS)
return decc$freopen (path, mode, stream);
#else #else
return freopen (path, mode, stream); return freopen (path, mode, stream);
#endif #endif
...@@ -661,7 +682,7 @@ __gnat_open_read (char *path, int fmode) ...@@ -661,7 +682,7 @@ __gnat_open_read (char *path, int fmode)
{ {
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
S2WS (wpath, path, GNAT_MAX_PATH_LEN); S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_RDONLY | o_fmode, 0444); fd = _topen (wpath, O_RDONLY | o_fmode, 0444);
} }
#else #else
...@@ -702,7 +723,7 @@ __gnat_open_rw (char *path, int fmode) ...@@ -702,7 +723,7 @@ __gnat_open_rw (char *path, int fmode)
{ {
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
S2WS (wpath, path, GNAT_MAX_PATH_LEN); S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_RDWR | o_fmode, PERM); fd = _topen (wpath, O_RDWR | o_fmode, PERM);
} }
#else #else
...@@ -728,7 +749,7 @@ __gnat_open_create (char *path, int fmode) ...@@ -728,7 +749,7 @@ __gnat_open_create (char *path, int fmode)
{ {
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
S2WS (wpath, path, GNAT_MAX_PATH_LEN); S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM); fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
} }
#else #else
...@@ -750,7 +771,7 @@ __gnat_create_output_file (char *path) ...@@ -750,7 +771,7 @@ __gnat_create_output_file (char *path)
{ {
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
S2WS (wpath, path, GNAT_MAX_PATH_LEN); S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM); fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
} }
#else #else
...@@ -776,7 +797,7 @@ __gnat_open_append (char *path, int fmode) ...@@ -776,7 +797,7 @@ __gnat_open_append (char *path, int fmode)
{ {
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
S2WS (wpath, path, GNAT_MAX_PATH_LEN); S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM); fd = _topen (wpath, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
} }
#else #else
...@@ -804,7 +825,7 @@ __gnat_open_new (char *path, int fmode) ...@@ -804,7 +825,7 @@ __gnat_open_new (char *path, int fmode)
{ {
TCHAR wpath[GNAT_MAX_PATH_LEN]; TCHAR wpath[GNAT_MAX_PATH_LEN];
S2WS (wpath, path, GNAT_MAX_PATH_LEN); S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
fd = _topen (wpath, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM); fd = _topen (wpath, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
} }
#else #else
...@@ -940,7 +961,7 @@ DIR* __gnat_opendir (char *name) ...@@ -940,7 +961,7 @@ DIR* __gnat_opendir (char *name)
#ifdef __MINGW32__ #ifdef __MINGW32__
TCHAR wname[GNAT_MAX_PATH_LEN]; TCHAR wname[GNAT_MAX_PATH_LEN];
S2WS (wname, name, GNAT_MAX_PATH_LEN); S2WSU (wname, name, GNAT_MAX_PATH_LEN);
return (DIR*)_topendir (wname); return (DIR*)_topendir (wname);
#else #else
...@@ -959,7 +980,7 @@ __gnat_readdir (DIR *dirp, char *buffer, int *len) ...@@ -959,7 +980,7 @@ __gnat_readdir (DIR *dirp, char *buffer, int *len)
if (dirent != NULL) if (dirent != NULL)
{ {
WS2S (buffer, dirent->d_name, GNAT_MAX_PATH_LEN); WS2SU (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
*len = strlen (buffer); *len = strlen (buffer);
return buffer; return buffer;
...@@ -1058,7 +1079,7 @@ __gnat_file_time_name (char *name) ...@@ -1058,7 +1079,7 @@ __gnat_file_time_name (char *name)
time_t ret = -1; time_t ret = -1;
TCHAR wname[GNAT_MAX_PATH_LEN]; TCHAR wname[GNAT_MAX_PATH_LEN];
S2WS (wname, name, GNAT_MAX_PATH_LEN); S2WSU (wname, name, GNAT_MAX_PATH_LEN);
HANDLE h = CreateFile HANDLE h = CreateFile
(wname, GENERIC_READ, FILE_SHARE_READ, 0, (wname, GENERIC_READ, FILE_SHARE_READ, 0,
...@@ -1195,7 +1216,7 @@ __gnat_set_file_time_name (char *name, time_t time_stamp) ...@@ -1195,7 +1216,7 @@ __gnat_set_file_time_name (char *name, time_t time_stamp)
} t_write; } t_write;
TCHAR wname[GNAT_MAX_PATH_LEN]; TCHAR wname[GNAT_MAX_PATH_LEN];
S2WS (wname, name, GNAT_MAX_PATH_LEN); S2WSU (wname, name, GNAT_MAX_PATH_LEN);
HANDLE h = CreateFile HANDLE h = CreateFile
(wname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, (wname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
...@@ -1462,7 +1483,7 @@ __gnat_stat (char *name, struct stat *statbuf) ...@@ -1462,7 +1483,7 @@ __gnat_stat (char *name, struct stat *statbuf)
int name_len; int name_len;
TCHAR last_char; TCHAR last_char;
S2WS (wname, name, GNAT_MAX_PATH_LEN + 2); S2WSU (wname, name, GNAT_MAX_PATH_LEN + 2);
name_len = _tcslen (wname); name_len = _tcslen (wname);
if (name_len > GNAT_MAX_PATH_LEN) if (name_len > GNAT_MAX_PATH_LEN)
...@@ -1854,7 +1875,7 @@ win32_no_block_spawn (char *command, char *args[]) ...@@ -1854,7 +1875,7 @@ win32_no_block_spawn (char *command, char *args[])
int wsize = csize * 2; int wsize = csize * 2;
TCHAR *wcommand = (TCHAR *) xmalloc (wsize); TCHAR *wcommand = (TCHAR *) xmalloc (wsize);
S2WS (wcommand, full_command, wsize); S2WSU (wcommand, full_command, wsize);
free (full_command); free (full_command);
...@@ -2145,7 +2166,7 @@ __gnat_locate_exec_on_path (char *exec_name) ...@@ -2145,7 +2166,7 @@ __gnat_locate_exec_on_path (char *exec_name)
apath_val = alloca (EXPAND_BUFFER_SIZE); apath_val = alloca (EXPAND_BUFFER_SIZE);
WS2S (apath_val, wapath_val, EXPAND_BUFFER_SIZE); WS2SU (apath_val, wapath_val, EXPAND_BUFFER_SIZE);
return __gnat_locate_exec (exec_name, apath_val); return __gnat_locate_exec (exec_name, apath_val);
#else #else
...@@ -2623,7 +2644,8 @@ _flush_cache() ...@@ -2623,7 +2644,8 @@ _flush_cache()
version of this procedure in libaddr2line.a. */ version of this procedure in libaddr2line.a. */
void void
convert_addresses (void *addrs ATTRIBUTE_UNUSED, convert_addresses (const char *file_name ATTRIBUTE_UNUSED,
void *addrs ATTRIBUTE_UNUSED,
int n_addr ATTRIBUTE_UNUSED, int n_addr ATTRIBUTE_UNUSED,
void *buf ATTRIBUTE_UNUSED, void *buf ATTRIBUTE_UNUSED,
int *len ATTRIBUTE_UNUSED) int *len ATTRIBUTE_UNUSED)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
-- -- -- --
-- B o d y -- -- B o d y --
-- -- -- --
-- Copyright (C) 1999-2005, AdaCore -- -- Copyright (C) 1999-2006, AdaCore --
-- -- -- --
-- 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- --
...@@ -44,38 +44,104 @@ package body GNAT.Traceback.Symbolic is ...@@ -44,38 +44,104 @@ package body GNAT.Traceback.Symbolic is
package TSL renames System.Soft_Links; package TSL renames System.Soft_Links;
-- To perform the raw addresses to symbolic form translation we rely on a
-- libaddr2line symbolizer which examines debug info from a provided
-- executable file name, and an absolute path is needed to ensure the file
-- is always found. This is "__gnat_locate_exec_on_path (gnat_argv [0])"
-- for our executable file, a fairly heavy operation so we cache the
-- result.
Exename : System.Address;
-- Pointer to the name of the executable file to be used on all
-- invocations of the libaddr2line symbolization service.
Exename_Resolved : Boolean := False;
-- Flag to indicate whether we have performed the executable file name
-- resolution already. Relying on a not null Exename for this purpose
-- would be potentially inefficient as this is what we will get if the
-- resolution attempt fails.
------------------------ ------------------------
-- Symbolic_Traceback -- -- Symbolic_Traceback --
------------------------ ------------------------
function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is
procedure convert_addresses procedure convert_addresses
(addrs : System.Address; (filename : System.Address;
n_addr : Integer; addrs : System.Address;
buf : System.Address; n_addrs : Integer;
len : System.Address); buf : System.Address;
len : System.Address);
pragma Import (C, convert_addresses, "convert_addresses"); pragma Import (C, convert_addresses, "convert_addresses");
-- This is the procedure version of the Ada aware addr2line that will -- This is the procedure version of the Ada aware addr2line. It places
-- use argv[0] as the executable containing the debug information. -- in BUF a string representing the symbolic translation of the N_ADDRS
-- raw addresses provided in ADDRS, looked up in debug information from
-- FILENAME. LEN is filled with the result length.
--
-- This procedure is provided by libaddr2line on targets that support -- This procedure is provided by libaddr2line on targets that support
-- it. A dummy version is in a-adaint.c for other targets so that build -- it. A dummy version is in adaint.c for other targets so that build
-- of shared libraries doesn't generate unresolved symbols. -- of shared libraries doesn't generate unresolved symbols.
-- --
-- Note that this procedure is *not* thread-safe. -- Note that this procedure is *not* thread-safe.
type Argv_Array is array (0 .. 0) of System.Address;
gnat_argv : access Argv_Array;
pragma Import (C, gnat_argv, "gnat_argv");
function locate_exec_on_path
(c_exename : System.Address) return System.Address;
pragma Import (C, locate_exec_on_path, "__gnat_locate_exec_on_path");
Res : String (1 .. 256 * Traceback'Length); Res : String (1 .. 256 * Traceback'Length);
Len : Integer; Len : Integer;
use type System.Address;
begin begin
if Traceback'Length > 0 then -- The symbolic translation of an empty set of addresses is the
TSL.Lock_Task.all; -- the empty string.
if Traceback'Length <= 0 then
return "";
end if;
-- If our input set of raw addresses is not empty, resort to the
-- libaddr2line service to symbolize it all.
-- Compute, cache and provide the absolute path to our executable file
-- name as the binary file where the relevant debug information is to
-- be found. If the executable file name resolution fails, we have no
-- sensible basis to invoke the symbolizer at all.
-- Protect all this against concurrent accesses explicitely, as the
-- underlying services are potentially thread unsafe.
TSL.Lock_Task.all;
if not Exename_Resolved then
Exename := locate_exec_on_path (gnat_argv (0));
Exename_Resolved := True;
end if;
if Exename /= System.Null_Address then
convert_addresses convert_addresses
(Traceback'Address, Traceback'Length, Res (1)'Address, Len'Address); (Exename, Traceback'Address, Traceback'Length,
TSL.Unlock_Task.all; Res (1)'Address, Len'Address);
end if;
TSL.Unlock_Task.all;
-- Return what the addr2line symbolizer has produced if we have called
-- it (the executable name resolution succeeded), or an empty string
-- otherwise.
if Exename /= System.Null_Address then
return Res (1 .. Len); return Res (1 .. Len);
else else
return ""; return "";
end if; end if;
end Symbolic_Traceback; end Symbolic_Traceback;
function Symbolic_Traceback (E : Exception_Occurrence) return String is function Symbolic_Traceback (E : Exception_Occurrence) return String is
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* * * *
* C Implementation File * * C Implementation File *
* * * *
* Copyright (C) 2000-2003 Free Software Foundation, Inc. * * Copyright (C) 2000-2006, 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- *
...@@ -54,7 +54,7 @@ static FILE *gmemfile; ...@@ -54,7 +54,7 @@ static FILE *gmemfile;
/* tb_len is the number of call level supported by this module */ /* tb_len is the number of call level supported by this module */
#define tb_len 200 #define tb_len 200
static char * tracebk [tb_len]; static void * tracebk [tb_len];
static int cur_tb_len, cur_tb_pos; static int cur_tb_len, cur_tb_pos;
#define LOG_EOF '*' #define LOG_EOF '*'
...@@ -67,8 +67,34 @@ struct struct_storage_elmt { ...@@ -67,8 +67,34 @@ struct struct_storage_elmt {
size_t Size; size_t Size;
}; };
extern void static void
convert_addresses (char *addrs[], int n_addr, void *buf, int *len); __gnat_convert_addresses (void *addrs[], int n_addrs, void *buf, int *len);
/* Place in BUF a string representing the symbolic translation of N_ADDRS raw
addresses provided in ADDRS. LEN is filled with the result length.
This is a GNAT specific interface to the libaddr2line convert_addresses
routine. The latter examines debug info from a provided executable file
name to perform the translation into symbolic form of an input sequence of
raw binary addresses. It attempts to open the file from the provided name
"as is", so an an absolute path must be provided to ensure the file is
always found. We compute this name once, at initialization time. */
static const char * exename = 0;
extern void convert_addresses (const char * , void *[], int, void *, int *);
extern char *__gnat_locate_exec_on_path (char *);
/* ??? Both of these extern functions are prototyped in adaint.h, which
also refers to "time_t" hence needs complex extra header inclusions to
be satisfied on every target. */
static void
__gnat_convert_addresses (void *addrs[], int n_addrs, void *buf, int *len)
{
if (exename != 0)
convert_addresses (exename, addrs, n_addrs, buf, len);
else
*len = 0;
}
/* reads backtrace information from gmemfile placing them in tracebk /* reads backtrace information from gmemfile placing them in tracebk
array. cur_tb_len is the size of this array array. cur_tb_len is the size of this array
...@@ -78,7 +104,7 @@ static void ...@@ -78,7 +104,7 @@ static void
gmem_read_backtrace (void) gmem_read_backtrace (void)
{ {
fread (&cur_tb_len, sizeof (int), 1, gmemfile); fread (&cur_tb_len, sizeof (int), 1, gmemfile);
fread (tracebk, sizeof (char *), cur_tb_len, gmemfile); fread (tracebk, sizeof (void *), cur_tb_len, gmemfile);
cur_tb_pos = 0; cur_tb_pos = 0;
} }
...@@ -106,14 +132,11 @@ int __gnat_gmem_initialize (char *dumpname) ...@@ -106,14 +132,11 @@ int __gnat_gmem_initialize (char *dumpname)
/* initialize addr2line library */ /* initialize addr2line library */
void __gnat_gmem_a2l_initialize (char *exename) void __gnat_gmem_a2l_initialize (char *exearg)
{ {
extern char **gnat_argv; /* Resolve the executable filename to use in later invocations of
char s [100]; the libaddr2line symbolization service. */
int l; exename = __gnat_locate_exec_on_path (exearg);
gnat_argv [0] = exename;
convert_addresses (tracebk, 1, s, &l);
} }
/* Read next allocation of deallocation information from the GMEM file and /* Read next allocation of deallocation information from the GMEM file and
...@@ -172,8 +195,7 @@ void __gnat_gmem_read_next_frame (void** addr) ...@@ -172,8 +195,7 @@ void __gnat_gmem_read_next_frame (void** addr)
void __gnat_gmem_symbolic (void * addr, char* buf, int* length) void __gnat_gmem_symbolic (void * addr, char* buf, int* length)
{ {
char* addresses [] = { (char*)addr }; void * addresses [] = { addr };
extern char** gnat_argv;
convert_addresses (addresses, 1, buf, length); __gnat_convert_addresses (addresses, 1, buf, length);
} }
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