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
This commit is contained in:
parent
4290763286
commit
c99c095f99
@ -324,6 +324,14 @@ to_ptr32 (char **ptr64)
|
||||
#define MAYBE_TO_PTR32(argv) argv
|
||||
#endif
|
||||
|
||||
OS_Time
|
||||
__gnat_current_time
|
||||
(void)
|
||||
{
|
||||
time_t res = time (NULL);
|
||||
return (OS_Time) res;
|
||||
}
|
||||
|
||||
void
|
||||
__gnat_to_gm_time
|
||||
(OS_Time *p_time,
|
||||
@ -418,8 +426,8 @@ __gnat_try_lock (char *dir, char *file)
|
||||
TCHAR wfile[GNAT_MAX_PATH_LEN];
|
||||
TCHAR wdir[GNAT_MAX_PATH_LEN];
|
||||
|
||||
S2WS (wdir, dir, GNAT_MAX_PATH_LEN);
|
||||
S2WS (wfile, file, GNAT_MAX_PATH_LEN);
|
||||
S2WSU (wdir, dir, GNAT_MAX_PATH_LEN);
|
||||
S2WSU (wfile, file, GNAT_MAX_PATH_LEN);
|
||||
|
||||
_stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
|
||||
fd = _topen (wfull_path, O_CREAT | O_EXCL, 0600);
|
||||
@ -542,7 +550,7 @@ __gnat_get_current_dir (char *dir, int *length)
|
||||
|
||||
_tgetcwd (wdir, *length);
|
||||
|
||||
WS2S (dir, wdir, GNAT_MAX_PATH_LEN);
|
||||
WS2SU (dir, wdir, GNAT_MAX_PATH_LEN);
|
||||
|
||||
#elif defined (VMS)
|
||||
/* Force Unix style, which is what GNAT uses internally. */
|
||||
@ -612,31 +620,44 @@ __gnat_get_debuggable_suffix_ptr (int *len, const char **value)
|
||||
}
|
||||
|
||||
FILE *
|
||||
__gnat_fopen (char *path, char *mode)
|
||||
__gnat_fopen (char *path, char *mode, int encoding)
|
||||
{
|
||||
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
|
||||
TCHAR wpath[GNAT_MAX_PATH_LEN];
|
||||
TCHAR wmode[10];
|
||||
|
||||
S2WS (wpath, path, GNAT_MAX_PATH_LEN);
|
||||
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);
|
||||
#elif defined (VMS)
|
||||
return decc$fopen (path, mode);
|
||||
#else
|
||||
return fopen (path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
TCHAR wpath[GNAT_MAX_PATH_LEN];
|
||||
TCHAR wmode[10];
|
||||
|
||||
S2WS (wpath, path, GNAT_MAX_PATH_LEN);
|
||||
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);
|
||||
#elif defined (VMS)
|
||||
return decc$freopen (path, mode, stream);
|
||||
#else
|
||||
return freopen (path, mode, stream);
|
||||
#endif
|
||||
@ -661,7 +682,7 @@ __gnat_open_read (char *path, int fmode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
@ -702,7 +723,7 @@ __gnat_open_rw (char *path, int fmode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
@ -728,7 +749,7 @@ __gnat_open_create (char *path, int fmode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
@ -750,7 +771,7 @@ __gnat_create_output_file (char *path)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
@ -776,7 +797,7 @@ __gnat_open_append (char *path, int fmode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
@ -804,7 +825,7 @@ __gnat_open_new (char *path, int fmode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#else
|
||||
@ -940,7 +961,7 @@ DIR* __gnat_opendir (char *name)
|
||||
#ifdef __MINGW32__
|
||||
TCHAR wname[GNAT_MAX_PATH_LEN];
|
||||
|
||||
S2WS (wname, name, GNAT_MAX_PATH_LEN);
|
||||
S2WSU (wname, name, GNAT_MAX_PATH_LEN);
|
||||
return (DIR*)_topendir (wname);
|
||||
|
||||
#else
|
||||
@ -959,7 +980,7 @@ __gnat_readdir (DIR *dirp, char *buffer, int *len)
|
||||
|
||||
if (dirent != NULL)
|
||||
{
|
||||
WS2S (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
|
||||
WS2SU (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
|
||||
*len = strlen (buffer);
|
||||
|
||||
return buffer;
|
||||
@ -1058,7 +1079,7 @@ __gnat_file_time_name (char *name)
|
||||
time_t ret = -1;
|
||||
TCHAR wname[GNAT_MAX_PATH_LEN];
|
||||
|
||||
S2WS (wname, name, GNAT_MAX_PATH_LEN);
|
||||
S2WSU (wname, name, GNAT_MAX_PATH_LEN);
|
||||
|
||||
HANDLE h = CreateFile
|
||||
(wname, GENERIC_READ, FILE_SHARE_READ, 0,
|
||||
@ -1195,7 +1216,7 @@ __gnat_set_file_time_name (char *name, time_t time_stamp)
|
||||
} t_write;
|
||||
TCHAR wname[GNAT_MAX_PATH_LEN];
|
||||
|
||||
S2WS (wname, name, GNAT_MAX_PATH_LEN);
|
||||
S2WSU (wname, name, GNAT_MAX_PATH_LEN);
|
||||
|
||||
HANDLE h = CreateFile
|
||||
(wname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
|
||||
@ -1462,7 +1483,7 @@ __gnat_stat (char *name, struct stat *statbuf)
|
||||
int name_len;
|
||||
TCHAR last_char;
|
||||
|
||||
S2WS (wname, name, GNAT_MAX_PATH_LEN + 2);
|
||||
S2WSU (wname, name, GNAT_MAX_PATH_LEN + 2);
|
||||
name_len = _tcslen (wname);
|
||||
|
||||
if (name_len > GNAT_MAX_PATH_LEN)
|
||||
@ -1854,7 +1875,7 @@ win32_no_block_spawn (char *command, char *args[])
|
||||
int wsize = csize * 2;
|
||||
TCHAR *wcommand = (TCHAR *) xmalloc (wsize);
|
||||
|
||||
S2WS (wcommand, full_command, wsize);
|
||||
S2WSU (wcommand, full_command, wsize);
|
||||
|
||||
free (full_command);
|
||||
|
||||
@ -2145,7 +2166,7 @@ __gnat_locate_exec_on_path (char *exec_name)
|
||||
|
||||
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);
|
||||
|
||||
#else
|
||||
@ -2623,7 +2644,8 @@ _flush_cache()
|
||||
version of this procedure in libaddr2line.a. */
|
||||
|
||||
void
|
||||
convert_addresses (void *addrs ATTRIBUTE_UNUSED,
|
||||
convert_addresses (const char *file_name ATTRIBUTE_UNUSED,
|
||||
void *addrs ATTRIBUTE_UNUSED,
|
||||
int n_addr ATTRIBUTE_UNUSED,
|
||||
void *buf ATTRIBUTE_UNUSED,
|
||||
int *len ATTRIBUTE_UNUSED)
|
||||
|
@ -6,7 +6,7 @@
|
||||
-- --
|
||||
-- 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 --
|
||||
-- terms of the GNU General Public License as published by the Free Soft- --
|
||||
@ -44,38 +44,104 @@ package body GNAT.Traceback.Symbolic is
|
||||
|
||||
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 --
|
||||
------------------------
|
||||
|
||||
function Symbolic_Traceback (Traceback : Tracebacks_Array) return String is
|
||||
|
||||
procedure convert_addresses
|
||||
(addrs : System.Address;
|
||||
n_addr : Integer;
|
||||
buf : System.Address;
|
||||
len : System.Address);
|
||||
(filename : System.Address;
|
||||
addrs : System.Address;
|
||||
n_addrs : Integer;
|
||||
buf : System.Address;
|
||||
len : System.Address);
|
||||
pragma Import (C, convert_addresses, "convert_addresses");
|
||||
-- This is the procedure version of the Ada aware addr2line that will
|
||||
-- use argv[0] as the executable containing the debug information.
|
||||
-- This is the procedure version of the Ada aware addr2line. It places
|
||||
-- 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
|
||||
-- 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.
|
||||
--
|
||||
-- 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);
|
||||
Len : Integer;
|
||||
|
||||
use type System.Address;
|
||||
|
||||
begin
|
||||
if Traceback'Length > 0 then
|
||||
TSL.Lock_Task.all;
|
||||
-- The symbolic translation of an empty set of addresses is the
|
||||
-- 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
|
||||
(Traceback'Address, Traceback'Length, Res (1)'Address, Len'Address);
|
||||
TSL.Unlock_Task.all;
|
||||
(Exename, Traceback'Address, Traceback'Length,
|
||||
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);
|
||||
else
|
||||
return "";
|
||||
end if;
|
||||
|
||||
end Symbolic_Traceback;
|
||||
|
||||
function Symbolic_Traceback (E : Exception_Occurrence) return String is
|
||||
|
@ -6,7 +6,7 @@
|
||||
* *
|
||||
* 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 *
|
||||
* terms of the GNU General Public License as published by the Free Soft- *
|
||||
@ -54,7 +54,7 @@ static FILE *gmemfile;
|
||||
|
||||
/* tb_len is the number of call level supported by this module */
|
||||
#define tb_len 200
|
||||
static char * tracebk [tb_len];
|
||||
static void * tracebk [tb_len];
|
||||
static int cur_tb_len, cur_tb_pos;
|
||||
|
||||
#define LOG_EOF '*'
|
||||
@ -67,8 +67,34 @@ struct struct_storage_elmt {
|
||||
size_t Size;
|
||||
};
|
||||
|
||||
extern void
|
||||
convert_addresses (char *addrs[], int n_addr, void *buf, int *len);
|
||||
static void
|
||||
__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
|
||||
array. cur_tb_len is the size of this array
|
||||
@ -78,7 +104,7 @@ static void
|
||||
gmem_read_backtrace (void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -106,14 +132,11 @@ int __gnat_gmem_initialize (char *dumpname)
|
||||
|
||||
/* initialize addr2line library */
|
||||
|
||||
void __gnat_gmem_a2l_initialize (char *exename)
|
||||
void __gnat_gmem_a2l_initialize (char *exearg)
|
||||
{
|
||||
extern char **gnat_argv;
|
||||
char s [100];
|
||||
int l;
|
||||
|
||||
gnat_argv [0] = exename;
|
||||
convert_addresses (tracebk, 1, s, &l);
|
||||
/* Resolve the executable filename to use in later invocations of
|
||||
the libaddr2line symbolization service. */
|
||||
exename = __gnat_locate_exec_on_path (exearg);
|
||||
}
|
||||
|
||||
/* Read next allocation of deallocation information from the GMEM file and
|
||||
@ -172,8 +195,7 @@ void __gnat_gmem_read_next_frame (void** addr)
|
||||
|
||||
void __gnat_gmem_symbolic (void * addr, char* buf, int* length)
|
||||
{
|
||||
char* addresses [] = { (char*)addr };
|
||||
extern char** gnat_argv;
|
||||
void * addresses [] = { addr };
|
||||
|
||||
convert_addresses (addresses, 1, buf, length);
|
||||
__gnat_convert_addresses (addresses, 1, buf, length);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user