mr-ZA
@mr-ZA

Компиляция c++?

Всем привет, объясните один момент по компиляции исходников, есть код в качестве примера:

#mainx.cpp#
#include <iostream>
#include "printx.h"		
using namespace std;

int main()
{
    int a = 4;

    cout << "Calling function!" << endl;
    cout << printx(a) << endl;


return 0;
}


#printx.h#
void printx(int );

#printx.cpp#
#include <iostream>
#include "printx.h"

void printx(int x)
{
   for (int i = 0; i < x; i++) {
      std::cout << "hello" << std::endl;
   }
}


Я так понимаю, что файл "printx.h" он по-сути вставляет прототип функции printx() в исходник "printx.cpp" и "mainx.cpp" для контроля за вызовом ее(например правильность количества аргументов). Тогда вопрос, получается mainx узнает о том что есть функция printx() на этапе линковки [mainx.o] и [printx.o]? Каким образом происходит передача информации в [mainx] что функция printx() существует?
  • Вопрос задан
  • 135 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
получается mainx узнает о том что есть функция printx() на этапе линковки [mainx.o] и [printx.o]?

Да.

Каким образом происходит передача информации в [mainx] что функция printx() существует?

Это работа линковщика связывать ссылки на неопределённые символы с определениями этих символов.
В main.o в месте вызова printx ставится команда вызова, в секции символов заводится неопределённый символ printx а в секции релокаций заводится запись, связывающая команду вызова с символом:

objdump -dr mainx.o
...
0000000000000000 <main>:
   0:   55                      push   %rbp
...
  3a:   89 c7                   mov    %eax,%edi
  3c:   e8 00 00 00 00          callq  41 <main+0x41>
                        3d: R_X86_64_PLT32      _Z6printxi-0x4
  41:   b8 00 00 00 00          mov    $0x0,%eax
  46:   c9                      leaveq 
  47:   c3                      retq   
...


readelf -a mainx.o
...
Relocation section '.rela.text' at offset 0x580 contains 12 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
...
00000000003d  001400000004 R_X86_64_PLT32    0000000000000000 _Z6printxi - 4
...

Symbol table '.symtab' contains 25 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
...
    20: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _Z6printxi
...


В printx.o в секции символов заводится символ, ассоциированный с адресом в коде, где определена функция printx:

readelf -a printx.cpp
...
Symbol table '.symtab' contains 24 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
...
    14: 0000000000000000    75 FUNC    GLOBAL DEFAULT    1 _Z6printxi
...

Здесь value == 0 -- потому что printx оказалась по адресу 0 в секции .text.

Линковщик объединяет входные секции согласно скрипту линковки, после чего вставляет конечные адреса символов в места, которые ссылаются на них.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы