2012-06-29 11 views
9

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

+0

आप दूरस्थ डीबगिंग चाहते हैं के लिए एक इंटरनेट सर्च करो"।। दूरस्थ डीबगिंग linux "लिंक बहुत – selbie

+0

@selbie : चीजों को करने का यह कठिन तरीका है। –

उत्तर

13

यह वास्तव में काफी आसान है। प्रतीकों तक पहुंचने के लिए आप dlopen/dlsym का उपयोग करते हैं। काम करने के लिए, प्रतीक गतिशील प्रतीक तालिका में मौजूद होना चाहिए। कई प्रतीक टेबल हैं!

#include <dlfcn.h> 
#include <stdio.h> 

__attribute__((visibility("default"))) 
const char A[] = "Value of A"; 

__attribute__((visibility("hidden"))) 
const char B[] = "Value of B"; 

const char C[] = "Value of C"; 

int main(int argc, char *argv[]) 
{ 
    void *hdl; 
    const char *ptr; 
    int i; 

    hdl = dlopen(NULL, 0); 
    for (i = 1; i < argc; ++i) { 
     ptr = dlsym(hdl, argv[i]); 
     printf("%s = %s\n", argv[i], ptr); 
    } 
    return 0; 
} 

गतिशील प्रतीक मेज पर सभी प्रतीकों को जोड़ने के लिए, -Wl,--export-dynamic का उपयोग करें। यदि आप प्रतीक तालिका (अनुशंसित) से अधिकतर प्रतीकों को हटाना चाहते हैं, तो -fvisibility=hidden सेट करें और फिर __attribute__((visibility("default"))) या अन्य विधियों में से एक को स्पष्ट रूप से उन प्रतीकों को जोड़ें।

 
~ $ gcc dlopentest.c -Wall -Wextra -ldl 
~ $ ./a.out A B C 
A = (null) 
B = (null) 
C = (null) 
~ $ gcc dlopentest.c -Wall -Wextra -ldl -Wl,--export-dynamic 
~ $ ./a.out A B C 
A = Value of A 
B = (null) 
C = Value of C 
~ $ gcc dlopentest.c -Wall -Wextra -ldl -Wl,--export-dynamic -fvisibility=hidden 
~ $ ./a.out A B C 
A = Value of A 
B = (null) 
C = (null) 

सुरक्षा

सूचना बुरा व्यवहार के लिए कमरे का एक बहुत है कि वहाँ।

 
$ ./a.out printf 
printf = ▯▯▯▯ (garbage) 

यदि आप इसे सुरक्षित रखना चाहते हैं, तो आपको अनुमत प्रतीकों का श्वेतसूची बनाना चाहिए।

+0

प्रिंटिंग गैर -स्ट्रिंग (poss शायद समाप्त नहीं किया गया) एक स्ट्रिंग के रूप में डेटा या कार्यों खतरनाक है। अन्यथा मुझे प्रतीकों को श्वेतसूची की आवश्यकता नहीं दिखती है। –

+0

@ आर ..: एचएम, मैंने सोचा था कि चर का उपयोग तब तक पढ़ा/लिखना था जब तक कि मैं प्रश्न को और अधिक अच्छी तरह से नहीं पढ़ता। अपडेट किया गया। –

+0

यह जो मैं चाहता हूं उसका आधा तरीका है ... समस्या यह है कि मैं प्रतीक के प्रकार के बावजूद सार्थक प्रतिक्रिया देने में सक्षम होना चाहता हूं। अर्थात। क्या होगा यदि ए "लम्बा" और बी एक "चार" और सी "char *" था? मुझे प्रतीक प्रकार के साथ-साथ इसके पते तक पहुंच की आवश्यकता है। – JimKleck

1

सुविधा की इस तरह के लिए सामान्य शब्द "reflection" है, और यह सी

का हिस्सा

यदि यह डीबगिंग उद्देश्यों के लिए है नहीं है, और यदि आप एक सी के पूरे राज्य का निरीक्षण करने में सक्षम होना चाहते कार्यक्रम दूर से, किसी भी चर की जांच शुरू करने और इसके निष्पादन को रोकने, और इतने पर, आप शायद विचार GDBremote debugging:

