在gcc和ld中需要什么-fPIE (-pie,“与位置无关的可执行文件”)选项? 它将如何改变代码,例如函数调用?
在x86_64 linux上使用gcc和ld我需要链接到更新版本的库(glibc 2.14),但可执行文件需要在具有较旧版本(2.5)的系统上运行。 由于唯一不兼容的符号是memcpy(需要memcpy@GLIBC_2.2.5,但提供memcpy@GLIBC_2.14的库),我想告诉链接器,不要使用memcpy的默认版本,而应该使用我指定的旧版本。 我发现一个非常尴尬的方法:只需在链接器命令行中指定一个旧的.so文件的副本。 这工作正常,但我不喜欢有多个.so文件(我只能通过指定所有旧链接库,我链接到,也有参考memcpy)的想法检查到svn和我的生成系统。 所以我正在寻找一种方法来告诉链接器采用旧版本的符号。 对我不起作用的select是: 使用asm.symver(在Trevor Pounds的Blog的Web Archive中可以看到),因为这将要求我确保symver是所有使用memcpy的代码,这将是非常困难的(复杂的代码库和第三方代码) 与旧图书馆保持搭build环境; 只是因为我想在我的桌面系统上开发,这将是一个皮塔同步在我们的networking中的东西。 当考虑链接器所做的所有工作时,似乎并不是一件困难的事情,毕竟它有一些代码也可以找出默认的符号版本。 任何与简单链接器命令行(如创build一个简单的链接器脚本等)复杂度相同的想法也是受欢迎的,只要它们不是像编辑所产生的二进制文件那样的奇怪黑客… 编辑:为了节约这给未来的读者,除了下面的想法,我发现了选项 – –wrap到链接器,这可能有时也是有用的。
input到链接器的文件称为对象文件 。 链接器产生一个Image文件 ,这个文件又被加载器用作input。 从“ 微软可移植可执行文件和通用目标文件格式规范 ” RVA(相对虚拟地址) 。 在一个图像文件中,将一个项目的地址加载到内存中,并从中减去图像文件的基地址。 一个项目的RVA几乎总是不同于它在磁盘上文件的位置(文件指针)。 在目标文件中,RVA没有意义,因为内存位置未分配。 在这种情况下,RVA将是一个部分(稍后在此表中描述)中的地址,在链接期间稍后将对其应用重定位。 为了简单起见,编译器应该将每个部分中的第一个RVA设置为零。 VA(虚拟地址) 。 与RVA相同,不同之处在于不会减去映像文件的基址。 该地址称为“VA”,因为Windows为每个进程创build独立于物理内存的独特VA空间。 几乎所有的目的,一个VA应该被视为一个地址。 VA并不像RVA那样可预测,因为加载器可能不会将图像加载到其首选位置。 即使阅读了这个,我仍然不明白。 我有很多问题。 任何人都可以用实际的方式来解释它吗? 请遵守所述的Object File和Image File术语。 我所知道的地址就是这样 无论是在对象文件还是在图像文件中,我们都不知道确切的内存位置, 生成目标文件时,汇编程序计算相对于.data & .text (用于函数名称)部分的地址。 以多个目标文件作为input的链接器生成一个图像文件。 在生成时,首先合并每个目标文件的所有部分,并在合并时重新计算相对于每个部分的地址偏移量。 而且,没有什么东西像全球抵消。 如果我所知道的东西有问题,请纠正我。 编辑: 看完弗朗西斯的回答后,我很清楚什么是Physical Address,VA&RVA以及它们之间的关系。 链接器在重定位期间必须计算所有variables和方法的RVA。 那么, (一个方法/variables的RVA的值)==(它从文件开始的偏移量) ? 一定是真的 但令人惊讶的是,它不是。 为什么这样? 我通过在c:\WINDOWS\system32\kernel32.dll上使用PEView检查了这一点,发现: RVA和FileOffset是相同的,直到部分的开始( .text是在这个DLL的第一部分)。 从.text开始.data , .rsrc到最后一节( .reloc )的最后一个字节RVA和FileOffset是不同的。 也是第一段第一个字节的RVA总是显示为0x1000 […]
我需要分发一个可以在尽可能多的x86 Linux发行版上运行的二进制文件。 这意味着我必须静态链接一些库,比如glibc,因为用户可能没有我使用的版本。 其他库必须dynamic链接,如fontconfig,因为它依赖于caching文件格式和每个系统上可能不同的硬编码位置。 什么是命令行选项来做到这一点? 如果我指定-static,那么gcc将拒绝dynamic链接任何库。
当我在我的一个库中nm: nm libmylib.so 我得到这样的一条线 U _ZNSs4_Rep20_S_empty_rep_storageE@@GLIBCXX_3.4 我检查了nm的手册页,我得到了“U”符号是未定义的。 未定义的符号究竟意味着什么? 如果它真的没有定义,那nm为什么要报告呢?
我有一个共享库,我希望链接使用GCC的可执行文件。 共享库的名称不是libNAME.soforms,所以我不能使用通常的-l选项。 (它恰巧也是一个Python扩展,所以没有'lib'前缀。) 我能够将path传递到库文件直接到链接命令行,但这会导致库path被硬编码到可执行文件中。 例如: g++ -o build/bin/myapp build/bin/_mylib.so 有没有办法链接到这个库,而不会导致path硬编码到可执行文件?
过去的一个半小时里,这让我疯狂。 我知道这是一件小事,但却找不到什么不对(事实上,星期五的下午,这个事实并没有帮助)。 我已经定义了下面的类,将保存从文件中读取的configuration参数,并让我从我的程序访问它们: class VAConfig { friend std::ostream& operator<<( std::ostream& lhs, const VAConfig& rhs); private: VAConfig(); static std::string configFilename; static VAConfig* pConfigInstance; static TiXmlDocument* pXmlDoc; std::map<std::string, std::string> valueHash; public: static VAConfig* getInstance(); static void setConfigFileName( std::string& filename ) { configFilename = filename; } virtual ~VAConfig(); void readParameterSet( std::string parameterGroupName ); template<typename T> T readParameter( const […]
我正在开发一个iOS应用程序的插件。 我正在编译成.a文件,然后由主xcode项目使用。 到目前为止,我已经在这个库中创build了一个UIDevice类的类。 当我使用这个库运行主项目时,由于无法识别的select器而崩溃 – [UIDevice平台]:无法识别的select器发送到实例 平台是我通过类添加的function之一。 所以我认为它根本就没有链接这些函数,并将ac函数添加到与UIDevice类别相同的文件,然后从我的代码中调用它。 这次主项目运行良好…所以我想也许这是我做的其他事情,并删除了C函数。 但是,看到它由于无法识别的select器再次坠毁。 我的问题:为什么xcode忽略类别定义,除非我调用在同一个文件中声明的函数? 是否有一个Xcode设置,我可以改变,使其包括UIDevice类别的这些方法,无论我是否从该文件调用函数? 干杯
如果一个朋友想运行我的Haskell二进制文件,他是否必须首先安装Haskell,或者他能立即运行二进制文件? Mac,Windows和Linux上的答案是一样的吗?
我有大约50个不同的静态库被链接到我的C + +项目和链接平均需要70年代。 我发现这次更改库的链接顺序。 如果链接器不需要在整个符号表中search一组符号,就可以预计到这一点。 我想我可以使用“nm”来获得静态库之间的依赖关系图。 但是,这只会给我一个“正确的”链接顺序。 获得最快链接顺序的因素是什么? 我觉得这将与上述依赖关系图有关,通过获得一个遍历,试图尽量减less一些数量,但我真的不知道是哪一个。 任何帮助,将不胜感激。 我现在主要是使用intel编译器和gcc编译器。 当我用top检查它们时,它们似乎都在使用GNU ld链接器。 希望这可以帮助… 所以为了澄清一下我想要问的东西,我已经知道如何从一组静态库中获得一个1遍的顺序。 我自己写了这个脚本,但是根据Olaf的回答,下面有这样的着名工具。 我的问题是,我已经有两个单程链接sorting,其中一个在〜85s内运行,另一个在〜70s内运行。 很明显,我们在1阶命令中还可以做更多的优化。