2016-04-03 8 views
-1

x86 memory access segmentation faultが見つかりました。私のコードでは機能しません。おそらく、私は別々の.textと.dataセグメントを使用せず、カスタムELFヘッダーを作成することですべてを1つのセグメントに保持するという違いがあります。 SYS_BRK呼び出しが失敗する理由を説明していますか?i386 LinuxでのアセンブリでのBRKの呼び出し

メモリページの読み込み/書き込み/実行などを行い、プログラムを続行します。 問題を説明した最小コードサンプルを探しました。

kdbgでは、サンプルは機能しますが、コマンドラインから起動した場合は表示されません。そのため、メッセージの印刷が行われます。

  cpu 386 
      bits 32 

; System calls used 
%assign  SYS_EXIT 1 
%assign  SYS_WRITE 4 
%assign  SYS_BRK  45 
%assign  SYS_MPROTECT 125 

; flags for SYS_MPROTECT 
%assign  PROT_READ 1 
%assign  PROT_WRITE 2 
%assign  PROT_EXEC 4 

%assign  STDOUT  1 

memstart: org   0x08048000 

ehdr:           ; Elf32_Ehdr (see https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 
      db  0x7F, "ELF"     ; e_ident[EI_MAG0..EI_MAG03] 
      db  1       ; e_ident[EI_CLASS] 
      db  1       ; e_ident[EI_DATA] 
      db  1       ; e_ident[EI_VERSION] 
      db  0       ; e_ident[EI_OSABI] 
      db  0       ; e_ident[EI_ABIVERSION] 
    times 7 db  0       ; e_ident[EI_PAD] 
      dw  2       ; e_type 
      dw  3       ; e_machine 
      dd  1       ; e_version 
      dd  start      ; e_entry 
      dd  phdr - $$     ; e_phoff 
      dd  0       ; e_shoff 
      dd  0       ; e_flags 
      dw  ehdrsize     ; e_ehsize 
      dw  phdrsize     ; e_phentsize 
      dw  1       ; e_phnum 
      dw  0       ; e_shentsize 
      dw  0       ; e_shnum 
      dw  0       ; e_shstrndx 
ehdrsize equ  $ - ehdr 

phdr:           ; Elf32_Phdr 
      dd  1       ; p_type 
      dd  0       ; p_offset 
      dd  $$       ; p_vaddr 
      dd  $$       ; p_paddr 
      dd  filesize     ; p_filesz 
      dd  filesize     ; p_memsz 
      dd  5       ; p_flags 
      dd  0x1000      ; p_align 
phdrsize equ  $ - phdr 

memsize: dd  16*4096      ; = 16 * 4K pages 
memtop:  dd  0 


start:  ;int  3 
      xor  ebx, ebx     ; find the amount of allocated memory 
      mov  eax, SYS_BRK 
      int  0x80      ; eax contains current memtop 

      sub  eax, memstart    ; got enough memory? 
      test eax, [memsize] 
      ja  memgood 

      mov  eax, memstart    ; raise memory limit to memstart + memsize 
      add  eax, [memsize] 
      mov  ebx, eax 
      mov  ecx, eax     ; save requested memory size in ecx 
      mov  eax, SYS_BRK 
      int  0x80 
      cmp  eax, ecx 
      jne  brk_error     ; raising memory limit failed 

memgood: mov  edx, (PROT_READ | PROT_WRITE | PROT_EXEC) 
      mov  ecx, [memsize]    ; make memory read/write/execute 
      mov  ebx, memstart 
      mov  eax, SYS_MPROTECT 
      int  0x80 
      test eax, eax 
      js  bailout 

      jmp  launch      ; lets start the party 


brk_error: mov  edx, brkelen 
      mov  ecx, brke 
      mov  ebx, STDOUT 
      mov  eax, SYS_WRITE 
      int  0x80 
      jmp  bailout 
brke:  db  'SYS_BRK failed, bye', 10 
brkelen  equ  $ - brke 

bailout: mov  eax, SYS_EXIT 
      xor  ebx, ebx 
      int  0x80 

launch:  mov  edx, succlen 
      mov  ecx, succ 
      mov  ebx, STDOUT 
      mov  eax, SYS_WRITE 
      int  0x80 
      jmp  bailout 
succ:  db  'Success with mem config, bye', 10 
succlen  equ  $ - succ 

filesize equ $ - $$ 
+0

私はあなたの答えを見て、それを検証働いた。ヘッダーは、単一のセグメントがあることを除いて規則的です。したがって、コード/データ/ bssの分離はありません。 (おっと、突然投稿します)。 質問を編集して完全な初期化を表示しますが、それで差は出ませんでした。 – LNoor

+1

申し訳ありませんが、初めてのユーザーです。私のコードの問題は、BRKの2番目の呼び出しです。 'int 3'を' int 128'の前に置くと、デバッガのブレークポイントについての期待されるメッセージが得られます。もし私がそれを置くなら、プログラムは決してそこに行きません。コンソールから実行すると、プログラムはハングアップするだけです。 – LNoor

+0

実際のコードを提供してくれたので、私はすべてのコメントを削除しました –

答えて

2

かわりtestのここcmpを使用する必要があります。

sub  eax, memstart    ; got enough memory? 
    test eax, [memsize] 
    ja  memgood 

SYS_BRKで説明したメモリ領域が実行した後、0x02000000に0のランダムオフセットを開始するアドレス空間レイアウトのランダム化が無効になっていない限り、どのIあなたのデバッガが疑う。 mmapを使用して、指定されたアドレスにメモリを割り当てることができます(既存のマッピングを上書きしない限り、MAP_FIXEDを設定しないでください)。

しかしbrkmprotectとこの全体の運動は、メモリを番組開始時のように離れてスタックから、むしろ無意味なようだあなたの代わりに、正確に指定されたELFヘッダとしてでき割り振られます

phdr:           ; Elf32_Phdr 
      dd  1       ; p_type 
      dd  0       ; p_offset 
      dd  $$       ; p_vaddr 
      dd  $$       ; p_paddr 
      dd  filesize     ; p_filesz 
      dd  16*4096      ; p_memsz 
      dd  7       ; p_flags 
      dd  0x1000      ; p_align 
phdrsize equ  $ - phdr 
+0

ティモシーありがとう。それはおそらく行く方法です。プログラムは、それを行うための余分なスペースを要求して書き換え、拡大します。私はアドレス空間レイアウトのランダム化を考慮しませんでした。しかし、Elfヘッダーを変更して再起動すると、そのトリックを行う必要があります。 – LNoor

+0

アドレス空間のランダム化を無効にすることが解決策であることが判明しました。そのため、プログラムは 'setarch $(uname -m)-RL。/ lf'として起動し、問題を解決しました。ありがとう@ティモシー。 [http://stackoverflow.com/questions/5194666/disable-randomization-of-memory-addresses]を参照してください。 – LNoor

関連する問題