执行共享对象文件 [英] Executing share object file

查看:105
本文介绍了执行共享对象文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所有讨论均针对x86.

All discussions are for x86.

如果我编写了一个简单的hello程序,例如以下程序:

If I wrote a simple hello program such as the one below:

#include <stdio.h>

int main(){
  printf("Hello\n");
  return 0;
}

并使用ubuntu在我的PC上进行编译

And compile it on my PC with ubuntu

$gcc -shared -mPIC -o hello_new hello.c

然后,当我尝试执行hello_new时,它将给我分段错误.当我将此二进制文件移动到Android手机时,也会发生同样的错误. (但是我可以使用静态链接的libc将其编译为二进制文件,然后在Android手机上运行)

Then it will give me segmentation fault when I try to execute hello_new. Same error when I move this binary to an android phone. (But I can compile it as a binary with statically linked libc and run it on the android phone)

是的,我想直接执行共享对象.

Yes, I want to execute a shared object directly.

原因如下: 我最近得到了别人编译的一个linux文件.当我使用linux命令filereadelf分析文件时.它说这是一个共享库(32位,用-m32编译).但是我可以像在手机上的android中的可执行文件一样执行共享对象:

The reason is below: I recently get a linux file compiled by someone else. When I use linux command file and readelf to analyze the file. It says it is a shared object (32-bit, compiled with -m32). But I can execute the shared object like an executable in android on a phone:

$./hello

这真的使我感到困惑.此共享库文件包含printf函数调用,不确定是静态链接还是动态链接.但是由于它可以通过ADB在Android上运行,因此我假定它与libc静态链接.

This really confuses me. This shared object file contains printf function calls, not sure if it is statically link or dynamically linked. But since it can run on Android through ADB, I assume it is statically linked against libc.

哪种编译技术可以允许人们直接执行共享对象?

What kind of compilation technique can allow one to execute shared object directly?

推荐答案

碰巧我目前正在从事此类工作. 在Linux下,可执行文件和共享库之间的主要区别之一是,可执行文件具有解释器和(有效)入口点. 例如,在最小程序上:

It happens that I am currently working on this type of thing. One of the main differences between executables and shared object under linux, is that an executable has an interpreter and a (valid) entry point. For example, on a minimal program :

$ echo 'int main;' | gcc -xc -

如果您查看它的小精灵程序标头:

If you look at it's elf program headers:

$ readelf --program-headers a.out
   ...
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
   ...

解释器程序负责程序的执行,要实现此目的,它将执行一些初始化,例如加载所需的共享库.实际上,它与脚本shebang非常相似,但适用于elf文件. 在这种情况下,/lib64/ld-linux-x86-64.so.2是amd64的加载程序.您可以有多个加载程序:例如,一个用于32位,一个用于64位.

The interpreter program is responsible of the execution of the program, to achieve this, it will perform some initializations like loading the needed shared objects. In fact, it is quite analogous to a script shebang, but for elf files. In this case, /lib64/ld-linux-x86-64.so.2 is the loader for amd64. You can have multiples loaders: e.g., one for 32bits, one for 64.

现在是入口点:

$ readelf --file-header a.out
ELF Header:
 ...
  Entry point address:               0x4003c0
 ...
$ readelf -a a.out | grep -w _start
    57: 00000000004003c0     0 FUNC    GLOBAL DEFAULT   13 _start

默认情况下,您可以看到_start被定义为入口点.

By default, you can see that _start is defined as the entry point.

因此,如果您考虑以下最小示例:

So if you consider the following minimal example :

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef INTERPRETER
const char interp[] __attribute__((section(".interp"))) = INTERPRETER;
#endif /* INTERPRETER */
void entry_point(void) {
    fprintf(stderr, "hello executable shared object world !\n");
    _exit(EXIT_SUCCESS);
}

如果将其编译为普通"共享库并执行:

If you compile it as a "normal" shared object and execute it :

$ gcc libexecutable.c -Wall -Wextra -fPIC -shared -o libexecutable.so
$ ./libexecutable.so 
Erreur de segmentation

您可以看到它的段错误.但是现在,如果您定义一个解释器(适应于readelf --program-headers之前给您的内容的路径),并告诉链接器您的入口点是什么:

You can see it segfaults. But now if you define an interpreter (adapt it's path to what readelf --program-headers gave you before) and tell to the linker what is your entry point :

$ gcc libexecutable.c -Wall -Wextra -fPIC -shared -o libexecutable.so -DINTERPRETER=\"/lib64/ld-linux-x86-64.so.2\" -Wl,-e,entry_point
$ ./libexecutable.so hello executable shared object world !

现在可以了.请注意,必须使用_exit()调用才能在执行结束时避免出现段错误.

now it works. Please note that the _exit() call is necessary to avoid a segfault at the end of the execution.

但是最后,请记住,由于您指定了一个自定义入口点,因此将绕过可能需要或不需要的libc初始化步骤,具体取决于您的需求.

But in the end, remember that because you specify a custom entry point, you will bypass libc initialization steps which could be needed or not, depending on your needs.

这篇关于执行共享对象文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