2009-08-06 11 views
50

मैं एक सिस्कल असेंबली निर्देश (आईएनटी निर्देश, मुझे विश्वास है) और जीडीबी के साथ हैंडलर देखने के लिए एक प्रोग्राम को अलग करने की कोशिश कर रहा हूं और इसके लिए एक छोटा प्रोग्राम (नीचे देखें) लिखा है जो फ़ाइल खोलता है और बंद करता है। मैं कॉल को निष्पादित किए जाने तक जीडीबी के साथ फॉपेन करने के लिए कॉल का पालन करने में सक्षम था। जब मैंने जीडीबी को "0x डिससेबल करें" (कॉल का पता) बताने की कोशिश की तो उसने 'नो फ़ंक्शन में निर्दिष्ट पता' दिया। क्या जीडीबी को डिस्सेबल करने के लिए मजबूर करना संभव है (या इसे जितना संभव हो सके असेंबलर में प्रदर्शित करें) मेमोरी पता? यदि हां, तो कैसे?मैं जीडीबी को अलग करने के लिए कैसे मजबूर कर सकता हूं?

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    FILE* f; 
    f = fopen("main.c", "r"); 
    if (!f) { 
     perror("open"); 
     return -1; 
    } 
fclose(f); 
return 0; 
} 
+2

fopen() एक सिस्टम कॉल नहीं है, यह सी मानक पुस्तकालय के लिए एक कॉल है। और आपको क्यों लगता है कि एक आईएनटी निर्देश के माध्यम से एक सिस्टम कॉल किया जाना चाहिए? –

+0

मैं गलत हो सकता हूं, लेकिन हमें सिखाया गया था कि अंततः फॉपेन कॉल का परिणाम कर्नेल को फ़ाइल खोलने और फ़ाइल डिस्क्रिप्टर को वापस करने के लिए सिस्टम कॉल में होता है? – Patrick

+1

पैट्रिक: हाँ, लेकिन उस निर्देश को करने की आवश्यकता नहीं है। आम तौर पर यह libc फ़ंक्शन को कॉल करता है जो तब कर्नेल में प्रवेश करता है। लेकिन कर्नेल को कॉल करना न केवल int (यह धीमा है) के साथ किया जा सकता है लेकिन प्रोसेसर आर्किटेक्चर के आधार पर syscall/sysenter के साथ ... – k3a

उत्तर

40

आप केवल अपने वास्तविक मुख्य एकत्रित न करना चाहते हैं? यदि ऐसा है तो यह प्रयास करें:

(gdb) info line main 
(gdb) disas STARTADDRESS ENDADDRESS 

तो जैसा:

[email protected] /cygdrive/c/prog/dsa 
$ gcc-3.exe -g main.c 

[email protected] /cygdrive/c/prog/dsa 
$ gdb a.exe 
GNU gdb 6.8.0.20080328-cvs (cygwin-special) 
... 
(gdb) info line main 
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+ 
(gdb) disas 0x401050 0x401075 
Dump of assembler code from 0x401050 to 0x401075: 
0x00401050 <main+0>: push %ebp 
0x00401051 <main+1>: mov %esp,%ebp 
0x00401053 <main+3>: sub $0x18,%esp 
0x00401056 <main+6>: and $0xfffffff0,%esp 
0x00401059 <main+9>: mov $0x0,%eax 
0x0040105e <main+14>: add $0xf,%eax 
0x00401061 <main+17>: add $0xf,%eax 
0x00401064 <main+20>: shr $0x4,%eax 
0x00401067 <main+23>: shl $0x4,%eax 
0x0040106a <main+26>: mov %eax,-0xc(%ebp) 
0x0040106d <main+29>: mov -0xc(%ebp),%eax 
0x00401070 <main+32>: call 0x4010c4 <_alloca> 
End of assembler dump. 

