summaryrefslogtreecommitdiff
path: root/ortho/mcode/elfdump.adb
blob: d4927591286f4cb8f97d4521ef2accf3bc51ec10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
--  ELF dumper (main program).
--  Copyright (C) 2006 Tristan Gingold
--
--  GHDL is free software; you can redistribute it and/or modify it under
--  the terms of the GNU General Public License as published by the Free
--  Software Foundation; either version 2, or (at your option) any later
--  version.
--
--  GHDL is distributed in the hope that it will be useful, but WITHOUT ANY
--  WARRANTY; without even the implied warranty of MERCHANTABILITY or
--  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
--  for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with GCC; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.
with Ada.Text_IO; use Ada.Text_IO;
with Elf_Common; use Elf_Common;
with Ada.Command_Line; use Ada.Command_Line;
with Hex_Images; use Hex_Images;
with Interfaces; use Interfaces;
with Elfdumper; use Elfdumper;

procedure Elfdump is
   Flag_Ehdr : Boolean := False;
   Flag_Shdr : Boolean := False;
   Flag_Strtab : Boolean := False;
   Flag_Symtab : Boolean := False;
   Flag_Dwarf_Info : Boolean := False;
   Flag_Dwarf_Abbrev : Boolean := False;
   Flag_Dwarf_Pubnames : Boolean := False;
   Flag_Dwarf_Aranges : Boolean := False;
   Flag_Dwarf_Line : Boolean := False;
   Flag_Dwarf_Frame : Boolean := False;
   Flag_Eh_Frame_Hdr : Boolean := False;
   Flag_Long_Shdr : Boolean := False;
   Flag_Phdr : Boolean := False;
   Flag_Note : Boolean := False;
   Flag_Dynamic : Boolean := False;

   procedure Disp_Max_Len (Str : String; Len : Natural)
   is
   begin
      if Str'Length > Len then
         Put (Str (Str'First .. Str'First + Len - 1));
      else
         Put (Str);
         Put ((Str'Length + 1 .. Len => ' '));
      end if;
   end Disp_Max_Len;

   procedure Disp_Section_Header (File : Elf_File; Index : Elf_Half) is
   begin
      Put ("Section " & Hex_Image (Index));
      Put (" ");
      Put (Get_Section_Name (File, Index));
      New_Line;
   end Disp_Section_Header;

   procedure Disp_Elf_File (Filename : String)
   is
      File : Elf_File;
      Ehdr : Elf_Ehdr_Acc;
      Shdr : Elf_Shdr_Acc;
      Phdr : Elf_Phdr_Acc;
      Sh_Strtab : Strtab_Type;
   begin
      Open_File (File, Filename);
      if Get_Status (File) /= Status_Ok then
         Put_Line ("cannot open elf file '" & Filename & "': " &
                   Elf_File_Status'Image (Get_Status (File)));
         return;
      end if;

      Ehdr := Get_Ehdr (File);

      if Flag_Ehdr then
         Disp_Ehdr (Ehdr.all);
      end if;

      Load_Shdr (File);
      Sh_Strtab := Get_Sh_Strtab (File);

      if Flag_Long_Shdr then
         if Ehdr.E_Shnum = 0 then
            Put ("no section");
         else
            for I in 0 .. Ehdr.E_Shnum - 1 loop
               Put ("Section " & Hex_Image (I));
               New_Line;
               Disp_Shdr (Get_Shdr (File, I).all, Sh_Strtab);
            end loop;
         end if;
      end if;
      if Flag_Shdr then
         if Ehdr.E_Shnum = 0 then
            Put ("no section");
         else
            Put ("Num   Name                Type       ");
            Put ("Offset   Size     Link Info Al Es");
            New_Line;
            for I in 0 .. Ehdr.E_Shnum - 1 loop
               declare
                  Shdr : Elf_Shdr_Acc := Get_Shdr (File, I);
               begin
                  Put (Hex_Image (I));
                  Put (" ");
                  Disp_Max_Len (Get_Section_Name (File, I), 20);
                  Put (" ");
                  Disp_Max_Len (Get_Shdr_Type_Name (Shdr.Sh_Type), 10);
                  Put (" ");
                  Put (Hex_Image (Shdr.Sh_Offset));
                  Put (" ");
                  Put (Hex_Image (Shdr.Sh_Size));
                  Put (" ");
                  Put (Hex_Image (Unsigned_16 (Shdr.Sh_Link and 16#Ffff#)));
                  Put (" ");
                  Put (Hex_Image (Unsigned_16 (Shdr.Sh_Info and 16#Ffff#)));
                  Put (" ");
                  Put (Hex_Image (Unsigned_8 (Shdr.Sh_Addralign and 16#ff#)));
                  Put (" ");
                  Put (Hex_Image (Unsigned_8 (Shdr.Sh_Entsize and 16#ff#)));
                  New_Line;
               end;
            end loop;
         end if;
      end if;

      if Flag_Phdr then
         Load_Phdr (File);
         if Ehdr.E_Phnum = 0 then
            Put ("no program segment");
         else
            for I in 0 .. Ehdr.E_Phnum - 1 loop
               Put ("segment " & Hex_Image (I));
               New_Line;
               Disp_Phdr (Get_Phdr (File, I).all);
            end loop;
         end if;
      end if;

      --  Dump each section.
      if Ehdr.E_Shnum > 0 then
         for I in 0 .. Ehdr.E_Shnum - 1 loop
            Shdr := Get_Shdr (File, I);
            case Shdr.Sh_Type is
               when SHT_SYMTAB =>
                  if Flag_Symtab then
                     Disp_Section_Header (File, I);
                     Disp_Symtab (File, I);
                  end if;
               when SHT_STRTAB =>
                  if Flag_Strtab then
                     Disp_Section_Header (File, I);
                     Disp_Strtab (File, I);
                  end if;
               when SHT_PROGBITS =>
                  declare
                     Name : String := Get_Section_Name (File, I);
                  begin
                     if Flag_Dwarf_Abbrev and then Name = ".debug_abbrev" then
                        Disp_Section_Header (File, I);
                        Disp_Debug_Abbrev (File, I);
                     elsif Flag_Dwarf_Info and then Name = ".debug_info" then
                        Disp_Section_Header (File, I);
                        Disp_Debug_Info (File, I);
                     elsif Flag_Dwarf_Line and then Name = ".debug_line" then
                        Disp_Section_Header (File, I);
                        Disp_Debug_Line (File, I);
                     elsif Flag_Dwarf_Frame and then Name = ".debug_frame" then
                        Disp_Section_Header (File, I);
                        Disp_Debug_Frame (File, I);
                     elsif Flag_Dwarf_Pubnames
                       and then Name = ".debug_pubnames"
                     then
                        Disp_Section_Header (File, I);
                        Disp_Debug_Pubnames (File, I);
                     elsif Flag_Eh_Frame_Hdr and then Name = ".eh_frame_hdr"
                     then
                        Disp_Section_Header (File, I);
                        Disp_Eh_Frame_Hdr (File, I);
                     elsif Flag_Dwarf_Aranges
                       and then Name = ".debug_aranges"
                     then
                        Disp_Section_Header (File, I);
                        Disp_Debug_Aranges (File, I);
                     end if;
                  end;
               when SHT_NOTE =>
                  if Flag_Note then
                     Disp_Section_Header (File, I);
                     Disp_Section_Note (File, I);
                  end if;
               when SHT_DYNAMIC =>
                  if Flag_Dynamic then
                     Disp_Section_Header (File, I);
                     Disp_Dynamic (File, I);
                  end if;
               when others =>
                  null;
            end case;
         end loop;
      elsif Ehdr.E_Phnum > 0 then
         Load_Phdr (File);
         for I in 0 .. Ehdr.E_Phnum - 1 loop
            Phdr := Get_Phdr (File, I);
            case Phdr.P_Type is
               when PT_NOTE =>
                  if Flag_Note then
                     Disp_Segment_Note (File, I);
                  end if;
               when others =>
                  null;
            end case;
         end loop;
      end if;
   end Disp_Elf_File;

begin
   for I in 1 .. Argument_Count loop
      declare
         Arg : String := Argument (I);
      begin
         if Arg (1) = '-' then
            --  An option.
            if Arg = "-e" then
               Flag_Ehdr := True;
            elsif Arg = "-t" then
               Flag_Strtab := True;
            elsif Arg = "-S" then
               Flag_Symtab := True;
            elsif Arg = "-s" then
               Flag_Shdr := True;
            elsif Arg = "-p" then
               Flag_Phdr := True;
            elsif Arg = "-n" then
               Flag_Note := True;
            elsif Arg = "-d" then
               Flag_Dynamic := True;
            elsif Arg = "--dwarf-info" then
               Flag_Dwarf_Info := True;
            elsif Arg = "--dwarf-abbrev" then
               Flag_Dwarf_Abbrev := True;
            elsif Arg = "--dwarf-line" then
               Flag_Dwarf_Line := True;
            elsif Arg = "--dwarf-frame" then
               Flag_Dwarf_Frame := True;
            elsif Arg = "--dwarf-pubnames" then
               Flag_Dwarf_Pubnames := True;
            elsif Arg = "--dwarf-aranges" then
               Flag_Dwarf_Aranges := True;
            elsif Arg = "--eh-frame-hdr" then
               Flag_Eh_Frame_Hdr := True;
            elsif Arg = "--long-shdr" then
               Flag_Long_Shdr := True;
            else
               Put_Line ("unknown option '" & Arg & "'");
               return;
            end if;
         else
            Disp_Elf_File (Arg);
         end if;
      end;
   end loop;
end Elfdump;