aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2021-06-18 16:47:48 +0200
committerPierre-Marie de Rodat <derodat@adacore.com>2021-07-12 12:50:56 +0000
commit5cb3843bca9a28c28dbc1fafd88c144a43e141df (patch)
treeb65375d205ff00b12376e0c0d503c749f50d8e03 /gcc/ada
parent9b89dabfd851f0ee0e9f0c6e141f8e3fba08d1d7 (diff)
downloadgcc-5cb3843bca9a28c28dbc1fafd88c144a43e141df.zip
gcc-5cb3843bca9a28c28dbc1fafd88c144a43e141df.tar.gz
gcc-5cb3843bca9a28c28dbc1fafd88c144a43e141df.tar.bz2
[Ada] Add DWARF 5 support to System.Dwarf_Line
gcc/ada/ * libgnat/s-dwalin.ads: Adjust a few comments left and right. (Line_Info_Register): Comment out unused components. (Line_Info_Header): Add DWARF 5 support. (Dwarf_Context): Likewise. Rename "prologue" into "header". * libgnat/s-dwalin.adb: Alphabetize "with" clauses. (DWARF constants): Add DWARF 5 support and reorder. (For_Each_Row): Adjust. (Initialize_Pass): Likewise. (Initialize_State_Machine): Likewise and fix typo. (Open): Add DWARF 5 support. (Parse_Prologue): Rename into... (Parse_Header): ...this and add DWARF 5 support. (Read_And_Execute_Isn): Rename into... (Read_And_Execute_Insn): ...this and adjust. (To_File_Name): Change parameter name and add DWARF 5 support. (Read_Entry_Format_Array): New procedure. (Skip_Form): Add DWARF 5 support and reorder. (Seek_Abbrev): Do not count entries and add DWARF 5 support. (Debug_Info_Lookup): Add DWARF 5 support. (Symbolic_Address.Set_Result): Likewise. (Symbolic_Address): Adjust.
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/libgnat/s-dwalin.adb842
-rw-r--r--gcc/ada/libgnat/s-dwalin.ads124
2 files changed, 653 insertions, 313 deletions
diff --git a/gcc/ada/libgnat/s-dwalin.adb b/gcc/ada/libgnat/s-dwalin.adb
index 55989c5..4a9d538 100644
--- a/gcc/ada/libgnat/s-dwalin.adb
+++ b/gcc/ada/libgnat/s-dwalin.adb
@@ -30,20 +30,20 @@
------------------------------------------------------------------------------
with Ada.Characters.Handling;
+with Ada.Containers.Generic_Array_Sort;
with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
with Ada.Unchecked_Deallocation;
-with Ada.Containers.Generic_Array_Sort;
with Interfaces; use Interfaces;
with System; use System;
-with System.Storage_Elements; use System.Storage_Elements;
with System.Address_Image;
+with System.Bounded_Strings; use System.Bounded_Strings;
with System.IO; use System.IO;
+with System.Mmap; use System.Mmap;
with System.Object_Reader; use System.Object_Reader;
with System.Traceback_Entries; use System.Traceback_Entries;
-with System.Mmap; use System.Mmap;
-with System.Bounded_Strings; use System.Bounded_Strings;
+with System.Storage_Elements; use System.Storage_Elements;
package body System.Dwarf_Lines is
@@ -60,13 +60,19 @@ package body System.Dwarf_Lines is
(S : in out Mapped_Stream;
Len : out Offset;
Is64 : out Boolean);
- -- Read initial length as specified by Dwarf-4 7.2.2
+ -- Read initial length as specified by 7.2.2
procedure Read_Section_Offset
(S : in out Mapped_Stream;
Len : out Offset;
Is64 : Boolean);
- -- Read a section offset, as specified by Dwarf-4 7.4
+ -- Read a section offset, as specified by 7.4
+
+ procedure Read_Entry_Format_Array
+ (S : in out Mapped_Stream;
+ A : out Entry_Format_Array;
+ Len : uint8);
+ -- Read an entry format array, as specified by 6.2.4.1
procedure Read_Aranges_Entry
(C : in out Dwarf_Context;
@@ -111,24 +117,24 @@ package body System.Dwarf_Lines is
-- a compilation unit.
procedure Initialize_Pass (C : in out Dwarf_Context);
- -- Seek to the first byte of the first prologue and prepare to make a pass
+ -- Seek to the first byte of the first header and prepare to make a pass
-- over the line number entries.
procedure Initialize_State_Machine (C : in out Dwarf_Context);
-- Set all state machine registers to their specified initial values
- procedure Parse_Prologue (C : in out Dwarf_Context);
- -- Decode a DWARF statement program prologue
+ procedure Parse_Header (C : in out Dwarf_Context);
+ -- Decode a DWARF statement program header
- procedure Read_And_Execute_Isn
+ procedure Read_And_Execute_Insn
(C : in out Dwarf_Context;
Done : out Boolean);
-- Read an execute a statement program instruction
function To_File_Name
(C : in out Dwarf_Context;
- Code : uint32) return String;
- -- Extract a file name from the prologue
+ File : uint32) return String;
+ -- Extract a file name from the header
type Callback is not null access procedure (C : in out Dwarf_Context);
procedure For_Each_Row (C : in out Dwarf_Context; F : Callback);
@@ -158,8 +164,25 @@ package body System.Dwarf_Lines is
-- DWARF constants --
-----------------------
+ -- 3.1.1 Full and Partial Compilation Unit Entries
+
+ DW_TAG_Compile_Unit : constant := 16#11#;
+
+ DW_AT_Stmt_List : constant := 16#10#;
+
+ -- 6.2.4.1 Standard Content Descriptions (DWARF 5)
+
+ DW_LNCT_path : constant := 1;
+ DW_LNCT_directory_index : constant := 2;
+ -- DW_LNCT_timestamp : constant := 3;
+ -- DW_LNCT_size : constant := 4;
+ DW_LNCT_MD5 : constant := 5;
+ DW_LNCT_lo_user : constant := 16#2000#;
+ DW_LNCT_hi_user : constant := 16#3fff#;
+
-- 6.2.5.2 Standard Opcodes
+ DW_LNS_extended_op : constant := 0;
DW_LNS_copy : constant := 1;
DW_LNS_advance_pc : constant := 2;
DW_LNS_advance_line : constant := 3;
@@ -175,45 +198,56 @@ package body System.Dwarf_Lines is
-- 6.2.5.3 Extended Opcodes
- DW_LNE_end_sequence : constant := 1;
- DW_LNE_set_address : constant := 2;
- DW_LNE_define_file : constant := 3;
-
- -- From the DWARF version 4 public review draft
-
+ DW_LNE_end_sequence : constant := 1;
+ DW_LNE_set_address : constant := 2;
+ DW_LNE_define_file : constant := 3;
DW_LNE_set_discriminator : constant := 4;
- -- Attribute encodings
-
- DW_TAG_Compile_Unit : constant := 16#11#;
-
- DW_AT_Stmt_List : constant := 16#10#;
-
- DW_FORM_addr : constant := 16#01#;
- DW_FORM_block2 : constant := 16#03#;
- DW_FORM_block4 : constant := 16#04#;
- DW_FORM_data2 : constant := 16#05#;
- DW_FORM_data4 : constant := 16#06#;
- DW_FORM_data8 : constant := 16#07#;
- DW_FORM_string : constant := 16#08#;
- DW_FORM_block : constant := 16#09#;
- DW_FORM_block1 : constant := 16#0a#;
- DW_FORM_data1 : constant := 16#0b#;
- DW_FORM_flag : constant := 16#0c#;
- DW_FORM_sdata : constant := 16#0d#;
- DW_FORM_strp : constant := 16#0e#;
- DW_FORM_udata : constant := 16#0f#;
- DW_FORM_ref_addr : constant := 16#10#;
- DW_FORM_ref1 : constant := 16#11#;
- DW_FORM_ref2 : constant := 16#12#;
- DW_FORM_ref4 : constant := 16#13#;
- DW_FORM_ref8 : constant := 16#14#;
- DW_FORM_ref_udata : constant := 16#15#;
- DW_FORM_indirect : constant := 16#16#;
- DW_FORM_sec_offset : constant := 16#17#;
- DW_FORM_exprloc : constant := 16#18#;
- DW_FORM_flag_present : constant := 16#19#;
- DW_FORM_ref_sig8 : constant := 16#20#;
+ -- 7.5.5 Classes and Forms
+
+ DW_FORM_addr : constant := 16#01#;
+ DW_FORM_block2 : constant := 16#03#;
+ DW_FORM_block4 : constant := 16#04#;
+ DW_FORM_data2 : constant := 16#05#;
+ DW_FORM_data4 : constant := 16#06#;
+ DW_FORM_data8 : constant := 16#07#;
+ DW_FORM_string : constant := 16#08#;
+ DW_FORM_block : constant := 16#09#;
+ DW_FORM_block1 : constant := 16#0a#;
+ DW_FORM_data1 : constant := 16#0b#;
+ DW_FORM_flag : constant := 16#0c#;
+ DW_FORM_sdata : constant := 16#0d#;
+ DW_FORM_strp : constant := 16#0e#;
+ DW_FORM_udata : constant := 16#0f#;
+ DW_FORM_ref_addr : constant := 16#10#;
+ DW_FORM_ref1 : constant := 16#11#;
+ DW_FORM_ref2 : constant := 16#12#;
+ DW_FORM_ref4 : constant := 16#13#;
+ DW_FORM_ref8 : constant := 16#14#;
+ DW_FORM_ref_udata : constant := 16#15#;
+ DW_FORM_indirect : constant := 16#16#;
+ DW_FORM_sec_offset : constant := 16#17#;
+ DW_FORM_exprloc : constant := 16#18#;
+ DW_FORM_flag_present : constant := 16#19#;
+ DW_FORM_strx : constant := 16#1a#;
+ DW_FORM_addrx : constant := 16#1b#;
+ DW_FORM_ref_sup4 : constant := 16#1c#;
+ DW_FORM_strp_sup : constant := 16#1d#;
+ DW_FORM_data16 : constant := 16#1e#;
+ DW_FORM_line_strp : constant := 16#1f#;
+ DW_FORM_ref_sig8 : constant := 16#20#;
+ DW_FORM_implicit_const : constant := 16#21#;
+ DW_FORM_loclistx : constant := 16#22#;
+ DW_FORM_rnglistx : constant := 16#23#;
+ DW_FORM_ref_sup8 : constant := 16#24#;
+ DW_FORM_strx1 : constant := 16#25#;
+ DW_FORM_strx2 : constant := 16#26#;
+ DW_FORM_strx3 : constant := 16#27#;
+ DW_FORM_strx4 : constant := 16#28#;
+ DW_FORM_addrx1 : constant := 16#29#;
+ DW_FORM_addrx2 : constant := 16#2a#;
+ DW_FORM_addrx3 : constant := 16#2b#;
+ DW_FORM_addrx4 : constant := 16#2c#;
---------
-- "<" --
@@ -235,6 +269,7 @@ package body System.Dwarf_Lines is
procedure Unchecked_Deallocation is new Ada.Unchecked_Deallocation
(Search_Array,
Search_Array_Access);
+
begin
if C.Has_Debug then
Close (C.Lines);
@@ -265,6 +300,7 @@ package body System.Dwarf_Lines is
procedure Dump_Row (C : in out Dwarf_Context) is
PC : constant Integer_Address := Integer_Address (C.Registers.Address);
Off : Offset;
+
begin
Tell (C.Lines, Off);
@@ -286,11 +322,13 @@ package body System.Dwarf_Lines is
Cache : constant Search_Array_Access := C.Cache;
S : Object_Symbol;
Name : String_Ptr_Len;
+
begin
if Cache = null then
Put_Line ("No cache");
return;
end if;
+
for I in Cache'Range loop
declare
E : Search_Entry renames Cache (I);
@@ -322,7 +360,7 @@ package body System.Dwarf_Lines is
Initialize_Pass (C);
loop
- Read_And_Execute_Isn (C, Done);
+ Read_And_Execute_Insn (C, Done);
if C.Registers.Is_Row then
F.all (C);
@@ -339,8 +377,7 @@ package body System.Dwarf_Lines is
procedure Initialize_Pass (C : in out Dwarf_Context) is
begin
Seek (C.Lines, 0);
- C.Next_Prologue := 0;
-
+ C.Next_Header := 0;
Initialize_State_Machine (C);
end Initialize_Pass;
@@ -350,17 +387,16 @@ package body System.Dwarf_Lines is
procedure Initialize_State_Machine (C : in out Dwarf_Context) is
begin
+ -- Table 6.4: Line number program initial state
+
C.Registers :=
(Address => 0,
File => 1,
Line => 1,
Column => 0,
- Is_Stmt => C.Prologue.Default_Is_Stmt = 0,
+ Is_Stmt => C.Header.Default_Is_Stmt /= 0,
Basic_Block => False,
End_Sequence => False,
- Prologue_End => False,
- Epilogue_Begin => False,
- ISA => 0,
Is_Row => False);
end Initialize_State_Machine;
@@ -378,8 +414,7 @@ package body System.Dwarf_Lines is
-- Low_Address --
-----------------
- function Low_Address (C : Dwarf_Context)
- return System.Address is
+ function Low_Address (C : Dwarf_Context) return System.Address is
begin
return C.Load_Address + C.Low;
end Low_Address;
@@ -393,19 +428,24 @@ package body System.Dwarf_Lines is
C : out Dwarf_Context;
Success : out Boolean)
is
- Line_Sec, Info_Sec, Abbrev_Sec, Aranges_Sec : Object_Section;
- Hi, Lo : uint64;
+ Abbrev, Aranges, Lines, Info, Line_Str : Object_Section;
+ Hi, Lo : uint64;
+
begin
-- Not a success by default
Success := False;
- -- Open file
+ -- Open file with In_Exception set so we can control the failure mode
- C.Obj := Open (File_Name, C.In_Exception);
+ C.Obj := Open (File_Name, In_Exception => True);
if C.Obj = null then
- return;
+ if C.In_Exception then
+ return;
+ else
+ raise Dwarf_Error with "could not open file";
+ end if;
end if;
Success := True;
@@ -420,21 +460,23 @@ package body System.Dwarf_Lines is
-- Create a stream for debug sections
if Format (C.Obj.all) = XCOFF32 then
- Line_Sec := Get_Section (C.Obj.all, ".dwline");
- Abbrev_Sec := Get_Section (C.Obj.all, ".dwabrev");
- Info_Sec := Get_Section (C.Obj.all, ".dwinfo");
- Aranges_Sec := Get_Section (C.Obj.all, ".dwarnge");
+ Abbrev := Get_Section (C.Obj.all, ".dwabrev");
+ Aranges := Get_Section (C.Obj.all, ".dwarnge");
+ Info := Get_Section (C.Obj.all, ".dwinfo");
+ Lines := Get_Section (C.Obj.all, ".dwline");
+ Line_Str := Get_Section (C.Obj.all, ".dwlistr");
else
- Line_Sec := Get_Section (C.Obj.all, ".debug_line");
- Abbrev_Sec := Get_Section (C.Obj.all, ".debug_abbrev");
- Info_Sec := Get_Section (C.Obj.all, ".debug_info");
- Aranges_Sec := Get_Section (C.Obj.all, ".debug_aranges");
+ Abbrev := Get_Section (C.Obj.all, ".debug_abbrev");
+ Aranges := Get_Section (C.Obj.all, ".debug_aranges");
+ Info := Get_Section (C.Obj.all, ".debug_info");
+ Lines := Get_Section (C.Obj.all, ".debug_line");
+ Line_Str := Get_Section (C.Obj.all, ".debug_line_str");
end if;
- if Line_Sec = Null_Section
- or else Abbrev_Sec = Null_Section
- or else Info_Sec = Null_Section
- or else Aranges_Sec = Null_Section
+ if Abbrev = Null_Section
+ or else Aranges = Null_Section
+ or else Info = Null_Section
+ or else Lines = Null_Section
then
pragma Annotate
(CodePeer, False_Positive,
@@ -444,21 +486,29 @@ package body System.Dwarf_Lines is
return;
end if;
- C.Lines := Create_Stream (C.Obj.all, Line_Sec);
- C.Abbrev := Create_Stream (C.Obj.all, Abbrev_Sec);
- C.Info := Create_Stream (C.Obj.all, Info_Sec);
- C.Aranges := Create_Stream (C.Obj.all, Aranges_Sec);
+ C.Abbrev := Create_Stream (C.Obj.all, Abbrev);
+ C.Aranges := Create_Stream (C.Obj.all, Aranges);
+ C.Info := Create_Stream (C.Obj.all, Info);
+ C.Lines := Create_Stream (C.Obj.all, Lines);
+
+ -- The .debug_line_str section may be available in DWARF 5
+
+ if Line_Str /= Null_Section then
+ C.Line_Str := Create_Stream (C.Obj.all, Line_Str);
+ end if;
-- All operations are successful, context is valid
C.Has_Debug := True;
end Open;
- --------------------
- -- Parse_Prologue --
- --------------------
+ ------------------
+ -- Parse_Header --
+ ------------------
+
+ procedure Parse_Header (C : in out Dwarf_Context) is
+ Header : Line_Info_Header renames C.Header;
- procedure Parse_Prologue (C : in out Dwarf_Context) is
Char : uint8;
Prev : uint8;
-- The most recently read character and the one preceding it
@@ -469,94 +519,147 @@ package body System.Dwarf_Lines is
Buf : Buffer;
Off : Offset;
- First_Byte_Of_Prologue : Offset;
- Last_Byte_Of_Prologue : Offset;
-
- Max_Op_Per_Insn : uint8;
- pragma Unreferenced (Max_Op_Per_Insn);
+ First_Byte_Of_Header : Offset;
+ Last_Byte_Of_Header : Offset;
- Prologue : Line_Info_Prologue renames C.Prologue;
+ Standard_Opcode_Lengths : Opcode_Length_Array;
+ pragma Unreferenced (Standard_Opcode_Lengths);
begin
- Tell (C.Lines, First_Byte_Of_Prologue);
- Prologue.Unit_Length := Read (C.Lines);
+ Tell (C.Lines, First_Byte_Of_Header);
+
+ Read_Initial_Length (C.Lines, Header.Unit_Length, Header.Is64);
+
Tell (C.Lines, Off);
- C.Next_Prologue := Off + Offset (Prologue.Unit_Length);
+ C.Next_Header := Off + Header.Unit_Length;
+
+ Header.Version := Read (C.Lines);
+
+ if Header.Version >= 5 then
+ Header.Address_Size := Read (C.Lines);
+ Header.Segment_Selector_Size := Read (C.Lines);
+ else
+ Header.Address_Size := 0;
+ Header.Segment_Selector_Size := 0;
+ end if;
- Prologue.Version := Read (C.Lines);
- Prologue.Prologue_Length := Read (C.Lines);
- Tell (C.Lines, Last_Byte_Of_Prologue);
- Last_Byte_Of_Prologue :=
- Last_Byte_Of_Prologue + Offset (Prologue.Prologue_Length) - 1;
+ Header.Header_Length := Read (C.Lines);
+ Tell (C.Lines, Last_Byte_Of_Header);
+ Last_Byte_Of_Header :=
+ Last_Byte_Of_Header + Offset (Header.Header_Length) - 1;
- Prologue.Min_Isn_Length := Read (C.Lines);
+ Header.Minimum_Insn_Length := Read (C.Lines);
- if Prologue.Version >= 4 then
- Max_Op_Per_Insn := Read (C.Lines);
+ if Header.Version >= 4 then
+ Header.Maximum_Op_Per_Insn := Read (C.Lines);
+ else
+ Header.Maximum_Op_Per_Insn := 0;
end if;
- Prologue.Default_Is_Stmt := Read (C.Lines);
- Prologue.Line_Base := Read (C.Lines);
- Prologue.Line_Range := Read (C.Lines);
- Prologue.Opcode_Base := Read (C.Lines);
+ Header.Default_Is_Stmt := Read (C.Lines);
+ Header.Line_Base := Read (C.Lines);
+ Header.Line_Range := Read (C.Lines);
+ Header.Opcode_Base := Read (C.Lines);
- -- Opcode_Lengths is an array of Opcode_Base bytes specifying the number
- -- of LEB128 operands for each of the standard opcodes.
+ -- Standard_Opcode_Lengths is an array of Opcode_Base bytes specifying
+ -- the number of LEB128 operands for each of the standard opcodes.
- for J in 1 .. uint32 (Prologue.Opcode_Base - 1) loop
- Prologue.Opcode_Lengths (J) := Read (C.Lines);
+ for J in 1 .. Integer (Header.Opcode_Base - 1) loop
+ Standard_Opcode_Lengths (J) := Read (C.Lines);
end loop;
- -- The include directories table follows. This is a list of null
- -- terminated strings terminated by a double null. We only store
- -- its offset for later decoding.
+ -- The directories table follows. Up to DWARF 4, this is a list of null
+ -- terminated strings terminated by a null byte. In DWARF 5, this is a
+ -- sequence of Directories_Count entries encoded as described by the
+ -- Directory_Entry_Format field. We store its offset for later decoding.
- Tell (C.Lines, Prologue.Includes_Offset);
- Char := Read (C.Lines);
+ if Header.Version <= 4 then
+ Tell (C.Lines, Header.Directories);
+ Char := Read (C.Lines);
- if Char /= 0 then
- loop
- Prev := Char;
- Char := Read (C.Lines);
- exit when Char = 0 and Prev = 0;
+ if Char /= 0 then
+ loop
+ Prev := Char;
+ Char := Read (C.Lines);
+ exit when Char = 0 and Prev = 0;
+ end loop;
+ end if;
+
+ else
+ Header.Directory_Entry_Format_Count := Read (C.Lines);
+ Read_Entry_Format_Array (C.Lines,
+ Header.Directory_Entry_Format,
+ Header.Directory_Entry_Format_Count);
+
+ Header.Directories_Count := Read_LEB128 (C.Lines);
+ Tell (C.Lines, Header.Directories);
+ for J in 1 .. Header.Directories_Count loop
+ for K in 1 .. Integer (Header.Directory_Entry_Format_Count) loop
+ Skip_Form (C.Lines,
+ Header.Directory_Entry_Format (K).Form,
+ Header.Is64,
+ Header.Address_Size);
+ end loop;
end loop;
end if;
- -- The file_names table is next. Each record is a null terminated string
- -- for the file name, an unsigned LEB128 directory index, an unsigned
- -- LEB128 modification time, and an LEB128 file length. The table is
- -- terminated by a null byte.
+ -- The file_names table is next. Up to DWARF 4, this is a list of record
+ -- containing a null terminated string for the file name, an unsigned
+ -- LEB128 directory index in the Directories table, an unsigned LEB128
+ -- modification time, and an unsigned LEB128 for the file length; the
+ -- table is terminated by a null byte. In DWARF 5, this is a sequence
+ -- of File_Names_Count entries encoded as described by the
+ -- File_Name_Entry_Format field. We store its offset for later decoding.
- Tell (C.Lines, Prologue.File_Names_Offset);
+ if Header.Version <= 4 then
+ Tell (C.Lines, Header.File_Names);
- loop
- -- Read the filename
+ -- Read the file names
- Read_C_String (C.Lines, Buf);
- exit when Buf (0) = 0;
- Dummy := Read_LEB128 (C.Lines); -- Skip the directory index.
- Dummy := Read_LEB128 (C.Lines); -- Skip the modification time.
- Dummy := Read_LEB128 (C.Lines); -- Skip the file length.
- end loop;
+ loop
+ Read_C_String (C.Lines, Buf);
+ exit when Buf (0) = 0;
+ Dummy := Read_LEB128 (C.Lines); -- Skip the directory index.
+ Dummy := Read_LEB128 (C.Lines); -- Skip the modification time.
+ Dummy := Read_LEB128 (C.Lines); -- Skip the file length.
+ end loop;
+
+ else
+ Header.File_Name_Entry_Format_Count := Read (C.Lines);
+ Read_Entry_Format_Array (C.Lines,
+ Header.File_Name_Entry_Format,
+ Header.File_Name_Entry_Format_Count);
+
+ Header.File_Names_Count := Read_LEB128 (C.Lines);
+ Tell (C.Lines, Header.File_Names);
+ for J in 1 .. Header.File_Names_Count loop
+ for K in 1 .. Integer (Header.File_Name_Entry_Format_Count) loop
+ Skip_Form (C.Lines,
+ Header.File_Name_Entry_Format (K).Form,
+ Header.Is64,
+ Header.Address_Size);
+ end loop;
+ end loop;
+ end if;
-- Check we're where we think we are. This sanity check ensures we think
- -- the prologue ends where the prologue says it does. It we aren't then
- -- we've probably gotten out of sync somewhere.
+ -- the header ends where the header says it does. It we aren't, then we
+ -- have probably gotten out of sync somewhere.
Tell (C.Lines, Off);
- if Prologue.Unit_Length /= 0
- and then Off /= Last_Byte_Of_Prologue + 1
+ if Header.Unit_Length /= 0
+ and then Off /= Last_Byte_Of_Header + 1
then
- raise Dwarf_Error with "Parse error reading DWARF information";
+ raise Dwarf_Error with "parse error reading DWARF information";
end if;
- end Parse_Prologue;
+ end Parse_Header;
- --------------------------
- -- Read_And_Execute_Isn --
- --------------------------
+ ---------------------------
+ -- Read_And_Execute_Insn --
+ ---------------------------
- procedure Read_And_Execute_Isn
+ procedure Read_And_Execute_Insn
(C : in out Dwarf_Context;
Done : out Boolean)
is
@@ -572,7 +675,7 @@ package body System.Dwarf_Lines is
Obj : Object_File renames C.Obj.all;
Registers : Line_Info_Registers renames C.Registers;
- Prologue : Line_Info_Prologue renames C.Prologue;
+ Header : Line_Info_Header renames C.Header;
begin
Done := False;
@@ -582,8 +685,8 @@ package body System.Dwarf_Lines is
Initialize_State_Machine (C);
end if;
- -- If we have reached the next prologue, read it. Beware of possibly
- -- empty blocks.
+ -- If we have reached the next header, read it. Beware of possibly empty
+ -- blocks.
-- When testing for the end of section, beware of possible zero padding
-- at the end. Bail out as soon as there's not even room for at least a
@@ -592,9 +695,9 @@ package body System.Dwarf_Lines is
-- or Off+3 > Section_Length.
Tell (C.Lines, Off);
- while Off = C.Next_Prologue loop
+ while Off = C.Next_Header loop
Initialize_State_Machine (C);
- Parse_Prologue (C);
+ Parse_Header (C);
Tell (C.Lines, Off);
exit when Off + 3 > Length (C.Lines);
end loop;
@@ -606,7 +709,7 @@ package body System.Dwarf_Lines is
-- We are finished when we either reach the end of the section, or we
-- have reached zero padding at the end of the section.
- if Prologue.Unit_Length = 0 or else Off + 3 > Length (C.Lines) then
+ if Header.Unit_Length = 0 or else Off + 3 > Length (C.Lines) then
Done := True;
return;
end if;
@@ -617,7 +720,7 @@ package body System.Dwarf_Lines is
-- Extended opcodes
- if Opcode = 0 then
+ if Opcode = DW_LNS_extended_op then
Extended_Length := Read_LEB128 (C.Lines);
Extended_Opcode := Read (C.Lines);
@@ -656,7 +759,7 @@ package body System.Dwarf_Lines is
-- Standard opcodes
- elsif Opcode < Prologue.Opcode_Base then
+ elsif Opcode < Header.Opcode_Base then
case Opcode is
-- Append a row to the line info matrix
@@ -671,7 +774,7 @@ package body System.Dwarf_Lines is
uint32_Operand := Read_LEB128 (C.Lines);
Registers.Address :=
Registers.Address +
- uint64 (uint32_Operand * uint32 (Prologue.Min_Isn_Length));
+ uint64 (uint32_Operand * uint32 (Header.Minimum_Insn_Length));
-- Add a signed word to the current source line
@@ -708,8 +811,8 @@ package body System.Dwarf_Lines is
Registers.Address :=
Registers.Address +
uint64
- (((255 - Prologue.Opcode_Base) / Prologue.Line_Range) *
- Prologue.Min_Isn_Length);
+ (((255 - Header.Opcode_Base) / Header.Line_Range) *
+ Header.Minimum_Insn_Length);
-- Advance the program counter by a constant
@@ -744,7 +847,7 @@ package body System.Dwarf_Lines is
Line_Increment : int32;
begin
- Opcode := Opcode - Prologue.Opcode_Base;
+ Opcode := Opcode - Header.Opcode_Base;
-- The adjusted opcode is a uint8 encoding an address increment
-- and a signed line increment. The upperbound is allowed to be
@@ -752,18 +855,16 @@ package body System.Dwarf_Lines is
-- prevent overflows.
Address_Increment :=
- int32 (Opcode / Prologue.Line_Range) *
- int32 (Prologue.Min_Isn_Length);
+ int32 (Opcode / Header.Line_Range) *
+ int32 (Header.Minimum_Insn_Length);
Line_Increment :=
- int32 (Prologue.Line_Base) +
- int32 (Opcode mod Prologue.Line_Range);
+ int32 (Header.Line_Base) +
+ int32 (Opcode mod Header.Line_Range);
Registers.Address :=
Registers.Address + uint64 (Address_Increment);
Registers.Line := uint32 (int32 (Registers.Line) + Line_Increment);
Registers.Basic_Block := False;
- Registers.Prologue_End := False;
- Registers.Epilogue_Begin := False;
Registers.Is_Row := True;
end;
end if;
@@ -775,7 +876,7 @@ package body System.Dwarf_Lines is
Registers.Is_Row := False;
Done := True;
- end Read_And_Execute_Isn;
+ end Read_And_Execute_Insn;
----------------------
-- Set_Load_Address --
@@ -792,10 +893,10 @@ package body System.Dwarf_Lines is
function To_File_Name
(C : in out Dwarf_Context;
- Code : uint32) return String
+ File : uint32) return String
is
Buf : Buffer;
- J : uint32;
+ Off : Offset;
Dir_Idx : uint32;
pragma Unreferenced (Dir_Idx);
@@ -806,25 +907,56 @@ package body System.Dwarf_Lines is
Length : uint32;
pragma Unreferenced (Length);
+ File_Entry_Format : Entry_Format_Array
+ renames C.Header.File_Name_Entry_Format;
+
begin
- Seek (C.Lines, C.Prologue.File_Names_Offset);
+ Seek (C.Lines, C.Header.File_Names);
- -- Find the entry
+ -- Find the entry. Note that, up to DWARF 4, the index is 1-based
+ -- whereas, in DWARF 5, it is 0-based.
- J := 0;
- loop
- J := J + 1;
- Read_C_String (C.Lines, Buf);
+ if C.Header.Version <= 4 then
+ for J in 1 .. File loop
+ Read_C_String (C.Lines, Buf);
- if Buf (Buf'First) = 0 then
- return "???";
- end if;
+ if Buf (Buf'First) = 0 then
+ return "???";
+ end if;
- Dir_Idx := Read_LEB128 (C.Lines);
- Mod_Time := Read_LEB128 (C.Lines);
- Length := Read_LEB128 (C.Lines);
- exit when J = Code;
- end loop;
+ Dir_Idx := Read_LEB128 (C.Lines);
+ Mod_Time := Read_LEB128 (C.Lines);
+ Length := Read_LEB128 (C.Lines);
+ end loop;
+
+ -- DWARF 5
+
+ else
+ for J in 0 .. File loop
+ for K in 1 .. Integer (C.Header.File_Name_Entry_Format_Count) loop
+ if File_Entry_Format (K).C_Type = DW_LNCT_path then
+ case File_Entry_Format (K).Form is
+ when DW_FORM_string =>
+ Read_C_String (C.Lines, Buf);
+
+ when DW_FORM_line_strp =>
+ Read_Section_Offset (C.Lines, Off, C.Header.Is64);
+ Seek (C.Line_Str, Off);
+ Read_C_String (C.Line_Str, Buf);
+
+ when others =>
+ raise Dwarf_Error with "DWARF form not implemented";
+ end case;
+
+ else
+ Skip_Form (C.Lines,
+ File_Entry_Format (K).Form,
+ C.Header.Is64,
+ C.Header.Address_Size);
+ end if;
+ end loop;
+ end loop;
+ end if;
return To_String (Buf);
end To_File_Name;
@@ -840,6 +972,7 @@ package body System.Dwarf_Lines is
is
Len32 : uint32;
Len64 : uint64;
+
begin
Len32 := Read (S);
if Len32 < 16#ffff_fff0# then
@@ -872,6 +1005,43 @@ package body System.Dwarf_Lines is
end if;
end Read_Section_Offset;
+ -----------------------------
+ -- Read_Entry_Format_Array --
+ -----------------------------
+
+ procedure Read_Entry_Format_Array
+ (S : in out Mapped_Stream;
+ A : out Entry_Format_Array;
+ Len : uint8)
+ is
+ C_Type, Form : uint32;
+ N : Integer;
+
+ begin
+ N := A'First;
+
+ for J in 1 .. Len loop
+ C_Type := Read_LEB128 (S);
+ Form := Read_LEB128 (S);
+
+ case C_Type is
+ when DW_LNCT_path .. DW_LNCT_MD5 =>
+ if N not in A'Range then
+ raise Dwarf_Error with "DWARF duplicate content type";
+ end if;
+
+ A (N) := (C_Type, Form);
+ N := N + 1;
+
+ when DW_LNCT_lo_user .. DW_LNCT_hi_user =>
+ null;
+
+ when others =>
+ raise Dwarf_Error with "DWARF content type not implemented";
+ end case;
+ end loop;
+ end Read_Entry_Format_Array;
+
--------------------
-- Aranges_Lookup --
--------------------
@@ -921,31 +1091,53 @@ package body System.Dwarf_Lines is
Ptr_Sz : uint8)
is
Skip : Offset;
+
begin
+ -- 7.5.5 Classes and Forms
+
case Form is
when DW_FORM_addr =>
Skip := Offset (Ptr_Sz);
+ when DW_FORM_addrx =>
+ Skip := Offset (uint32'(Read_LEB128 (S)));
+ when DW_FORM_block1 =>
+ Skip := Offset (uint8'(Read (S)));
when DW_FORM_block2 =>
Skip := Offset (uint16'(Read (S)));
when DW_FORM_block4 =>
Skip := Offset (uint32'(Read (S)));
- when DW_FORM_data2 | DW_FORM_ref2 =>
- Skip := 2;
- when DW_FORM_data4 | DW_FORM_ref4 =>
- Skip := 4;
- when DW_FORM_data8 | DW_FORM_ref8 | DW_FORM_ref_sig8 =>
- Skip := 8;
- when DW_FORM_string =>
- while uint8'(Read (S)) /= 0 loop
- null;
- end loop;
- return;
when DW_FORM_block | DW_FORM_exprloc =>
Skip := Offset (uint32'(Read_LEB128 (S)));
- when DW_FORM_block1 | DW_FORM_ref1 =>
- Skip := Offset (uint8'(Read (S)));
- when DW_FORM_data1 | DW_FORM_flag =>
+ when DW_FORM_addrx1
+ | DW_FORM_data1
+ | DW_FORM_flag
+ | DW_FORM_ref1
+ | DW_FORM_strx1
+ =>
Skip := 1;
+ when DW_FORM_addrx2
+ | DW_FORM_data2
+ | DW_FORM_ref2
+ | DW_FORM_strx2
+ =>
+ Skip := 2;
+ when DW_FORM_addrx3 | DW_FORM_strx3 =>
+ Skip := 3;
+ when DW_FORM_addrx4
+ | DW_FORM_data4
+ | DW_FORM_ref4
+ | DW_FORM_ref_sup4
+ | DW_FORM_strx4
+ =>
+ Skip := 4;
+ when DW_FORM_data8
+ | DW_FORM_ref8
+ | DW_FORM_ref_sup8
+ | DW_FORM_ref_sig8
+ =>
+ Skip := 8;
+ when DW_FORM_data16 =>
+ Skip := 16;
when DW_FORM_sdata =>
declare
Val : constant int32 := Read_LEB128 (S);
@@ -953,9 +1145,12 @@ package body System.Dwarf_Lines is
begin
return;
end;
- when DW_FORM_strp | DW_FORM_ref_addr | DW_FORM_sec_offset =>
- Skip := (if Is64 then 8 else 4);
- when DW_FORM_udata | DW_FORM_ref_udata =>
+ when DW_FORM_udata
+ | DW_FORM_ref_udata
+ | DW_FORM_loclistx
+ | DW_FORM_rnglistx
+ | DW_FORM_strx
+ =>
declare
Val : constant uint32 := Read_LEB128 (S);
pragma Unreferenced (Val);
@@ -964,11 +1159,24 @@ package body System.Dwarf_Lines is
end;
when DW_FORM_flag_present =>
return;
- when DW_FORM_indirect =>
+ when DW_FORM_ref_addr
+ | DW_FORM_sec_offset
+ | DW_FORM_strp
+ | DW_FORM_line_strp
+ | DW_FORM_strp_sup
+ =>
+ Skip := (if Is64 then 8 else 4);
+ when DW_FORM_string =>
+ while uint8'(Read (S)) /= 0 loop
+ null;
+ end loop;
+ return;
+ when DW_FORM_implicit_const | DW_FORM_indirect =>
raise Constraint_Error;
when others =>
raise Constraint_Error;
end case;
+
Seek (S, Tell (S) + Skip);
end Skip_Form;
@@ -981,20 +1189,21 @@ package body System.Dwarf_Lines is
Abbrev_Offset : Offset;
Abbrev_Num : uint32)
is
- Num : uint32;
Abbrev : uint32;
Tag : uint32;
Has_Child : uint8;
- pragma Unreferenced (Abbrev, Tag, Has_Child);
+ pragma Unreferenced (Tag, Has_Child);
+
begin
Seek (C.Abbrev, Abbrev_Offset);
- Num := 1;
+ -- 7.5.3 Abbreviations Tables
loop
- exit when Num = Abbrev_Num;
+ Abbrev := Read_LEB128 (C.Abbrev);
+
+ exit when Abbrev = Abbrev_Num;
- Abbrev := Read_LEB128 (C.Abbrev);
Tag := Read_LEB128 (C.Abbrev);
Has_Child := Read (C.Abbrev);
@@ -1002,12 +1211,19 @@ package body System.Dwarf_Lines is
declare
Name : constant uint32 := Read_LEB128 (C.Abbrev);
Form : constant uint32 := Read_LEB128 (C.Abbrev);
+ Cst : int32;
+ pragma Unreferenced (Cst);
+
begin
- exit when Name = 0 and Form = 0;
+ -- DW_FORM_implicit_const takes its value from the table
+
+ if Form = DW_FORM_implicit_const then
+ Cst := Read_LEB128 (C.Abbrev);
+ end if;
+
+ exit when Name = 0 and then Form = 0;
end;
end loop;
-
- Num := Num + 1;
end loop;
end Seek_Abbrev;
@@ -1029,23 +1245,40 @@ package body System.Dwarf_Lines is
Abbrev : uint32;
Has_Child : uint8;
pragma Unreferenced (Has_Child);
+ Unit_Type : uint8;
+ pragma Unreferenced (Unit_Type);
+
begin
Line_Offset := 0;
Success := False;
Seek (C.Info, Info_Offset);
+ -- 7.5.1.1 Compilation Unit Header
+
Read_Initial_Length (C.Info, Unit_Length, Is64);
Version := Read (C.Info);
- if Version not in 2 .. 4 then
- return;
- end if;
- Read_Section_Offset (C.Info, Abbrev_Offset, Is64);
+ if Version >= 5 then
+ Unit_Type := Read (C.Info);
+
+ Addr_Sz := Read (C.Info);
+ if Addr_Sz /= (Address'Size / SSU) then
+ return;
+ end if;
+
+ Read_Section_Offset (C.Info, Abbrev_Offset, Is64);
+
+ elsif Version >= 2 then
+ Read_Section_Offset (C.Info, Abbrev_Offset, Is64);
+
+ Addr_Sz := Read (C.Info);
+ if Addr_Sz /= (Address'Size / SSU) then
+ return;
+ end if;
- Addr_Sz := Read (C.Info);
- if Addr_Sz /= (Address'Size / SSU) then
+ else
return;
end if;
@@ -1060,17 +1293,9 @@ package body System.Dwarf_Lines is
Seek_Abbrev (C, Abbrev_Offset, Abbrev);
- -- First ULEB128 is the abbrev code
-
- if Read_LEB128 (C.Abbrev) /= Abbrev then
- -- Ill formed abbrev table
- return;
- end if;
-
-- Then the tag
if Read_LEB128 (C.Abbrev) /= uint32'(DW_TAG_Compile_Unit) then
- -- Expect compile unit
return;
end if;
@@ -1104,8 +1329,6 @@ package body System.Dwarf_Lines is
end if;
end;
end loop;
-
- return;
end Debug_Info_Lookup;
-------------------------
@@ -1121,6 +1344,7 @@ package body System.Dwarf_Lines is
Is64 : Boolean;
Version : uint16;
Sz : uint8;
+
begin
Success := False;
Info_Offset := 0;
@@ -1149,6 +1373,7 @@ package body System.Dwarf_Lines is
end if;
-- Handle alignment on twice the address size
+
declare
Cur_Off : constant Offset := Tell (C.Aranges);
Align : constant Offset := 2 * Address'Size / SSU;
@@ -1173,6 +1398,7 @@ package body System.Dwarf_Lines is
is
begin
-- Read table
+
if Address'Size = 32 then
declare
S, L : uint32;
@@ -1182,6 +1408,7 @@ package body System.Dwarf_Lines is
Start := Storage_Offset (S);
Len := Storage_Count (L);
end;
+
elsif Address'Size = 64 then
declare
S, L : uint64;
@@ -1191,6 +1418,7 @@ package body System.Dwarf_Lines is
Start := Storage_Offset (S);
Len := Storage_Count (L);
end;
+
else
raise Constraint_Error;
end if;
@@ -1202,8 +1430,11 @@ package body System.Dwarf_Lines is
procedure Enable_Cache (C : in out Dwarf_Context) is
Cache : Search_Array_Access;
+
begin
- -- Phase 1: count number of symbols. Phase 2: fill the cache.
+ -- Phase 1: count number of symbols.
+ -- Phase 2: fill the cache.
+
declare
S : Object_Symbol;
Val : uint64;
@@ -1220,6 +1451,7 @@ package body System.Dwarf_Lines is
while S /= Null_Symbol loop
-- Discard symbols of length 0 or located outside of the
-- execution code section outer boundaries.
+
Sz := uint32 (Size (S));
Val := Value (S);
@@ -1227,11 +1459,11 @@ package body System.Dwarf_Lines is
and then Val >= Xcode_Low
and then Val <= Xcode_High
then
-
Addr := uint32 (Val - Xcode_Low);
-- Try to filter symbols at the same address. This is a best
-- effort as they might not be consecutive.
+
if Addr /= Prev_Addr then
Nbr_Symbols := Nbr_Symbols + 1;
Prev_Addr := Addr;
@@ -1251,6 +1483,7 @@ package body System.Dwarf_Lines is
if Phase = 1 then
-- Allocate the cache
+
Cache := new Search_Array (1 .. Nbr_Symbols);
C.Cache := Cache;
end if;
@@ -1258,13 +1491,16 @@ package body System.Dwarf_Lines is
pragma Assert (Nbr_Symbols = C.Cache'Last);
end;
- -- Sort the cache.
+ -- Sort the cache
+
Sort_Search_Array (C.Cache.all);
-- Set line offsets
+
if not C.Has_Debug then
return;
end if;
+
declare
Info_Offset : Offset;
Line_Offset : Offset;
@@ -1285,6 +1521,7 @@ package body System.Dwarf_Lines is
exit when not Success;
-- Read table
+
loop
Read_Aranges_Entry (C, Ar_Start, Ar_Len);
exit when Ar_Start = 0 and Ar_Len = 0;
@@ -1293,6 +1530,7 @@ package body System.Dwarf_Lines is
Start := uint32 (Ar_Start - C.Low);
-- Search START in the array
+
First := Cache'First;
Last := Cache'Last;
Mid := First; -- In case of array with one element
@@ -1307,9 +1545,10 @@ package body System.Dwarf_Lines is
end if;
end loop;
- -- Fill info.
+ -- Fill info
-- There can be overlapping symbols
+
while Mid > Cache'First
and then Cache (Mid - 1).First <= Start
and then Cache (Mid - 1).First + Cache (Mid - 1).Size > Start
@@ -1321,9 +1560,11 @@ package body System.Dwarf_Lines is
and then Start + Len > Cache (Mid).First
then
-- MID is within the bounds
+
Cache (Mid).Line := uint32 (Line_Offset);
elsif Start + Len <= Cache (Mid).First then
-- Over
+
exit;
end if;
Mid := Mid + 1;
@@ -1350,7 +1591,7 @@ package body System.Dwarf_Lines is
procedure Set_Result (Match : Line_Info_Registers) is
Dir_Idx : uint32;
- J : uint32;
+ Off : Offset;
Mod_Time : uint32;
pragma Unreferenced (Mod_Time);
@@ -1358,46 +1599,123 @@ package body System.Dwarf_Lines is
Length : uint32;
pragma Unreferenced (Length);
+ Directory_Entry_Format : Entry_Format_Array
+ renames C.Header.Directory_Entry_Format;
+
+ File_Entry_Format : Entry_Format_Array
+ renames C.Header.File_Name_Entry_Format;
+
begin
- Seek (C.Lines, C.Prologue.File_Names_Offset);
+ Seek (C.Lines, C.Header.File_Names);
+ Dir_Idx := 0;
- -- Find the entry
+ -- Find the entry. Note that, up to DWARF 4, the index is 1-based
+ -- whereas, in DWARF 5, it is 0-based.
- J := 0;
- loop
- J := J + 1;
- File_Name := Read_C_String (C.Lines);
+ if C.Header.Version <= 4 then
+ for J in 1 .. Match.File loop
+ File_Name := Read_C_String (C.Lines);
- if File_Name (File_Name'First) = ASCII.NUL then
- -- End of file list, so incorrect entry
- return;
- end if;
+ if File_Name (File_Name'First) = ASCII.NUL then
+ -- End of file list, so incorrect entry
+ return;
+ end if;
- Dir_Idx := Read_LEB128 (C.Lines);
- Mod_Time := Read_LEB128 (C.Lines);
- Length := Read_LEB128 (C.Lines);
- exit when J = Match.File;
- end loop;
+ Dir_Idx := Read_LEB128 (C.Lines);
+ Mod_Time := Read_LEB128 (C.Lines);
+ Length := Read_LEB128 (C.Lines);
+ end loop;
+
+ if Dir_Idx = 0 then
+ -- No directory
+
+ Dir_Name := null;
+
+ else
+ Seek (C.Lines, C.Header.Directories);
+
+ for J in 1 .. Dir_Idx loop
+ Dir_Name := Read_C_String (C.Lines);
- if Dir_Idx = 0 then
- -- No directory
- Dir_Name := null;
+ if Dir_Name (Dir_Name'First) = ASCII.NUL then
+ -- End of directory list, so ill-formed table
+
+ return;
+ end if;
+ end loop;
+ end if;
+
+ -- DWARF 5
else
- Seek (C.Lines, C.Prologue.Includes_Offset);
+ for J in 0 .. Match.File loop
+ for K in 1 .. Integer (C.Header.File_Name_Entry_Format_Count)
+ loop
+ if File_Entry_Format (K).C_Type = DW_LNCT_path then
+ case File_Entry_Format (K).Form is
+ when DW_FORM_string =>
+ File_Name := Read_C_String (C.Lines);
- J := 0;
- loop
- J := J + 1;
- Dir_Name := Read_C_String (C.Lines);
+ when DW_FORM_line_strp =>
+ Read_Section_Offset (C.Lines, Off, C.Header.Is64);
+ Seek (C.Line_Str, Off);
+ File_Name := Read_C_String (C.Line_Str);
- if Dir_Name (Dir_Name'First) = ASCII.NUL then
- -- End of directory list, so ill-formed table
- return;
- end if;
+ when others =>
+ raise Dwarf_Error with "DWARF form not implemented";
+ end case;
+
+ elsif File_Entry_Format (K).C_Type = DW_LNCT_directory_index
+ then
+ case File_Entry_Format (K).Form is
+ when DW_FORM_data1 =>
+ Dir_Idx := uint32 (uint8'(Read (C.Lines)));
+
+ when DW_FORM_data2 =>
+ Dir_Idx := uint32 (uint16'(Read (C.Lines)));
+
+ when DW_FORM_udata =>
+ Dir_Idx := Read_LEB128 (C.Lines);
- exit when J = Dir_Idx;
+ when others =>
+ raise Dwarf_Error with "invalid DWARF";
+ end case;
+ else
+ Skip_Form (C.Lines,
+ File_Entry_Format (K).Form,
+ C.Header.Is64,
+ C.Header.Address_Size);
+ end if;
+ end loop;
+ end loop;
+
+ Seek (C.Lines, C.Header.Directories);
+
+ for J in 0 .. Dir_Idx loop
+ for K in 1 .. Integer (C.Header.Directory_Entry_Format_Count)
+ loop
+ if Directory_Entry_Format (K).C_Type = DW_LNCT_path then
+ case Directory_Entry_Format (K).Form is
+ when DW_FORM_string =>
+ Dir_Name := Read_C_String (C.Lines);
+
+ when DW_FORM_line_strp =>
+ Read_Section_Offset (C.Lines, Off, C.Header.Is64);
+ Seek (C.Line_Str, Off);
+ Dir_Name := Read_C_String (C.Line_Str);
+
+ when others =>
+ raise Dwarf_Error with "DWARF form not implemented";
+ end case;
+
+ else
+ Skip_Form (C.Lines,
+ Directory_Entry_Format (K).Form,
+ C.Header.Is64,
+ C.Header.Address_Size);
+ end if;
+ end loop;
end loop;
end if;
@@ -1414,13 +1732,15 @@ package body System.Dwarf_Lines is
begin
-- Initialize result
+
Dir_Name := null;
File_Name := null;
Subprg_Name := (null, 0);
Line_Num := 0;
+ -- Look up the symbol in the cache
+
if C.Cache /= null then
- -- Look in the cache
declare
Addr_Off : constant uint32 := uint32 (Addr - C.Low);
First, Last, Mid : Natural;
@@ -1447,12 +1767,13 @@ package body System.Dwarf_Lines is
S := Read_Symbol (C.Obj.all, Offset (C.Cache (Mid).Sym));
Subprg_Name := Object_Reader.Name (C.Obj.all, S);
else
- -- Not found
return;
end if;
end;
+
+ -- Search for the symbol in the binary
+
else
- -- Search symbol
S := First_Symbol (C.Obj.all);
while S /= Null_Symbol loop
if Spans (S, Addr_Int) then
@@ -1479,15 +1800,15 @@ package body System.Dwarf_Lines is
end if;
Seek (C.Lines, Line_Offset);
- C.Next_Prologue := 0;
+ C.Next_Header := 0;
Initialize_State_Machine (C);
- Parse_Prologue (C);
+ Parse_Header (C);
Previous_Row.Line := 0;
-- Advance to the first entry
loop
- Read_And_Execute_Isn (C, Done);
+ Read_And_Execute_Insn (C, Done);
if C.Registers.Is_Row then
Previous_Row := C.Registers;
@@ -1499,8 +1820,8 @@ package body System.Dwarf_Lines is
-- Read the rest of the entries
- while Tell (C.Lines) < C.Next_Prologue loop
- Read_And_Execute_Isn (C, Done);
+ while Tell (C.Lines) < C.Next_Header loop
+ Read_And_Execute_Insn (C, Done);
if C.Registers.Is_Row then
if not Previous_Row.End_Sequence
@@ -1533,6 +1854,7 @@ package body System.Dwarf_Lines is
return I - Str'First;
end if;
end loop;
+
return Str'Last;
end String_Length;
@@ -1558,6 +1880,7 @@ package body System.Dwarf_Lines is
Subprg_Name : String_Ptr_Len;
Line_Num : Natural;
Off : Natural;
+
begin
if not C.Has_Debug then
Symbol_Found := False;
@@ -1657,4 +1980,5 @@ package body System.Dwarf_Lines is
Append (Res, ASCII.LF);
end loop;
end Symbolic_Traceback;
+
end System.Dwarf_Lines;
diff --git a/gcc/ada/libgnat/s-dwalin.ads b/gcc/ada/libgnat/s-dwalin.ads
index c7bb103..132d3e1 100644
--- a/gcc/ada/libgnat/s-dwalin.ads
+++ b/gcc/ada/libgnat/s-dwalin.ads
@@ -30,13 +30,10 @@
------------------------------------------------------------------------------
-- 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.
+-- a binary 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.
+-- Files must be compiled with at least minimal debugging information (-g1).
with Ada.Exceptions.Traceback;
@@ -50,11 +47,11 @@ package System.Dwarf_Lines is
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.
+ -- Type encapsulating the state of the DWARF reader. When In_Exception is
+ -- True, we are parsing as part of an exception handler decorator so we do
+ -- not want another exception to be raised and the parsing is done safely,
+ -- skipping binary files that cannot be read or have been stripped from
+ -- their debug sections for example.
procedure Open
(File_Name : String;
@@ -65,14 +62,13 @@ package System.Dwarf_Lines is
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.
+ -- Independent Executable) binaries.
function Is_Inside (C : Dwarf_Context; Addr : Address) return Boolean;
pragma Inline (Is_Inside);
-- Return true iff a run-time address Addr is within the module
- function Low_Address (C : Dwarf_Context)
- return System.Address;
+ function Low_Address (C : Dwarf_Context) return System.Address;
pragma Inline (Low_Address);
-- Return the lowest address of C, accounting for the module load address
@@ -83,7 +79,7 @@ package System.Dwarf_Lines is
-- Dump the cache (if present)
procedure Enable_Cache (C : in out Dwarf_Context);
- -- Read symbols information to speed up Symbolic_Traceback.
+ -- Read symbol information to speed up Symbolic_Traceback.
procedure Symbolic_Traceback
(Cin : Dwarf_Context;
@@ -102,45 +98,64 @@ package System.Dwarf_Lines is
private
-- The following section numbers reference
- -- "DWARF Debugging Information Format, Version 3"
+ -- "DWARF Debugging Information Format, Version 5"
-- 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;
+ 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;
+ -- Discriminator : SOR.uint32; -- DWARF 4/5
+ Is_Row : Boolean; -- local
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;
+ -- 6.2.4 The Line Number Program Header
+
+ MAX_OPCODE : constant := 256;
+
+ type Opcode_Length_Array is array (1 .. MAX_OPCODE) of SOR.uint8;
+
+ MAX_ENTRY : constant := 5;
+
+ type Entry_Format_Pair is record
+ C_Type : SOR.uint32;
+ Form : SOR.uint32;
+ end record;
+
+ type Entry_Format_Array is array (1 .. MAX_ENTRY) of Entry_Format_Pair;
+
+ type Line_Info_Header is record
+ Unit_Length : SOR.Offset;
+ Version : SOR.uint16;
+ Address_Size : SOR.uint8; -- DWARF 5
+ Segment_Selector_Size : SOR.uint8; -- DWARF 5
+ Header_Length : SOR.uint32;
+ Minimum_Insn_Length : SOR.uint8;
+ Maximum_Op_Per_Insn : SOR.uint8; -- DWARF 4/5
+ Default_Is_Stmt : SOR.uint8;
+ Line_Base : SOR.int8;
+ Line_Range : SOR.uint8;
+ Opcode_Base : SOR.uint8;
+ -- Standard_Opcode_Lengths : Opcode_Length_Array;
+ Directory_Entry_Format_Count : SOR.uint8; -- DWARF 5
+ Directory_Entry_Format : Entry_Format_Array; -- DWARF 5
+ Directories_Count : SOR.uint32; -- DWARF 5
+ Directories : SOR.Offset;
+ File_Name_Entry_Format_Count : SOR.uint8; -- DWARF 5
+ File_Name_Entry_Format : Entry_Format_Array; -- DWARF 5
+ File_Names_Count : SOR.uint32; -- DWARF 5
+ File_Names : SOR.Offset;
+ Is64 : Boolean; -- local
end record;
type Search_Entry is record
@@ -175,15 +190,16 @@ private
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
+ Abbrev : SOR.Mapped_Stream;
+ Aranges : SOR.Mapped_Stream;
+ Info : SOR.Mapped_Stream;
+ Lines : SOR.Mapped_Stream;
+ Line_Str : SOR.Mapped_Stream; -- DWARF 5
+ -- DWARF sections
- Prologue : Line_Info_Prologue;
- Registers : Line_Info_Registers;
- Next_Prologue : SOR.Offset;
+ Header : Line_Info_Header;
+ Registers : Line_Info_Registers;
+ Next_Header : SOR.Offset;
-- State for lines
end record;