http://mocheng.wordpress.com/2006/07/17/what-is-ilt%EF%BC%88incremental-link-table/

WHAT IS ILT(INCREMENTAL LINK TABLE)?

07月 17, 2006, 9:49 am 
Filed under:  技术体会

这两天研究了一下DLL的import/export原理,看了一些资料,无意中发现网上有一篇文章存在错误,而这篇文章流传还甚广,恐怕也误了不少子弟,觉得有必要说一下:)

随便用哪个搜索引擎来搜索“C++ 虚函数 ILT”,排在前面的都有“C++虚函数调用的反汇编解析”一文,此文被转来转去,都不知道最初出处是哪里了。原文作者亲自动手研究了一下VC产生的汇编代码,钻研精神可嘉,不过对一些概念理解有错误。

文中提到:

004010DC call @ILT+5(Test) (0040100a)//调用Test函数;
//这里@ILT+5就是跳转到Test函数的的jmp指令的地址,一个模块中所有的
//函数调用都会是象这样@ILT+5*n,n表示这个模块中的第n个函数,而ILT的意思
//是Import Lookup Table,程序调用函数的时候就是通过这个表来跳转到相应函数而执//行代码的。

作者显然只是试验了Debug版本,因为只有Debug才会出现@ILT,而ILT这里也不是Import Lookup Table的意思,Import Lookup Table是使用DLL时才用到的概念,和C++虚函数实现没有任何关系,这里的ILT是Incremental Link Table的意思,缩写冲突真烦人:)

什么是Incremental Link Table呢?

想想如果我们自己要做编译器(compiler)和连接器(linker),当然希望编译连接运行得越快越好,同时也希望产生的二进制代码也是又快又小,上帝是公平的,鱼与熊掌不可兼得,所以我们自然想到用两种build方式,一种Release,编译慢一些,但是产生的二进制代码紧凑精悍,一种Debug,编译运行快,产生的代码臃肿一点没关系,Debug版本嘛,就是指望程序员在开发的时候反复的build,为了不浪费程序员的时候,要想尽办法让编译连接速度变快。

假如一个程序有连续两个foo和bar (所谓连续,就是他们编译连接之后函数体连续存放), foo入口位置在0x0400,长度为0x200个字节,那么bar入口就应该在0x0600 = 0x0400+0x0200。程序员在开发的时候总是频繁的修改code然后build,假如程序员在foo里面增加了一些内容,现在foo函数体占0x300个字节了,bar的入口也就只好往后移0x100变成了0x0700,这样就有一个问题,如果foo在程序中被调用了n次,那么linker不得不修改这n个函数调用点,虽然linker不嫌累,但是link时间长了,程序员会觉得不爽。所以MSVC在Debug版的build,不会让各个函数体之间这么紧凑,每个函数体后都有padding(全是汇编代码int 3,作用是引发中断,这样因为古怪原因运行到不该运行的padding部分,会发生异常),有了这些padding,就可以一定程度上缓解上面提到的问题,不过当函数增加内容太多超过padding,还是有问题,怎么办呢?MSVC在Debug build中用上了Incremental Link Table, ILT其实就是一串jmp语句,每个jmp语句对应一个函数,jmp的目的地就是函数的入口点,和没有ILT的区别是,现在对函数的调用不是直接call到函数入口点了,而是call到ILT中对应的位置,而这个位置上什么也不做,直接jmp到函数中去。这样的好处是,当一个函数入口地址改变时,只要修改ILT中对应值就搞定了,用不着修改每一个调用位置,用一个冗余的ITL把时间复杂度从O(n)将为O(1),值得,当然Debug版的二进制文件会稍大稍慢,Release版不会用上ILT。

回到网上那篇文章上来,原作者作了一些探索,反先了函数调用以ILT为跳板jmp一下,觉得很有意思,可惜没有试验一下release版,所以也没有进一步探索一下ILT到底是什么东西,真是可惜。如果研究一下Release版的汇编代码,会看到非常紧凑简洁的汇编代码,那才是真正纯正的vtable实现。

WHAT IS ILT(INCREMENTAL LINK TABLE)?

07月 17, 2006, 9:49 am 
Filed under:  技术体会

