2009-12-18 19 views
14

Có thể nào đó có thể bắt được các lỗi liên kết dữ liệu ngay cả trên i386 không? Có lẽ bằng cách thiết lập một máy tính đăng ký i386 cụ thể hoặc một cái gì đó như thế.x86: cách nắm bắt các lỗi liên kết dữ liệu (còn gọi là SIGBUS trên sparc)

Trên Solaris-Sparc Tôi nhận được SIGBUS trong trường hợp này, nhưng trên i386 mọi thứ đều ổn.

Môi trường:

  • 32-bit ứng dụng
  • Ubuntu Karmic
  • gcc/g ++ v4.4.1

EDIT: Dưới đây là lý do tại sao tôi yêu cầu này:

  • ứng dụng của chúng tôi gặp sự cố trên Sol-Sparc với SIGBUS. Đối với mục đích gỡ lỗi, tôi sẽ cố gắng để có được một hành vi tương tự trên nền tảng i386 của chúng tôi.
  • Máy Sol-sparc của chúng tôi rất chậm, do đó việc biên dịch và gỡ lỗi mất rất nhiều thời gian ở đó. Và máy i386 của chúng tôi là không thể tin được nhanh (8 lõi, bộ nhớ 32G).
  • Ngay cả trên nền tảng i386 có chi phí hoạt động trên các lỗi liên kết dữ liệu. Và do đó tôi muốn sửa các lỗi liên kết dữ liệu bất cứ khi nào có thể.
+0

Có vẻ như chạy thử nghiệm của bạn trong 'qemu' (có thể nhắm mục tiêu SPARC) có thể nhanh hơn chạy trên phần cứng thực tế? – ephemient

+0

Tôi chưa bao giờ thử qemu, nhưng điều đó nghe có vẻ thú vị. Điều đó làm việc mà không có một số loại "System-ROM" hoặc một cái gì đó tương tự? –

+1

Dự án QEMU bao gồm 'openbios-sparc', đủ để cho' qemu-system-sparc' giống như một cỗ máy thực sự. Ngoài ra còn có 'qemu-sparc' chỉ chạy một tập tin thực thi Linux duy nhất trong mô phỏng, dịch các syscalls thành kernel nguyên gốc. – ephemient

Trả lời

3

Để mở rộng câu trả lời của Vokuhila-Oliba, hãy xem chủ đề "SOF Mis-aligned pointers on x86." có vẻ như gcc có thể tạo mã có quyền truy cập bộ nhớ liên kết sai. AFAIK bạn không có quyền kiểm soát điều này.

Bật kiểm tra căn chỉnh trên mã được biên dịch gcc sẽ là một ý tưởng tồi. Bạn có nguy cơ gặp lỗi SIGBUS đối với mã số tốt C.

Đã chỉnh sửa: Xin lỗi về điều đó

+0

@alexandre: I * muốn * để nhận các lỗi SIGBUS này. Không phải trong mã sản xuất của khóa học, nhưng chỉ để gỡ lỗi. –

+3

Bạn có nguy cơ gặp SIGBUS cho mã __work trên SPARC__. Dường như x86 gcc thực hiện truy cập sai ở những nơi như khởi tạo biến và tôi không chắc chắn bạn có thể thay đổi hành vi đó. –

+0