मैं तथापि आपके सिस्टम बाधा कॉल नहीं दिख रहा। (यह थोड़ी देर के बाद से मैंने असेंबली में सिस्टम कॉल करने की कोशिश की थी। आईएनटी 21h हालांकि, आखिरकार मुझे याद है

+0

ठीक है, तो मैं भविष्य में INT 21h देखने की कोशिश करूंगा। उस संकेत के लिए धन्यवाद। लेकिन मैं जो कोशिश करना चाहता था वह है fopen() में इसे कॉल अनुक्रम का पालन करना (इसे अपने कोड में नहीं देखें ...) 'नीचे' जब तक कि मैं INT कमांड नहीं देख पाता। – Patrick

+1

इसे प्रबंधित किया - जाने का तरीका आपके उत्तर और फालेना दोनों का उपयोग करना है। मुझे इसे gcc --static main.c के साथ स्थिर रूप से संकलित करना था और फिर सी पुस्तकालय में गहराई से जाने के लिए gdb/objdump का उपयोग करना था। अल्टीमेटिवली, इसके परिणामस्वरूप __open_nocancel को कॉल किया गया, जिसने * INT 0x80 * किया था। आप दोनों को धन्यवाद – Patrick

+4

नोट: कम से कम संस्करण gdb 7.7 में 'disas 0x401050 0x401075' वाक्यविन्यास काम नहीं करेगा। आपने इसे 'disas 0x401050,0x401075' की तरह लिखा है। इसके अलावा शायद आप उपसर्ग «/ m» को स्रोत कोड दिखाने के लिए जोड़ना चाहेंगे: 'disas \ m 0x401050,0x401075' –

28

यह आपके प्रश्न का सीधा जवाब नहीं है, लेकिन चूंकि आप बस बाइनरी को अलग करना चाहते हैं , शायद तुम सिर्फ objdump इस्तेमाल कर सकते हैं:

objdump -d program 

यह आपको देना चाहिए इसके dissassembly आप -S जोड़ सकते हैं यदि आप इसे स्रोत-एनोटेट चाहते

+0

-'-S' के लिए, मुझे नहीं पता था कि इसमें स्रोत कोड शामिल हो सकता है। –

6

आप जोड़कर सीधे विधानसभा कोड को उत्पादन के लिए जीसीसी मजबूर कर सकते हैं।। -एस स्विच

gcc -S hello.c 
83

हाँ, डिस्सेबल यहां उपयोग करने का सबसे अच्छा आदेश नहीं है। आदेश आप चाहते हैं "एक्स/मैं" (निर्देश के रूप में की जांच) है:

(gdb) x/i 0xdeadbeef 
+3

धन्यवाद! इस पाठ को दूसरों को इस संकेत को ढूंढने में मदद करने के लिए जोड़ना: यह निर्देश है कि बाइनरी ब्लॉब को अलग करने, रोम को अलग करने, बाइनरी छवि फ़ाइल आदि में निर्देश की जांच करने के लिए उपयोग किया जाने वाला निर्देश है। बाइनरी ब्लॉब को बफर में फ़्रेड करने के लिए एक छोटा सी प्रोग्राम लिखें। फिर बफर पर 'x/i' करें। – user188012

+0

@ user188012 यदि आप बाइनरी ब्लॉब को अलग करना चाहते हैं, तो ऐसा करने का एक आसान तरीका एक स्टैंडअलोन डिस्सेबलर जैसे कि एंजाइज़्म या इसी तरह का उपयोग करना है। –

+0

आप पीसी के लिए निर्देश प्राप्त करने के लिए x/i $ pc का उपयोग कर सकते हैं जो वर्तमान निर्देश – k3a

3

सब जो आप चाहते, INTC कॉल के साथ disassembly देख objdump -d का उपयोग किसी को उल्लेख किया लेकिन उपयोग करने के लिए है - संकलन करते समय स्थिर विकल्प। अन्यथा फॉपेन फ़ंक्शन को एल्फ़ में संकलित नहीं किया जाता है और रनटाइम पर लिंक किया जाता है।

7

fopen() एक सी लाइब्रेरी फ़ंक्शन है और इसलिए आपको अपने कोड में कोई सिस्कोल निर्देश नहीं दिखाई देगा, केवल एक नियमित फ़ंक्शन कॉल। किसी बिंदु पर, यह खुले (2) को कॉल करता है, लेकिन यह एक ट्रैम्पोलिन के माध्यम से करता है। बस VDSO पृष्ठ पर एक कूद है, जो कर्नेल द्वारा प्रत्येक प्रक्रिया में प्रदान की जाती है। वीडीएसओ फिर सिस्टम कॉल करने के लिए कोड प्रदान करता है। आधुनिक प्रोसेसर पर, SYSCALL या SYSENTER निर्देशों का उपयोग किया जाएगा, लेकिन आप x86 प्रोसेसर पर INT 80h का भी उपयोग कर सकते हैं।

1

आपको gdb का उपयोग करने की आवश्यकता नहीं है। जीसीसी यह करेगा।

gcc -S foo.c 

यह foo.s बना देगा जो असेंबली है।

gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst 

उपरोक्त संस्करण एक लिस्टिंग फ़ाइल तैयार करेगा जिसमें सी और असेंबली दोनों उत्पन्न होंगी। GCC FAQ

1

जीडीबी डिस्सेबल में निर्देशों के साथ स्रोत कोड शामिल करने के लिए ए/एम है। यह objdump -S के बराबर है, ब्याज की केवल एक कार्य (या पता-सीमा) को सीमित करने के अतिरिक्त लाभ के साथ।

संबंधित मुद्दे

 संबंधित मुद्दे