Неразумная путаница в именах в LLVM

Я пытался построить и выполнить модули LLVM. Мой код для генерации модулей довольно длинный, поэтому я не буду публиковать его здесь. Вместо этого мой вопрос о том, как Clang и LLVM работают вместе, чтобы добиться искажения имен. Я объясню свою конкретную проблему, чтобы мотивировать вопрос.

Вот исходный код одного из моих модулей LLVM:

#include <iostream>

int main() {
  std::cout << "Hello, world. " << std::endl;
  return 0;
}

Вот сгенерированный LLVM IR; он слишком велик для Stackru.

Когда я пытаюсь выполнить мой модуль, используя lliЯ получаю следующую ошибку:

ОШИБКА LLVM: Программа использовала внешнюю функцию '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc', которая не может быть разрешена!

При прохождении символа через деманглера, отсутствующий символ:

_std:: __ 1:: basic_string, std:: __ 1:: allocator>:: basic_string (unsigned long, char)

Экстра _ подозрительно, и функция без начального подчеркивания, кажется, существует в IR!

; Function Attrs: alwaysinline ssp uwtable
define available_externally hidden void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc(%"class.std::__1::basic_string"*, i64, i8 signext) unnamed_addr #2 align 2 {
  %4 = alloca %"class.std::__1::basic_string"*, align 8
  %5 = alloca i64, align 8
  %6 = alloca i8, align 1
  store %"class.std::__1::basic_string"* %0, %"class.std::__1::basic_string"** %4, align 8
  store i64 %1, i64* %5, align 8
  store i8 %2, i8* %6, align 1
  %7 = load %"class.std::__1::basic_string"*, %"class.std::__1::basic_string"** %4, align 8
  %8 = load i64, i64* %5, align 8
  %9 = load i8, i8* %6, align 1
  call void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2Emc(%"class.std::__1::basic_string"* %7, i64 %8, i8 signext %9)
  ret void
}

Я нахожусь на macOS, поэтому стоит ожидать подчеркивания, но я думаю, что Clang может добавить его дважды.

Я просмотрел источник LLVM / Clang, и кажется, что есть два шага искажения:

  1. Взяв, возможно, перегруженные функции C++ и переназначив их на уникальные имена для LLVM IR
  2. Извлечение искаженного имени из IR LLVM и добавление любых специфических для платформы причуд, таких как начальные подчеркивания

Впрочем, это всего лишь моя теория. Может кто-нибудь объяснить, как процесс искажения работает в Clang и LLVM? Как мне создать свой llvm::DataLayout объекты, чтобы получить правильное искажение для моей платформы?


nm -gU /usr/lib/libc++.dylib а также nm -gU /usr/lib/libc++abi.dylib не содержат __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorI‌​cEEEC1Emc


Когда я пытаюсь скомпилировать IR, я получаю эту ошибку:

llc generated.ll
clang++ generated.s

Неопределенные символы для архитектуры x86_64: "std::__1::basic_string, std::__1::allocator >::data() const", на которую ссылается: std::__1::ostreambuf_iterator > std::__1::__pad_and_output >(std::__1::ostreambuf_iterator >, char const*, char const*, char const*, std::__1::ios_base&, char) в генерируемом-b4252a.o "std::__1::basic_ostream >::sentry::operator bool() const", на который ссылаются из: std::__1::basic_ostream >& std::__1::__put_character_sequence >(std::__1::basic_ostream >&, char const*, unsigned long) в сгенерированном-b4252a.o "std::__1::basic_ios >::fill() const", на который ссылаются из: std::__1::basic_ostream >& std::__1::__put_character_sequence >(std::__1::basic_ostream >&, char const*, unsigned long) в генерируемом -b4252a.o "std::__1::basic_ios >::rdbuf() const", на который ссылается: std::__1::ostreambuf_iterator >::ostreambuf_iterator(std::__1::basic_ostream >&) в созданном-b4252a.o "std::__1::basic_ios >::widen(char) const", на который ссылается: std::__1::basic_ostream >& std::__1::endl >(станд:: __ 1:: барельефа ic_ostream> &) в созданном-b4252a.o "std::__1::basic_string, std::__1::allocator >::basic_string(unsigned long, char)", на который ссылается: std::__1::ostreambuf_iterator > std::__1::__pad_and_output >(std::__1::ostreambuf_iterator >, char const*, char const*, char const*, std::__1::ios_base&, char) в генерируемом-b4252a.o "std::__1::basic_ios >::setstate(unsigned int)", на который ссылаются из: std::__1::basic_ostream >& std::__1::__put_character_sequence >(std::__1::basic_ostream >&, char const*, unsigned long) в созданном-b4252a.o ld: символ (ы) не найден для архитектуры x86_64 clang-3.9: ошибка: сбой команды компоновщика с кодом выхода 1 (используйте -v для просмотра вызова)

1 ответ

Я бы не заподозрил проблему искажения имени. Искажение имени в C++ происходит на внешнем интерфейсе (т.е. clang) и это часть довольно четко определенного / документированного стандарта ABI.

Кроме того, я не думаю, что есть ложное подчеркивание, причина, которая не дает действительного C++ name back и искаженное имя в предоставленной вами ссылке на pastebin выглядит следующим образом:

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc

Я не на Mac OS, но симулирую с моим LLVM 3.8.1 на Linux (используя --stdlib=libc++), используя тот же источник и сопоставляя ИК построчно, я получаю следующий символ:

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc

который восстанавливает обратно к:

std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(unsigned long, char)

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

Итак, я считаю, что ваш компоновщик подхватывает неправильно libc++ версия.

Вы можете проверить символы, доступные в libc++ это связано с Clang/LLVM, который вы используете, находится в каталоге, заданном llvm-config --libdir или даже проверяя запись rpath ваших бинарных файлов с помощью readelf -d $(which lli),

Если существует несколько установок LLVM (например, система, одна из которых вы сами скомпилировали из источников), вам, возможно, придется поиграться с -L вариант clang который направляет ld чтобы добавить этот путь в свой список поиска. Быстрая альтернатива (которую я бы не рекомендовал для регулярного использования) - сделать это в командной строке:

LD_LIBRARY_PATH=$(llvm-config --libdir) clang generated.s

Другие вопросы по тегам