2012-03-20 7 views
6

हम लिनक्स के तहत आर्म-एबी-जीसीसी के साथ संकलित एक सी प्रोग्राम पर काम कर रहे हैं।संरचना डंप में किसी फ़ील्ड का सापेक्ष पता कैसे प्राप्त करें। [सी]

हम एक बड़ी संरचना के डंप का उपयोग कर रहे हैं और हमें यह निर्धारित करने में समस्याएं आ रही हैं कि हमें किस संरचना में हमारी संरचना के विभिन्न क्षेत्रों (जैसे उनमें से 50) पढ़ना चाहिए, (स्मृति संरेखण और पैडिंग इतनी उम्मीदवार नहीं है मुझे)।

क्या हमारे कंपाइलर द्वारा उत्पादित संरचना की मेमोरी मैपिंग प्राप्त करने का कोई तरीका है। जीडीबी में एक विकल्प? या कोई उपकरण हमें डंप में फ़ील्ड और एड्रेस के बीच पत्राचार खोजने में मदद करता है?

+0

मुझे शायद यहां कुछ स्पष्ट याद आ रहा है, लेकिन यदि आपके पास एक चर है (चलो कहें 'x') जिसे संरचना उदाहरण (या संरचना के लिए सूचक) के रूप में घोषित किया गया है, तो आपको बस ' सभी सदस्यों को डंप करने के लिए gdb में x x (या 'print * x' अगर कोई सूचक) मुद्रित करें। –

+0

मैं उस डंप को पाने की कोशिश नहीं कर रहा हूं जिसे मैं डंप करना चाहता हूं। मेरे पास पहले से ही डंप है और सभी सदस्यों के सापेक्ष पते की आवश्यकता है। – Akhneyzar

उत्तर

23

आप इसे gdb के साथ कर सकते हैं। gdb में

struct A { 
    int a; 
    char b; 
    short c; 
}; 

int main() { 
    struct A a; 
} 

द्विआधारी अप लोड हो रहा है: उदाहरण के लिए, मैं इस स्रोत का उपयोग करेंगे

(gdb) print (int)&((struct A*)0)->a 
$1 = 0 
(gdb) print (int)&((struct A*)0)->b 
$2 = 4 
(gdb) print (int)&((struct A*)0)->c 
$3 = 6 

अद्यतन:

आप एक बड़ी संख्या के लिए यह करने के लिए की जरूरत है फ़ील्ड के बाद, आपको GDB के नए पायथन इंटरफ़ेस का उपयोग करने में आसान लगेगा (आपको इसका उपयोग करने के लिए जीडीबी के हाल के संस्करण की आवश्यकता होगी, मैं 7.4 का उपयोग कर रहा हूं)। मैं offsets.py बना लिया है:

python 
sys.path.insert(0, '/path/to/script/dir') 
import offsets 
end 

फिर इसे का उपयोग GDB में की तरह,:

(gdb) offsets-of "struct A" 
struct A { 
    a => 0 
    b => 4 
    c => 6 
} 

यह स्क्रिप्ट एक बनाता है

import gdb 

class Offsets(gdb.Command): 
    def __init__(self): 
     super (Offsets, self).__init__ ('offsets-of', gdb.COMMAND_DATA) 

    def invoke(self, arg, from_tty): 
     argv = gdb.string_to_argv(arg) 
     if len(argv) != 1: 
      raise gdb.GdbError('offsets-of takes exactly 1 argument.') 

     stype = gdb.lookup_type(argv[0]) 

     print argv[0], '{' 
     for field in stype.fields(): 
      print ' %s => %d' % (field.name, field.bitpos//8) 
     print '}' 

Offsets() 

तो फिर आप अपने .gdbinit को जोड़ सकते हैं कुछ सरल धारणाएं, जैसे कि आप बिटफील्ड का उपयोग नहीं करते हैं, और यह नेस्टेड structs में खोद नहीं है, लेकिन यदि आप की जरूरत है तो वे परिवर्तन 3 काफी सरल हैं।

+0

तक करने की अनुमति नहीं देता है, लेकिन मैं वहां 50 आवश्यक फ़ील्ड की तरह सूचीबद्ध करना चाहता हूं। – Akhneyzar

+0

मैंने प्रेरणा के लिए धन्यवाद, इसका एक और पूरा संस्करण बनाया। [क्लिकी] (https://github.com/Craxic/PyGDBOffsets/blob/master/offsets.py) – AStupidNoob

+0

आपका '.gdbinit' अजीब दिखता है। क्यों नहीं 'स्रोत/पथ/से/स्क्रिप्ट/dir/offsets.py' – zhangyoufu

-1

मुझे लगता है कि आप इस संकलन स्थिति में गणना करने के लिए बाइट में ऑफसेट आवश्यक फ़ील्ड

struct MyStruct S; 
int Offset_of_X=((long)&(S.X))-((long)&S); 

के लिए इस तरह कोड का एक सा लिख ​​सकते हैं।

यह कंपाइलर के किसी भी संरेखण के मुद्दों के लिए जिम्मेदार होना चाहिए।

+0

लेकिन इसमें 50 फ़ील्ड या उससे अधिक के लिए दक्षता की कमी है। – Akhneyzar

+0

यह संकलित नहीं करता है: पॉइंटर अंकगणित आपको एक सूचक से एक्स तक एक सूचक को X. –

2

stddef.h में परिभाषित मानक offsetof() मैक्रो का उपयोग करके आप इसे सी प्रोग्राम से कर सकते हैं। हालांकि मुझे यकीन नहीं है कि यह वही है जो आप चाहते हैं, क्योंकि आप इसे चलाने में असमर्थ हो सकते हैं (मेजबान पर इसे संकलित करने से शायद गलत ऑफसेट वापस आ जाएंगे)।

#include <stdio.h> 
#include <stddef.h> 

struct A { 
    int a; 
    char b; 
    short c; 
}; 

int main() { 
    printf("Offset of b in A is %zu\n", offsetof(struct A, b)); 
    return 0; 
} 

हालांकि, आप इसे क्रियान्वित करने के बिना कुछ हैक्स एक संकलित बाइनरी से ऑफसेट करने के लिए रोजगार के लिए सक्षम हो सकता है। हो सकता है कि एक स्थिर वैरिएबल ऑफ़सेट मान असाइन करें, और इसका मूल्य प्राप्त करने का कोई तरीका ढूंढें।

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