Update documentation
[platform/upstream/nasm.git] / misc / nasmstab
1 #!/usr/bin/perl
2  
3 sub StabLine  ($ $ $ $ $ $) {
4         local ($comment,$n_strx,$type,$other,$desc,$value) = @_;
5         print $comment;
6         print "","dd",$n_strx;
7         print "","db",$type;
8         print "","db",$other;
9         print "","dw",$desc;
10         print "","dd","0" . $value . "h";
11 }
12
13 sub RStabLine  ($ $ $ $ $) {
14         local ($comment,$offset,$info,$type,$symbol) = @_;
15         print $comment;
16         print "","dd",$offset;
17         print "","db",$type;
18         print "","db",$symbol;
19         print "","dw",$info;
20 }
21
22 #this sub exists because i've no idea how to print non-ascii numbers in perl
23
24 sub OutBin ( $ $ ) {
25         local ($offset, $shnum) = @_;
26         seek(FINAL,$offset,0);
27         if ( $shnum == 2 ) { printf FINAL "\x02" } ;
28         if ( $shnum == 3 ) { printf FINAL "\x03" } ;
29         if ( $shnum == 4 ) { printf FINAL "\x04" } ;
30         if ( $shnum == 5 ) { printf FINAL "\x05" } ;
31         if ( $shnum == 6 ) { printf FINAL "\x06" } ;
32         if ( $shnum == 7 ) { printf FINAL "\x07" } ;
33         if ( $shnum == 8 ) { printf FINAL "\x08" } ;
34         if ( $shnum == 9 ) { printf FINAL "\x09" } ;
35         if ( $shnum == 10 ) { printf FINAL "\x0a" } ;
36         if ( $shnum == 11 ) { printf FINAL "\x0b" } ;
37         if ( $shnum == 12 ) { printf FINAL "\x0c" } ;
38         if ( $shnum == 13 ) { printf FINAL "\x0d" } ;
39         if ( $shnum == 14 ) { printf FINAL "\x0e" } ;
40         if ( $shnum == 15 ) { printf FINAL "\x0f" } ;
41 }
42
43 sub DispHelp () {
44         $\="\n";
45         print "Usage:";
46         print "\t-f,--input-file";
47         print "\t\tThe input file name (only required option)";
48         print "\t-o,--output-file";
49         print "\t\tThe output file name (if not specified, *.asm becomes *.o";
50         print "\t\tand anything else becomes a.out)";
51         print "\t-l,--list-file";
52         print "\t\tThe listing file's name (default: trailing .asm is
53 removed";
54         print "\t\tif there and .lst is appended)";
55         print "\t-s,--second-asm-file";
56         print "\t\tThe second asm file's name (default: trailing .asm is";
57         print "\t\tremoved if there and .nasm is appended)";
58         print "\n";
59         exit ;
60 }
61
62 if ( $ARGV[0] eq "" ) { $ARGV[0] = "-h" };
63
64 $i = 0;
65 $filename = "";
66 $outname  = "";
67
68 while ( $ARGV[$i] ne "" ) {
69         $_ = $ARGV[$i];
70         if ( m/^-/ ) {
71                 if ( m/^-f$/ ) { $filename = $ARGV[++$i] };
72                 if ( m/^-o$/ ) { $outname  = $ARGV[++$i] };
73                 if ( m/^-l$/ ) { $listname = $ARGV[++$i] };
74                 if ( m/^-s$/ ) { $asmname  = $ARGV[++$i] };
75                 if ( m/^-h$/ ) { DispHelp };
76         } elsif ( m/^--\w+/ ) {
77                 if ( m/^--input-file$/ )      { $filename = $ARGV[++$i] };
78                 if ( m/^--output-file$/ )     { $outname  = $ARGV[++$i] };
79                 if ( m/^--list-file$/ )       { $listname = $ARGV[++$i] };
80                 if ( m/^--second-asm-file$/ ) { $asmname  = $ARGV[++$i] };
81                 if ( m/^--help/ ) { DispHelp };
82         } elsif ( m/^--$/ ) {
83                 while ( $ARGV[++$i] ) {
84                         $NasmOptions .= " ";
85                         $NasmOptions .= $_;
86                 };
87         } else {
88                 DispHelp()
89         };
90         $i++;
91 };
92
93 if ( $filename eq "" ) { DispHelp() };
94
95 if ( $outname eq "" ) {
96         $outname = $filename;
97         $outname =~ s/\.asm/.o/;
98         if ( $outname eq $filename ) { $outname = "a.out" };
99 };
100
101 if ( $listname eq "" ) {
102         $listname = $filename;
103         $listname =~ s/\.asm//;
104         $listname .= ".lst";
105 };
106
107 if ( $asmname eq "" ) {
108         $asmname = $filename;
109         $asmname =~ s/\.asm//;
110         $asmname .= ".nasm";
111 };
112
113 $err = `nasm -f elf ${filename} -l ${listname} -o ${outname} `;
114
115 if ( $err ) { die "\n$err\n"};
116
117 open(LISTFILE,"${listname}") or die "\n $0: Could not reopen list file!\n";
118 open(ASMFILE,">${asmname}")  or die "\n $0: Could not open asm file!\n";
119
120 select ASMFILE;
121
122 open(OLDASM,$filename) or die "\n$0: Cannot open file $filename\n";
123
124 while ( $x = <OLDASM> ) {
125         print $x;
126 }
127
128 @stab = ("n_desc", "value");
129 @rel_stab = ("offset");
130 $i = 0;
131 $current_section = "";
132 $has_text = 'FALSE';
133 $midst_of_macro = 'FALSE';
134 $line_dec = 0 ;
135
136 while ( $x = <LISTFILE> ) {
137         if ( $x =~ m/[^;]*%include/ ) {
138                 $x = <LISTFILE>;
139                 while ( $x =~ m/\s+\d+\s+\<\d+\>\s+/ ) {
140                         $x = <LISTFILE>;
141                         $line_dec++;
142                 }
143         }
144         if ( $current_section eq ".text" ) {
145                 if ( $x =~ m/^\s+(\S+)\s+(\S+)\s+(\S+)\s+[^<]+$/ ) {
146                         $stab[$i++] = $1-$line_dec;     #linenum
147                         $stab[$i++] = $2;               #offset
148                         $count++;
149                         if ( $3 =~ m/-/ ) {
150                                 $x = <LISTFILE>;
151                                 $line_dec++;
152                         }
153                         $midst_of_macro = 'FALSE';
154                 } elsif ( $x =~ m/^\s+(\S+)\s+(\S+)\s+(\S+)\s+<\d+>/ ) {
155                         if ( $midst_of_macro eq 'TRUE' ) {
156                                 $stab[$i] = $stab[$i-2]; #same linenum
157                                 $line_dec++;
158                         } else {
159                                 $stab[$i] = $1 - ++$line_dec;
160                                 $midst_of_macro = 'TRUE';
161                         }
162                         $count++;
163                         $i++;
164                         $stab[$i++] = $2;
165                         if ( $3 =~ m/-/ ) {
166                                 $x = <LISTFILE>;
167                                 $line_dec++;
168                         }
169
170                 }
171                 $has_text = 'TRUE';
172         } elsif ( $x =~ m/\s+\S+\s+\S+\s+\S+\s+<\d+>/ ) { # is it a macro?
173                 $line_dec++;
174         }
175         if ( $x =~ s/(section|segment)\s+([^\s]+)/$2/ ) {
176                         $current_section = $2;
177         }
178 };
179
180 close LISTFILE;
181
182 unless ( $has_text eq "TRUE" ) {
183         $err = `nasm -f elf ${asmname} -o ${outname}`;
184         print STDERR $err;
185         exit;
186 }
187
188 #Write Stab section
189 $, = "\t";      #output field separator
190 $\ = "\n";      #output record separator
191
192 print "section .stab noalloc";
193 StabLine(";header",1,0,0,$count+1,length($filename)*2+3);
194 StabLine(";so",length($asmname)+2,"064h",0,0,0);
195
196 $offset = 12;
197 $i = 0;
198 $j = 0;
199 $rel_stab[$j++] = $offset + 8;
200
201 while ( $stab[$i] ) {
202         StabLine(";N_SLINE" . " " . ( ($i+2) / 2 ), 0, "044h", 0,
203                 $stab[$i++], $stab[$i++]);
204         $offset += 12;
205         $rel_stab[$j++] = $offset + 8;
206 }
207
208 #Write .rel.stab section
209 print "\n\nsection .rel.stab noalloc";
210
211 open (READELF,"readelf -s ${outname} |") or die "\n$0: Could not run readelf\n";
212
213 while ( $x = <READELF> ) {
214    if ( $x =~ m/\s+(\d+):\s+00000000\s+\d+\s+SECTION\s+\w+\s+\w+\s+1\s+/){ $textsymnum = $1;
215    };
216 };
217 close READELF;
218
219 $i = 0;
220
221 while ( $rel_stab[$i] ne "" ) {
222         RStabLine(";relocation for N_SLINE " . ($i), $rel_stab[$i], 0, 1, $textsymnum);
223         $i++;
224 } ;
225
226 #Write .stabstr section
227
228 print "\n\nsection .stabstr noalloc";
229
230 print "","db","0";
231 print "","db",'"' . $asmname . '"';
232 print "","db","0";
233 print "","db",'"' . $asmname . '"' ;
234 print "","db","0";
235
236 close ASMFILE;
237
238 $err = `nasm -f elf ${asmname} -o ${outname}`;
239
240 if ( $err ) { die "\n$err\n" } ;
241
242 open (READELF,"readelf -h -S ${outname} |") or die "\n$0: Could not run readelf\n";
243
244
245 while ( $x = <READELF> ) {
246         if ( $x =~ m/Start\s+of\s+section\s+headers:\s+(\d+)\s+/ ) {
247                 $shoff = $1;
248         }
249         if ( $x =~ m/Size\s+of\s+section\s+headers:\s+(\d+)\s+/ ) {
250                 $shentsize = $1;
251         }
252         if ( $x =~ m/\[\s*(\d+)\]\s+.rel.stab\s+/ ) {
253                 $relnum = $1;
254         }
255         if ( $x =~ m/\[\s*(\d+)\]\s+.stab\s+/ ) {
256                 $stabnum = $1;
257         }
258         if ( $x =~ m/\[\s*(\d+)\]\s+.stabstr\s+/ ) {
259                 $stabstrnum = $1;
260         }
261         if ( $x =~ m/\[\s*(\d+)\]\s+.symtab\s+/ ) {
262                 $symtabnum = $1;
263         }
264 }
265 close READELF;
266
267 sysopen (FINAL,"${outname}",2,0) or die "\n$0: Could not open ${outname}";
268 $, = "";        #output field separator
269 $\ = "";        #output record separator
270
271 #set .rel.stab->type to rel
272 OutBin($shoff + ($shentsize * $relnum) + 4,9);
273
274 #set .rel.stab->link to .symtab
275 OutBin($shoff + ($shentsize * $relnum) + 24,$symtabnum);
276
277 #set .rel.stab->info to .stab
278 OutBin($shoff + ($shentsize * $relnum) + 28,$stabnum);
279
280 #set .rel.stab->entsize to 8
281 OutBin($shoff + ($shentsize * $relnum) + 36,8);
282
283 #set .stab->link to .stabstr
284 OutBin($shoff + ($shentsize * $stabnum) + 24,$stabstrnum);
285
286 #set .stab->entsize to 12
287 OutBin($shoff + ($shentsize * $stabnum) + 36,12);
288
289 #set .stabstr->type to strtab
290 OutBin($shoff + ($shentsize * $stabstrnum) + 4,3);
291
292 close FINAL;
293
294 #Date: 17 Mar 2002 15:51:20 -0800
295 #From: kitsred@hotmail.com (kired)
296 #Newsgroups: alt.lang.asm