s-dwalin.ads, [...]: New.

2017-09-08  Arnaud Charlet <charlet@adacore.com>

	* s-dwalin.ads, s-dwalin.adb, s-trasym-dwarf.adb, s-objrea.ads,
	s-objrea.adb, s-tsmona-linux.adb, s-tsmona-mingw.adb: New.
	* gcc-interface/Makefile.in: Enable s-trasym-dwarf.adb on x86*linux.

From-SVN: r251887
This commit is contained in:
Arnaud Charlet 2017-09-08 13:00:52 +02:00
parent 6a237c4530
commit a2529c0aa7
8 changed files with 5512 additions and 0 deletions

View File

@ -429,6 +429,25 @@ X86_64_TARGET_PAIRS = \
a-numaux.adb<a-numaux-x86.adb \
s-atocou.adb<s-atocou-builtin.adb
# Implementation of symbolic traceback based on dwarf
TRASYM_DWARF_UNIX_PAIRS = \
s-trasym.adb<s-trasym-dwarf.adb \
s-mmosin.ads<s-mmosin-unix.ads \
s-mmosin.adb<s-mmosin-unix.adb \
s-mmauni.ads<s-mmauni-long.ads
TRASYM_DWARF_MINGW_PAIRS = \
s-trasym.adb<s-trasym-dwarf.adb \
s-mmosin.ads<s-mmosin-mingw.ads \
s-mmosin.adb<s-mmosin-mingw.adb
TRASYM_DWARF_COMMON_OBJS = s-objrea$(objext) s-dwalin$(objext) s-mmap$(objext) \
s-mmosin$(objext)
TRASYM_DWARF_UNIX_OBJS = $(TRASYM_DWARF_COMMON_OBJS) s-mmauni$(objext)
TRASYM_DWARF_MINGW_OBJS = $(TRASYM_DWARF_COMMON_OBJS)
# Shared library version
LIB_VERSION = $(strip $(shell grep ' Library_Version :' $(fsrcpfx)ada/gnatvsn.ads | sed -e 's/.*"\(.*\)".*/\1/'))
@ -1085,7 +1104,9 @@ ifeq ($(strip $(filter-out %86 linux%,$(target_cpu) $(target_os))),)
s-inmaop.adb<s-inmaop-posix.adb \
s-intman.adb<s-intman-posix.adb \
s-tpopsp.adb<s-tpopsp-tls.adb \
$(TRASYM_DWARF_UNIX_PAIRS) \
g-sercom.adb<g-sercom-linux.adb \
s-tsmona.adb<s-tsmona-linux.adb \
a-exetim.adb<a-exetim-posix.adb \
a-exetim.ads<a-exetim-default.ads \
s-linux.ads<s-linux.ads \
@ -1111,6 +1132,7 @@ ifeq ($(strip $(filter-out %86 linux%,$(target_cpu) $(target_os))),)
EH_MECHANISM=-gcc
THREADSLIB = -lpthread -lrt
EXTRA_GNATRTL_NONTASKING_OBJS += g-sse.o g-ssvety.o
EXTRA_GNATRTL_NONTASKING_OBJS += $(TRASYM_DWARF_UNIX_OBJS)
EXTRA_GNATRTL_TASKING_OBJS=s-linux.o a-exetim.o
TOOLS_TARGET_PAIRS = indepsw.adb<indepsw-gnu.adb
@ -1907,6 +1929,8 @@ ifeq ($(strip $(filter-out %x86_64 linux%,$(target_cpu) $(target_os))),)
s-tpopsp.adb<s-tpopsp-tls.adb \
s-taspri.ads<s-taspri-posix.ads \
g-sercom.adb<g-sercom-linux.adb \
$(TRASYM_DWARF_UNIX_PAIRS) \
s-tsmona.adb<s-tsmona-linux.adb \
$(ATOMICS_TARGET_PAIRS) \
$(X86_64_TARGET_PAIRS) \
system.ads<system-linux-x86.ads
@ -1914,6 +1938,7 @@ ifeq ($(strip $(filter-out %x86_64 linux%,$(target_cpu) $(target_os))),)
TOOLS_TARGET_PAIRS = indepsw.adb<indepsw-gnu.adb
EXTRA_GNATRTL_NONTASKING_OBJS += g-sse.o g-ssvety.o
EXTRA_GNATRTL_NONTASKING_OBJS += $(TRASYM_DWARF_UNIX_OBJS)
EXTRA_GNATRTL_TASKING_OBJS=s-linux.o a-exetim.o
EH_MECHANISM=-gcc

1627
gcc/ada/s-dwalin.adb Normal file

File diff suppressed because it is too large Load Diff

191
gcc/ada/s-dwalin.ads Normal file
View File

