Bir TCP soketine (belirli bir bağlantı noktasına bağlı) gönderilen isteği işleyen bir Linux C programım var. C programının iç durumunu bu bağlantı noktasına bir istek ile sorgulayabilmek istiyorum, ancak global değişkenlerin sorgulanabileceği sabit bir kod istemiyorum. Bu yüzden sorgunun, bir global ve C kodunun dize adını içermesini ve bu dizginin adres tablosunu bulmak için sembol tablosuna bakmasını ve ardından değerini TCP soketine geri göndermesini istiyorum. Tabii ki sembol tablosu soyulmamış olmalı. Bu yüzden C programı kendi sembol tablosunu bile bulabilir ve isimleri verilen sembollere bakmak için bir kütüphane arayüzü var mı? Bu, gcc ile oluşturulmuş bir ELF yürütülebilir C programıdır.Çalışan bir C programı kendi sembol tablosuna erişebilir mi?
cevap
Bu aslında oldukça kolaydır. Sembollere erişmek için dlopen
/dlsym
kullanın. Bunun çalışması için sembollerin dinamik sembol tablosunda bulunması gerekir. Birden fazla sembol tablosu var! Dinamik sembol tablosuna bütün sembolleri eklemek için
#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
kullanın. Sembollerin çoğunu sembol tablosundan kaldırmak (önerilir) istiyorsanız, -fvisibility=hidden
'u ayarlayın ve ardından __attribute__((visibility("default")))
ile istediğiniz sembolleri veya diğer yöntemlerden birini açıkça ekleyin.
~ $ 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)
Emniyet kötü davranış için bir sürü oda olduğunu
dikkat edin.
$ ./a.out printf printf = ▯▯▯▯ (garbage)
bu güvenli olmak istiyorsanız, izin verilen sembollerin bir beyaz liste oluşturmalısınız.
Baskı dışı -string ibly sonlandırılmadı) veri veya dizge olarak işlevler tehlikelidir. Aksi takdirde, sembollerin beyaz listeye alınması gerekmiyor. –
@R ..: Hm, soruyu daha ayrıntılı okuyana kadar değişkenin okuma/yazmada kullanıldığını düşündüm. Güncellenmiş. –
Bu, istediğim şeyin yarısıdır ... sorun şu ki, sembolün türüne bakılmaksızın anlamlı bir şekilde yanıt verebilmek istiyorum. Yani Ya A “uzun” ve B “char” ve C a “char *” ise? Sembol türüne ve adresine erişmem gerekiyor. – JimKleck
özelliği bu tür için genel terim "reflection" olduğunu ve bu hata ayıklama amacıyla ise o C
parçasıdeğildir ve bir C eyaletinin tamamını incelemek isterler Program uzaktan, herhangi bir değişkeni incelemek başlatmak ve yürütme durdurma ve benzeri, aşağıdakileri düşünebilirsiniz GDBremote debugging:
GDB gömülü sistemler ayıklarken sıklıkla kullanılan bir 'uzak' modunu sunar. GDB tek bir makinede çalıştığında ve hata ayıklanmış programında başka bir işlem yürütüldüğünde uzaktan işlem gerçekleştirilir. GDB, Seri veya TCP/IP üzerinden GDB protokolünü anlayan uzak 'saplama' ile iletişim kurabilir. bir saplama programı, GDB ile sağlanan uygun saplama dosyalarına bağlantı kurarak iletişim protokolünün hedef tarafını uygulayarak oluşturulabilir. Alternatif olarak, gdbserver herhangi bir şekilde değiştirmeye gerek kalmadan programı hata ayıklamak için kullanılabilir.
Bu üretim içindir ve bir arama tablosunu sürdürmek zorunda kalmadan herhangi bir simgeye göz atmak istiyorum ... sonuçta bu bilgi zaten sembol tablosundadır. – JimKleck
dosyası: 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;
}
dosyası: reflect.h
#include <stdio.h>
struct sym_table_t {
char *name;
void *addr;
};
void * reflect_query_symbol(const char *name);
dosyası:
sadece #include main.c "yansıtmaktadır.h" ve çağrı reflect_query_symbol
örnek:
#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;
}
dosyası:. 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
Sadece "reflect.c" ve "reflect.h" gibi iki dosya yazmanız ve "Makefile" nizi değiştirmeniz yeterlidir, sembol ismini ve sembolün ilgili adresini alacaktır. –
Sembolün veya adresin yanı sıra en az boyuta sahip bir simge istiyorum. Nm için "-S" bayrağı bunu yapacak gibi görünüyor. Nbl_sym_table için doğru boyutu almak için son çalıştırılabilirde nm'yi çalıştırmam gerekmiyor (birden fazla .o'dan beri), sonra tekrar adreslerle doldurmak için nm'yi tekrar çalıştır mı? Sonra sonunda reflect.o'yu yeniden oluşturun ve hepsini çalıştırılabilir duruma getirin mi? – JimKleck
Aslında, neden nm ve makefile sihirbazlık ile uğraşmak? Nm programı sembol tablosuna erişmek için bir miktar API kullanmalıdır, bu API'nin doğrudan programımda kullanılmasını istiyorum. – JimKleck
- 1. Clojure programı kendi MANIFEST.MF okunurken
- 2. geçerli bir C programı
- 3. Bir Objective-C komut satırı programı bir NSAutoreleasePool gerektirir mi?
- 4. Bir Web API'si ActionFilterAttribute modele erişebilir mi?
- 5. bir program kendi elf bölümünü okuyabilir mi?
- 6. Spring Bean kendi ipliğiyle çalışan
- 7. C++ programı
- 8. python'da C++ programı tokenize
- 9. C++ çözümlenmemiş harici sembol
- 10. yinelenen sembol hatası C++
- 11. Uzak bir makinede çalışan bir işlem mi?
- 12. "Kendi" gerekli mi?
- 13. USB cihazları doğrudan donanımlara erişebilir mi?
- 14. C/C++ Allegro programı alışkanlık
- 15. İç sınıftaki bir yöntem, bir üst sınıf yöntemine erişebilir mi?
- 16. Arkadaş canlısı şablonum, kendi özel üyemden kendi ifadesinden bahsedebilir mi?
- 17. İstemci sunucu programı C
- 18. C++ OpenMP programı
- 19. Çoktan çoğa ilişkilendirme tablosuna silmek mi istiyorsunuz?
- 20. tanımsız sembol: mysql_options
- 21. C#: Kendi karıştırıcımı yazdı; C# öğrenmek amacıyla blackjack programı üzerinde çalışıyorum güverte
- 22. Her işlemin neden kendi sayfa tablosuna ihtiyacı var?
- 23. C kendinden silme programı ++ anlama
- 24. C (kendi) yineleyici türü ++ (STL)
- 25. Gömülü bir Flash nesnesi, ana belgenin DOM'sine erişebilir mi?
- 26. İki farklı denetleyici, mvc'de tek bir görünüme erişebilir mi?
- 27. Çalışan bir python işlemini mi yapıyorsunuz?
- 28. Subpackajların kendi ithalatı ya da değil mi?
- 29. C++ - Kendi akışımı gerçekleştirme
- 30. Heroku'da çalışan gecikmeli işçi mi?
uzaktan hata ayıklama istiyorum için bir internet arama yapın "." uzaktan hata ayıklama linux linkleri Bol – selbie
@selbie : Bu bir şeyleri yapmanın zor yolu. –