Kodunuzun düzgün çalıştığından ve en sonunda sorun yaşadığından şüpheleniyorum: a++
'dan sonra ne olur?
mymain()
, arayana geri dönmeyi deneyecek sıradan bir C işlevidir.
Ancak, ELF giriş noktası olarak ayarladığınıza göre, ELF yükleyicisine program bölümlerini doğru yere yükledikten sonra atlayabileceğini söyler ve geri dönmenizi beklemez. Bu "crt1.o
, crti.o
ve gibi diğer nesne dosyaları ve" crtn.o
", bu tür C programlarında normal olarak kullanılır. Bir C programı için ELF giriş noktası, main()
değil - bunun yerine, main()
için uygun bir ortam oluşturan bir sarmalayıcıdır (örneğin, platforma bağlı olarak veya kayıt defterinde argc
ve argv
argümanlarını ayarlama), main()
çağrıları (geri dönebileceği beklentisi ile) ve daha sonra exit
sistem çağrısını (main()
'dan geri dönüş koduyla) çağırır.
[Güncelleme aşağıdaki yorumlar:]: mymain
bir kesme noktası ayarlandıktan sonra, sonra atlama Ben gdb
ile örnek çalıştığınızda
, ben gerçekten mymain()
dönen başarısız oluyor görüyoruz
$ gcc -g -c main.c
$ ld -o prog -T my_script.lds main.o
$ gdb ./prog
...
(gdb) b mymain
Breakpoint 1 at 0x10006: file main.c, line 4.
(gdb) r
Starting program: /tmp/prog
Breakpoint 1, mymain() at main.c:4
4 a++;
(gdb) display/i $pc
1: x/i $pc
0x10006 <mymain+6>: addl $0x1,-0x4(%ebp)
(gdb) si
5 }
1: x/i $pc
0x1000a <mymain+10>: leave
(gdb) si
Cannot access memory at address 0x4
(gdb) si
0x00000001 in ??()
1: x/i $pc
Disabling display 1 to avoid infinite recursion.
0x1: Cannot access memory at address 0x1
(gdb) q
: talimatlar, o zaman fonksiyon sonsözünde sorun içine alır, bu artışı gerçekleştiren görüyoruz
En azından i386 için, yüklenen kodu girmeden önce ELF yükleyici hassas bir yığın oluşturur, böylece ELF giriş noktasını bir C işlevine ayarlayabilir ve makul bir davranış elde edebilirsiniz; Ancak, yukarıda belirttiğim gibi, temiz bir proses çıkışını kendiniz halletmelisiniz. C çalışma zamanını kullanmıyorsanız, C çalışma zamanına bağlı olan herhangi bir kütüphaneyi kullanmamanız daha iyi olur.a
nihai değer olarak sahip ama bilinen bir değere a
sıfırlayabilirsiniz ve bir exit
sistem çağrısı çağırmak için modifiye C kodu ile (satır içi montaj kullanarak) -
Yani burada orijinal bağlayıcı script kullanarak, bu bir örnektir çıkış kodu. (Not: Kullandığınız platformun tam olarak ne olduğunu söylemediniz, Linux'u burada görüyorum.)
$ cat main2.c
void mymain(void)
{
int a = 42;
a++;
asm volatile("mov $1,%%eax; mov %0,%%ebx; int $0x80" : : "r"(a) : "%eax");
}
$ gcc -c main2.c
$ ld -o prog2 -T my_script.lds main2.o
$ ./prog2 ; echo $?
43
$
Anwser için teşekkürler Matthew. Programın başlangıçta kilitlendiğini söylüyorum çünkü gdb bunu söylüyor ... 'Ana' işlevinin daha önce çağrıldığını biliyorum, örneğin sandığım sanırım. Ama eğer 'ana' için başka bir isim yaparsam, bunu nerede belirtmeliyim? Ve eğer programımı açıkça 'ld' ile bağlarsam c çalışma zamanı nesne dosyalarını da geçmeliyim? – MirkoBanchi
Neye ulaşmaya çalışıyorsunuz? Normal C çalışma zamanını ve kitaplıklarını kullanmak mı istiyorsunuz? Eğer öyleyse, ana işleviniz 'ana' olarak adlandırılmalıdır: C çalışma zamanı çağrıları budur. (Bu normalde 'crt1.o'da _start' olan ELF giriş noktasıyla aynı şey değildir.) ' ld' doğrudan çağırıyorsanız, o zaman, çeşitli C çalışma zamanı dosyalarını kendiniz bağlamanız gerekir. Eğer 'gcc' kullanıyorsanız, bunu sizin için yapacak. Gcc -v ile ne yaptığını görebiliyorsunuz, ancak 'ld' yi bir sarmalayıcı, 'topla2' ile çağırdığını bilmeniz gerekiyor (bkz. [Here] (http://gcc.gnu.org/onlinedocs/gcc) -4.6.1/gccint/Collect2.html)). –
Mümkünse, c çalışma zamanı nesneleri dosyalarına bağlamadan doğru şekilde çalışan bir çalıştırılabilir (ELF formatı) oluşturulabileceğini bilirim. – MirkoBanchi