nasmstab 8.7 KB

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