home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Asuka / source / mapconv.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  7.6 KB  |  316 lines

  1. //    Asuka - VirtualDub Build/Post-Mortem Utility
  2. //    Copyright (C) 2005 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "stdafx.h"
  19. #include <vector>
  20. #include <algorithm>
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include <vd2/system/vdalloc.h>
  27. #include <vd2/system/VDString.h>
  28. #include <vd2/system/text.h>
  29. #include <vd2/system/vdstl.h>
  30. #include <vd2/system/filesys.h>
  31.  
  32. #include "symbols.h"
  33. #include "utils.h"
  34.  
  35. vdfastvector<char> fnambuf;
  36. vdfastvector<char> cnambuf;
  37.  
  38. ///////////////////////////////////////////////////////////////////////////
  39.  
  40. void parsename(sint64 rva, char *buf0) {
  41.     char *buf = buf0;
  42.     char *func_name = NULL;
  43.     char *class_name = NULL;
  44.     char c;
  45.     int special_func = 0;
  46.  
  47.     if (*buf++ != '?') {
  48.         func_name = buf;
  49.     } else {
  50.  
  51.         if (*buf == '?') {
  52.             // ??0
  53.             // ??1
  54.             // ??_G
  55.             // ??_E
  56.  
  57.             ++buf;
  58.             c=*buf++;
  59.  
  60.             special_func = 31;
  61.             if (c=='0')
  62.                 special_func = 1;        // constructor
  63.             else if (c=='1')
  64.                 special_func = 2;        // destructor
  65.             else if (c=='_') {
  66.                 c = *buf++;
  67.  
  68.                 if (c == 'G')
  69.                     special_func = 3;        // scalar deleting destructor
  70.                 else if (c == 'E')
  71.                     special_func = 4;        // vector deleting destructor?
  72.             }
  73.         } else {
  74.             func_name = buf;
  75.  
  76.             while(*buf != '@') {
  77.                 if (!*buf) {
  78.                     printf("    unrecognizable name: %s\n", buf0);
  79.                     throw "bad decorated name";
  80.                 }
  81.  
  82.                 ++buf;
  83.             }
  84.  
  85.             if (buf == func_name)
  86.                 printf("    warning: empty function name generated from: '%s'\n", func_name);
  87.  
  88.             *buf++ = 0;
  89.         }
  90.  
  91.         // Look for a class name.
  92.  
  93.         if (*buf != '@') {
  94.             if (!*buf) {
  95.                 printf("    unrecognizable name: %s\n", buf0);
  96.                 throw "bad decorated name";
  97.             }
  98.  
  99.             class_name = buf;
  100.  
  101.             while(*buf != '@') {
  102.                 if (!*buf)
  103.                     throw "bad decorated name (class)";
  104.  
  105.                 ++buf;
  106.             }
  107.  
  108.             if (buf == class_name)
  109.                 printf("    warning: empty class name generated from: '%s'\n", class_name);
  110.  
  111.             *buf++ = 0;
  112.         }
  113.     }
  114.  
  115.     // write out to buffers
  116.  
  117.     if (class_name) {
  118.         int idx = 0;
  119.         bool found = false;
  120.  
  121.         if (!cnambuf.empty()) {
  122.             char *csptr = &cnambuf[0];
  123.             char *csend = csptr + cnambuf.size();
  124.             while(csptr < csend) {
  125.                 if (!strcmp(csptr, class_name)) {
  126.                     found = true;
  127.                     break;
  128.                 }
  129.                 while(*csptr++);
  130.                 ++idx;
  131.             }
  132.         }
  133.  
  134.         if (!found)
  135.             cnambuf.insert(cnambuf.end(), class_name, class_name + strlen(class_name) + 1);
  136.  
  137.         fnambuf.push_back(1 + (idx / 128));
  138.         fnambuf.push_back(1 + (idx % 128));
  139.  
  140.         if (special_func)
  141.             fnambuf.push_back(special_func);
  142.     }
  143.  
  144.     if (func_name) {
  145.         if (!*func_name)
  146.             printf("    warning: writing out empty function name\n");
  147.         fnambuf.insert(fnambuf.end(), func_name, func_name + strlen(func_name) + 1);
  148.     } else {
  149.         if (!class_name)
  150.             printf("    warning: function name absent: '%s'\n", buf);
  151.         fnambuf.push_back(0);
  152.     }
  153. }
  154.  
  155. void VDNORETURN help_mapconv() {
  156.     printf("usage: mapconv <listing-file> <output-name> <disassembler module>\n");
  157.     exit(5);
  158. }
  159.  
  160. void tool_mapconv(const vdfastvector<const char *>& args, const vdfastvector<const char *>& switches, bool amd64) {
  161.     FILE *fo;
  162.     int i;
  163.  
  164.     if (args.size() < 3)
  165.         help_mapconv();
  166.  
  167.     // Begin parsing file
  168.  
  169.     vdautoptr<IVDSymbolSource> syms(VDCreateSymbolSourceLinkMap());
  170.     vdfastvector<VDSymbol> rvabuf;
  171.     syms->Init(VDTextAToW(args[0]).c_str());
  172.  
  173.     if (!(fo=fopen(args[1], "wb")))
  174.         fail("    can't open output file \"%s\"\n", args[1]);
  175.  
  176.     int disasm_size = 0;
  177.     {
  178.         FILE *fd;
  179.  
  180.         if (!(fd=fopen(args[2], "rb")))
  181.             fail("    can't open disassembler module \"%s\"\n", args[2]);
  182.  
  183.         void *buf = malloc(32768);
  184.         int act;
  185.  
  186.         while((act = fread(buf, 1, 32768, fd)) > 0) {
  187.             disasm_size += act;
  188.             fwrite(buf, act, 1, fo);
  189.         }
  190.  
  191.         free(buf);
  192.         fclose(fd);
  193.     }
  194.  
  195.     // delete all entries that take no space -- these often crop up with inline classes
  196.  
  197.     const uint32 code_segs(syms->GetCodeGroupMask());
  198.  
  199.     printf("%x\n", code_segs);
  200.  
  201.     syms->GetAllSymbols(rvabuf);
  202.  
  203.     int j=0;
  204.     for(i=0; size_t(i)<rvabuf.size()-1; ++i) {
  205.         VDSymbol& sym = rvabuf[i];
  206.  
  207.         if (!(code_segs & (1<<sym.group)))
  208.             continue;
  209.  
  210.         if (!strncmp(sym.name, "__ehhandler$", 12) || !strncmp(sym.name, "__unwindfunclet$", 16))
  211.             continue;
  212.  
  213.         if (rvabuf[i+1].rva - sym.rva) {
  214.             rvabuf[j++] = sym;
  215.         }
  216.     }
  217.     rvabuf[j++] = rvabuf[i];    // last entry is always copied
  218.  
  219.     printf("    Deleted %d zero-size and EH stub entries from RVA table\n", i+1-j);
  220.     rvabuf.resize(j);
  221.  
  222.     size_t rvabufsize = rvabuf.size();
  223.     for(i=0; size_t(i)<rvabufsize; i++) {
  224.         VDSymbol& sym = rvabuf[i];
  225.  
  226.         parsename(sym.rva, sym.name);
  227.     }
  228.     
  229.     int segcnt = syms->GetSectionCount();
  230.     vdfastvector<uint32> segbuf(segcnt * 2);
  231.     for(i=0; i<segcnt; i++) {
  232.         const VDSection *sect = syms->GetSection(i);
  233.         segbuf[i*2+0] = (uint32)(sect->mAbsStart);
  234.         segbuf[i*2+1] = sect->mLength;
  235.         printf("        #%-2d  %08lx-%08lx\n", i+1, sect->mStart, sect->mStart + sect->mLength - 1);
  236.     }
  237.  
  238.     printf("        Raw statistics:\n");
  239.     printf("            Disassembler:     %ld bytes\n", disasm_size);
  240.     printf("            RVA bytes:        %ld\n", rvabuf.size()*4);
  241.     printf("            Class name bytes: %ld\n", cnambuf.size());
  242.     printf("            Func name bytes:  %ld\n", fnambuf.size());
  243.  
  244.     printf("    Packing RVA data..."); fflush(stdout);
  245.  
  246.     vdfastvector<VDSymbol>::iterator itRVA = rvabuf.begin(), itRVAEnd = rvabuf.end();
  247.     vdfastvector<char> rvaout;
  248.     sint64 firstrva = (*itRVA++).rva;
  249.     sint64 lastrva = firstrva;
  250.  
  251.     for(; itRVA != itRVAEnd; ++itRVA) {
  252.         sint64 rvadiff = (*itRVA).rva - lastrva;
  253.  
  254.         lastrva += rvadiff;
  255.  
  256.         if (rvadiff & 0xF0000000) rvaout.push_back((char)(0x80 | ((rvadiff>>28) & 0x7F)));
  257.         if (rvadiff & 0xFFE00000) rvaout.push_back((char)(0x80 | ((rvadiff>>21) & 0x7F)));
  258.         if (rvadiff & 0xFFFFC000) rvaout.push_back((char)(0x80 | ((rvadiff>>14) & 0x7F)));
  259.         if (rvadiff & 0xFFFFFF80) rvaout.push_back((char)(0x80 | ((rvadiff>> 7) & 0x7F)));
  260.         rvaout.push_back((char)(rvadiff & 0x7F));
  261.     }
  262.  
  263.     printf("%ld bytes\n", rvaout.size());
  264.  
  265.     // dump data
  266.  
  267.     long t;
  268.  
  269.     static const char header[64]="[01|01] VirtualDub symbolic debug information\r\n\x1A";
  270.  
  271.     fwrite(header, 64, 1, fo);
  272.  
  273.     t = get_version();
  274.     fwrite(&t, 4, 1, fo);
  275.  
  276.     t = rvaout.size() + 4;
  277.     fwrite(&t, 4, 1, fo);
  278.  
  279.     t = cnambuf.size();
  280.     fwrite(&t, 4, 1, fo);
  281.  
  282.     t = fnambuf.size();
  283.     fwrite(&t, 4, 1, fo);
  284.  
  285.     t = segcnt;
  286.     fwrite(&t, 4, 1, fo);
  287.  
  288.     fwrite(&firstrva, 4, 1, fo);
  289.     fwrite(rvaout.data(), rvaout.size(), 1, fo);
  290.     fwrite(cnambuf.data(), cnambuf.size(), 1, fo);
  291.     fwrite(fnambuf.data(), fnambuf.size(), 1, fo);
  292.     fwrite(segbuf.data(), segcnt*8, 1, fo);
  293.  
  294.     // really all done
  295.  
  296.     if (fclose(fo))
  297.         throw "output file close failed";
  298.  
  299.     FILE *fLock = fopen("autobuild.lock", "r");
  300.     if (fLock) {
  301.         fclose(fLock);
  302.     } else {
  303.         ProjectSetup ps;
  304.  
  305.         if (VDDoesPathExist(L"build.cfg")) {
  306.             ps.Read(L"build.cfg");
  307.         } else {
  308.             ps.Query();
  309.             ps.Write(L"build.cfg");
  310.         }
  311.  
  312.         inc_version(ps.mCounterTag.empty() ? NULL : ps.mCounterTag.c_str());
  313.         write_version(ps.mCounterTag.empty() ? NULL : ps.mCounterTag.c_str());
  314.     }
  315. }
  316.