Tôi đang cố gắng hiểu rõ mã thực thi mà GCC (4.4.3) đang tạo cho máy x86_64 chạy trên Ubuntu Linux. Đặc biệt, tôi không hiểu cách mã theo dõi các khung ngăn xếp. Trong những ngày cũ, trong mã 32-bit, tôi đã quen với việc nhìn thấy điều này "mở đầu" trong chỉ là về tất cả các chức năng:x86_64 quy ước gọi và ngăn xếp khung
push %ebp
movl %esp, %ebp
Sau đó, vào cuối của hàm, sẽ đến một "lời bạt," hoặc
sub $xx, %esp # Where xx is a number based on GCC's accounting.
pop %ebp
ret
hoặc đơn giản là
leave
ret
mà hoàn thành được điều tương tự:
- Đặt Con trỏ ngăn xếp ở trên cùng của khung hiện tại, ngay bên dưới địa chỉ trả lại
- Khôi phục giá trị Con trỏ khung cũ.
Trong mã 64 bit, như tôi thấy thông qua việc tháo gỡ objdump, nhiều chức năng không tuân theo quy ước này - chúng không đẩy% rbp và sau đó lưu% rsp thành% rbp, Trình gỡ lỗi như thế nào GDB xây dựng một backtrace?
Mục tiêu thực sự của tôi ở đây là cố gắng tìm ra một địa chỉ hợp lý để xem xét ở vị trí trên cùng (địa chỉ cao nhất) của ngăn xếp người dùng khi thực thi đạt đến chức năng tùy ý trong chương trình, nơi có thể là Stack Pointer đã di chuyển xuống. Ví dụ, đối với "top", địa chỉ ban đầu của argv sẽ là lý tưởng - nhưng tôi không có quyền truy cập vào nó từ một hàm tùy ý mà các cuộc gọi chính. Lúc đầu tôi nghĩ rằng tôi có thể sử dụng phương pháp backtrace cũ: theo đuổi giá trị Frame Pointer đã lưu cho đến khi giá trị được lưu là 0 - sau đó, giá trị tiếp theo sau đó có thể được tính là giá trị thực tế cao nhất. (Điều này không giống như nhận địa chỉ của argv, nhưng nó sẽ làm - giả sử, để tìm ra giá trị Stack Pointer tại _start hoặc bất kỳ lệnh gọi _start nào [ví dụ, __libc_start_main].) Bây giờ, tôi không biết làm thế nào để lấy địa chỉ tương đương trong mã 64 bit.
Cảm ơn.
Thật vậy. Và nó không chỉ với '-fomit-frame-pointer'. –
Bạn đã thử -fno-omit-frame-pointer chưa? Bạn có thể biên dịch mã khác với lá cờ đó không? –
Mã nguồn để 'libunwind' có thể hữu ích. – Nemo