Связывание нескольких модулей LLVM C++ вместе segfaults в lli

Я пробую очень простой пример с LLVM/clang и, кажется, терплю неудачу.

Я пробую следующее:

  1. clang++ -emit-llvm -c -x c++ -o main.bc -isystem include/ main.cc
  2. clang++ -emit-llvm -c -x c++ -o test_class.bc -isystem include/ test_class.cc
  3. llvm-ссылка main.bc test_class.bc -o all.bc
  4. лли all.bc

Однако 4. терпит неудачу (segfaults) с:

0  libLLVM-3.3.so  0x0000003b890f9e52 llvm::sys::PrintStackTrace(_IO_FILE*) + 34
1  libLLVM-3.3.so  0x0000003b890f9cb9
2  libpthread.so.0 0x0000003b8520efa0
3  libLLVM-3.3.so  0x0000003b89982790 llvm::MachineJumpTableInfo::getEntrySize(llvm::DataLayout const&) const + 0
4  libLLVM-3.3.so  0x0000003b894bfb23
5  libLLVM-3.3.so  0x0000003b894c8dc3
6  libLLVM-3.3.so  0x0000003b8981b27f
7  libLLVM-3.3.so  0x0000003b8969d2d6 llvm::FPPassManager::runOnFunction(llvm::Function&) + 422
8  libLLVM-3.3.so  0x0000003b8969d3f6 llvm::FunctionPassManagerImpl::run(llvm::Function&) + 102
9  libLLVM-3.3.so  0x0000003b8969d4cb llvm::FunctionPassManager::run(llvm::Function&) + 91
10 libLLVM-3.3.so  0x0000003b894b3264 llvm::JIT::jitTheFunction(llvm::Function*, llvm::MutexGuard const&) + 36
11 libLLVM-3.3.so  0x0000003b894b394f llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard const&) + 15
12 libLLVM-3.3.so  0x0000003b894b3b7e llvm::JIT::getPointerToFunction(llvm::Function*) + 254
13 libLLVM-3.3.so  0x0000003b894c6649
14 libLLVM-3.3.so  0x0000003b894c909c
15 libLLVM-3.3.so  0x0000003b8981b27f
16 libLLVM-3.3.so  0x0000003b8969d2d6 llvm::FPPassManager::runOnFunction(llvm::Function&) + 422
17 libLLVM-3.3.so  0x0000003b8969d3f6 llvm::FunctionPassManagerImpl::run(llvm::Function&) + 102
18 libLLVM-3.3.so  0x0000003b8969d4cb llvm::FunctionPassManager::run(llvm::Function&) + 91
19 libLLVM-3.3.so  0x0000003b894b3264 llvm::JIT::jitTheFunction(llvm::Function*, llvm::MutexGuard const&) + 36
20 libLLVM-3.3.so  0x0000003b894b394f llvm::JIT::runJITOnFunctionUnlocked(llvm::Function*, llvm::MutexGuard const&) + 15
21 libLLVM-3.3.so  0x0000003b894b3b7e llvm::JIT::getPointerToFunction(llvm::Function*) + 254
22 lli             0x00000000004073cf main + 2527
23 libc.so.6       0x0000003b84621b75 __libc_start_main + 245
24 lli             0x000000000040a271
Stack dump:
0.      Program arguments: lli all.bc 
1.      Running pass 'X86 Machine Code Emitter' on function '@main'
2.      Running pass 'X86 Machine Code Emitter' on function '@_ZN10test_classC2ESs'
[1]    15327 segmentation fault (core dumped)  lli all.bc

Есть ли у меня фундаментальное непонимание того, как это должно работать? Моя конечная цель — сделать часть компиляции с использованием API libclang, но сейчас было бы здорово понять, что я здесь делаю неправильно! Спасибо!

Я приложил исходный код для примера ниже:

включить/test_class.h:

#ifndef __TEST_CLASS_H__
#define __TEST_CLASS_H__

#include <string>
#include <iostream>

struct test_class
{
  test_class(std::string foo);
  ~test_class();

  std::string foo;
};

#endif

test_class.cc:

#include <test_class.h>

test_class::test_class(std::string foo) : foo(foo)
{
  std::cout << foo << std::endl;
}

test_class::~test_class(void)
{
}

основной.cc:

#include <cstdlib>
#include <string>
#include <iostream>

#include <test_class.h>

int main(int argc, char** argv)
{
  test_class test("foo");

  return EXIT_SUCCESS;
}

person Moritz Fischer    schedule 25.08.2013    source источник


Ответы (1)


В test_class вы ссылаетесь на std::string. Я полагаю, вызовы связанных функций помечаются external, если вы заглянете в IR (например: llvm-dis < all.bc).

Если вы компилируете в «обычный» исполняемый код, эти вызовы разрешаются компоновщиком. Поскольку вы компонуете вручную с помощью llvm-link, вам придется предоставить IR-код для библиотек C++, иначе выполнение может завершиться ошибкой.

person cpt. jazz    schedule 25.08.2013
comment
Спасибо за ответ, но не исправил. - person Moritz Fischer; 25.08.2013
comment
Вы можете подтвердить мою теорию? Если это так, то решение нетривиальное, потому что вам нужно управлять компиляцией библиотек C++ (+ их зависимостей) в IR-код. Связывание с двоичным файлом (как в обычном процессе компиляции) здесь невозможно. - person cpt. jazz; 25.08.2013
comment
Даже если я удалю std::string и std::cout, произойдет то же самое. Спасибо, в любом случае. - person Moritz Fischer; 25.08.2013
comment
Ну, если вы можете предоставить мне вывод llvm-dis < all.bc (через GIST или аналогичный), я быстро посмотрю. ;) - person cpt. jazz; 25.08.2013
comment
Код IR полон вызовов std::*, и если вы посмотрите, функции, на которые ссылаются, только declared, но не defined (например, у них есть нет тела функции) -- как сказано выше, традиционно это решается компоновщиком, который заменяет эти адреса вызовов адресами уже скомпилированных библиотек. Поскольку вы пытаетесь выполнить с помощью интерпретатора, lli не знает, что делать при вызове таких функций. Когда вы удалили вызовы std::string и т. д., вы также удалили #include? Если нет, сделайте это, потому что там, кажется, есть некоторая статическая инициализация. - person cpt. jazz; 26.08.2013
comment
Кажется, я ошибался: я попробовал минимальный пример, и lli, похоже, может динамически связываться с библиотеками libstdc++, а cout, string и т. д. работают правильно. Ваша проблема должна быть где-то в другом... - person cpt. jazz; 26.08.2013
comment
@cpt.jazz Привет, как получить ссылку lli на стандартную библиотеку. Насколько я знаю, он просто компилирует модуль и запускает его. Если я был неправ, пожалуйста, дайте мне знать! - person PreeJackie; 22.03.2019