2009-10-30 20 views
28

Có một tập hợp các tùy chọn dòng lệnh sẽ thuyết phục gcc tạo ra tệp nhị phân phẳng từ tệp nguồn độc lập không? Ví dụ: giả sử nội dung của foo.c làCó cách nào để có được gcc để sản xuất nhị phân liệu?

static int f(int x) 
{ 
    int y = x*x; 
    return y+2; 
} 

Không có tham chiếu bên ngoài, không có gì để xuất sang trình liên kết. Tôi muốn lấy một tập tin nhỏ chỉ với các hướng dẫn của máy cho chức năng này, không có bất kỳ trang trí nào khác. Sắp xếp giống như tệp .COM .COM ngoại trừ chế độ được bảo vệ 32 bit.

+1

Hai câu trả lời tốt được gửi cùng một lúc. Tôi không biết cái nào để đánh dấu. –

+0

Bạn có thể xem xét chấp nhận [câu trả lời gần đây hơn] (http://stackoverflow.com/a/23502466/1483676) trực tiếp trả lời câu hỏi của bạn (trình biên dịch tinh khiết/câu trả lời liên kết). – cubuspl42

Trả lời

30

Hãy thử điều này:

$ cc -c test.c 
$ objcopy -O binary test.o binfile 

Bạn có thể chắc chắn rằng nó đúng với objdump:

$ objdump -d test.o 
test.o:  file format pe-i386 


Disassembly of section .text: 

00000000 <_f>: 
    0: 55      push %ebp 
    1: 89 e5     mov %esp,%ebp 
    3: 83 ec 04    sub $0x4,%esp 
    6: 8b 45 08    mov 0x8(%ebp),%eax 
    9: 0f af 45 08    imul 0x8(%ebp),%eax 
    d: 89 45 fc    mov %eax,-0x4(%ebp) 
    10: 8b 45 fc    mov -0x4(%ebp),%eax 
    13: 83 c0 02    add $0x2,%eax 
    16: c9      leave 
    17: c3      ret 

Và so sánh với các tập tin nhị phân:

$ hexdump -C binfile 
00000000 55 89 e5 83 ec 04 8b 45 08 0f af 45 08 89 45 fc |U......E...E..E.| 
00000010 8b 45 fc 83 c0 02 c9 c3       |.E......| 
00000018 
+1

Tôi đã bao gồm '-j .text' làm tham số cho' objcopy' để có kết quả chính xác. – SpellingD

+0

Tại sao? Điều gì đã xảy ra khi bạn không làm vậy? –

+0

Nó đã sao chép phần sai (không phải .tiếp theo) từ tệp .o. Phiên bản: 'GNU objcopy phiên bản 2.22.52.0.1-10.fc17 20120131' – SpellingD

15

Bạn có thể sử dụng objcopy để kéo đoạn văn bản ra khỏi tệp .o hoặc tệp a.out.

$ cat q.c 
f() {} 
$ cc -S -O q.c 
$ cat q.s 
     .file "q.c" 
     .text 
.globl f 
     .type f, @function 
f: 
     pushl %ebp 
     movl %esp, %ebp 
     popl %ebp 
     ret 
     .size f, .-f 
     .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3" 
     .section  .note.GNU-stack,"",@progbits 
$ cc -c -O q.c 
$ objcopy -O binary q.o q.bin 
$ od -X q.bin 
0000000 5de58955 000000c3 
0000005 
$ objdump -d q.o 
q.o:  file format elf32-i386 
Disassembly of section .text: 
00000000 <f>: 
    0: 55      push %ebp 
    1: 89 e5     mov %esp,%ebp 
    3: 5d      pop %ebp 
    4: c3      ret  
+1

Bạn dường như đã mất liên kết. –

+0

Cố định, cảm ơn .... – DigitalRoss

11

Các khác câu trả lời chắc chắn con đường để đi. Tuy nhiên, tôi đã phải xác định thêm các đối số dòng lệnh để objcopy để cho đầu ra của tôi được như mong đợi. Lưu ý rằng tôi đang phát triển mã 32 bit trên máy 64 bit, do đó đối số -m32. Ngoài ra, tôi thích cú pháp lắp ráp intel tốt hơn, vì vậy bạn sẽ thấy rằng trong các đối số là tốt.

$ cat test.c 
int main() { return 0; } 
$ gcc -nostdinc -m32 -masm=intel -Wall -c test.c -o test.o 
$ objdump --disassemble --disassembler-options intel test.o 

test.o:  file format elf32-i386 


Disassembly of section .text: 

00000000 <main>: 
    0: 55      push ebp 
    1: 89 e5     mov ebp,esp 
    3: b8 00 00 00 00   mov eax,0x0 
    8: 5d      pop ebp 
    9: c3      ret  

Ok, đây là nơi mà tôi đã xác định rằng tôi đặc biệt chỉ muốn phần .text:

$ objcopy --only-section=.text --output-target binary test.o test.bin 
$ hexdump -C test.bin 
00000000 55 89 e5 b8 00 00 00 00 5d c3 |U.......].| 
0000000a 

Tôi mất khoảng 2 giờ đọc và cố gắng tùy chọn khác nhau trước khi tôi figured this out. Hy vọng rằng điều này giúp người khác tiết kiệm thời gian đó.

9

Bạn có thể vượt qua tùy chọn để mối liên kết trực tiếp với -Wl,<linker option>

Các tài liệu liên quan được sao chép dưới đây từ man gcc

-Wl, tùy chọn
đèo lựa chọn như một tùy chọn để mối liên kết. Nếu tùy chọn chứa dấu phẩy, thì nó được chia thành nhiều tùy chọn tại dấu phẩy. Bạn có thể sử dụng cú pháp này để chuyển đối số cho tùy chọn. Ví dụ: -Wl, -Map, output.map chuyển đầu ra -Map.ap vào trình liên kết. Khi sử dụng trình liên kết GNU, bạn cũng có thể có được hiệu ứng tương tự với -Wl, -Map = output.map.

Vì vậy, khi biên soạn với gcc nếu bạn vượt qua -Wl,--oformat=binary, bạn sẽ tạo tệp nhị phân thay vì định dạng elf. Trong đó --oformat=binary yêu cầu ld tạo tệp nhị phân.

Điều này sẽ loại bỏ sự cần thiết phải objcopy riêng biệt.

Lưu ý rằng --oformat=binary có thể được biểu thị là OUTPUT_FORMAT("binary") từ trong một linker script.Nếu bạn muốn đối phó với các tệp nhị phân phẳng, có nhiều khả năng bạn sẽ được hưởng lợi từ mức kiểm soát cao mà các trình liên kết cung cấp.

+0

Trên thực tế câu trả lời này là câu trả lời thực sự hợp lệ duy nhất ở đây ... Tôi muốn nói rằng những người khác là cách giải quyết chấp nhận được. – cubuspl42

+0

Để tham khảo trong tương lai: giải pháp '--oformat = binary' dường như phát ra mã máy không đúng trong một số trường hợp * hoặc * Tôi không biết điều gì, nhưng nếu bạn gặp phải một số hành vi kỳ lạ của các ký hiệu bên ngoài, hãy thử 'objcopy' giải pháp. – cubuspl42

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