路明非和绘梨衣:Mangled name的结构(borland)

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 21:29:12
前言 
  在C++和Pascal中,由于重载,也就是同名而参数不同的函数/过程的出现,使得编 
译器必须根据函数的参数,为每一个函数生产独一无二的名字,以标记代码段的一个 
地址.否则linker将无法正确的找到所需函数.这个有源代码中的名字变化得到obj 
文件中的名字的过程就是mangling.但是C++标准中并没有规定magle的标准,工业界 
也不存在事实标准.于是各家编译器各自为政,每家的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的部分比较复杂,给个例子说得比较清楚 
$qqrp20File1@nested@CMangler17System@AnsiStringt1 
 
  最前面的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表示