- Clang. Часть 1: введение
- Что такое Clang?
- Как работает Clang?
- Clang AST
- Как использовать Clang?
- Clang Plugin
- LibTooling (Clang Tool)
- LibClang
- Начинаем работать с Clang
- Знакомьтесь — Linux From Scratch
- Вместо вступления
- Единственный бумажный дистрибутив
- Но почему начинать с него?
- Цифры и суровая правда жизни
- Состав дистрибутива
- Вместо заключения
- Clang linux from scratch
Clang. Часть 1: введение
Что такое Clang?
Я провёл последние несколько месяцев, работая с Clang, фронтендом LLVM. Clang умеет парсить и анализировать любой исходный код на языках семейства С (C, C++, ObjectiveC, и т.п. ) и имеет удивительную модульную структуру, которая делает его простым в использовании.
Если вы ищете статический анализатор кода, я настоятельно рекомендую Clang, он существенно превосходит другие статические анализаторы (такие, как CIL. ) и хорошо документирован. Также список рассылки Clang очень активен и полезен, если вы застряли на чём-то.
Лично я использую Clang для статического анализа драйверов ввода-вывода ядра Linux, включая драйвера камеры и драйвера DRM графической карты. Код ядра, особенно код драйвера, может быть очень сложным и трудным для анализа, но Clang позволяет нам легко поддерживать его. Давайте посмотрим, что можно сделать с его помощью.
Как работает Clang?
В большинстве случаев, Clang запустит препроцессор (который разворачивает все макросы) и парсит исходник, превращая его в абстрактное синтаксическое дерево (AST). C AST работать гораздо проще, чем с исходным кодом, но вы всегда можете получить ссылки на исходник. Фактически, каждая структура в Clang-е, используемая для представления кода (AST, CFG и т.п.), всегда имеет ссылку на оригинальный исходник, полезный для целей анализа, рефакторинга и т.п.
если вам нужно анализировать и модифицировать код на уровне исходника, Clang лучше, чем LLVM. Анализ с помощью LLVM означает, что вы можете использовать язык внутреннего представления LLVM, похожий на ассемблер.
Clang AST
Практически каждый компилятор и статический анализатор использует AST для представления исходного кода. AST, используемое в Clang, очень детализированное и сложное, но вы получите удовольствие, изучая различные классы элементов Clang AST. Ниже приводится краткое введение в Clang AST, но самый простой путь изучить его, это просто делать дампы AST для простых исходников, и смотреть, какое AST им соответствует.
В общем, Clang AST сделано из двух очень гибких классов: Decl и Stmt. У обоих есть множество подклассов, вот несколько примеров:
FunctionDecl — прототип или объявление функции
BinaryOperator — бинарный оператор, например (a + b)
CallExpr — вызов функции, например, foo(x);
Большинство классов имеют «говорящие» имена, например, ForStmt, IfStmt, и ReturnStmt. Вы поймёте суть AST, поиграв с ним несколько минут. Вы можете найти документацию по классам AST, поискав что-либо вроде “Clang FunctionDecl.”
Как использовать Clang?
Clang может использоваться как прямая замена gcc и предлагает несколько крутых инструментов статического анализа. Как программист (а не как нормальный пользователь!), вы можете получить доступ к всей мощи clang, используя его как библиотеку одним из трёх способов, в зависимости от того, как вы решите.
Для начала, ознакомьтесь с описанием интерфейсов clang. В дополнение к тому, что написано в этом описании, я выделю другие существенные различия между различными интерфейсами clang.
Clang Plugin
Ваш код является плагином, и запускается каждый раз заново для каждого файла исходника, что означает, что вы не можете сохранять глобальную информацию или другую контекстную информацию между двумя разными исходными файлами (но вы можете запустить плагин для множества файлов последовательно). Плагин запускается путём передачи соответствующих опций системе компиляции (Clang, Make и т.п.) через аргументы командной строки. Это похоже на то, как вы включаете оптимизацию в GCC (т.е. «-O1»). Вы не можете запустить какую-либо свою задачу до или после того, как исходный файл будет проанализирован.
LibTooling (Clang Tool)
Ваш код — обычная программа на С++, с нормальной функцией main(). LibTooling используется для запуска некоторого анализа на исходном коде (с множеством файлов, при желании) без запуска обычного процесса компиляции. Новый экземпляр кода для анализа (и новый AST) будет создан для каждого нового файла исходника (как и в случае Clang Plugin), но вы можете сохранять контекстную информацию между файлами исходников в своих глобальных переменных. Так как у вас есть функция main(), вы можете запускать какие-либо задачи перед или после того, как clang завершит анализ ваших исходных файлов.
LibClang
LibClang хорош тем, что это стабильный API. Clang периодически меняется, и если вы используете Plugin или Libtooling, вам нужно будет править ваш код, чтобы отслеживать эти изменения (но это не так сложно!). Если вам нужен доступ к Clang API из языков, отличных от C++ (например, из Python), вы должны использовать LibClang.
Примечание: LibClang не даёт полный доступ к AST (только высокоуровневый доступ), но другие два варианта дают. Как правило, нам нужен полный доступ к AST.
Если вы не можете решить, что использовать, я бы порекомендовал начать с интерфейса LibTooling. Он проще, и работает так, как вы ожидаете. Он предлагает гибкость и полный доступ к AST, как и Plugin, без потери глобального контекста между исходными файлами. LibTooling не сложнее в использовании, чем Plugin.
Начинаем работать с Clang
Сейчас, когда вы знаете основы, давайте начнём! Эта инструкция будет работать на любой версии Linux (и, возможно, OS X), но тестировалось на Ubuntu. Вы можете получить LLVM и Clang, проделав следующие шаги (взято из официальной инструкции к Clang):
Скачать и установить (например, с помощью apt-get) все необходимые пакеты.
(Типичный дистрибутив Linux идёт со всем необходимым, кроме subversion).
Смените директорию на ту, в которую вы хотите установить LLVM (например,
/static_analysis/). Будем называть её директорией верхнего уровня. Выполните следующие команды в терминале:
Компиляция LLVM и Clang займёт некоторое время.
Для проверки запустите:
Можно протестировать Clang, запустив классический пример Hello World:
В этом руководстве я использую Clang 3.4 на Ubuntu 13.04, но вы можете использовать другие варианты и того, и другого.
Сейчас перейдём к программированию на Clang.
Источник
Знакомьтесь — Linux From Scratch
Вместо вступления
«Хочешь начать изучать GNU/Linux? Начни с Linux From Scratch.»
Единственный бумажный дистрибутив
LFS (здесь и далее аббревиатура от Linux From Scratch) – книга, написанная Герардом Бикмансом, описывающая процесс сборки минимального рабочего варианта GNU/Linux из исходных кодов. Почему бумажный? В свое время книгу можно было купить в твердом переплете, что делает «дистрибутив» несколько необычным, не правда-ли? Помимо самой книги, для сборки конечно-же понадобится интернет (или заранее загруженные исходные коды), свободный раздел на жестком диске, и любая операционная система на базе ядра Linux, имеющая компилятор. Лично я всегда использую либо уже собранный дистрибутив LFS, либо полную установку Slackware – в нем есть все необходимое, чего не скажешь про (например) Ubuntu. Конечно, всегда можно загрузить нехватающие пакеты, но ведь мы хотим только-только научиться линуксу? А Slackware даже в своей базовой установке и без конфигурирования предоставляет требуемый инструментарий.
Следует сказать сразу — дистрибутив собранный по книге LFS не умеет толком ничего. Вернее, ничего такого, что потребуется неискушенному пользователю. Он умеет включаться, выключаться, перезагружаться, использовать Ethernet подключение, но что самое главное — компилировать. Так существуют другие книги, теперь уже поддерживаемые сообществом — Beyond LFS позволяет собрать те самые, интересные пользователю, программы. От браузера и графической среды, до систем управления базами данных и DHCP сервера. Книга имеет свойство отставать в версии от базовой книги, но полученный от LFS опыт обычно достаточен, для самостоятельного разрешения конфликтов версий. Три другие книги — Automated LFS, Cross LFS и Hardened LFS полностью соответствуют названиям и выходят за пределы этой статьи. Впрочем, всегда можно почитать в интернете, правда?
Но почему начинать с него?
Все очень просто, если не сказать — до смешного. Помимо инструкций, в книге много теоретического (но крайне сжатого и как следствие — не заунывного) материала. Установите Ubuntu. Вы знаете что делает пакет Libtool? Или Gawk? После пары успешных сборок LFS, вы будете знать каждый пакет в своей системе и что самое главное — представлять, как они взаимодействуют. Да, состав системы минимальный, но это постоянно подогревает интерес к ее усовершенствованию. Приучит частенько обращаться за помощью к Google и читать англоязычную документацию. Поначалу вы не будете понимать и половины своих действий, внимательно перепечатывая или копируя блоки кода в консоль. Но в самом конце, осознание того, что эту неказистую, без поддержки графики и вашей мощной видеокарты, без новомодного Aero и сенсорных экранов, операционную систему вы собрали сами, придаст вам такой запас сил и гордость, что вы сами потянитесь за новыми знаниями и новыми победами. Я немного утрирую, но ощущения после первой перезагрузки в новую систему сложно забыть даже сейчас.
Цифры и суровая правда жизни
LFS вовсе не минимальный по своему весу дистрибутив. Для сборки потребуется порядка 3 свободный гигабайтов на диске (это помимо уже рабочей Linux-Based системы) — тем не менее, после определенных танцев, систему можно будет превратить в Live-CD. Если у меня будет такая возможность, я расскажу как это делается, в последствии. Компиляция всего и вся (с учетом необходимости создания конфигурационных файлов и прочего) занимает около двух дней. Это если с перерывами на сон, питание и отключение компьютера на ночь. С другой стороны, это зависит от производительности компьютера, на котором собирается система. Моей первой жертвой был ноутбук MSI X-340 — процессор Intel Core 2 Solo с тактовой частотой 1.2 гигагерца (вообще говоря, LFS рекомендуется собирать на одноядерной системе). Оперативная память — 2GB DDR2. Вполне достаточно даже более низких характеристик, а на быстром процессоре сборка пойдет значительно быстрее.
Кстати, приблизительное время сборки каждого из пакетов указано в учебнике. За единицу времени, принимается время сборки пакета Binutils — ассемблера, линкера и ряда других, более мелких утилит для работы с объектными файлами. На вышеуказанной системе это заняло три минуты.
Состав дистрибутива
Перечислять все входящие в LFS пакеты не имеет большого смысла. Список получится длинным, и практически ни о чем не говорящим новичку; избыточным для человека разбирающегося. В этом небольшом разделе я лишь хотел дать несколько общих советов. Во-первых, собирая пакет, не описанный в книге, загляните в репозиторий патчей — возможно его уже адаптировали для использования в LFS. Во-вторых, BLFS почти полностью состоит из опциональных пакетов — просто выбирайте те, которые вам нужны и смело добавляйте в свою сборку LFS. И третье: с самого начала используйте пакетный менеджер. В книге этому уделяется глава, но практические инструкции отсутствуют чуть менее, чем полностью. Я лишь могу порекомендовать Guarded Installation Tool – написанный на Bash’е скрипт, обеспечивающий минимальный набор команд, для управления пакетами, зависимостями и версиями. В LFS этого будет достаточно. В последствии вы можете скомпилировать из исходных кодов APT или DPKG — это неплохо освещено на форумах сообщества.
Вместо заключения
За прошедшие полтора года я сильно продвинулся в своем изучении. Продвинулся со стадии «Есть такая операционная система» до уровня «Подниму сервер под Gentoo за трое суток». Я еще очень далек от идеала и вряд ли могу даже называть себя настоящий линуксоидом — на домашнем компьютере уживаются старенькая Windows XP и Xubuntu 10.10, но знаете что я отвечаю, когда меня спрашивают с чего начать изучать линукс? Начните с Linux From Scratch.
Источник
Clang linux from scratch
CMLFS — Clang Musl Linux From Scratch
CMLFS can either mean «Clang-built Musl Linux from Scratch» or «Clang MLFS». It started as a hobby to see if a Linux system can be built with clang as primary toolchain and GCC as secondary (for packages that cannot be built with clang). This is based on Linux From Scratch (www.linuxfromscratch.org) and my previous work MLFS (https://github.com/dslm4515/Musl-LFS).
- C Runtime Library (system libc): Musl
- Default C Compiler: clang (LLVM)
- Default C++ compiler: clang++ (LLVM)
- Default linker: lld (LLVM)
- Default binary tools: (LLVM)
- Secondary C Compiler: GCC
- Secondary C++ compiler: GCC
- Secondary binary tools: GNU Binutils
- Secondary linker(s): bfd, gold
- C++ standard library: libcxx (LLVM)
- C++ ABI library: libcxxabi (LLVM)
- Unwinding Library: libunwind (LLVM)
- Init system: skarnet’s S6 & S6-rc
- Device manager: Udev
- TLS Implementaion: LibreSSL
- System Shell: Bash
- System Gettext: gettext-tiny
- AMD64/x86_64: Toolchains and final system build sucessfully (musl & glibc hosts) .
- i686: Pending
- AARCH64/ARM64: Pending
- ARMV7L: Pending
- Build a toolchain (llvmtools) with LLVM+stage1_clang but without GCC
- Build final root filesystem with LLVM
- Set default linker as lld(LLVM)
- Set default C++ standard library as libcxx(LLVM)
- Set default C++ ABI library as libcxxabi(LLVM)
- Set default stack unwinding library as libunwind(LLVM)
- Eliminate dependacy on GCC’s libgcc_s
- Build GCC as a secondary systen compiler.
- Build toolchain (llvmtools) with GCC as secondary compiler
- Merge cross-tools build with cgnutools
- Build successfully on a Glibc host
- Reduce LLVM size & build time for cgnutools and llvmtools
- Build on aarch64
Host System Requirements
Required Base Development tools (may refer to LFS)
- bash 3.2 (/bin/sh should be a symbolic or hard link to bash)
- binutils 2.25
- bison 2.7 (/usr/bin/yacc should be a link to bison or small script that executes bison)
- bzip2 1.0.4
- coreutils 6.9
- diffutils 2.8.1
- findutils 4.2.31
- gawk 4.0.1 (/usr/bin/awk should be a link to gawk)
- GCC 6.2 *including the C++ compiler, g++
- Glibc 2.11 / Musl Libc 1.20
- Grep 2.5.1a
- gzip 1.3.12
- linux kernel 3.2 (not sure if it matters, as most distros are running 4.x/5.x kernels
- m4 1.4.10
- make 4.0
- patch 2.5.4
- Python 3.4
- sed 4.1.5
- tar 1.22
- texinfo 4.7
- xz 5.0.0
* (if hostdistro is MLFS/LFS, then all development packages are installed)
Build or use ‘cross-tools’ from Musl-LFS to cross-compile stage0 clang. This stage0 clang will still link to libgcc_s but will later be used to build a stage1 clang free of libbgcc_s . The goal is to build clang+friends with clang and not GCC.
- Build `cgnutools` with host’s GCC
- Build a stage0 clang with GCC libraries with `cgnutools`: build clang via llvm source with clang+lld unpacked in `llvm/tools` and libunwind, libcxxabi & libcxx in `lvm/projects`.
- Build individually in LLVM source tree libunwind, libcxxabi and libcxx with stage0 clang and install in `llvmtools`.
- Build a new stage1 clang with stage0 clang. This new stage1 clang will not have GCC libraries. This will install in `llvmtools`.
- Using stage1 clang, build toolchain (llvmtools) for use in chroot
- Build final root filesystem in chroot with stage1 clang and toolchain (llvmtools)
Источник