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
268
269
270
271
272
|
-- COFF dumper.
-- Copyright (C) 2006 Tristan Gingold
--
-- This program 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 of the License, or
-- (at your option) any later version.
--
-- This program 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 this program. If not, see <gnu.org/licenses>.
with Coff; use Coff;
with Interfaces; use Interfaces;
with System;
with Ada.Unchecked_Conversion;
with Ada.Command_Line; use Ada.Command_Line;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with Ada.Text_IO; use Ada.Text_IO;
with Hex_Images; use Hex_Images;
procedure Coffdump is
type Cstring is array (Unsigned_32 range <>) of Character;
type Cstring_Acc is access Cstring;
type Section_Array is array (Unsigned_16 range <>) of Scnhdr;
type Section_Array_Acc is access Section_Array;
-- Array of sections.
Sections : Section_Array_Acc;
type External_Symbol is array (0 .. Symesz - 1) of Character;
type External_Symbol_Array is array (Unsigned_32 range <>)
of External_Symbol;
type Symbol_Array_Acc is access External_Symbol_Array;
-- Symbols table.
External_Symbols : Symbol_Array_Acc;
-- String table.
Str : Cstring_Acc;
Str_Size : Natural;
Hdr : Filehdr;
--Sym : Syment;
Fd : File_Descriptor;
Skip : Natural;
Skip_Kind : Unsigned_8;
Aux_File : Auxent_File;
Aux_Scn : Auxent_Scn;
Rel : Reloc;
Len : Natural;
Nul : constant Character := Character'Val (0);
function Find_Nul (S : String) return String is
begin
for I in S'Range loop
if S (I) = Nul then
return S (S'First .. I - 1);
end if;
end loop;
return S;
end Find_Nul;
function Get_String (N : Strent_Type; S : String) return String
is
begin
if N.E_Zeroes /= 0 then
return Find_Nul (S);
else
for I in N.E_Offset .. Str'Last loop
if Str (I) = Nul then
return String (Str (N.E_Offset .. I - 1));
end if;
end loop;
raise Program_Error;
end if;
end Get_String;
procedure Memcpy
(Dst : System.Address; Src : System.Address; Size : Natural);
pragma Import (C, Memcpy);
function Get_Section_Name (N : Unsigned_16) return String is
begin
if N = N_UNDEF then
return "UNDEF";
elsif N = N_ABS then
return "ABS";
elsif N = N_DEBUG then
return "DEBUG";
elsif N > Hdr.F_Nscns then
return "???";
else
return Find_Nul (Sections (N).S_Name);
end if;
end Get_Section_Name;
function Get_Symbol (N : Unsigned_32) return Syment is
function Unchecked_Conv is new Ada.Unchecked_Conversion
(Source => External_Symbol, Target => Syment);
begin
if N > Hdr.F_Nsyms then
raise Constraint_Error;
end if;
return Unchecked_Conv (External_Symbols (N));
end Get_Symbol;
function Get_Symbol_Name (N : Unsigned_32) return String
is
S : Syment := Get_Symbol (N);
begin
return Get_String (S.E.E, S.E.E_Name);
end Get_Symbol_Name;
begin
for I in 1 .. Argument_Count loop
Fd := Open_Read (Argument (I), Binary);
if Fd = Invalid_FD then
Put_Line ("cannot open " & Argument (I));
return;
end if;
-- Read file header.
if Read (Fd, Hdr'Address, Filehdr_Size) /= Filehdr_Size then
Put_Line ("cannot read header");
return;
end if;
Put_Line ("File: " & Argument (I));
Put_Line ("magic: " & Hex_Image (Hdr.F_Magic));
Put_Line ("number of sections: " & Hex_Image (Hdr.F_Nscns));
Put_Line ("time and date stamp: " & Hex_Image (Hdr.F_Timdat));
Put_Line ("symtab file pointer: " & Hex_Image (Hdr.F_Symptr));
Put_Line ("nbr symtab entries: " & Hex_Image (Hdr.F_Nsyms));
Put_Line ("opt header size: " & Hex_Image (Hdr.F_Opthdr));
Put_Line ("flags: " & Hex_Image (Hdr.F_Flags));
-- Read sections header.
Lseek (Fd, Long_Integer (Hdr.F_Opthdr), Seek_Cur);
Sections := new Section_Array (1 .. Hdr.F_Nscns);
Len := Scnhdr_Size * Natural (Hdr.F_Nscns);
if Read (Fd, Sections (1)'Address, Len) /= Len then
Put_Line ("cannot read section header");
return;
end if;
for I in 1 .. Hdr.F_Nscns loop
declare
S: Scnhdr renames Sections (I);
begin
Put_Line ("Section " & Find_Nul (S.S_Name));
Put_Line ("Physical address : " & Hex_Image (S.S_Paddr));
Put_Line ("Virtual address : " & Hex_Image (S.S_Vaddr));
Put_Line ("section size : " & Hex_Image (S.S_Size));
Put_Line ("section pointer : " & Hex_Image (S.S_Scnptr));
Put_Line ("relocation pointer : " & Hex_Image (S.S_Relptr));
Put_Line ("line num pointer : " & Hex_Image (S.S_Lnnoptr));
Put_Line ("Nbr reloc entries : " & Hex_Image (S.S_Nreloc));
Put_Line ("Nbr line num entries : " & Hex_Image (S.S_Nlnno));
Put_Line ("Flags : " & Hex_Image (S.S_Flags));
end;
end loop;
-- Read string table.
Lseek (Fd,
Long_Integer (Hdr.F_Symptr + Hdr.F_Nsyms * Unsigned_32 (Symesz)),
Seek_Set);
if Read (Fd, Str_Size'Address, 4) /= 4 then
Put_Line ("cannot read string table size");
return;
end if;
Str := new Cstring (0 .. Unsigned_32 (Str_Size));
if Read (Fd, Str (4)'Address, Str_Size - 4) /= Str_Size - 4 then
Put_Line ("cannot read string table");
return;
end if;
-- Read symbol table.
Lseek (Fd, Long_Integer (Hdr.F_Symptr), Seek_Set);
External_Symbols := new External_Symbol_Array (0 .. Hdr.F_Nsyms - 1);
Len := Natural (Hdr.F_Nsyms) * Symesz;
if Read (Fd, External_Symbols (0)'Address, Len) /= Len then
Put_Line ("cannot read symbol");
return;
end if;
Skip := 0;
Skip_Kind := C_NULL;
for I in External_Symbols'range loop
if Skip > 0 then
case Skip_Kind is
when C_FILE =>
Memcpy (Aux_File'Address, External_Symbols (I)'Address,
Aux_File'Size / 8);
Put_Line ("aux file : " & Get_String (Aux_File.X_N,
Aux_File.X_Fname));
Skip_Kind := C_NULL;
when C_STAT =>
Memcpy (Aux_Scn'Address, External_Symbols (I)'Address,
Aux_Scn'Size / 8);
Put_Line ("section len: " & Hex_Image (Aux_Scn.X_Scnlen));
Put_Line ("nbr reloc ent: " & Hex_Image (Aux_Scn.X_Nreloc));
Put_Line ("nbr line num: " & Hex_Image (Aux_Scn.X_Nlinno));
when others =>
Put_Line ("skip");
end case;
Skip := Skip - 1;
else
declare
S : Syment := Get_Symbol (I);
begin
Put_Line ("Symbol #" & Hex_Image (I));
Put_Line ("symbol name : " & Get_Symbol_Name (I));
Put_Line ("symbol value: " & Hex_Image (S.E_Value));
Put_Line ("section num : " & Hex_Image (S.E_Scnum)
& " " & Get_Section_Name (S.E_Scnum));
Put_Line ("type : " & Hex_Image (S.E_Type));
Put ("sclass : " & Hex_Image (S.E_Sclass));
if Sclass_Desc (S.E_Sclass).Name /= null then
Put (" (");
Put (Sclass_Desc (S.E_Sclass).Name.all);
Put (" - ");
Put (Sclass_Desc (S.E_Sclass).Meaning.all);
Put (")");
end if;
New_Line;
Put_Line ("numaux : " & Hex_Image (S.E_Numaux));
if S.E_Numaux > 0 then
case S.E_Sclass is
when C_FILE =>
Skip_Kind := C_FILE;
when C_STAT =>
Skip_Kind := C_STAT;
when others =>
Skip_Kind := C_NULL;
end case;
end if;
Skip := Natural (S.E_Numaux);
end;
end if;
end loop;
-- Disp relocs.
for I in 1 .. Hdr.F_Nscns loop
if Sections (I).S_Nreloc > 0 then
-- Read relocations.
Put_Line ("Relocations for section " & Get_Section_Name (I));
Lseek (Fd, Long_Integer (Sections (I).S_Relptr), Seek_Set);
for J in 1 .. Sections (I).S_Nreloc loop
if Read (Fd, Rel'Address, Relsz) /= Relsz then
Put_Line ("cannot read reloc");
return;
end if;
Put_Line ("reloc virtual addr: " & Hex_Image (Rel.R_Vaddr));
Put_Line ("symbol index : " & Hex_Image (Rel.R_Symndx)
& " " & Get_Symbol_Name (Rel.R_Symndx));
Put ("type of relocation: " & Hex_Image (Rel.R_Type));
case Rel.R_Type is
when Reloc_Rel32 =>
Put (" RELOC_REL32");
when Reloc_Addr32 =>
Put (" RELOC_ADDR32");
when others =>
null;
end case;
New_Line;
end loop;
end if;
end loop;
Close (Fd);
end loop;
end Coffdump;
|