GCC добавляет "лишний" код в функцию.

Тема в разделе "WASM.OS.DEVEL", создана пользователем KIV, 23 мар 2011.

  1. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    Написал функцию для отладочного вывода числа на экран в своей ОС:
    Код (Text):
    1. void  dbg_print_number(size_t number, char base, char digit_count) {
    2.     char buffer[64 + 1];
    3.     buffer[sizeof(buffer) - 1] = 0;
    4.     char i = sizeof(buffer) - 2;
    5.     do {
    6.         buffer[i] = digits[number % base];
    7.         i--;
    8.         if (digit_count) digit_count--;
    9.         number = number / base;    
    10.     } while (number);
    11.     for (; digit_count; digit_count--) {
    12.         buffer[i] = '0';
    13.         i--;
    14.     }
    15.     dbg_print_string(&buffer[i + 1]);
    16. }
    Но GCC почему то добавляет весьма странный код в начало этой функции:
    [​IMG]
    Разумеется, он не работает корректно и рушит систему.
    Что это такое и как от этой ерунды избавится?
     
  2. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Ты бы хоть первую цифру версии gcc озвучил бы. Лучше парочку. У меня 4.4.5, он делает так:
    Код (Text):
    1. dbg_print_number:
    2. .LFB0:
    3.     .cfi_startproc
    4.     pushq   %rbp    #
    5.     .cfi_def_cfa_offset 16
    6.     movq    %rsp, %rbp  #,
    7.     .cfi_offset 6, -16
    8.     .cfi_def_cfa_register 6
    9.     pushq   %rbx    #
    10.     subq    $120, %rsp  #,
    11.     movq    %rdi, -104(%rbp)    # number, number
    12.     movl    %esi, %ecx  # base, tmp67
    13.     movl    %edx, %eax  # digit_count, tmp68
    14.     movb    %cl, -108(%rbp) # tmp67, base
    15.     movb    %al, -112(%rbp) # tmp68, digit_count
    16.     movb    $0, -32(%rbp)   #, buffer
    17.     movb    $63, -17(%rbp)  #, i
    18. .L3:
    19.     movsbl  -17(%rbp),%ecx  # i, D.2130
    Как видим ничего не пытается писать по адресу 0x28.

    Но как бы там ни было, попробуй при компиляции использовать во-первых, -Wall, во-вторых -O2. Первое поможет тебе код чище писать, второе заставит gcc иначе подходить к генерации процессорного кода.
     
  3. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    -O2 не помогает - так инструкция всё равно присутствует.
    Код (Text):
    1. $ gcc --version
    2. gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
    У меня такое ощущение, что я не все стандартные библиотеки обрубил и он ещё пытается использовать какие-то структуры данных ОС.
    Вот флаги компиляции:
    Код (Text):
    1. CFLAGS = -ffreestanding -m64 -mcmodel=kernel
    Может ещё какую-нибудь опцию забыл?
     
  4. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    С твоими флагами компиляции мне всё равно не удаётся получить обращение к gs:0x28. Попробовал ещё gcc-4.3.4 тоже не вышло.
    AFAIK, gcc по-любому будет линковать с libgcc.a. Или её надо вручную указывать... Не знаю, честно говоря, с этими вопросами я лишь понаслышке знаком.
    Вообще, я краем уха слышал, что fs и gs используются в лине для организации TLS. Ты там с __thread ничего не мутил?
     
  5. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    -fno-stack-protector
     
  6. KIV

    KIV Member

    Публикаций:
    0
    Регистрация:
    16 июл 2009
    Сообщения:
    231
    А вот это помогло. Заодно смог убрать пустую __stack_chk_fail, которую пришлось объявить, чтобы не было ошибки линковки.
    А теперь мне уже просто интересно, что всё это было и как это работает.
     
  7. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Видать убунта втыкает stack-protector по-умолчанию. То ли в spec файлах, то ли ещё как.
    KIV
    Не знаю будет ли это достаточным ответом, но всё же, вот цитата из info gcc:
    Код (Text):
    1. `-fstack-protector'
    2.      Emit extra code to check for buffer overflows, such as stack
    3.      smashing attacks.  This is done by adding a guard variable to
    4.      functions with vulnerable objects.  This includes functions that
    5.      call alloca, and functions with buffers larger than 8 bytes.  The
    6.      guards are initialized when a function is entered and then checked
    7.      when the function exits.  If a guard check fails, an error message
    8.      is printed and the program exits.