@ -0,0 +1,191 @@
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S Y S T E M . D W A R F _ L I N E S --
-- --
-- S p e c --
-- --
-- Copyright (C) 2009-2017, 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- --
-- 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 --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This package provides routines to read DWARF line number information from
-- a generic object file with as little overhead as possible. This allows
-- conversions from PC addresses to human readable source locations.
--
-- Objects must be built with debugging information, however only the
-- .debug_line section of the object file is referenced. In cases where object
-- size is a consideration it's possible to strip all other .debug sections,
-- which will decrease the size of the object significantly.
pragma Polling (Off);
-- We must turn polling off for this unit, because otherwise we can get
-- elaboration circularities when polling is turned on
with Ada.Exceptions.Traceback;
with System.Object_Reader;
with System.Storage_Elements;
with System.Bounded_Strings;
package System.Dwarf_Lines is
package AET renames Ada.Exceptions.Traceback;
package SOR renames System.Object_Reader;
type Dwarf_Context (In_Exception : Boolean := False) is private;
-- Type encapsulation the state of the Dwarf reader. When In_Exception
-- is True we are parsing as part of a exception handler decorator, we do
-- not want an exception to be raised, the parsing is done safely skipping
-- DWARF file that cannot be read or with stripped debug section for
-- example.
procedure Open
(File_Name : String;
C : out Dwarf_Context;
Success : out Boolean);
procedure Close (C : in out Dwarf_Context);
-- Open and close files
procedure Set_Load_Address (C : in out Dwarf_Context; Addr : Address);
-- Set the load address of a file. This is used to rebase PIE (Position
-- Independant Executable) binaries.
function Is_Inside (C : Dwarf_Context; Addr : Address) return Boolean;
pragma Inline (Is_Inside);
-- Return true iff Addr is within the module
function Low (C : Dwarf_Context) return Address;
pragma Inline (Low);
-- Return the lowest address of C
procedure Dump (C : in out Dwarf_Context);
-- Dump each row found in the object's .debug_lines section to standard out
procedure Dump_Cache (C : Dwarf_Context);
-- Dump the cache (if present)
procedure Enable_Cache (C : in out Dwarf_Context);
-- Read symbols information to speed up Symbolic_Traceback.
procedure Symbolic_Traceback
(Cin : Dwarf_Context;
Traceback : AET.Tracebacks_Array;
Suppress_Hex : Boolean;
Symbol_Found : in out Boolean;
Res : in out System.Bounded_Strings.Bounded_String);
-- Generate a string for a traceback suitable for displaying to the user.
-- If one or more symbols are found, Symbol_Found is set to True. This
-- allows the caller to fall back to hexadecimal addresses.
Dwarf_Error : exception;
-- Raised if a problem is encountered parsing DWARF information. Can be a
-- result of a logic error or malformed DWARF information.
private
-- The following section numbers reference
-- "DWARF Debugging Information Format, Version 3"
-- published by the Standards Group, http://freestandards.org.
-- 6.2.2 State Machine Registers
type Line_Info_Registers is record
Address : SOR.uint64;
File : SOR.uint32;
Line : SOR.uint32;
Column : SOR.uint32;
Is_Stmt : Boolean;
Basic_Block : Boolean;
End_Sequence : Boolean;
Prologue_End : Boolean;
Epilogue_Begin : Boolean;
ISA : SOR.uint32;
Is_Row : Boolean;
end record;
-- 6.2.4 The Line Number Program Prologue
MAX_OPCODE_LENGTHS : constant := 256;
type Opcodes_Lengths_Array is
array (SOR.uint32 range 1 .. MAX_OPCODE_LENGTHS) of SOR.uint8;
type Line_Info_Prologue is record
Unit_Length : SOR.uint32;
Version : SOR.uint16;
Prologue_Length : SOR.uint32;
Min_Isn_Length : SOR.uint8;
Default_Is_Stmt : SOR.uint8;
Line_Base : SOR.int8;
Line_Range : SOR.uint8;
Opcode_Base : SOR.uint8;
Opcode_Lengths : Opcodes_Lengths_Array;
Includes_Offset : SOR.Offset;
File_Names_Offset : SOR.Offset;
end record;
type Search_Entry is record
First : SOR.uint32;
Size : SOR.uint32;
-- Function bounds as offset to the base address.
Sym : SOR.uint32;
-- Symbol offset to get the name.
Line : SOR.uint32;
-- Dwarf line offset.
end record;
type Search_Array is array (Natural range <>) of Search_Entry;
type Search_Array_Access is access Search_Array;
type Dwarf_Context (In_Exception : Boolean := False) is record
Load_Slide : System.Storage_Elements.Integer_Address := 0;
Low, High : Address;
-- Bounds of the module
Obj : SOR.Object_File_Access;
-- The object file containing dwarf sections
Has_Debug : Boolean;
-- True if all debug sections are available
Cache : Search_Array_Access;
-- Quick access to symbol and debug info (when present).
Lines : SOR.Mapped_Stream;
Aranges : SOR.Mapped_Stream;
Info : SOR.Mapped_Stream;
Abbrev : SOR.Mapped_Stream;
-- Dwarf line, aranges, info and abbrev sections
Prologue : Line_Info_Prologue;
Registers : Line_Info_Registers;
Next_Prologue : SOR.Offset;
-- State for lines
end record;
end System.Dwarf_Lines;

2246
gcc/ada/s-objrea.adb Normal file

File diff suppressed because it is too large Load Diff

451
gcc/ada/s-objrea.ads Normal file
View File

