WHAT IS ILT(INCREMENTAL LINK TABLE)?
http://mocheng.wordpress.com/2006/07/17/what-is-ilt%EF%BC%88incremental-link-table/
WHAT IS ILT(INCREMENTAL LINK TABLE)?
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)?
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)?相关推荐
- 什么是Incremental Link Table[转]
想想如果我们自己要做编译器(compiler)和连接器(linker),当然希望编译连接运行得越快越好,同时也希望产生的二进制代码也是又快又小,上帝是公平的,鱼与熊掌不可兼得,所以我们自然想到用两种b ...
- 增量加载(Incremental Loads)
增量聚集(Incremental Aggregation) PowerCenter Server 运行你增量的修改目标(target),而不是强迫process整个源和重新计算. 用增量聚集的条件: ...
- R语言使用两个分类变量创建双向表(Two Way Table、两个分类变量的频率表)实战: 矩阵的双向表、dataframe的双向表、条形图和马赛克图来可视化频率表
R语言使用两个分类变量创建双向表(Two Way Table.两个分类变量的频率表)实战: 矩阵的双向表.dataframe的双向表.条形图和马赛克图来可视化频率表 目录
- Oracle 11g新特性之--只读表(read only table)
Oracle 11g新特性之--只读表(read only table) Oracle11g推出了一个新的特性,可以将table置于read only状态,处于该状态的table的不能执行 ...
- Oracle - 临时表(GLOBAL TEMPORARY TABLE)
http://aofengblog.blog.163.com/blog/static/6317021200951664351836/ Oracle - 临时表(GLOBAL TEMPORARY TAB ...
- 计算机网络笔记Part3 数据链路层(Data Link Layer)
本人计算机网络笔记总目录 计算机网络笔记Part1 概述 计算机网络笔记Part2 物理层(Physical Layer) 计算机网络笔记Part3 数据链路层(Data Link Layer) 计算 ...
- 迅雷、QQ旋风-链接自动转换(Download link conversion)
插件介绍: 在使用互联网的过程中,想必各位小伙伴都遇到过这样的情况,在花了不少时间找到自己需要的资源后,发现下载链接仅支持迅雷,而恰好电脑里又没有迅雷,又得花时间去找下载迅雷,其实这个问题很简单,只需 ...
- Qlikview Data Modeling---创建一个Key/Link Table
这一篇我们将来学习下在什么情况下需要在QlikView里创建一个Key或者Link Table来避免事实表loops 和 qlikview自动产生synthetic keys.当两个事实表共享同样 ...
- 利用API读取日文输入方法表(Romaji-Kana conversion table)
本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一.小鱼)相关研究.学习内容所做的笔记,欢迎广大朋友指正 利用API读取日文输入转换表(Romaji- ...
最新文章
- 小冰公司CEO李笛:AI不会江郎才尽,创造力只会持续向上攀升丨MEET2022
- C# 字符串 数据类型 判断 与特定规则验证
- HuMoments函数
- 对学校的希望和寄语_家长对学校的寄语怎么写
- Silverlight Unit Test Framework
- Oracle入门(十四A)之PL/SQL 基本结构
- csharp:Nhibernate Procedure with CreateSQLQuery and GetNamedQuery
- java设置字体大小和颜色_Java 设置Excel图表背景填充(颜色、图片填充)
- 《团队激励与沟通》第 2 讲——激励的方法与应用 重点部分总结
- 鸿蒙系统发布IT直播,华为开源平台上线:鸿蒙系统、方舟编译器在列
- struts过滤器和拦截器的区别
- Winform Echarts 显示百度地图的用法(3)
- Android完全关闭(退出)应用程序
- python爬虫学习整理——爬虫入门(1)
- TripAdvisor猫途鹰翻译志愿者线上任务评测
- 基于java jsp企业人事管理系统mysql
- 阿里云商标注册怎么样?附上申请步骤流程
- 如何将FLV格式视频转换成高清MP4格式方法
- 大唐天下平台模式开发
- 5招在不添加内存、显卡、ssd前提下有效提升windows系统pc性能