GDB अक्सर इस्तेमाल किया जाता है जब एम्बेडेड सिस्टम डिबगिंग एक 'दूरस्थ' मोड प्रदान करता है। रिमोट ऑपरेशन तब होता है जब जीडीबी एक मशीन पर चलता है और प्रोग्राम दूसरे पर डीबग किए गए रन होते हैं। जीडीबी रिमोट 'स्टब' से संचार कर सकता है जो सीरियल या टीसीपी/आईपी के माध्यम से जीडीबी प्रोटोकॉल को समझता है। एक स्टब प्रोग्राम जीडीबी के साथ प्रदान की गई उपयुक्त स्टब फ़ाइलों को लिंक करके बनाया जा सकता है, जो संचार प्रोटोकॉल के लक्ष्य पक्ष को लागू करता है। वैकल्पिक रूप से, gdbserver को दूरस्थ रूप से किसी भी तरह से बदलने की आवश्यकता के बिना प्रोग्राम को डीबग करने के लिए उपयोग किया जा सकता है।

+1

यह उत्पादन के लिए है, और मैं लुकअप टेबल को बनाए रखने के बिना किसी भी प्रतीक को ब्राउज़ करने में सक्षम होना चाहता हूं ... आखिरकार, वह जानकारी पहले से ही प्रतीक तालिका में है। – JimKleck

6

फ़ाइल: reflect.c

#include <stdio.h> 
#include "reflect.h" 

struct sym_table_t gbl_sym_table[1] __attribute__((weak)) = {{NULL, NULL}}; 

void * reflect_query_symbol(const char *name) 
{ 
    struct sym_table_t *p = &gbl_sym_table[0]; 

    for(; p->name; p++) { 
     if(strcmp(p->name, name) == 0) { 
      return p->addr; 
     } 
    } 
    return NULL; 
} 

फ़ाइल: reflect.h

#include <stdio.h> 

struct sym_table_t { 
    char *name; 
    void *addr; 
}; 

void * reflect_query_symbol(const char *name); 

फ़ाइल: main.c

सिर्फ #include "को दर्शाते हैं।ज "और फोन reflect_query_symbol

उदाहरण:

#include <stdio.h> 
#include "reflect.h" 

void foo(void) 
{ 
    printf("bar test\n"); 
} 

int uninited_data; 

int inited_data = 3; 

int main(int argc, char *argv[]) 
{ 
    int i; 
    void *addr; 

    for(i=1; i<argc; i++) { 
     addr = reflect_query_symbol(argv[i]); 
     if(addr) { 
      printf("%s lay at: %p\n", argv[i], addr); 
     } else { 
      printf("%s NOT found\n", argv[i], addr); 
     } 
    } 

    return 0; 
} 

फ़ाइल:। Makefile

objs = main.o reflect.o 

main: $(objs) 
     gcc -o [email protected] $^ 
     nm [email protected] | awk 'BEGIN{ print "#include <stdio.h>"; print "#include \"reflect.h\""; print "struct sym_table_t gbl_sym_table[]={" } { if(NF==3){print "{\"" $$3 "\", (void*)0x" $$1 "},"}} END{print "{NULL,NULL} };"}' > .reflect.real.c 
     gcc -c .reflect.real.c -o .reflect.real.o 
     gcc -o [email protected] $^ .reflect.real.o 
     nm [email protected] | awk 'BEGIN{ print "#include <stdio.h>"; print "#include \"reflect.h\""; print "struct sym_table_t gbl_sym_table[]={" } { if(NF==3){print "{\"" $$3 "\", (void*)0x" $$1 "},"}} END{print "{NULL,NULL} };"}' > .reflect.real.c 
     gcc -c .reflect.real.c -o .reflect.real.o 
     gcc -o [email protected] $^ .reflect.real.o 
+0

आपको केवल "reflect.c" और "reflect.h" दिखाने जैसी दो फाइलें लिखनी होंगी और अपने "मेकफ़ाइल" को संशोधित करें, आपको प्रतीक का एक सारणी और प्रतीक के संबंधित पते मिलेगा। –

+0

मुझे प्रतीक प्रकार, या कम से कम आकार, साथ ही पते चाहिए। ऐसा लगता है कि एनएम के लिए "-एस" ध्वज ऐसा करेगा। Gbl_sym_table के लिए सही आकार प्राप्त करने के लिए मुझे अंतिम निष्पादन योग्य (क्योंकि मेरे पास एकाधिक .o है) पर एनएम चलाने की आवश्यकता है, फिर पते के साथ भरने के लिए फिर से एनएम चलाएं? फिर आखिरकार पुनर्निर्माण करें। और इसे निष्पादन योग्य में लाने के लिए रिलिकिंक करें? – JimKleck

+0

वास्तव में, एनएम और मेकफ़ाइल जादूगर से परेशान क्यों? एनएम प्रोग्राम को प्रतीक तालिका तक पहुंचने के लिए कुछ एपीआई का उपयोग करना चाहिए, मैं चाहता हूं कि एपीआई सीधे मेरे प्रोग्राम में उपयोग करे। – JimKleck

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