@ -0,0 +1,451 @@
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S Y S T E M . O B J E C T _ R E A D E R --
-- --
-- S p e c --
-- --
-- Copyright (C) 2009-2017, 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- --
-- 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 --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This package implements a simple, minimal overhead reader for object files
-- composed of sections of untyped heterogeneous binary data.
with Interfaces;
with System.Mmap;
package System.Object_Reader is
--------------
-- Limits --
--------------
BUFFER_SIZE : constant := 8 * 1024;
------------------
-- Object files --
------------------
type Object_File (<>) is private;
type Object_File_Access is access Object_File;
---------------------
-- Object sections --
----------------------
type Object_Section is private;
Null_Section : constant Object_Section;
--------------------
-- Object symbols --
--------------------
type Object_Symbol is private;
------------------------
-- Object format type --
------------------------
type Object_Format is
(ELF32,
-- Object format is 32-bit ELF
ELF64,
-- Object format is 64-bit ELF
PECOFF,
-- Object format is Microsoft PECOFF
PECOFF_PLUS,
-- Object format is Microsoft PECOFF+
XCOFF32);
-- Object format is AIX 32-bit XCOFF
-- PECOFF | PECOFF_PLUS appears so often as a case choice, would
-- seem a good idea to have a subtype name covering these two choices ???
------------------------------
-- Object architecture type --
------------------------------
type Object_Arch is
(Unknown,
-- The target architecture has not yet been determined
SPARC,
-- 32-bit SPARC
SPARC64,
-- 64-bit SPARC
i386,
-- Intel IA32
MIPS,
-- MIPS Technologies MIPS
x86_64,
-- x86-64 (64-bit AMD/Intel)
IA64,
-- Intel IA64
PPC,
-- 32-bit PowerPC
PPC64);
-- 64-bit PowerPC
------------------
-- Target types --
------------------
subtype Offset is Interfaces.Integer_64;
subtype uint8 is Interfaces.Unsigned_8;
subtype uint16 is Interfaces.Unsigned_16;
subtype uint32 is Interfaces.Unsigned_32;
subtype uint64 is Interfaces.Unsigned_64;
subtype int8 is Interfaces.Integer_8;
subtype int16 is Interfaces.Integer_16;
subtype int32 is Interfaces.Integer_32;
subtype int64 is Interfaces.Integer_64;
type Buffer is array (0 .. BUFFER_SIZE - 1) of uint8;
type String_Ptr_Len is record
Ptr : Mmap.Str_Access;
Len : Natural;
end record;
-- A string made from a pointer and a length. Not all strings for name
-- are C strings: COFF inlined symbol names have a max length of 8.
-------------------------------------------
-- Operations on buffers of untyped data --
-------------------------------------------
function To_String (Buf : Buffer) return String;
-- Construct string from C style null-terminated string stored in a buffer
function To_String_Ptr_Len
(Ptr : Mmap.Str_Access;
Max_Len : Natural := Natural'Last) return String_Ptr_Len;
-- Convert PTR to a String_Ptr_Len.
function Strlen (Buf : Buffer) return int32;
-- Return the length of a C style null-terminated string
-------------------------
-- Opening and closing --
-------------------------
function Open
(File_Name : String;
In_Exception : Boolean := False) return Object_File_Access;
-- Open the object file and initialize the reader. In_Exception is true
-- when the parsing is done as part of an exception handler decorator. In
-- this mode we do not want to raise an exception.
procedure Close (Obj : in out Object_File);
-- Close the object file
-----------------------
-- Sequential access --
-----------------------
type Mapped_Stream is private;
-- Provide an abstraction of a stream on a memory mapped file
function Create_Stream (Mf : System.Mmap.Mapped_File;
File_Offset : System.Mmap.File_Size;
File_Length : System.Mmap.File_Size)
return Mapped_Stream;
-- Create a stream from Mf
procedure Close (S : in out Mapped_Stream);
-- Close the stream (deallocate memory)
procedure Read_Raw
(S : in out Mapped_Stream;
Addr : Address;
Size : uint32);
pragma Inline (Read_Raw);
-- Read a number of fixed sized records
procedure Seek (S : in out Mapped_Stream; Off : Offset);
-- Seek to an absolute offset in bytes
procedure Tell (Obj : in out Mapped_Stream; Off : out Offset)
with Inline;
function Tell (Obj : Mapped_Stream) return Offset
with Inline;
-- Fetch the current offset
function Length (Obj : Mapped_Stream) return Offset
with Inline;
-- Length of the stream
function Read (S : in out Mapped_Stream) return Mmap.Str_Access;
-- Provide a pointer in memory at the current offset
function Read (S : in out Mapped_Stream) return String_Ptr_Len;
-- Provide a pointer in memory at the current offset
function Read (S : in out Mapped_Stream) return uint8;
function Read (S : in out Mapped_Stream) return uint16;
function Read (S : in out Mapped_Stream) return uint32;
function Read (S : in out Mapped_Stream) return uint64;
function Read (S : in out Mapped_Stream) return int8;
function Read (S : in out Mapped_Stream) return int16;
function Read (S : in out Mapped_Stream) return int32;
function Read (S : in out Mapped_Stream) return int64;
-- Read a scalar
function Read_Address
(Obj : Object_File; S : in out Mapped_Stream) return uint64;
-- Read either a 64 or 32 bit address from the file stream depending on the
-- address size of the target architecture and promote it to a 64 bit type.
function Read_LEB128 (S : in out Mapped_Stream) return uint32;
function Read_LEB128 (S : in out Mapped_Stream) return int32;
-- Read a value encoding in Little-Endian Base 128 format
procedure Read_C_String (S : in out Mapped_Stream; B : out Buffer);
function Read_C_String (S : in out Mapped_Stream) return Mmap.Str_Access;
-- Read a C style NULL terminated string
function Offset_To_String
(S : in out Mapped_Stream;
Off : Offset) return String;
-- Construct a string from a C style NULL terminated string located at an
-- offset into the object file.
------------------------
-- Object information --
------------------------
function Arch (Obj : Object_File) return Object_Arch;
-- Return the object architecture
function Format (Obj : Object_File) return Object_Format;
-- Return the object file format
function Get_Load_Address (Obj : Object_File) return uint64;
-- Return the load address defined in Obj. May raise Format_Error if not
-- implemented
function Num_Sections (Obj : Object_File) return uint32;
-- Return the number of sections composing the object file
function Get_Section
(Obj : in out Object_File;
Shnum : uint32) return Object_Section;
-- Return the Nth section (numbered from zero)
function Get_Section
(Obj : in out Object_File;
Sec_Name : String) return Object_Section;
-- Return a section by name
function Create_Stream
(Obj : Object_File;
Sec : Object_Section) return Mapped_Stream;
-- Create a stream for section Sec
procedure Get_Memory_Bounds
(Obj : in out Object_File;
Low, High : out uint64);
-- Return the low and high addresses of the code for the object file. Can
-- be used to check if an address in within this object file. This
-- procedure is not efficient and the result should be saved to avoid
-- recomputation.
-------------------------
-- Section information --
-------------------------
function Name
(Obj : in out Object_File;
Sec : Object_Section) return String;
-- Return the name of a section as a string
function Size (Sec : Object_Section) return uint64;
-- Return the size of a section in bytes
function Num (Sec : Object_Section) return uint32;
-- Return the index of a section from zero
function Off (Sec : Object_Section) return Offset;
-- Return the byte offset of the section within the object
------------------------------
-- Symbol table information --
------------------------------
Null_Symbol : constant Object_Symbol;
-- An empty symbol table entry.
function First_Symbol (Obj : in out Object_File) return Object_Symbol;
-- Return the first element in the symbol table or Null_Symbol if the
-- symbol table is empty.
function Next_Symbol
(Obj : in out Object_File;
Prev : Object_Symbol) return Object_Symbol;
-- Return the element following Prev in the symbol table, or Null_Symbol if
-- Prev is the last symbol in the table.
function Read_Symbol
(Obj : in out Object_File;
Off : Offset) return Object_Symbol;
-- Read symbol at Off
function Name
(Obj : in out Object_File;
Sym : Object_Symbol) return String_Ptr_Len;
-- Return the name of the symbol
function Decoded_Ada_Name
(Obj : in out Object_File;
Sym : String_Ptr_Len) return String;
-- Return the decoded name of a symbol encoded as per exp_dbug.ads
function Strip_Leading_Char
(Obj : in out Object_File;
Sym : String_Ptr_Len) return Positive;
-- Return the index of the first character to decode the name. This can
-- strip one character for ABI with a prefix (like x86 for PECOFF).
function Value (Sym : Object_Symbol) return uint64;
-- Return the name of the symbol
function Size (Sym : Object_Symbol) return uint64;
-- Return the size of the symbol in bytes
function Spans (Sym : Object_Symbol; Addr : uint64) return Boolean;
-- Determine whether a particular address corresponds to the range
-- referenced by this symbol.
function Off (Sym : Object_Symbol) return Offset;
-- Return the offset of the symbol.
----------------
-- Exceptions --
----------------
IO_Error : exception;
-- Input/Output error reading file
Format_Error : exception;
-- Encountered a problem parsing the object
private
type Mapped_Stream is record
Region : System.Mmap.Mapped_Region;
Off : Offset;
Len : Offset;
end record;
subtype ELF is Object_Format range ELF32 .. ELF64;
subtype Any_PECOFF is Object_Format range PECOFF .. PECOFF_PLUS;
type Object_File (Format : Object_Format) is record
Mf : System.Mmap.Mapped_File :=
System.Mmap.Invalid_Mapped_File;
Arch : Object_Arch := Unknown;
Num_Sections : uint32 := 0;
-- Number of sections
Symtab_Last : Offset; -- Last offset of symbol table
In_Exception : Boolean := False;
-- True if the parsing is done as part of an exception handler
Sectab_Stream : Mapped_Stream;
-- Section table
Symtab_Stream : Mapped_Stream;
-- Symbol table
Symstr_Stream : Mapped_Stream;
-- Symbol strings
case Format is
when ELF =>
Secstr_Stream : Mapped_Stream;
-- Section strings
when Any_PECOFF =>
ImageBase : uint64; -- ImageBase value from header
-- Cache for latest result of Get_Section_Virtual_Address
GSVA_Sec : uint32 := uint32'Last;
GSVA_Addr : uint64;
when XCOFF32 =>
null;
end case;
end record;
subtype ELF_Object_File is Object_File; -- with
-- Predicate => ELF_Object_File.Format in ELF;
subtype PECOFF_Object_File is Object_File; -- with
-- Predicate => PECOFF_Object_File.Format in Any_PECOFF;
subtype XCOFF32_Object_File is Object_File; -- with
-- Predicate => XCOFF32_Object_File.Format in XCOFF32;
-- ???Above predicates cause the compiler to crash when instantiating
-- ELF64_Ops (see package body).
type Object_Section is record
Num : uint32 := 0;
-- Section index in the section table
Off : Offset := 0;
-- First byte of the section in the object file
Addr : uint64 := 0;
-- Load address of the section. Valid only when Flag_Alloc is true.
Size : uint64 := 0;
-- Length of the section in bytes
Flag_Alloc : Boolean := False;
-- True if the section is mapped in memory by the OS loader
end record;
Null_Section : constant Object_Section := (0, 0, 0, 0, False);
type Object_Symbol is record
Off : Offset := 0; -- Offset of underlying symbol on disk
Next : Offset := 0; -- Offset of the following symbol
Value : uint64 := 0; -- Value associated with this symbol
Size : uint64 := 0; -- Size of the referenced entity
end record;
Null_Symbol : constant Object_Symbol := (0, 0, 0, 0);
end System.Object_Reader;

689
gcc/ada/s-trasym-dwarf.adb Normal file
View File

@ -0,0 +1,689 @@
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- S Y S T E M . T R A C E B A C K . S Y M B O L I C --
-- --
-- B o d y --
-- --
-- Copyright (C) 1999-2017, 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 --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- Run-time symbolic traceback support for targets using DWARF debug data
pragma Polling (Off);
-- We must turn polling off for this unit, because otherwise we can get
-- elaboration circularities when polling is turned on.
with Ada.Unchecked_Deallocation;
with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
with Ada.Containers.Generic_Array_Sort;
with System.Address_To_Access_Conversions;
with System.Soft_Links;
with System.CRTL;
with System.Dwarf_Lines;
with System.Exception_Traces;
with System.Standard_Library;
with System.Traceback_Entries;
with System.Strings;
with System.Bounded_Strings;
package body System.Traceback.Symbolic is
use System.Bounded_Strings;
use System.Dwarf_Lines;
subtype Big_String is String (Positive);
-- To deal with C strings
package Big_String_Conv is new System.Address_To_Access_Conversions
(Big_String);
type Module_Cache;
type Module_Cache_Acc is access all Module_Cache;
type Module_Cache is record
Name : Strings.String_Access;
-- Name of the module
C : Dwarf_Context (In_Exception => True);
-- Context to symbolize an address within this module
Chain : Module_Cache_Acc;
end record;
procedure Free is new Ada.Unchecked_Deallocation
(Module_Cache,
Module_Cache_Acc);
Cache_Chain : Module_Cache_Acc;
-- Simply linked list of modules
type Module_Array is array (Natural range <>) of Module_Cache_Acc;
type Module_Array_Acc is access Module_Array;
Modules_Cache : Module_Array_Acc;
-- Sorted array of cached modules (if not null)
Exec_Module : aliased Module_Cache;
-- Context for the executable
type Init_State is (Uninitialized, Initialized, Failed);
Exec_Module_State : Init_State := Uninitialized;
-- How Exec_Module is initialized
procedure Init_Exec_Module;
-- Initialize Exec_Module if not already initialized
function Symbolic_Traceback
(Traceback : System.Traceback_Entries.Tracebacks_Array;
Suppress_Hex : Boolean) return String;
function Symbolic_Traceback
(E : Ada.Exceptions.Exception_Occurrence;
Suppress_Hex : Boolean) return String;
-- Suppress_Hex means do not print any hexadecimal addresses, even if the
-- symbol is not available.
function Lt (Left, Right : Module_Cache_Acc) return Boolean;
-- Sort function for Module_Cache
procedure Init_Module
(Module : out Module_Cache;
Success : out Boolean;
Module_Name : String;
Load_Address : Address := Null_Address);
-- Initialize Module
procedure Close_Module (Module : in out Module_Cache);
-- Finalize Module
function Value (Item : System.Address) return String;
-- Return the String contained in Item, up until the first NUL character
pragma Warnings (Off, "*Add_Module_To_Cache*");
procedure Add_Module_To_Cache (Module_Name : String);
-- To be called by Build_Cache_For_All_Modules to add a new module to the
-- list. May not be referenced.
package Module_Name is
procedure Build_Cache_For_All_Modules;
-- Create the cache for all current modules
function Get (Addr : access System.Address) return String;
-- Returns the module name for the given address, Addr may be updated
-- to be set relative to a shared library. This depends on the platform.
-- Returns an empty string for the main executable.
function Is_Supported return Boolean;
pragma Inline (Is_Supported);
-- Returns True if Module_Name is supported, so if the traceback is
-- supported for shared libraries.
end Module_Name;
package body Module_Name is separate;
function Executable_Name return String;
-- Returns the executable name as reported by argv[0]. If gnat_argv not
-- initialized or if argv[0] executable not found in path, function returns
-- an empty string.
function Get_Executable_Load_Address return System.Address;
pragma Import
(C,
Get_Executable_Load_Address,
"__gnat_get_executable_load_address");
-- Get the load address of the executable, or Null_Address if not known
procedure Hexa_Traceback
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean;
Res : in out Bounded_String);
-- Non-symbolic traceback (simply write addresses in hexa)
procedure Symbolic_Traceback_No_Lock
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean;
Res : in out Bounded_String);
-- Like the public Symbolic_Traceback_No_Lock except there is no provision
-- against concurrent accesses.
procedure Module_Symbolic_Traceback
(Traceback : Tracebacks_Array;
Module : Module_Cache;
Suppress_Hex : Boolean;
Res : in out Bounded_String);
-- Returns the Traceback for a given module
procedure Multi_Module_Symbolic_Traceback
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean;
Res : in out Bounded_String);
-- Build string containing symbolic traceback for the given call chain
procedure Multi_Module_Symbolic_Traceback
(Traceback : Tracebacks_Array;
Module : Module_Cache;
Suppress_Hex : Boolean;
Res : in out Bounded_String);
-- Likewise but using Module
Max_String_Length : constant := 4096;
-- Arbitrary limit on Bounded_Str length
-----------
-- Value --
-----------
function Value (Item : System.Address) return String is
begin
if Item /= Null_Address then
for J in Big_String'Range loop
if Big_String_Conv.To_Pointer (Item) (J) = ASCII.NUL then
return Big_String_Conv.To_Pointer (Item) (1 .. J - 1);
end if;
end loop;
end if;
return "";
end Value;
-------------------------
-- Add_Module_To_Cache --
-------------------------
procedure Add_Module_To_Cache (Module_Name : String) is
Module : Module_Cache_Acc;
Success : Boolean;
begin
Module := new Module_Cache;
Init_Module (Module.all, Success, Module_Name);
if not Success then
Free (Module);
return;
end if;
Module.Chain := Cache_Chain;
Cache_Chain := Module;
end Add_Module_To_Cache;
----------------------
-- Init_Exec_Module --
----------------------
procedure Init_Exec_Module is
begin
if Exec_Module_State = Uninitialized then
declare
Exec_Path : constant String := Executable_Name;
Exec_Load : constant Address := Get_Executable_Load_Address;
Success : Boolean;
begin
Init_Module (Exec_Module, Success, Exec_Path, Exec_Load);
if Success then
Exec_Module_State := Initialized;
else
Exec_Module_State := Failed;
end if;
end;
end if;
end Init_Exec_Module;
--------
-- Lt --
--------
function Lt (Left, Right : Module_Cache_Acc) return Boolean is
begin
return Low (Left.C) < Low (Right.C);
end Lt;
-----------------------------
-- Module_Cache_Array_Sort --
-----------------------------
procedure Module_Cache_Array_Sort is new Ada.Containers.Generic_Array_Sort
(Natural,
Module_Cache_Acc,
Module_Array,
Lt);
------------------
-- Enable_Cache --
------------------
procedure Enable_Cache (Include_Modules : Boolean := False) is
begin
-- Can be called at most once
if Cache_Chain /= null then
return;
end if;
-- Add all modules
Init_Exec_Module;
Cache_Chain := Exec_Module'Access;
if Include_Modules then
Module_Name.Build_Cache_For_All_Modules;
end if;
-- Build and fill the array of modules
declare
Count : Natural;
Module : Module_Cache_Acc;
begin
for Phase in 1 .. 2 loop
Count := 0;
Module := Cache_Chain;
while Module /= null loop
Count := Count + 1;
if Phase = 1 then
Enable_Cache (Module.C);
else
Modules_Cache (Count) := Module;
end if;
Module := Module.Chain;
end loop;
if Phase = 1 then
Modules_Cache := new Module_Array (1 .. Count);
end if;
end loop;
end;
-- Sort the array
Module_Cache_Array_Sort (Modules_Cache.all);
end Enable_Cache;
---------------------
-- Executable_Name --
---------------------
function Executable_Name return String is
-- We have to import gnat_argv as an Address to match the type of
-- gnat_argv in the binder generated file. Otherwise, we get spurious
-- warnings about type mismatch when LTO is turned on.
Gnat_Argv : System.Address;
pragma Import (C, Gnat_Argv, "gnat_argv");
type Argv_Array is array (0 .. 0) of System.Address;
package Conv is new System.Address_To_Access_Conversions (Argv_Array);
function locate_exec_on_path (A : System.Address) return System.Address;
pragma Import (C, locate_exec_on_path, "__gnat_locate_exec_on_path");
begin
if Gnat_Argv = Null_Address then
return "";
end if;
declare
Addr : constant System.Address :=
locate_exec_on_path (Conv.To_Pointer (Gnat_Argv) (0));
Result : constant String := Value (Addr);
begin
-- The buffer returned by locate_exec_on_path was allocated using
-- malloc, so we should use free to release the memory.
if Addr /= Null_Address then
System.CRTL.free (Addr);
end if;
return Result;
end;
end Executable_Name;
------------------
-- Close_Module --
------------------
procedure Close_Module (Module : in out Module_Cache) is
begin
Close (Module.C);
Strings.Free (Module.Name);
end Close_Module;
-----------------
-- Init_Module --
-----------------
procedure Init_Module
(Module : out Module_Cache;
Success : out Boolean;
Module_Name : String;
Load_Address : Address := Null_Address)
is
begin
-- Early return if the module is not known
if Module_Name = "" then
Success := False;
return;
end if;
Open (Module_Name, Module.C, Success);
-- If a module can't be opened just return now, we just cannot give more
-- information in this case.
if not Success then
return;
end if;
Set_Load_Address (Module.C, Load_Address);
Module.Name := new String'(Module_Name);
end Init_Module;
-------------------------------
-- Module_Symbolic_Traceback --
-------------------------------
procedure Module_Symbolic_Traceback
(Traceback : Tracebacks_Array;
Module : Module_Cache;
Suppress_Hex : Boolean;
Res : in out Bounded_String)
is
Success : Boolean := False;
begin
if Symbolic.Module_Name.Is_Supported then
Append (Res, '[');
Append (Res, Module.Name.all);
Append (Res, ']' & ASCII.LF);
end if;
Dwarf_Lines.Symbolic_Traceback
(Module.C,
Traceback,
Suppress_Hex,
Success,
Res);
if not Success then
Hexa_Traceback (Traceback, Suppress_Hex, Res);
end if;
-- We must not allow an unhandled exception here, since this function
-- may be installed as a decorator for all automatic exceptions.
exception
when others =>
return;
end Module_Symbolic_Traceback;
-------------------------------------
-- Multi_Module_Symbolic_Traceback --
-------------------------------------
procedure Multi_Module_Symbolic_Traceback
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean;
Res : in out Bounded_String)
is
F : constant Natural := Traceback'First;
begin
if Traceback'Length = 0 or else Is_Full (Res) then
return;
end if;
if Modules_Cache /= null then
-- Search in the cache
declare
Addr : constant Address := Traceback (F);
Hi, Lo, Mid : Natural;
begin
Lo := Modules_Cache'First;
Hi := Modules_Cache'Last;
while Lo <= Hi loop
Mid := (Lo + Hi) / 2;
if Addr < Low (Modules_Cache (Mid).C) then
Hi := Mid - 1;
elsif Is_Inside (Modules_Cache (Mid).C, Addr) then
Multi_Module_Symbolic_Traceback
(Traceback,
Modules_Cache (Mid).all,
Suppress_Hex,
Res);
return;
else
Lo := Mid + 1;
end if;
end loop;
-- Not found
Hexa_Traceback (Traceback (F .. F), Suppress_Hex, Res);
Multi_Module_Symbolic_Traceback
(Traceback (F + 1 .. Traceback'Last),
Suppress_Hex,
Res);
end;
else
-- First try the executable
if Is_Inside (Exec_Module.C, Traceback (F)) then
Multi_Module_Symbolic_Traceback
(Traceback,
Exec_Module,
Suppress_Hex,
Res);
return;
end if;
-- Otherwise, try a shared library
declare
Addr : aliased System.Address := Traceback (F);
M_Name : constant String := Module_Name.Get (Addr'Access);
Module : Module_Cache;
Success : Boolean;
begin
Init_Module (Module, Success, M_Name, System.Null_Address);
if Success then
Multi_Module_Symbolic_Traceback
(Traceback,
Module,
Suppress_Hex,
Res);
Close_Module (Module);
else
-- Module not found
Hexa_Traceback (Traceback (F .. F), Suppress_Hex, Res);
Multi_Module_Symbolic_Traceback
(Traceback (F + 1 .. Traceback'Last),
Suppress_Hex,
Res);
end if;
end;
end if;
end Multi_Module_Symbolic_Traceback;
procedure Multi_Module_Symbolic_Traceback
(Traceback : Tracebacks_Array;
Module : Module_Cache;
Suppress_Hex : Boolean;
Res : in out Bounded_String)
is
Pos : Positive;
begin
-- Will symbolize the first address...
Pos := Traceback'First + 1;
-- ... and all addresses in the same module
Same_Module :
loop
exit Same_Module when Pos > Traceback'Last;
-- Get address to check for corresponding module name
exit Same_Module when not Is_Inside (Module.C, Traceback (Pos));
Pos := Pos + 1;
end loop Same_Module;
Module_Symbolic_Traceback
(Traceback (Traceback'First .. Pos - 1),
Module,
Suppress_Hex,
Res);
Multi_Module_Symbolic_Traceback
(Traceback (Pos .. Traceback'Last),
Suppress_Hex,
Res);
end Multi_Module_Symbolic_Traceback;
--------------------
-- Hexa_Traceback --
--------------------
procedure Hexa_Traceback
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean;
Res : in out Bounded_String)
is
use System.Traceback_Entries;
begin
if Suppress_Hex then
Append (Res, "...");
Append (Res, ASCII.LF);
else
for J in Traceback'Range loop
Append_Address (Res, PC_For (Traceback (J)));
Append (Res, ASCII.LF);
end loop;
end if;
end Hexa_Traceback;
--------------------------------
-- Symbolic_Traceback_No_Lock --
--------------------------------
procedure Symbolic_Traceback_No_Lock
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean;
Res : in out Bounded_String)
is
begin
if Symbolic.Module_Name.Is_Supported then
Multi_Module_Symbolic_Traceback (Traceback, Suppress_Hex, Res);
else
if Exec_Module_State = Failed then
Append (Res, "Call stack traceback locations:" & ASCII.LF);
Hexa_Traceback (Traceback, Suppress_Hex, Res);
else
Module_Symbolic_Traceback
(Traceback,
Exec_Module,
Suppress_Hex,
Res);
end if;
end if;
end Symbolic_Traceback_No_Lock;
------------------------
-- Symbolic_Traceback --
------------------------
function Symbolic_Traceback
(Traceback : Tracebacks_Array;
Suppress_Hex : Boolean) return String
is
Res : Bounded_String (Max_Length => Max_String_Length);
begin
System.Soft_Links.Lock_Task.all;
Init_Exec_Module;
Symbolic_Traceback_No_Lock (Traceback, Suppress_Hex, Res);
System.Soft_Links.Unlock_Task.all;
return To_String (Res);
exception
when others =>
System.Soft_Links.Unlock_Task.all;
raise;
end Symbolic_Traceback;
function Symbolic_Traceback
(Traceback : System.Traceback_Entries.Tracebacks_Array) return String is
begin
return Symbolic_Traceback (Traceback, Suppress_Hex => False);
end Symbolic_Traceback;
function Symbolic_Traceback_No_Hex
(Traceback : System.Traceback_Entries.Tracebacks_Array) return String is
begin
return Symbolic_Traceback (Traceback, Suppress_Hex => True);
end Symbolic_Traceback_No_Hex;
function Symbolic_Traceback
(E : Ada.Exceptions.Exception_Occurrence;
Suppress_Hex : Boolean) return String
is
begin
return Symbolic_Traceback
(Ada.Exceptions.Traceback.Tracebacks (E),
Suppress_Hex);
end Symbolic_Traceback;
function Symbolic_Traceback
(E : Ada.Exceptions.Exception_Occurrence) return String
is
begin
return Symbolic_Traceback (E, Suppress_Hex => False);
end Symbolic_Traceback;
function Symbolic_Traceback_No_Hex
(E : Ada.Exceptions.Exception_Occurrence) return String is
begin
return Symbolic_Traceback (E, Suppress_Hex => True);
end Symbolic_Traceback_No_Hex;
Exception_Tracebacks_Symbolic : Integer;
pragma Import
(C,
Exception_Tracebacks_Symbolic,
"__gl_exception_tracebacks_symbolic");
-- Boolean indicating whether symbolic tracebacks should be generated.
use Standard_Library;
begin
-- If this version of this package is available, and the binder switch -Es
-- was given, then we want to use this as the decorator by default, and we
-- want to turn on tracing for Unhandled_Raise_In_Main. Note that the user
-- cannot have already set Exception_Trace, because the runtime library is
-- elaborated before user-defined code.
if Exception_Tracebacks_Symbolic /= 0 then
Exception_Traces.Set_Trace_Decorator (Symbolic_Traceback'Access);
pragma Assert (Exception_Trace = RM_Convention);
Exception_Trace := Unhandled_Raise_In_Main;
end if;
end System.Traceback.Symbolic;

190
gcc/ada/s-tsmona-linux.adb Normal file
View File

@ -0,0 +1,190 @@
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- G N A T . T R A C E B A C K . S Y M B O L I C . M O D U L E _ N A M E --
-- --
-- B o d y --
-- --
-- Copyright (C) 2012-2017, 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 --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This is the GNU/Linux specific version of this package
with Interfaces.C; use Interfaces.C;
with System.Address_Operations; use System.Address_Operations;
separate (System.Traceback.Symbolic)
package body Module_Name is
use System;
pragma Linker_Options ("-ldl");
function Is_Shared_Lib (Base : Address) return Boolean;
-- Returns True if a shared library
-- The principle is:
-- 1. We get information about the module containing the address.
-- 2. We check that the full pathname is pointing to a shared library.
-- 3. for shared libraries, we return the non relocated address (so
-- the absolute address in the shared library).
-- 4. we also return the full pathname of the module containing this
-- address.
-------------------
-- Is_Shared_Lib --
-------------------
function Is_Shared_Lib (Base : Address) return Boolean is
EI_NIDENT : constant := 16;
type u16 is mod 2 ** 16;
-- Just declare the needed header information, we just need to read the
-- type encoded in the second field.
type Elf32_Ehdr is record
e_ident : char_array (1 .. EI_NIDENT);
e_type : u16;
end record;
ET_DYN : constant := 3; -- A shared lib if e_type = ET_DYN
Header : Elf32_Ehdr;
pragma Import (Ada, Header);
-- Suppress initialization in Normalized_Scalars mode
for Header'Address use Base;
begin
return Header.e_type = ET_DYN;
exception
when others =>
return False;
end Is_Shared_Lib;
---------------------------------
-- Build_Cache_For_All_Modules --
---------------------------------
procedure Build_Cache_For_All_Modules is
type link_map;
type link_map_acc is access all link_map;
pragma Convention (C, link_map_acc);
type link_map is record
l_addr : Address;
-- Base address of the shared object
l_name : Address;
-- Null-terminated absolute file name
l_ld : Address;
-- Dynamic section
l_next, l_prev : link_map_acc;
-- Chain
end record;
pragma Convention (C, link_map);
type r_debug_type is record
r_version : Integer;
r_map : link_map_acc;
end record;
pragma Convention (C, r_debug_type);
r_debug : r_debug_type;
pragma Import (C, r_debug, "_r_debug");
lm : link_map_acc;
begin
lm := r_debug.r_map;
while lm /= null loop
if Big_String_Conv.To_Pointer (lm.l_name) (1) /= ASCII.NUL then
-- Discard non-file (like the executable itself or the gate).
Add_Module_To_Cache (Value (lm.l_name));
end if;
lm := lm.l_next;
end loop;
end Build_Cache_For_All_Modules;
---------
-- Get --
---------
function Get (Addr : access System.Address) return String is
-- Dl_info record for Linux, used to get sym reloc offset
type Dl_info is record
dli_fname : System.Address;
dli_fbase : System.Address;
dli_sname : System.Address;
dli_saddr : System.Address;
end record;
function dladdr
(addr : System.Address;
info : not null access Dl_info) return int;
pragma Import (C, dladdr, "dladdr");
-- This is a Linux extension and not POSIX
info : aliased Dl_info;
begin
if dladdr (Addr.all, info'Access) /= 0 then
-- If we have a shared library we need to adjust the address to
-- be relative to the base address of the library.
if Is_Shared_Lib (info.dli_fbase) then
Addr.all := SubA (Addr.all, info.dli_fbase);
end if;
return Value (info.dli_fname);
-- Not found, fallback to executable name
else
return "";
end if;
exception
when others =>
return "";
end Get;
------------------
-- Is_Supported --
------------------
function Is_Supported return Boolean is
begin
return True;
end Is_Supported;
end Module_Name;

View File

@ -0,0 +1,93 @@
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME COMPONENTS --
-- --
-- G N A T . T R A C E B A C K . S Y M B O L I C . M O D U L E _ N A M E --
-- --
-- B o d y --
-- --
-- Copyright (C) 2012-2017, 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 --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This is the Windows specific version of this package
with System.Win32; use System.Win32;
separate (System.Traceback.Symbolic)
package body Module_Name is
use System;
---------------------------------
-- Build_Cache_For_All_Modules --
---------------------------------
procedure Build_Cache_For_All_Modules is
begin
null;
end Build_Cache_For_All_Modules;
---------
-- Get --
---------
function Get (Addr : access System.Address) return String is
Res : DWORD;
hModule : aliased HANDLE;
Path : String (1 .. 1_024);
begin
if GetModuleHandleEx
(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
Addr.all,
hModule'Access) = Win32.TRUE
then
Res := GetModuleFileName (hModule, Path'Address, Path'Length);
if FreeLibrary (hModule) = Win32.FALSE then
null;
end if;
if Res > 0 then
return Path (1 .. Positive (Res));
end if;
end if;
return "";
exception
when others =>
return "";
end Get;
------------------
-- Is_Supported --
------------------
function Is_Supported return Boolean is
begin
return True;
end Is_Supported;
end Module_Name;