2012-03-20 9 views
6

Linux altında arm-eabi-gcc ile derlenen bir C programı üzerinde çalışıyoruz.Yapı dökümündeki bir alanın göreli adresi nasıl alınır. [C]

Büyük bir yapının dökümünü kullanıyoruz ve yapımızın çeşitli alanlarını (50 tanesi gibi) okumamız gereken adresi belirleme konusunda problemler yaşıyoruz (bellek hizalama ve dolgulama bu kadar öngörülemez ben mi).

Derleyicimizin ürettiği yapının bellek eşlemesini elde etmenin bir yolu var mı? Gdb bir seçenek? Veya çöplükteki alanlar ile adres arasındaki uygunluğu bulmamıza yardımcı olan herhangi bir araç mı?

+0

Muhtemelen burada bariz bir şey eksik, ama bir yapı örneği (veya yapısına bir işaretçi) olarak bildirilen bir değişkeniniz varsa ('x' diyelim), o zaman sadece yazabilmeniz gerekir. Tüm üyeleri boşaltmak için gdb’de x' (ya da 'işaretçi x''se işaretçi) yazdırın. –

+0

Ben dökmek istediğimin adresini almaya çalışmıyorum. Zaten çöplüğüm var ve tüm üyelerin göreli adresine ihtiyacım var. – Akhneyzar

cevap

23

Sen gdb ile bunu yapabilirsiniz. gdb yılında

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

int main() { 
    struct A a; 
} 

ikili yukarı yükleme: Örnek olarak, ben bu kaynağı kullanacağız

(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 

GÜNCELLEME: Eğer çok sayıda için bunu yapmak gerekiyorsa

alanların daha sonra GDB'nin yeni python arayüzünü kullanmak için kullanışlı bulabilirsin (bunu kullanmak için GDB'nin yeni bir sürümüne ihtiyacınız olacak, 7.4 kullanıyorum). Ben offsets.py oluşturduk: gibi, GDB kullanmadan Sonra

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

:

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

Bu komut bir hale getirir

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() 

Sonra .gdbinit ekleyebileceğiniz varsayımları basitleştirerek, bitfields kullanmamanız gibi, ve iç içe geçmiş yapıları kazmıyorsunuz, ancak bu değişiklikler, ihtiyaç duyduğunuzda oldukça basittir.

+0

Altında duruyorum ama oradaki 50 gerekli alan gibi listelemek istiyorum. – Akhneyzar

+0

Bunun daha eksiksiz bir versiyonunu yaptım, ilham için teşekkürler. [Clicky] (https://github.com/Craxic/PyGDBOffsets/blob/master/offsets.py) – AStupidNoob

+0

Sizin '.gdbinit' tuhaf görünüyor. Neden source/path/to/script/dir/offsets.py' – zhangyoufu

-1

bu derleme durumda bayt ofset hesaplamak için gerekli alanları

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

için böyle bir kod biraz yazabilirsiniz Bana kalırsa. Bu, herhangi bir uyum için hesap gerektiğini

derleyici sahiptir verir.

+0

Ancak 50 alan veya daha fazla verim eksik. – Akhneyzar

+0

Bu derleme değil: pointer arithmetics bir işaretçiyi bir işaretçiden X'e çıkarmanıza izin vermez. –

2

stddef.h numaralı belgede tanımlanan standart offsetof() makrosunu kullanarak bir C programından yapabilirsiniz. Ancak, istediğinizi bu olduğundan emin değilim, çünkü onu çalıştıramıyor olabilirsiniz (sunucuda derlemek, muhtemelen yanlış ofsetleri döndürecektir).

#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; 
} 

Ancak, bunu uygulamadan bir derlenmiş ikili ofset almak için bazı hacks istihdam mümkün olabilir. Belki bir statik değişken ofset değerini atayın ve değerini elde etmenin bir yolunu bulun.