Table extractor tool
Benjamin Larsson <[email protected]> Tue, 20 Dec 2005 19:55:44 +0000
| Newsgroups | gmane.comp.video.xine.codec.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi, I have meant to release this tool for some time now but I've been lazy. Anyway it's called elftractor and can extract tables from elf executables with the info from the symbol tables. To use it just run it with ./elftractor.pl --analyse "file". A default database file is then created. This file is a regular textfile that can be edited. After the database has been edited, just run ./elftractor.pl --generate-tables "file" to extract the tables from the file. Currently only 1 and 2 dimensional tables can be generated correctly. I've attached one example db for the indeo4 decoder elf. This file can be found in the all codec package from mplayerhq. MvH Benjamin Larsson -- "incorrect information" is an oxymoron. Information is, by definition, factual, correct.
elftractor.pl
(text/plain, 11.7 KB)
#!/usr/bin/perl
#Argument parser
if (@ARGV){
if ($ARGV[0] eq "--analyse"){
$demange=0;
analyse();
}
if ($ARGV[0] eq "--analyse-demangle"){
$demangle=1;
analyse();
}
if ($ARGV[0] eq "--generate-skeleton"){
generate_skeleton();
}
if ($ARGV[0] eq "--generate-tables"){
generate_tables();
}
if ($ARGV[0] eq "--generate-all"){
generate_tables();
generate_skeleton();
}
} else{
print "Usage:\n";
print "./elftractor.pl [command] binary\n";
print "--analyse - analyses and creates a database\n";
print "--analyse-demangle - analyse and demangle of function names\n";
print "--generate-skeleton - generates code skeleton from database\n";
print "--generate-tables - generates datatables from database\n";
print "--generate-all - generates tables and function skeleton\n";
exit;
}
exit;
sub generate_skeleton
{
#parse the input file
$FILE1 = $ARGV[1];
$ts = 0;
$tn = 0;
open(DATAFILE, "<$FILE1.db") or die "File doesn't exist\n";
while ($rad = <DATAFILE>)
{
if ($rad eq "[functions end]\n") {$ts = 0;}
if ($ts == 1) {
chomp($rad);
@tmpsplit=split /;/,$rad;
$functions_name[$tn] = $tmpsplit[0];
$functions_address[$tn] = $tmpsplit[1];
$functions_size[$tn] = $tmpsplit[2];
$functions_argument[$tn] = $tmpsplit[3];
$tn++;
}
if ($rad eq "[functions begin]\n") {$ts = 1;}
}
#open outputfile
open(OUTFILE, ">$FILE1.c") or die "can't open $FILE1.c: $!";
print OUTFILE "#include \"$FILE1.h\"\n\n\n\n";
for ($i=0 ; $i<$tn; $i++){
print OUTFILE "static void $functions_name[$i]$functions_argument[$i]\n{\n}\n\n";
}
close(OUTFILE);
print "$tn functions written to $FILE1.c\n";
}
sub generate_tables
{
#parse the input file
$FILE1 = $ARGV[1];
$ts = 0;
$tn = 0;
open(DATAFILE, "<$FILE1.db") or die "File doesn't exist\n";
while ($rad = <DATAFILE>)
{
if ($rad eq "[tables end]\n") {$ts = 0;}
if ($ts == 1) {
chomp($rad);
@tmpsplit=split /;/,$rad;
$tabler_name[$tn] = $tmpsplit[0];
$tabler_address[$tn] = $tmpsplit[1];
$tabler_size[$tn] = $tmpsplit[2];
$tabler_type[$tn] = $tmpsplit[3];
$tabler_cols[$tn] = $tmpsplit[4];
$tabler_readonly[$tn] = $tmpsplit[5];
$tabler_dimensions[$tn] = $tmpsplit[6];
for ($i=0 ; $i<$tabler_dimensions[$tn] ; $i++){
$tabler_dsize[$tn][$i] = $tmpsplit[7+$i];
}
$tn++;
#print "$tmpsplit[0] - $tmpsplit[5]\n";
}
if ($rad eq "[tables begin]\n") {$ts = 1;}
}
close(DATAFILE);
#get .data and .rodata offsets
open(DATAFILE, "<$FILE1.db") or die "File doesn't exist\n";
$ts = 0;
while ($rad = <DATAFILE>)
{
if ($rad eq "[offset end]\n") {$ts = 0;}
if ($ts == 2) {
@tmpsplit=split /;/,$rad;
$doffset = $tmpsplit[1];
$ts = 3;
}
if ($ts == 1) {
@tmpsplit=split /;/,$rad;
$drooffset = $tmpsplit[1];
$ts = 2;
}
if ($rad eq "[offset begin]\n") {$ts = 1;}
}
close(DATAFILE);
#open outputfile
open(OUTFILE, ">$FILE1.h") or die "can't open $FILE1.h: $!";
#print "$drooffset $doffset\n";
for ($i=0 ; $i<$tn; $i++){
#type to unpacktype
$unpacktype="";
$delim=0;
$floatfix=0;
if ($tabler_type[$i] eq "int8_t") {$unpacktype="c";}
if ($tabler_type[$i] eq "uint8_t") {$unpacktype="C";}
if ($tabler_type[$i] eq "int16_t") {$unpacktype="s";}
if ($tabler_type[$i] eq "uint16_t") {$unpacktype="S";}
if ($tabler_type[$i] eq "int32_t") {$unpacktype="i";}
if ($tabler_type[$i] eq "uint32_t") {$unpacktype="I";}
if ($tabler_type[$i] eq "int64_t") {$unpacktype="l";}
if ($tabler_type[$i] eq "uint64_t") {$unpacktype="L";}
if ($tabler_type[$i] eq "float") {$unpacktype="f";$floatfix = 1;}
if ($tabler_type[$i] eq "double") {$unpacktype="d";$floatfix = 1;}
if ($tabler_type[$i] eq "hex8_t") {$unpacktype="h";$delim=2;}
if ($tabler_type[$i] eq "hex16_t") {$unpacktype="h";$delim=4;}
if ($tabler_type[$i] eq "hex32_t") {$unpacktype="h";$delim=8;}
if ($tabler_type[$i] eq "hex64_t") {$unpacktype="h";$delim=16;}
#get right offset
if ($tabler_readonly[$i]==1){
$ofs = $drooffset;
} else {
$ofs = $doffset;
}
#calculate the seek address
$seekaddress = hex($tabler_address[$i]) - $ofs;
#access the file for data
open(BINFILE, $FILE1) or die "can't open $FILE1: $!";
seek(BINFILE, $seekaddress, 0) or die "seek:$!";
read(BINFILE, $BUFFER, $tabler_size[$i]);
close(BINFILE);
@fields = unpack("$unpacktype*",$BUFFER);
#divide the hex numbers
if ($delim > 0) {
$hexdata = $fields[0];
$fptr = 0;
for ($nptr=0;$nptr < (length($hexdata));$nptr = $nptr + $delim) {
$fields[$fptr] = "\"0x".substr("$hexdata", $nptr, $delim)."\"";
$fptr++;
}
#rename the type hex to uint
$tabler_type[$i] =~ s/hex/uint/;
}
#numbers of elements
$numelements = $#fields+1;
#const or not
$const = "";
if ($tabler_readonly[$i]==1){
$const = "const ";
}
$tsize = 1;
$dimstring = "";
#evaluate the dimensions
for ($j=0; $j<$tabler_dimensions[$i]-1; $j++){
$tsize = $tsize*$tabler_dsize[$i][$j];
$dimstring = $dimstring."\[$tabler_dsize[$i][$j]\]";
}
$numelements_last = $numelements/$tsize;
$dimstring = $dimstring."\[$numelements_last\]";
print OUTFILE "static $const$tabler_type[$i] $tabler_name[$i]$dimstring = {\n ";
if ($tabler_dimensions[$tn]>1) {
print OUTFILE "{ ";
}
$colcounter = 0;
$elcounter = 0;
foreach $rad (@fields) {
for ($j=0; $j<$tabler_dimensions[$i]-1; $j++){
if (($elcounter%$numelements_last == 0)) {
$colcounter = 0;
if ($elcounter == 0){
print OUTFILE "{";
} else {
print OUTFILE " {";
}
}
}
$elcounter++;
if ($colcounter == $tabler_cols[$i]) {
print OUTFILE "\n ";
$colcounter = 0;
}
#fix missing .0 for floats
if ($floatfix==1) {
if ($rad=~ m/\./) {
} else {
$rad = "$rad.0";
}
}
print OUTFILE "$rad,";
$colcounter ++;
for ($j=0; $j<$tabler_dimensions[$i]-1; $j++){
if ($elcounter%$numelements_last == 0){
$colcounter = 0;
print OUTFILE "},\n";
}
}
}
if ($tabler_dimensions[$i]>1) {
print OUTFILE "};\n\n";
} else {
print OUTFILE "\n};\n\n";
}
#print "$tabler_name[$i] $tabler_address[$i] $tabler_size[$i] $seekaddress\n @fields\n";
}
print "$tn tables written to $FILE1.h.\n";
close(OUTFILE);
}
sub analyse
{
my $k;
$tn = 0;
$tron = 0;
$fnum = 0;
$FILE1 = $ARGV[1];
print "$FILE1\n";
# get SYMBOL TABLE
if ($demangle == 1) {
@symtable = `objdump -C -tT $FILE1`;
} else {
@symtable = `objdump -tT $FILE1`;
}
foreach $rad (@symtable) {
#parse readwrite tables
if ($rad =~ m/\.data/) {
#print $rad;
$address = (substr $`,0,8);
$rad = $';
while (($rad =~ s/ / /g) || ($rad =~ s/\t//g)){}
#print $rad;
$size = (substr $rad,0,8);
$name = (substr $rad,9);
chomp($name);
$size = hex($size);
if ($size > 0) {
#print "$name $size $address\n";
$tabler_name[$tn] = $name;
$tabler_size[$tn] = $size;
$tabler_address[$tn] = $address;
$tn++;
}
}
#parse readonly tables
if ($rad =~ m/\.rodata/) {
#print $rad;
$address = (substr $`,0,8);
$rad = $';
while (($rad =~ s/ / /g) || ($rad =~ s/\t//g)){}
#print $rad;
$size = (substr $rad,0,8);
$name = (substr $rad,9);
chomp($name);
$size = hex($size);
#print "$name $size $address\n";
if ($size > 0) {
#print "$name $size $address\n";
$tablero_name[$tron] = $name;
$tablero_size[$tron] = $size;
$tablero_address[$tron] = $address;
$tron++;
}
}
#parse functions
if ($rad =~ m/\.text/) {
$address = (substr $`,0,8);
#print $rad;
$rad = $';
while (($rad =~ s/ / /g) || ($rad =~ s/\t//g)){}
$argument="(n/a)";
$size = (substr $rad,0,8);
$name = (substr $rad,9);
chomp($name);
if ($demangle == 1) {
if($name =~ m/\(/) {
$argument = "(".$';
$name = $`;
}
}
$size = hex($size);
#print "$name $argument $size\n";
if ($size > 0) {
#print "$name $argument $size\n";
$functions_name[$fnum] = $name;
$functions_address[$fnum] = $address;
$functions_size[$fnum] = $size;
$functions_argument[$fnum] = $argument;
$fnum++;
}
}
}
#get .data and .rodata offsets
@offsets = `readelf -S $FILE1`;
foreach $rad (@offsets) {
if ($rad=~ m/ \.data/) {
$dataaddress = (substr $rad,41,8);
$dataoffset = (substr $rad,50,6);
$doffset = hex($dataaddress) - hex($dataoffset);
}
if ($rad=~ m/ \.rodata/) {
$rodataaddress = (substr $rad,41,8);
$rodataoffset = (substr $rad,50,6);
$drooffset = hex($rodataaddress) - hex($rodataoffset);
}
}
#write the database
open(DB, ">".$FILE1.".db") or die "File doesn't exist\n";
print DB "# offsets for data tables in non hex format(decimal), the order is fixed\n";
print DB "[offset begin]\n";
print DB "ro_offset;$drooffset;\n";
print DB "rw_offset;$doffset;\n";
print DB "[offset end]\n";
print DB "# name(string), address(hex), size(int), type(string), cols(int), readonly(bolean), dimensions(int), dim 1 to n-1 size...(int)\n";
print DB "[tables begin]\n";
#write read/write tables
for ($i=0 ; $i<$tn; $i++){
print DB "$tabler_name[$i];$tabler_address[$i];$tabler_size[$i];hex8_t;8;0;1;\n";
}
#write readonly tables
for ($i=0 ; $i<$tron; $i++){
print DB "$tablero_name[$i];$tablero_address[$i];$tablero_size[$i];hex8_t;8;1;1;\n";
}
print DB "[tables end]\n";
#write functions
print DB "# name(string); address(hex); size(int); arguments(string)\n";
print DB "[functions begin]\n";
for ($i=0 ; $i<$fnum; $i++){
print DB "$functions_name[$i];$functions_address[$i];$functions_size[$i];$functions_argument[$i];\n";
}
print DB "[functions end]\n";
close DB;
print "Found $tn rw tables, $tron readonly tables and $fnum functions.\n";
print "Database $FILE1.db written.\n";
}
vid_iv41.xa.db
(text/plain, 6 KB)
# offsets for data tables in non hex format(decimal), the order is fixed [offset begin] ro_offset;0; rw_offset;4096; [offset end] # name(string), address(hex), size(int), type(string), cols(int), readonly(bolean), dimensions(int), dim 1 to n-1 size...(int) [tables begin] ubScan;0002e4c0;1024;uint8_t;8;0;2;16; MapTbl3;000283e0;1424;uint8_t;8;1;1; xform_to_scan;0002a860;18;hex8_t;8;1;1; ClampDitherY_0e;0001d800;256;uint8_t;8;1;1; MapTbl4;00028980;1424;hex8_t;8;1;1; CP_ClampDitherY_06;00022740;256;hex8_t;8;1;1; au16ScaleTables;0002be80;5632;uint16_t;8;1;1; MapTbl7;00029a60;1424;hex8_t;8;1;1; ComPicSizes;0002a7e8;56;uint32_t;8;1;1; au16BaseTables;0002a880;5632;hex16_t;8;1;1; MapTbl0;00027300;1424;hex8_t;8;1;1; NullFrmHeader;0002a724;12;uint8_t;8;1;1; ClampDitherY_02;0001d500;256;hex8_t;8;1;1; MapTbl2;00027e40;1424;hex8_t;8;1;1; DitherTable;0001e100;16384;hex32_t;8;1;1; MapTbl6;000294c0;1424;hex8_t;8;1;1; MapTbl1;000278a0;1424;hex8_t;8;1;1; MapTbl5;00028f20;1424;hex8_t;8;1;1; TruncateV;0001d900;1024;uint32_t;8;1;1; CP_PalTable;00022280;944;uint8_t;8;1;2;16; CP_ClampDitherY_0e;00022940;256;hex8_t;8;1;1; FP_PalTable;0001d140;944;uint8_t;8;1;1; ClampDitherY_0a;0001d700;256;hex8_t;8;1;1; CP_ClampDitherY_0a;00022840;256;hex8_t;8;1;1; CP_ClampDitherY_02;00022640;256;hex8_t;8;1;1; TileSizeTable;0002a7bc;32;uint16_t;8;1;1; MapTbl8;0002a000;1424;hex8_t;8;1;1; TruncateU;0001dd00;1024;uint32_t;8;1;1; ClampDitherY_06;0001d600;256;hex8_t;8;1;1; CP_DitherTable;00022a40;16384;hex32_t;8;1;1; [tables end] # name(string); address(hex); size(int); arguments(string) [functions begin] inv_bits;0001ca60;67;(n/a); PB2Huff;0001c310;319;(n/a); transform;00011d50;2560;(n/a); HiveCreateMutex;00005fd0;12;(n/a); DecMcRectInterp;0001a9c0;890;(n/a); BitBuff2Mem;0001c180;174;(n/a); BitBuffOverWrite;0001bec0;225;(n/a); DecodeDebugGet;00006d50;12;(n/a); DecodeResetBrightness;00008670;97;(n/a); DecodeChangeSaturation;00008580;229;(n/a); DecodeStartup;00006a40;267;(n/a); DecodeGetCompressedSize;000067b0;90;(n/a); DecodeResetContrast;000086e0;97;(n/a); DecodeUseFixedPalette;00006fb0;232;(n/a); HiveLocalPtrCheck;00005f00;25;(n/a); CDecompressBegin;00008100;109;(n/a); DecodeConstantInit;00006070;327;(n/a); HiveDecTimer;00006020;39;(n/a); CDecompress;000070a0;1648;(n/a); HiveGlobalFreePtr;00005f20;41;(n/a); DecodeGetDefaultPersData;00006d70;12;(n/a); make_quant;0000f440;193;(n/a); GetRVMapTbl;0001c830;131;(n/a); HiveGlobalPtrCheck;00005f50;25;(n/a); HiveClosestPaletteIndex;00006060;12;(n/a); DecodeGetSupportedAlgorithms;00006e40;40;(n/a); BlockPut;00012870;162;(n/a); C_YVU9toConfigurablePalette;00016e40;13150;(n/a); What_The;00005bf0;132;(n/a); MatCopyFast;0000a540;41;(n/a); bDecodeThisTile;0001a780;87;(n/a); BitBuffFlush;0001bfb0;52;(n/a); BitBuffAlloc;0001bd50;72;(n/a); HiveGlobalUnlockHandle;00005f80;25;(n/a); DecodeGetPersData;00006e30;12;(n/a); tounsigned;0001c2c0;27;(n/a); readTransTileData;0000ad60;704;(n/a); dec_transform;00010d30;2459;(n/a); MatSet;00009fd0;88;(n/a); HiveEndCriticalSection;00006010;12;(n/a); HiveGlobalAllocHandle;00005e80;66;(n/a); DecodeFreePrivateData;000066c0;229;(n/a); GetHuffmanTbls;0001c5a0;76;(n/a); MatConvU8;0000a0e0;422;(n/a); DecodeQuery;00006810;310;(n/a); HiveLocalFreePtr;00005ed0;41;(n/a); C_YVU9toActivePalette;00015d60;4308;(n/a); HiveBeginCriticalSection;00005ff0;25;(n/a); DecPlaneOpen;00008bb0;182;(n/a); DecodeImageDimInit;00006e70;66;(n/a); YVU9_to_RGB24;0000f6c0;4996;(n/a); BitBuffRead;0001bff0;223;(n/a); SysFreeFunc;0001cb00;45;(n/a); HiveFreeMutex;00005fe0;12;(n/a); readTransBandHdr;0000a810;1350;(n/a); MatAllocFunc;0000a290;94;(n/a); DecodeSequenceEnd;00006ee0;12;(n/a); InitYVU2RGBContribs;0000f550;361;(n/a); BitBuffByteRead;0001c0d0;171;(n/a); BitBuffWrite;0001b010;295;(n/a); MatAdd;0000a3c0;100;(n/a); BitBuffSize;0001c260;64;(n/a); ModifyContrastOrSaturation;00008830;114;(n/a); DecBandOpen;0001a630;228;(n/a); C_YVU9toCLUT8;00012a00;13150;(n/a); readPicHdrSt;0000d380;3141;(n/a); DecodeResetSaturation;00008750;59;(n/a); DecodeChangeContrast;000083e0;259;(n/a); DecodeUpdateChroma;000087e0;73;(n/a); HiveGlobalAllocPtr;00005e30;66;(n/a); HiveGlobalLockHandle;00005f70;16;(n/a); DecodeSetPersData;00006f00;12;(n/a); BlockGetDiff;00012750;286;(n/a); MatCopyFull;0000a490;172;(n/a); DecodeIsKeyFrame;00006ec0;32;(n/a); InitRVMapTbl;0001c950;264;(n/a); MatAddFull;0000a030;167;(n/a); MatFreeFunc;0000a2f0;26;(n/a); make_scan;0000f510;57;(n/a); DecodeShutdown;00006f10;148;(n/a); NpMBitBuffWrite;0001be70;72;(n/a); HuffEncBitBuff;0001b600;1126;(n/a); BitBuffHist;0001b250;937;(n/a); MatCksum;0000a360;94;(n/a); BitBuffFree;0001be20;68;(n/a); DecodeUpdateLuma;00008790;73;(n/a); DecodeDebugSet;00006d60;12;(n/a); InitStaticEncodeTables;0001c450;99;(n/a); GetRVMapTbls;0001c5f0;208;(n/a); MatCopy;0000a430;86;(n/a); DecodeSequenceSetup;00006950;234;(n/a); DecodeFrame;000061c0;1273;(n/a); SkipPad2DWord;0001ba70;357;(n/a); DecBand;0001a1a0;1156;(n/a); CDecompressEnd;00007710;299;(n/a); ColorConvert;000088b0;756;(n/a); tosigned;0001c2a0;23;(n/a); HuffRead;0001bbe0;360;(n/a); ComputeDynamicClut;00008ec0;3471;(n/a); InitQuantTables;0001cb30;410;(n/a); DecodeSetPaletteConfiguration;00006ef0;12;(n/a); MatSetFast;00009fa0;44;(n/a); DecPlaneClose;00008c70;95;(n/a); DecodeChangeBrightness;000084f0;129;(n/a); DecodeGetPalette;00006d80;162;(n/a); DecBandClose;0001a720;88;(n/a); HiveEncodeProgressFunc;00006050;12;(n/a); MatSetFull;0000a310;72;(n/a); PicInfoStAllocPlanes;0000f320;277;(n/a); HiveLocalAllocPtr;00005de0;66;(n/a); SysMallocFunc;0001cab0;71;(n/a); HiveGlobalFreeHandle;00005fa0;41;(n/a); InitStaticDecodeTables;0001c4c0;223;(n/a); DecMcRectInterpAvg;0001ad40;706;(n/a); PicInfoStClose;0000a5a0;624;(n/a); HaarBands;00009e40;344;(n/a); GetDecHuffmanTable;0001c6c0;360;(n/a); HaarInv;00009c50;489;(n/a); PicInfoStOpen;0000dfd0;4942;(n/a); DecodeUseThisPalette;00006b50;502;(n/a); BitBuffSkip2ByteAlign;0001b140;266;(n/a); BitBuffInit;0001bda0;116;(n/a); DecPlane;00008cd0;258;(n/a); SetMatrixRect;0000a570;47;(n/a); BitBuffByteAlign;0001c230;42;(n/a); CreateHuffDecTable;0001c8c0;139;(n/a); BlockGet;00012920;216;(n/a); [functions end]