@alexandre: bạn đã đúng!Câu trả lời thứ hai của tôi cho thấy cách kiểm tra lỗi liên kết trên i386. Nhưng mã này hoạt động hoàn hảo trên Sparc. Trên i386 nó nhận SIGBUS. Hành vi của GCC cho i386 có thể được thay đổi bằng cách sử dụng ví dụ: thuộc tính __ ((liên kết (sizeof (char *)))). Nhưng nó không thể làm điều đó trên toàn cầu bằng cách thiết lập một lá cờ GCC toàn cầu. Chỉ có thể cài đặt __attribute riêng lẻ trên một mục dữ liệu. Và đó là quá nhiều nỗ lực cho dự án tôi đang làm việc :-( –

0

Intel tích hợp sẵn công nghệ chuyển không được ký hiệu ngay từ đầu - đó là một trong những điểm bán khi x86 là thương hiệu mới. Tôi hiểu lý do của bạn vì muốn bẫy truy cập chưa được ký, nhưng tôi không nghĩ rằng điều đó là có thể.

Chỉnh sửa: rất vui khi được chứng minh là sai.

+0

bạn không hoàn toàn sai. Mặc dù SIGBUS có thể bị ép buộc ngay cả trên i386, nó không giúp ích gì nhiều. Đó là bởi vì trên SPARC, "ngăn xếp sai lệch" không được coi là có hại và không gây ra SIGBUS. Nhưng trên i386 nó gây ra SIBGUS ngay cả đối với một vô hại "ngăn xếp mis-alignment" khi cờ AC được thiết lập. –

7

Trong khi đó, tôi tìm thấy tài liệu CPU Intel giải quyết chủ đề này.

Xem Intel® 64 and IA-32 Architectures Software Developer’s Manual.

Có vẻ như rất khó để kết hợp tất cả nội dung này với nhau. Tuy nhiên nó không có vẻ như nó là hoàn toàn không thể. Chương thú vị là 4.10.5 Kiểm tra Alignment

EDIT (một số tài liệu đặc từ các tài liệu đề cập):

trang 5-60

Interrupt 17 Alignment Check Exception (#AC) 

to enable alignment checking, the following conditions must be true: 

AM flag is set(bit 18 of control regisster CR0) 
AC flag is set (bit 18 of the EFLAGS) 
The CPL is 3 (protected mode or virtual-8086 mode). 

thêm - trong 14.8.2.6 - Lỗi bộ điều khiển bộ nhớ được đề cập. Tôi không biết nếu nó chỉ giống nhau nói cách khác:

table 14-11, Encoding of MMM and CCCC Sub-Fields 
Address/Command Error AC 011 
+0

Thật không may, tất cả mã chế độ người dùng đều chạy ở vòng 3; ở trên sẽ không tạo ra ngoại lệ. – ephemient

+0

Tôi thiếu kiến ​​thức về các "vòng" CPU này. Nhưng nếu một chương trình bình thường sử dụng ring-3 thì nó sẽ là đủ tốt. –

+0

Xin lỗi, tôi đã đọc sai trước đó; "Bộ xử lý không tạo ra ngoại lệ liên kết khi hoạt động ở mức đặc quyền 0, 1 hoặc 2" chắc chắn sẽ bỏ chuông 3 rõ ràng. – ephemient

3

Tôi đã tìm thấy một giải pháp rất đơn giản trên SOF! Xem: Mis-aligned pointers on x86.

int main(int argc, char **argv) 
{ 
# if defined i386 
    /* EDIT: enable AC check */ 
    asm("pushf; " 
    "orl $(1<<18), (%esp); " 
    "popf;"); 
# endif 

    char d[] = "12345678"; /* yep! - causes SIGBUS even on Linux-i386 */ 
    return 0; 
} 

Nhưng tôi phải thú nhận rằng tôi không hiểu tại sao sự phân công

char d [] = "12345678";

được giả định là căn chỉnh sai?

EDIT:

trên máy SPARC không có SIGBUS trên dòng gán để char d [].

2

Intel rất lớn về hỗ trợ tải không được căn chỉnh. Nếu tôi phải phát hiện các tải như vậy trên nền tảng Intel, tôi nghĩ rằng tôi sẽ phải sửa đổi valgrind để xử lý các tải không được gán dưới dạng lỗi. Một sửa đổi như vậy không phải là tầm thường, nhưng valgrind được thiết kế với ý tưởng rằng người dùng có thể tạo ra 'công cụ' mới. Tôi nghĩ rằng một sửa đổi đơn giản đối với công cụ memcheck sẽ phát hiện các tham chiếu chưa được căn chỉnh của bạn. Và báo cáo lỗi thực sự rất hay.

0

Nhiều năm sau: nếu gcc/clang của bạn đủ mới (GCC 4.9, clang 3.3?), Bạn có thể xây dựng mã của mình bằng trình khử trùng hành vi không xác định (-fsanitize=undefined) để nhận cảnh báo về truy cập không đúng trên nền tảng đã cho (nhưng nhớ rằng các nền tảng khác nhau có yêu cầu liên kết khác nhau, các trình biên dịch khác nhau sẽ chọn các bố cục khác nhau, v.v.). Xem https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.htmlhttps://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ để biết chi tiết.

Các vấn đề liên quan