Что обозначают выходные метки сборки gcc? - PullRequest
5 голосов
/ 21 марта 2012

Я написал простую программу на C test.c:

#include <stdio.h>
#include <stdlib.h>
int add(int a, int b);
int main()
{
    int i=5,j=10;
    int result;
    result = add(i, j);
    printf("result is %d\n", result);
}
int add(int a, int b)
{
    return (a + b);
}

и скомпилировал ее:

gcc -S -Os -o test.s test.c 

и получил файл сборки test.s:

        .file   "test3.c"
    .section    .rodata
.LC0:
    .string "result is %d\n"
    .text
.globl main
    .type   main, @function
main:
.LFB5:
    pushq   %rbp
.LCFI0:
    movq    %rsp, %rbp
.LCFI1:
    subq    $16, %rsp
.LCFI2:
    movl    $5, -12(%rbp)
    movl    $10, -8(%rbp)
    movl    -8(%rbp), %esi
    movl    -12(%rbp), %edi
    call    add
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    leave
    ret
.LFE5:
    .size   main, .-main
.globl add
    .type   add, @function
add:
.LFB6:
    pushq   %rbp
.LCFI3:
    movq    %rsp, %rbp
.LCFI4:
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -8(%rbp), %eax
    addl    -4(%rbp), %eax
    leave
    ret
.LFE6:
    .size   add, .-add
    .section    .eh_frame,"a",@progbits
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .string "zR"
    .uleb128 0x1
    .sleb128 -8
    .byte   0x10
    .uleb128 0x1
    .byte   0x3
    .byte   0xc
    .uleb128 0x7
    .uleb128 0x8
    .byte   0x90
    .uleb128 0x1
    .align 8
.LECIE1:
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB5
    .long   .LFE5-.LFB5
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI0-.LFB5
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI1-.LCFI0
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE1:
.LSFDE3:
    .long   .LEFDE3-.LASFDE3
.LASFDE3:
    .long   .LASFDE3-.Lframe1
    .long   .LFB6
    .long   .LFE6-.LFB6
    .uleb128 0x0
    .byte   0x4
    .long   .LCFI3-.LFB6
    .byte   0xe
    .uleb128 0x10
    .byte   0x86
    .uleb128 0x2
    .byte   0x4
    .long   .LCFI4-.LCFI3
    .byte   0xd
    .uleb128 0x6
    .align 8
.LEFDE3:
    .ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)"
    .section    .note.GNU-stack,"",@progbits

Я понимаю все эти инструкции, но я действительно не понимаю, что означают эти ярлыки..LC0, .LFB5, .LCFI0, .LCFI1, .LCFI2, .LFE5, ... Эти ярлыки генерируются автоматически gcc.Зачем нужны эти ярлыки?Кажется, что некоторые метки являются избыточными.

  • gcc версия: 4.1.2
  • машина: x86_64

Ответы [ 2 ]

5 голосов
/ 21 марта 2012

Компилятор сгенерирует метку для любого места, где он должен ссылаться на адрес, будь то инструкция перехода или перехода, или для местоположения данных.

Компилятору не нужно создавать интуитивноименованные метки, поскольку на них ссылается только код, который он генерирует и не имеет видимости для конечного пользователя, поэтому он генерирует более или менее последовательно именованные метки со схемой, предотвращающей случайное создание одной и той же метки для двух разных местоположений.

Нет абсолютно никаких недостатков в маркировке одного и того же местоположения двумя (или более) метками, поэтому нет попытки избежать этого.Вот почему есть несколько мест с двумя последовательными метками без промежуточных операций.

Если вы действительно хотите узнать, что означают, например, серии LCx и LFBx, прочитайте исходный код компилятора .Это нетривиальная кодовая база, поэтому ожидайте потратить часы, просто ища соответствующий модуль.


Я принял вызов, поэтому, имея некоторый опыт написания компиляторов, я нашел модуль /trunk/gcc/dwarf2out.c, который, кажется, генерирует имена меток, используя ту же стратегию.Посмотрите вокруг строки 250 для кратких подсказок о том, что означают символы.Большая часть этого модуля определяет метки, но его длина составляет почти 23 000 строк, поэтому он вполне может проверить ваше любопытство.

1 голос
/ 21 марта 2012

Попробуйте gcc -fverbose-asm -fdump-tree-all -S -Os -o test.s test.c, чтобы получить гораздо больше информации, особенно много файлов "dump" test.c.*, содержащих частичное представление внутренних представлений GCC.

Не смущайтесь явно бесполезными ярлыками. Я думаю, что GCC может генерировать один для каждого базового блока.

Напомним, что GCC много работает над внутренними представлениями (Gimple, Tree), особенно. Проходы оптимизации (их сотни) значительно модифицируют эти внутренние представления. Большинство оптимизаций находятся на среднем уровне, работают на Gimple и т.д ...

Мои слайды на http://gcc -melt.org / содержат немного более подробные объяснения (и вы можете найти много других в Интернете).

Подумайте об использовании MELT (предметно-ориентированный язык для расширения GCC 4.6 или новее) для изучения (или даже изменения) внутренних представлений GCC. MELT очень хорошо подходит для этой цели.


Примечание:

вашему gcc-4.1 несколько лет. GCC 4.7 только что выпущен (фактически 4.7.0 второй кандидат на выпуск ). И GCC добился большого прогресса с 4.1 (появился в 2006 году). Вы действительно должны использовать более новые версии (как минимум 4.6), если вы заботитесь об оптимизации. Вы можете задать вопросы о внутреннем компоненте GCC на gcc@gcc.gnu.org (списки для тех, кто разрабатывает или взламывает компилятор), но большинство участников GCC забыли подробности о 4.1. Используйте gcc-help@gcc.gnu.org для общей справки о GCC (то есть, как его построить или использовать).

...