Mangled name的结构(borland)

来源:互联网 发布:跨越阶层 知乎 编辑:程序博客网 时间:2024/04/30 08:27
前言 
        在C++和Pascal中,由于重载,也就是同名而参数不同的函数/过程的出现,使得编译器必须根据函数的参数,为每一个函数生产独一无二的名字,以标记代码段的一个地址.否则linker将无法正确的找到所需函数.这个由源代码中的名字变化得到obj文件中的名字的过程就是mangling.但是C++标准中并没有规定mangle的标准,工业界也不存在事实标准.于是各家编译器各自为政,每家的mangling标准都不同.本文分析的是Borland的的方法. 
   
  Mangled name的结构 
  mangle后的函数名结构是@UnitName@ClassName@FunctionName@$Params 
 

        UnitName对应pascal中的,很简单啦,就是你unit后面写的那个名字,但是记住,无论你怎么写这个UnitName,最后Mangle以后都是第一个字母大写,其他小写;在C++中则是namespace的名字,而且是区分大小写的.如果你的namespace有嵌套,就将域分隔符::换为@,比如类File1::nested::CMangle就变化为@File1@nested@CMangle,如果是全局namespace,那么就直接@ClassName 


      ClassName没什么可说的,pascal中是使用定义类时的拼写,而C++是区分大小写的。如果不是类的方法,就直接写@UnitName@FunctionName,如果C++中连namespace也是global的,就直接@FunctionName.而静态函数仍有前面的类名. 
 
       FunctionName当然就是定义的方法/函数的名字.但是对构造函数和析构函数来说 ,略有不同,他们分别被改为$bctr和$bdtr,也就是说@ClassName@$bctr$qv是个构造函数,而@ClassName@$bdtr$qv是个析构函数. 
 
  Param的含义 
  Param的部分比较复杂,给个例子说得比较清楚 
$qqr p20 File1@nested@CMangle r17 System@AnsiString t1 
 

       最前面的qqr表示调用协定,分别有

__fastcall对应qqr,

__stdcall对应qqs,

__cdecl对应q 

C++中缺省的是__cdecl,而pascal中缺省的是__fastcall 
 
      后面的p20File1@nested@CMangle表示一个File1::nested::CMangle的指针,显然 p表示指针,还可以换为r表示引用,在pascal中,就是var了.注意虽然源代码中没有UnitName,但是这里一定会有。中间的20则表示后面20个字符都是这个类的描述. 
       那么显而易见,第二个参数是 AnsiString&, pascal中是var string; 
       第三个,t1,表示这个参数和第一个参数类型一样,当然,会有t2,t3等等。这是为了缩短mangle后的名字的长度。如果类型的描述小于等于2个字符,如int类型只用一个i,则不用tn这种方法. 
      内置类型有固定的代码表示,比如int用i,表示,unsigned用一个u表示,short用s 表示,所以DWORD就是ui,WORD是us 
      上面这段参数就是__fastcall (File1::nested::CMangle *, System:: AnsiString &, File1::nested::CMangle *); 
  如果一个函数没有参数,可以认为是有一个void参数,用v表示,比如 
__fastcall int foo();就是@foo$qqrv 

  function的返回值,即pascal里procedure和function的区别对mangle没有影响. 


     const修饰用x表示,const成员函数就在$和q之间加一个x,即$xq, 相应的

const  char *就是pxc, 

const char * const就是xpxc, 

const char &就是rxc 

  与const相似的,volatile用w表示 
0 0
原创粉丝点击