我有一个包含符号的大二进制文件。我可以在nm或 中看到符号objdump。
我知道使用了该符号,否则链接器不会包含它(更准确地说,我知道使用了同一源文件中的某些符号)。
我试图找出它的使用方式。
如果引用是通过函数(例如函数调用函数,使用全局变量的函数),我可以使用objdump -rd反汇编文件并找到引用。
但是如果引用是由一个变量(例如一个全局指针初始化为指向某个变量),反汇编不会显示它。
我没有找到任何可以做到的方法。
这是一个演示它的示例。在这个例子中,很明显谁使用了x,但我不知道如何检查生成的二进制文件并找到它。
// x.c
int x = 3;
// main.c
extern int x;
static int *y = &x;
int main() {
return *y;
}
// Build process
gcc -o x.o -c x.c
ar r libx.a x.o
gcc -o main.o -c main.c
gcc -o main main.o -L. -lx
Run Code Online (Sandbox Code Playgroud) 据我所知,PLT并且GOT是处理动态链接功能的部分。
如果代码调用printflibc 的函数,
1. 首先它调用PLTgetprintf的地址。
2. 并将此地址写入GOT部分。
3. 从第二次调用开始,代码使用编写的函数GOT。
当我仔细查看 ELF 二进制文件时,
- 我发现PLTELF 中的section名称是<.plt>.
-GOT在 ELF 中部分的名称是<.got.plt>.
但是...... <.got>ELF中也有部分。
我无法理解如何使用此部分。
Q.<.got>节的用法是什么?和部分有
什么区别?<.got><.got.plt>
PS 1. 这个<.got>部分非常小,(在我的示例二进制文件中它只包含 4byte。)
在这里我附上<.got>部分的IDA 视图:
.got:08049FFC ; ===========================================================================
.got:08049FFC
.got:08049FFC ; Segment type: Pure data
.got:08049FFC ; Segment permissions: Read/Write
.got:08049FFC _got segment …Run Code Online (Sandbox Code Playgroud) 当我将 Fedora 28 的/usr/bin/ls文件加载到 GDB 时,我可以访问符号abformat_init,即使它既不是字符串也不是二进制文件的符号表。
$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=d6d0ea6be508665f5586e90a30819d090710842f, stripped, too many notes (256)
$ readelf -S /usr/bin/ls | grep abformat
$ nm /usr/bin/ls
nm: /usr/bin/ls: no symbols
$ strings /usr/bin/ls | grep abformat
$ gdb /usr/bin/ls
[...]
Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Missing separate debuginfos, use: dnf debuginfo-install …Run Code Online (Sandbox Code Playgroud) 我有一个独立的 Linux 独立 x86_64 hello world 工作岗位:
电源
.text
.global _start
_start:
asm_main_after_prologue:
/* Write */
mov $1, %rax /* syscall number */
mov $1, %rdi /* stdout */
lea msg(%rip), %rsi /* buffer */
mov $len, %rdx /* len */
syscall
/* Exit */
mov $60, %rax /* syscall number */
mov $0, %rdi /* exit status */
syscall
msg:
.ascii "hello\n"
len = . - msg
Run Code Online (Sandbox Code Playgroud)
我可以组装和运行:
as -o main.o main.S
ld -o main.out main.o
./main.out
Run Code Online (Sandbox Code Playgroud)
由于RIP …
以下程序:
#include <stdio.h>
int main(int argc, char *argv[])
{
for (int j = 0; j < argc; j++)
printf("%d: %s\n", j, argv[j]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
内置于静态链接的 PIE 中:
gcc -g -fpie main.c -static-pie -o ld.so
Run Code Online (Sandbox Code Playgroud)
工作正常:
$ ./ld.so foo bar
0: ./ld.so
1: foo
2: bar
Run Code Online (Sandbox Code Playgroud)
但是当我将该程序用作另一个程序的 ELF 解释器时:
$ gcc -g main.c -Wl,-I./ld.so -o a.out
Run Code Online (Sandbox Code Playgroud)
它像这样崩溃:
gdb -q ./a.out
(gdb) run
Starting program: /tmp/a.out
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7da84e2 in __ctype_init () at ctype-info.c:31
31 …Run Code Online (Sandbox Code Playgroud) // foo.c
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
当我编译上面的代码时,我注意到一些符号位于*ABS*:
$ gcc foo.c
$ objdump -t a.out | grep ABS
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000000000 l df *ABS* 0000000000000000 foo.c
0000000000000000 l df *ABS* 0000000000000000 crtstuff.c
0000000000000000 l df *ABS* 0000000000000000
Run Code Online (Sandbox Code Playgroud)
看起来它们是一些调试符号,但调试信息不是存储在类似.debug_info部分的地方吗?
根据man objdump:
*ABS* 如果该部分是绝对的(即不与任何部分连接)
我不明白,因为这里没有给出例子。
这里的问题显示了一种有趣的方式来传递一些额外的符号*ABS*by --defsym。但我认为通过传递宏可能会更容易。
那么这个*ABS*部分是什么,什么时候有人会使用它?
编辑:
绝对符号不会被重新定位,它们的虚拟地址(在您给出的示例中为 0000000000000000)是固定的。
我写了一个演示,但似乎可以修改绝对符号的地址。
$ gcc foo.c
$ objdump -t a.out | grep ABS
0000000000000000 l …Run Code Online (Sandbox Code Playgroud) 我有一个使用无服务器、express 和libxmljs(将 JavaScript 绑定到 libxml)的超级基本 AWS Lambda 函数:
无服务器.xml:
service: xmltest
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: us-east-1
functions:
app:
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
plugins:
- serverless-offline
Run Code Online (Sandbox Code Playgroud)
索引.js:
const serverless = require('serverless-http');
const express = require('express');
const libxml = require("libxmljs");
const app = express();
app.use(express.json());
app.post('/lookup', async function (req, res) {
res.send({result: "hello world"});
});
module.exports.handler = serverless(app);
Run Code Online (Sandbox Code Playgroud)
当我在本地运行时:
$ curl -X POST http://localhost:3000/lookup -d …Run Code Online (Sandbox Code Playgroud) elf libxml2 amazon-web-services aws-lambda serverless-framework
我正在为我的某个项目编写一些汇编代码,我看到了一些有趣的东西。链接时二进制文件的大小是如此之大。所以我进行了测试和测试,即使使用尽可能少的代码行,输出 Elf 二进制文件也是如此之大。例如:
.section .text
.global _start
_start:
movl $1,%eax
movl $0,%ebx
int $0x80
Run Code Online (Sandbox Code Playgroud)
组装和链接以上代码后,结果二进制文件超过 4kb!有趣的是,大多数二进制文件都填充了零。
我尝试了很多事情来找出没有成功的原因。
有人可以向我解释这里有什么问题吗?
我只是组装和链接文件:
.section .text
.global _start
_start:
movl $1,%eax
movl $0,%ebx
int $0x80
Run Code Online (Sandbox Code Playgroud)
推荐任何形式的资源以供进一步阅读会很好。
你可能猜到了,我使用 64 位 GNU/Linux
谢谢。
.plt: 在 REplt[n]可用段中,蹦床在0 之外运行,.got.plt 解析器链接在plt[0]
.got .got.plt : 在可读写段中,只需寻址
我从这篇文章中了解到:https : //eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/
实际的 Linux shell 命令给了我不同的答案
$readelf -l /bin/bash
Run Code Online (Sandbox Code Playgroud)
我倾倒了两个部分(plt,plt.got)并得到了这个程序集
.plt 是我了解到的 plt:

.plt.got ,这是做什么用的?

对不起,倾销不好,它是由
objcopy -O binary --only-section=.plt.got /bin/bash ./pltgot
objcopy -O binary --only-section=.plt /bin/bash ./plt
Run Code Online (Sandbox Code Playgroud)
如果使用 dlopen() 再次加载相同的库,则返回相同的文件句柄。
“同一个图书馆”是什么意思?相同的文件名?一样的路?同一个节点?同一个 SONAME?还有什么?这种行为如何与软链接交互?
假设我对 ELF so's 和主流 Linux 发行版(Debian / Arch / RHEL 系列)感兴趣。
示例后果: