[英]unable to access global assembly label data from c program linked with shared library
[英]Will the assembly program be linked with a C library?
我有以下匯編程序,它通過適當的系統調用將“hello world”打印到屏幕上:
.global _start
.text
_start:
# write(1, message, 13)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
mov $message, %rsi # address of string to output
mov $13, %rdx # number of bytes
syscall # invoke operating system to do the write
# exit(0)
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # we want return code 0
syscall # invoke operating system to exit
message:
.ascii "Hello, world\n"
如果我在 ubuntu 終端中發出命令gcc hello.s
,匯編代碼是否會與網頁中的某個人爭辯的 C 庫相關聯? 如果是,那是為什么? 匯編代碼似乎沒有在任何地方引用 C 代碼。
如果我在 ubuntu 終端中發出命令 gcc hello.s ,匯編代碼是否會與網頁中的某個人競爭的 C 庫鏈接?
是的。
如果是,那是為什么?
這是gcc
命令在鏈接時的記錄默認行為,因為它主要用於 C 程序。
匯編代碼似乎沒有在任何地方引用 C 代碼。
沒關系,因為匯編器和 linker 不檢查是否有。
默認行為是設置涉及 C 庫、其標准啟動代碼和您的代碼的鏈接。 如果您運行gcc -v hello.s
,您可以看到詳細信息:
/usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccVrfSjS.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. /tmp/cc17H49O.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
crt*.o
文件是啟動代碼, -lc
鏈接 C 庫。
在 C 程序中,標准啟動代碼應該是第一個運行的東西,以便初始化庫並按照編譯的 C 代碼所期望的方式設置各種東西。 因此,它定義了用作程序入口點的_start
label,它包含對名為main
的符號的調用。 因此,只有在您提供的代碼確實定義了一個名為main
的符號並且沒有定義一個名為_start
的符號時,鏈接才能成功(因為不允許有兩個,否則 linker 將不知道使用哪個)。 無論哪種情況,您的代碼都不是這種情況。
如果您想要一些其他行為,它由命令行開關決定,而不是由代碼的內容決定。 -nostdlib
告訴 linker 不要包含 C 庫及其啟動代碼; 在這種情況下,您的代碼必須提供_start
並且不需要main
。 因此,如果您使用gcc -nostdlib -no-pie foo.s
編譯,您的代碼將成功編譯並運行。
(需要-no-pie
選項,因為您的代碼在mov $message, %rsi
中使用絕對 static 地址作為立即數。這些限制為 32 位,因此如果要將代碼重新定位到任意位置,則無法工作在 64 位地址空間中。更好的做法是使用 RIP 相對尋址: lea message(%rip), %rsi
,然后你就不需要-no-pie
了。你也可以使用mov
的形式64 位立即數, movabs $message, %rsi
,但它使用更多字節的代碼。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.