这两天研究了一下DLL的import/export原理,看了一些资料,无意中发现网上有一篇文章存在错误,而这篇文章流传还甚广,恐怕也误了不少子弟,觉得有必要说一下:)

随便用哪个搜索引擎来搜索“C++ 虚函数 ILT”,排在前面的都有“C++虚函数调用的反汇编解析”一文,此文被转来转去,都不知道最初出处是哪里了。原文作者亲自动手研究了一下VC产生的汇编代码,钻研精神可嘉,不过对一些概念理解有错误。

文中提到:

004010DC call @ILT+5(Test) (0040100a)//调用Test函数;
//这里@ILT+5就是跳转到Test函数的的jmp指令的地址,一个模块中所有的
//函数调用都会是象这样@ILT+5*n,n表示这个模块中的第n个函数,而ILT的意思
//是Import Lookup Table,程序调用函数的时候就是通过这个表来跳转到相应函数而执//行代码的。

作者显然只是试验了Debug版本,因为只有Debug才会出现@ILT,而ILT这里也不是Import Lookup Table的意思,Import Lookup Table是使用DLL时才用到的概念,和C++虚函数实现没有任何关系,这里的ILT是Incremental Link Table的意思,缩写冲突真烦人:)

什么是Incremental Link Table呢?

想想如果我们自己要做编译器(compiler)和连接器(linker),当然希望编译连接运行得越快越好,同时也希望产生的二进制代码也是又快又小,上帝是公平的,鱼与熊掌不可兼得,所以我们自然想到用两种build方式,一种Release,编译慢一些,但是产生的二进制代码紧凑精悍,一种Debug,编译运行快,产生的代码臃肿一点没关系,Debug版本嘛,就是指望程序员在开发的时候反复的build,为了不浪费程序员的时候,要想尽办法让编译连接速度变快。

假如一个程序有连续两个foo和bar (所谓连续,就是他们编译连接之后函数体连续存放), foo入口位置在0x0400,长度为0x200个字节,那么bar入口就应该在0x0600 = 0x0400+0x0200。程序员在开发的时候总是频繁的修改code然后build,假如程序员在foo里面增加了一些内容,现在foo函数体占0x300个字节了,bar的入口也就只好往后移0x100变成了0x0700,这样就有一个问题,如果foo在程序中被调用了n次,那么linker不得不修改这n个函数调用点,虽然linker不嫌累,但是link时间长了,程序员会觉得不爽。所以MSVC在Debug版的build,不会让各个函数体之间这么紧凑,每个函数体后都有padding(全是汇编代码int 3,作用是引发中断,这样因为古怪原因运行到不该运行的padding部分,会发生异常),有了这些padding,就可以一定程度上缓解上面提到的问题,不过当函数增加内容太多超过padding,还是有问题,怎么办呢?MSVC在Debug build中用上了Incremental Link Table, ILT其实就是一串jmp语句,每个jmp语句对应一个函数,jmp的目的地就是函数的入口点,和没有ILT的区别是,现在对函数的调用不是直接call到函数入口点了,而是call到ILT中对应的位置,而这个位置上什么也不做,直接jmp到函数中去。这样的好处是,当一个函数入口地址改变时,只要修改ILT中对应值就搞定了,用不着修改每一个调用位置,用一个冗余的ITL把时间复杂度从O(n)将为O(1),值得,当然Debug版的二进制文件会稍大稍慢,Release版不会用上ILT。

回到网上那篇文章上来,原作者作了一些探索,反先了函数调用以ILT为跳板jmp一下,觉得很有意思,可惜没有试验一下release版,所以也没有进一步探索一下ILT到底是什么东西,真是可惜。如果研究一下Release版的汇编代码,会看到非常紧凑简洁的汇编代码,那才是真正纯正的vtable实现。

WHAT IS ILT(INCREMENTAL LINK TABLE)?相关推荐

  1. 什么是Incremental Link Table[转]

    想想如果我们自己要做编译器(compiler)和连接器(linker),当然希望编译连接运行得越快越好,同时也希望产生的二进制代码也是又快又小,上帝是公平的,鱼与熊掌不可兼得,所以我们自然想到用两种b ...

  2. 增量加载(Incremental Loads)

    增量聚集(Incremental Aggregation) PowerCenter Server 运行你增量的修改目标(target),而不是强迫process整个源和重新计算. 用增量聚集的条件: ...

  3. R语言使用两个分类变量创建双向表(Two Way Table、两个分类变量的频率表)实战: 矩阵的双向表、dataframe的双向表、条形图和马赛克图来可视化频率表

    R语言使用两个分类变量创建双向表(Two Way Table.两个分类变量的频率表)实战: 矩阵的双向表.dataframe的双向表.条形图和马赛克图来可视化频率表 目录

  4. Oracle 11g新特性之--只读表(read only table)

    Oracle 11g新特性之--只读表(read only table)       Oracle11g推出了一个新的特性,可以将table置于read only状态,处于该状态的table的不能执行 ...

  5. Oracle - 临时表(GLOBAL TEMPORARY TABLE)

    http://aofengblog.blog.163.com/blog/static/6317021200951664351836/ Oracle - 临时表(GLOBAL TEMPORARY TAB ...

  6. 计算机网络笔记Part3 数据链路层(Data Link Layer)

    本人计算机网络笔记总目录 计算机网络笔记Part1 概述 计算机网络笔记Part2 物理层(Physical Layer) 计算机网络笔记Part3 数据链路层(Data Link Layer) 计算 ...

  7. 迅雷、QQ旋风-链接自动转换(Download link conversion)

    插件介绍: 在使用互联网的过程中,想必各位小伙伴都遇到过这样的情况,在花了不少时间找到自己需要的资源后,发现下载链接仅支持迅雷,而恰好电脑里又没有迅雷,又得花时间去找下载迅雷,其实这个问题很简单,只需 ...

  8. Qlikview Data Modeling---创建一个Key/Link Table

    这一篇我们将来学习下在什么情况下需要在QlikView里创建一个Key或者Link Table来避免事实表loops 和 qlikview自动产生synthetic keys.当两个事实表共享同样 ...

  9. 利用API读取日文输入方法表(Romaji-Kana conversion table)

    本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一.小鱼)相关研究.学习内容所做的笔记,欢迎广大朋友指正 利用API读取日文输入转换表(Romaji- ...

最新文章

  1. 小冰公司CEO李笛:AI不会江郎才尽,创造力只会持续向上攀升丨MEET2022
  2. C# 字符串 数据类型 判断 与特定规则验证
  3. HuMoments函数
  4. 对学校的希望和寄语_家长对学校的寄语怎么写
  5. Silverlight Unit Test Framework
  6. Oracle入门(十四A)之PL/SQL 基本结构
  7. csharp:Nhibernate Procedure with CreateSQLQuery and GetNamedQuery
  8. java设置字体大小和颜色_Java 设置Excel图表背景填充(颜色、图片填充)
  9. 《团队激励与沟通》第 2 讲——激励的方法与应用 重点部分总结
  10. 鸿蒙系统发布IT直播,华为开源平台上线:鸿蒙系统、方舟编译器在列
  11. struts过滤器和拦截器的区别
  12. Winform Echarts 显示百度地图的用法(3)
  13. Android完全关闭(退出)应用程序
  14. python爬虫学习整理——爬虫入门(1)
  15. TripAdvisor猫途鹰翻译志愿者线上任务评测
  16. 基于java jsp企业人事管理系统mysql
  17. 阿里云商标注册怎么样?附上申请步骤流程
  18. 如何将FLV格式视频转换成高清MP4格式方法
  19. 大唐天下平台模式开发
  20. 5招在不添加内存、显卡、ssd前提下有效提升windows系统pc性能

热门文章

  1. 图片渲染 类得修改 图片版本得适配
  2. Linux永久修改Mysql最大连接数
  3. 如何设置小型企业服务器机房
  4. php 方差函数,excel中方差的函数是什么,方差的简单计算公式
  5. 强制退出mac上的应用程序
  6. 美化我们的Ubuntu桌面(仿苹果)
  7. 微信小程序之消息模板推送
  8. CSS 中文字体的一些英文名称
  9. 云创大数据助力全国技能大赛河北省选拔赛云计算赛项
  10. linux 配置远程gnome,debian下安装gnome桌面和用vnc远程访问