Tôi muốn viết chương trình C sẽ in nội dung của bộ đếm chương trình PC
. Điều này có thể được thực hiện từ không gian người dùng, hoặc lắp ráp, hoặc một số thói quen hạt nhân cụ thể được sử dụng?Cách in giá trị chính xác của bộ đếm chương trình trong C
Trả lời
Bạn sẽ có thể xác định máy tính bằng cách sử dụng các __current_pc()
intrinsic trong trình biên dịch ARM toolchain (trình biên dịch ARM hỗ trợ nhiều của cùng một phần mở rộng như GCC). * Đây là đặc biệt đến ARM:
int main() {
printf("%#x\n", __current_pc());
printf("%#x\n", __current_pc());
printf("%#x\n", __current_pc());
return 0;
}
* Nhờ FrankH. để chỉ ra sự hiện diện của
__current_pc()
Nói chung, PC được lưu làm địa chỉ trả lại trong cuộc gọi hàm. Trên các hệ thống không phải ARM linux với GCC, bạn có thể gọi __builtin_return_address(0)
để lấy địa chỉ trả về của ngữ cảnh cuộc gọi hàm hiện tại. Việc truy cập bộ đếm chương trình theo cách này sẽ gây ra hình phạt khi thêm một cuộc gọi hàm, nhưng nó tránh việc lắp ráp nội tuyến, vì vậy kỹ thuật này có thể di chuyển đến bất kỳ hệ thống nào được GCC hỗ trợ.
void * get_pc() { return __builtin_return_address(0); }
int main() {
printf("%p\n", get_pc());
printf("%p\n", get_pc());
printf("%p\n", get_pc());
return 0;
}
Khi tôi chạy chương trình trên trên hệ thống x86
của tôi, nó tạo ra kết quả:
0x8048432
0x8048447
0x804845c
Khi tháo rời trong gdb
:
Dump of assembler code for function main:
0x08048424 <+0>: push %ebp
0x08048425 <+1>: mov %esp,%ebp
0x08048427 <+3>: and $0xfffffff0,%esp
0x0804842a <+6>: sub $0x10,%esp
0x0804842d <+9>: call 0x804841c <get_pc>
0x08048432 <+14>: mov %eax,0x4(%esp)
0x08048436 <+18>: movl $0x8048510,(%esp)
0x0804843d <+25>: call 0x80482f0 <[email protected]>
0x08048442 <+30>: call 0x804841c <get_pc>
0x08048447 <+35>: mov %eax,0x4(%esp)
0x0804844b <+39>: movl $0x8048510,(%esp)
0x08048452 <+46>: call 0x80482f0 <[email protected]>
0x08048457 <+51>: call 0x804841c <get_pc>
0x0804845c <+56>: mov %eax,0x4(%esp)
0x08048460 <+60>: movl $0x8048510,(%esp)
0x08048467 <+67>: call 0x80482f0 <[email protected]>
0x0804846c <+72>: mov $0x0,%eax
0x08048471 <+77>: leave
0x08048472 <+78>: ret
End of assembler dump.
địa chỉ trả lại và PC ('EIP' /' RIP') là _not_ cùng một điều. –
xin lỗi, trong ARM tôi nên nói, địa chỉ trả về ('LR') và' PC' là _not_ cùng một điều. –
Và nhiều hơn nữa ... lý do tại sao bạn làm việc là vì bạn _force một hàm call_ (mà làm cho 'LR' trong func của bạn' PC' của trang gọi). Đây là _không cần thiết. –
Tôi nghĩ bạn có thể lấy thông tin bằng cách chèn các khối lắp ráp bên trong mã C của bạn. Điều này sẽ hoàn toàn phụ thuộc vào trình biên dịch của bạn và bộ đăng ký của nền tảng của bạn. tôi đã làm nó như thế này:
int get_counter1()
{
__asm__ ("lea (%rip), %eax ") ;
}
int get_counter2()
{
int x = 0;
__asm__ ("lea (%rip), %eax") ;
}
int main()
{
printf("%x\n",get_counter1());
printf("%x\n",get_counter2());
return 0;
}
4004ce
4004e1
On ARM, bạn có thể sử dụng:
static __inline__ void * get_pc(void) {
void *pc;
asm("mov %0, pc" : "=r"(pc));
return pc;
}
Hoặc cái này nên làm việc cũng như:
static __inline__ void * get_pc(void) {
register void * pc __asm__("pc");
__asm__("" : "=r"(pc));
return pc;
}
Các nội tuyến buộc là quan trọng ở đây, bởi vì đó đảm bảo bạn lấy PC
theo trang web của cuộc gọi.
Chỉnh sửa: chỉ cần nhớ, __current_pc()
ARM intrinsic. GCC cũng nên có điều này.
- 1. Bộ đếm chương trình?
- 2. ARM Cortex M3 Làm cách nào để xác định giá trị bộ đếm chương trình trước một lỗi cứng?
- 3. Tại sao C in các giá trị hex của tôi không chính xác?
- 4. Lô đếm chính mỗi đếm giá trị duy nhất trong gấu trúc
- 5. Giá trị R chính xác trong C++ là gì?
- 6. Bảng phân vùng in - Chương trình C
- 7. Giá trị chính xác 4 giá trị chính xác, các bộ tách riêng và lôgarit ma trận
- 8. In tên và giá trị của macro
- 9. Cách tạo chương trình có 2 giá trị khác nhau của biến trong CMake
- 10. cặp giá trị chính trong C# Params
- 11. Cache Hit/Miss cho một giá trị trong C/C++ Chương trình
- 12. Chương trình đếm từ trong Hive
- 13. cách chính xác để chạy các chương trình setuid trong C
- 14. Cách in thời gian tới 6 chữ số chính xác cho giá trị giây
- 15. Kiểm tra giá trị trả về của chương trình C trong tập lệnh bash?
- 16. đếm chính xác trong C++ nghĩa là gì ?,
- 17. Làm cách nào để in toàn bộ giá trị của chuỗi dài trong gdb?
- 18. đếm giá trị chỉ truthy trong một bộ sưu tập
- 19. theano - giá trị in của TensorVariable
- 20. Nhận các dấu chính xác từ bộ đếm thời gian trong C#
- 21. Làm cách nào để in nội dung của ngăn xếp trong chương trình C?
- 22. Tôi nên làm gì để có được toàn bộ giá trị trả về của chương trình c từ dòng lệnh?
- 23. Bộ đếm hiệu suất chính xác để nhận CPU và sử dụng bộ nhớ của một quy trình là gì?
- 24. Đặt bộ nhớ cache đầu ra của trang VaryByTùy chỉnh giá trị theo chương trình
- 25. Giá trị băm và giá trị băm in của Ruby
- 26. Cách xác định trong LaTeX một bộ đếm mới bao gồm số chương?
- 27. luận đèo từ csh chương trình, chính xác như họ
- 28. cách truy cập giá trị Bộ đếm Mapper trong Bộ giảm tốc?
- 29. Làm cách nào để tìm hàm chính (...) của chương trình?
- 30. JDT Eclipse: Gọi 'thụt lề chính xác' theo chương trình?
Điều khiển mã của trình gỡ lỗi/truy cập PC nên có cách tôi nghĩ bằng cách sử dụng lắp ráp nội tuyến. –
@GrijeshChauhan: Bạn có nghĩ rằng có thể có phần mở rộng GCC cho bộ đếm chương trình không? –
Có, tôi không chắc lắm nhưng tôi cảm thấy có một số cách để giải quyết vấn đề này: nếu trong một đoạn mã bạn có một 'lable:' thì bạn có thể in địa chỉ của nó bằng '& lable' (điều này làm cho tôi nói có). Mã rất phía sau (hợp pháp) sử dụng loại hướng dẫn này nhưng thường sử dụng trong mã phần mềm độc hại để một Tính năng tốt của nó. –