首页 > 编程语言 >高版本gcc编译出的程序在低版本glibc机器上运行

高版本gcc编译出的程序在低版本glibc机器上运行

时间:2023-12-01 15:47:34浏览次数:41  
标签:gcc lib 低版本 glibc ld 编译 so interpreter rpath

比如我们用gcc 9.3.0编译程序,但需要发布的机器gcc版本是4.8.5,怎么办?

你可能想到如下方法

  1. 静态编译
  2. 容器发布
  3. 打包依赖的so,使用本地so运行程序

1.静态编译

将libc和libstdc++静态编译,编译时带上如下参数。

g++ -static-libgcc -static-libstdc++

glibc并不推荐静态链接,你依赖的其他库可能依赖的了glibc,并且往往是动态链接的,可以通过nm <bin> | grep GLIBC_确定你的程序是否依赖了glibc。

2.容器发布

使用携带gcc9.3.0环境的容器发布程序,是可以的。但是在一些没有容器且没有sudo权限的场合,依然不太友好。

3.打包依赖的so发布

这个方法虽然听起来不是很优雅,但其实如果你对elf文件有一些了解,是不错的方式。下面说下具体的方法。

3.1 方式1 在编译时设置rpath和dynamic linker

当你有条件获得程序源码,并能够重新编译时,可以直接在编译时指定相关参数来解决。
先说编译时要增加的参数:

# 绝对路径
gcc -Wl,-rpath='/my/lib',-dynamic-linker='/my/lib/ld-linux.so.2'

gcc参数

-Wl,option
Pass option as an option to the linker.

ld参数

-rpath=dir
Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects.
--dynamic-linker=file
Set the name of the dynamic linker.

这两个参数分别设置的elf文件中的rpath和interpreter字段。

rpath
全名run-time search path,是elf文件中一个字段,它指定了可执行文件执行时搜索so文件的第一优先位置,一般编译器默认将该字段设为空。elf文件中还有一个类似的字段runpath,其作用与rpath类似,但搜索优先级稍低。搜索优先级:

rpath > LD_LIBRARY_PATH > runpath > ldconfig缓存 > 默认的/lib,/usr/lib等

如果你需要使用相对路径指定lib文件夹,可以使用ORIGIN变量,ld会将ORIGIN理解成可执行文件所在的路径。

gcc -Wl,-rpath='$ORIGIN/../lib'

interpreter
动态库加载器,程序启动时,操作系统会先把控制权转交给ld-linux-x86-64.so.2,该so负责加载所有程序依赖的so。。这个字段在链接时会帮你自动设置,64bit程序一般为/lib64/ld-linux-x86-64.so.2。修改rpath或者LD_LIBRARY_PATH指向本地lib目录,但通过ldd程序,发现/lib64/ld-linux-x86-64.so.2这个so仍然指向系统so。原因就是这个字段是写死在elf文件中的,并不受LD_LIBRARY_PATH影响。

编译时带上这两个参数,下面只需要将你程序依赖的so打包一份,随程序进行发布即可。

3.2 方式2 直接修改二进制程序的rpath和interpreter

当你无法编译程序时,也可以通过其他方式修改rpath和interpreter。这种情况需要使用到一个工具patchelf,通过dnf install patchelf即可安装。你可以通过它修改elf文件的rpath和interpreter:

patchelf --set-rpath /my/lib your_program
patchelf --set-interpreter /my/lib/ld-linux.so.2 your_program

除了绝对路径,一种比较常见的方式是在部署前,使用pwd获取当前路径,使用相对路径指向本地lib。

patchelf --set-rpath `pwd`/../lib your_program
patchelf --set-interpreter `pwd`/../lib/ld-linux-x86-64.so.2 ./your_program

 

标签:gcc,lib,低版本,glibc,ld,编译,so,interpreter,rpath
From: https://www.cnblogs.com/lidabo/p/17869830.html

相关文章

  • linux虚拟机gcc命令安装
    我从网上找的安装命令是"sudoapt-getinstallgcc",但是我无法成功,它提示未找到apt-get命令,于是我把apt-get命令更换成yum命令,也就是"sudoyuminstallgcc",这个命令就没有问题了,直接安装成功。所以可以直接使用yum命令。 附:当apt-get命令找不到时,可能有以下几个原因和解决......
  • Android app兼容低版本Java环境
    原文地址:Androidapp兼容低版本Java环境-Stars-One的杂货小窝起因是修复一个Bug遇到的问题,找到了一个可以让app兼容低版本java的方法众所周知,Android版本更新后,其内置的JRE环境也随之更新了假如我们在app中用到了JDK8的特有的属性,而用户的手机设备系统还是比较低,而没......
  • 基于空间截面的通用地理因果模型GCCM
      ......
  • GCC常用编译选项及内置宏
    1.__has_include__has_include是一个C++17标准定义的宏,它的用途是检查指定的文件是否存在,从而决定是否继续编译。它可以在头文件包含中使用,这样编译器就可以根据它的返回值来决定是否继续编译,从而提升编译的效率。用法示例:#ifdefined__has_include#if__has_include......
  • Linux训练营(gcc编译器)
    (文章目录)前言本篇文章我们来讲解gcc编译器,gcc编译器在Linux中是用来将从代码编译为可执行程序。为了更加深入了解程序编译生成的过程我们有必要来学习gcc的相关知识。一、gcc编译器介绍GCC(GNUCompilerCollection)是一款广泛使用的开源编译器套件,由GNU项目开发。它支持多种......
  • ./SNeP_111: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by ./SNeP
     001、软件报错如下: 002、系统(base)[root@pc1software]#cat/etc/redhat-releaseCentOSLinuxrelease7.6.1810(Core) 003、查看glibc版本(base)[root@pc1software]#lsSNeP_111(base)[root@pc1software]#./SNeP_111##报错如下./SNeP_111:......
  • npm降低版本,设置指定版本
    npm降低版本,设置指定版本方法一npm版本太高了,项目启不起来,或者其他需求需要低版本可能有些版本已经不支持下载了,可以去官网看看哪些还可以下载,大部分版本都还可以下载[email protected] 查看npm版本,是否修改成功npm-v 方法二使用cnpm来管理npm,对npm进......
  • 如何用gcc+makefile改造STM32Keil项目
    1、环境配置,本地需要安装gcc+make环境,将w64devkit中的bin路径放入环境变量D:\download\storage\arm_gcc\w64devkit然后再cmd中输入gcc-v和make-v测试gcc和make环境是否可以正常运行,如果有下面这种显示就说明gcc和make环境配置好了2、获取芯片的启动文件文件和链接文件,stm32......
  • 【GCC】windows环境编译dll文件
    使用如下指令生成动态库:gcctest.c-I./inc-fPIC-shared-olibtest.dll参数解释:-I:添加头文件搜索目录-fPIC:生成位置无关的代码,在编译动态库的时候需要使用该选项-shared:表明生成一个共享对象,也就是动态库......
  • Glibc堆利用之house of系列总结
    目录1-前言2-houseof系列2.1-houseofspirit漏洞成因适用范围利用原理相关技巧利用效果2.2-houseofeinherjar漏洞成因适用范围利用原理相关技巧利用效果2.3-houseofforce漏洞成因适用范围利用原理相关技巧利用效果2.4-houseoflore漏洞成因适用范围利用原理相关技巧利用效......