2017-07-22 89 views
4

我有Raspberry Pi 3與Raspbian GNU/Linux 8(Jessie)操作系統。爲什麼在Raspberry Pi上可執行堆棧段?

我寫了這個簡單的程序。我編譯它與gcc -o hello hello.c

#include <stdio.h> 

void main(){ 
    printf("hello!\n"); 
} 

從從readelf輸出似乎一切都OK:

Program Headers: 
    Type   Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 
    EXIDX   0x0004cc 0x000104cc 0x000104cc 0x00008 0x00008 R 0x4 
    PHDR   0x000034 0x00010034 0x00010034 0x00120 0x00120 R E 0x4 
    INTERP   0x000154 0x00010154 0x00010154 0x00019 0x00019 R 0x1 
     [Requesting program interpreter: /lib/ld-linux-armhf.so.3] 
    LOAD   0x000000 0x00010000 0x00010000 0x004d8 0x004d8 R E 0x10000 
    LOAD   0x000f0c 0x00020f0c 0x00020f0c 0x0011c 0x00120 RW 0x10000 
    DYNAMIC  0x000f18 0x00020f18 0x00020f18 0x000e8 0x000e8 RW 0x4 
    NOTE   0x000170 0x00010170 0x00010170 0x00044 0x00044 R 0x4 
    GNU_STACK  0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10 
    GNU_RELRO  0x000f0c 0x00020f0c 0x00020f0c 0x000f4 0x000f4 R 0x1 

但是當我運行該程序堆棧是可執行文件:

0x7efdf000 0x7f000000 0x00000000 rwx [stack] 

我嘗試與選項-z noexecstack也編譯,但沒有任何變化。

我也嘗試下載具有此代碼的libarmmem.so版本:

#if defined(__linux__) && defined(__ELF__) 
.section .note.GNU-stack,"",%progbits 
#endif 

但沒有什麼變化。

爲什麼在Raspberry Pi上可執行堆棧段?

編輯我添加LD_DEBUG的輸出=文件./hello命令

 23110: 
    23110: file=/usr/lib/arm-linux-gnueabihf/libarmmem.so [0]; needed by ./hello [0] 
    23110: file=/usr/lib/arm-linux-gnueabihf/libarmmem.so [0]; generating link map 
    23110: dynamic: 0x76f273fc base: 0x76f13000 size: 0x00014524 
    23110:  entry: 0x76f13568 phdr: 0x76f13034 phnum:   6 
    23110: 
    23110: 
    23110: file=libc.so.6 [0]; needed by ./hello [0] 
    23110: file=libc.so.6 [0]; generating link map 
    23110: dynamic: 0x76f0ef20 base: 0x76dd4000 size: 0x0013e550 
    23110:  entry: 0x76dea840 phdr: 0x76dd4034 phnum:   10 
    23110: 
    23110: 
    23110: calling init: /lib/arm-linux-gnueabihf/libc.so.6 
    23110: 
    23110: 
    23110: calling init: /usr/lib/arm-linux-gnueabihf/libarmmem.so 
    23110: 
    23110: 
    23110: initialize program: ./hello 
    23110: 
    23110: 
    23110: transferring control: ./hello 
    23110: 
hello! 
    23110: 
    23110: calling fini: ./hello [0] 
    23110: 
    23110: 
    23110: calling fini: /usr/lib/arm-linux-gnueabihf/libarmmem.so [0] 
    23110: 

添加更多的信息: 我編輯文件architecture.S和化妝後,我收到:

gcc -std=gnu99 -O2 -c -o trampoline.o trampoline.c 
gcc -shared -o libarmmem.so architecture.o memcmp.o memcpymove.o memcpymove-a7.o memset.o trampoline.o 
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o 
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o 
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o 
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o 
collect2: error: ld returned 1 exit status 
Makefile:13: recipe for target 'libarmmem.so' failed 
make: *** [libarmmem.so] Error 1 
+0

請原諒我的無知......你是如何得到這個結果的:'0x7efdf000 0x7f000000 0x00000000 rwx [stack]'。這是「痕跡」的一部分嗎? – jww

+0

@jww no just/proc /'pidof hello'/maps – Livio

+1

請運行'LD_DEBUG = files。/ hello'程序並將輸出添加到您的文章中。有一些報告稱LD_PRELOAD庫會導致這種情況。 –

回答

2

這很可能是/usr/lib/arm-linux-gnueabihf/libarmmem.so造成的。我發現這個源文件:

它缺乏非可執行堆棧的註釋,所以glibc的保守使得棧可執行文件時的DSO預裝。其它源文件有這樣的:

/* Prevent the stack from becoming executable */ 
#if defined(__linux__) && defined(__ELF__) 
.section .note.GNU-stack,"",%progbits 
#endif 

因此,您只需將它複製到architecture.S(在文件的結尾)和重建。

您可以用eu-readelf -l /usr/lib/arm-linux-gnueabihf/libarmmem.so進行驗證,如果這個DSO確實是罪魁禍首。它應該根本沒有顯示GNU_STACK程序標題,或者在倒數第二列顯示程序標題爲RWE

+0

@Livio,對不起,看起來有點亂碼。評論框不是發佈編譯器輸出消息的好地方。請修改帖子,說明你做了什麼,結果如何。 –

+0

對不起:我把輸出添加到文章 – Livio

+1

對不起,我錯過了'architecture.S'在開始時沒有section指令。您需要將我發佈在文件末尾的片段,或者如果在開始時放置片段,請在它後面添加一個'.data'指令。 –