2009-06-30 22 views
15

Soạn ra một mô-đun hạt nhân trên 32-Bit kết quả Linux kernel trong__udivdi3 undefined - cách tìm mã sử dụng mã đó?

"__udivdi3" [mymodule.ko] undefined! 
"__umoddi3" [mymodule.ko] undefined! 

Mọi thứ đều tốt trên hệ thống 64-bit. Theo như tôi biết, lý do cho điều này là phân chia số nguyên 64 bit và modulo không được hỗ trợ bên trong hạt nhân Linux 32 bit.

Tôi làm cách nào để tìm mã phát hành các hoạt động 64 bit. Chúng khó tìm bằng tay vì tôi không thể dễ dàng kiểm tra xem "/" có rộng 32 bit hay rộng 64 bit không. Nếu các hàm "bình thường" không xác định, tôi có thể grep chúng, nhưng điều này là không thể ở đây. Có cách nào khác tốt để tìm kiếm các tài liệu tham khảo? Một số loại "mã máy grep"?

Mô-đun này bao gồm một số nghìn dòng mã. Tôi thực sự không thể kiểm tra từng dòng một cách thủ công.

Trả lời

19

Trước tiên, bạn có thể thực hiện phân chia 64 bit bằng cách sử dụng macro do_div. (Lưu ý các nguyên mẫu là uint32_t do_div(uint64_t dividend, uint32_t divisor) và rằng "dividend" chưa được đánh giá nhiều lần.

{ 
    unsigned long long int x = 6; 
    unsigned long int y = 4; 
    unsigned long int rem; 

    rem = do_div(x, y); 
    /* x now contains the result of x/y */ 
} 

Ngoài ra, bạn sẽ có thể hoặc là tìm cách sử dụng của long long int (hoặc uint64_t) các loại trong mã của bạn, hoặc luân phiên, bạn có thể xây dựng mô-đun của bạn với -g cờ và sử dụng objdump -S để có được một nguồn tháo chú thích

lưu ý:. này áp dụng đối với hạt nhân 2.6, tôi đã không kiểm tra việc sử dụng cho bất cứ điều gì thấp

+9

để thêm một chút thông tin, do_div() được xác định trong tiêu đề . –

+1

Có vẻ như vô lý khi Linux khăng khăng làm cho bạn sử dụng một chức năng xấu xí để phân chia, thay vì chỉ thực hiện '__udivdi3' vv. Chúng dễ thực hiện, và nếu bạn làm điều đó, chúng sẽ hiệu quả hơn nhiều Các phiên bản của libgcc (có thể nhanh hơn 2-3 lần). –

+0

@WilliBallenthin ngay cả sau khi sử dụng , đối mặt với vấn đề này.Vì vậy, bất kỳ ai đề xuất tôi cần phải làm gì để giải quyết vấn đề này? –

2

Sau giai đoạn biên dịch, bạn sẽ có thể nhận được một số tập hợp được ghi lại và thấy rằng các chức năng đó được gọi. Cố gắng gây rối với CFLAGS và thêm cờ -S. Biên soạn phải dừng ở giai đoạn lắp ráp. Sau đó, bạn có thể grep cho cuộc gọi hàm vi phạm trong tệp assembly.

1

Thực ra, số nguyên divi 64 bit và modulo được hỗ trợ trong hạt nhân Linux 32 bit; tuy nhiên, bạn phải sử dụng các macro chính xác để làm như vậy (các macro phụ thuộc vào phiên bản hạt nhân của bạn, vì các phiên bản mới hơn đã được tạo ra IIRC). Các macro sẽ làm điều đúng theo cách hiệu quả nhất cho bất kỳ kiến ​​trúc nào bạn đang biên dịch.

Cách dễ nhất để tìm nơi chúng đang được sử dụng là (như đã đề cập trong câu trả lời của @ shodanex) để tạo mã lắp ráp; IIRC, cách để làm như vậy là một cái gì đó giống như make directory/module.s (cùng với bất kỳ thông số nào bạn đã phải vượt qua để make). Cách dễ nhất tiếp theo là để tháo rời tệp .o (với một cái gì đó như objdump --disassemble). Cả hai cách sẽ cung cấp cho bạn các chức năng mà các cuộc gọi đang được tạo ra (và, nếu bạn biết cách đọc lắp ráp, một ý tưởng chung về vị trí trong phạm vi chức năng phân chia đang diễn ra).

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